├── .gitignore ├── Readme.md ├── bin └── create-graphless ├── package-lock.json ├── package.json ├── src ├── cli.js └── main.js └── templates ├── db ├── .funcignore ├── .gitignore ├── azure-pipelines.yml ├── db-utils │ └── db.js ├── extensions.csproj ├── graphiql │ ├── env.js │ └── index.html ├── graphless │ ├── function.json │ └── index.js ├── graphql-utils │ ├── resolvers.js │ └── schema.js ├── host.json ├── package.json ├── proxies.json └── scripts │ ├── deployment │ ├── env │ ├── graphiql │ ├── env.js │ └── index.html │ └── template │ └── azuredeploy.json └── javascript ├── .funcignore ├── .gitignore ├── azure-pipelines.yml ├── extensions.csproj ├── graphiql ├── env.js └── index.html ├── graphless ├── function.json └── index.js ├── graphql-utils ├── resolvers.js └── schema.js ├── host.json ├── local.settings.json ├── package.json ├── proxies.json └── scripts ├── deployment ├── env ├── graphiql ├── env.js └── index.html └── template └── azuredeploy.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | 24 | # nyc test coverage 25 | .nyc_output 26 | 27 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 28 | .grunt 29 | 30 | # Bower dependency directory (https://bower.io/) 31 | bower_components 32 | 33 | # node-waf configuration 34 | .lock-wscript 35 | 36 | # Compiled binary addons (https://nodejs.org/api/addons.html) 37 | build/Release 38 | 39 | # Dependency directories 40 | node_modules/ 41 | jspm_packages/ 42 | 43 | # TypeScript v1 declaration files 44 | typings/ 45 | 46 | # Optional npm cache directory 47 | .npm 48 | 49 | # Optional eslint cache 50 | .eslintcache 51 | 52 | # Optional REPL history 53 | .node_repl_history 54 | 55 | # Output of 'npm pack' 56 | *.tgz 57 | 58 | # Yarn Integrity file 59 | .yarn-integrity 60 | 61 | # dotenv environment variables file 62 | .env 63 | .env.test 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Graphless 2 | 3 | CLI that generates the code you need for running Graphql with Azure Functions 4 | 5 | ## Prerequisites 6 | 7 | 1. A recent version of [Node](https://nodejs.org/en/download) (8+) 8 | 9 | 1. [Azure Functions CLI](https://docs.microsoft.com/azure/azure-functions/functions-run-local?WT.mc_id=graphqless-github-sicotin) 10 | 11 | 1. [Free Azure Account](https://azure.microsoft.com/en-us/free/?wt.mc_id=graphless-github-sicotin) 12 | 13 | ## How to run it 14 | 15 | 1. Install package ```npm i @simonaco/create-graphless -g``` 16 | 17 | 1. Create new project by running ```create-graphless --git --install``` 18 | 19 | 1. Run project ```npm start``` 20 | 21 | ## License 22 | 23 | [![Creative Commons License](http://mirrors.creativecommons.org/presskit/buttons/88x31/svg/cc-zero.svg)](https://creativecommons.org/publicdomain/zero/1.0/) -------------------------------------------------------------------------------- /bin/create-graphless: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require = require('esm')(module /*, options*/); 4 | require('../src/cli').cli(process.argv); -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@simonaco/create-graphless", 3 | "version": "1.0.3", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@samverschueren/stream-to-observable": { 8 | "version": "0.3.0", 9 | "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", 10 | "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", 11 | "requires": { 12 | "any-observable": "^0.3.0" 13 | } 14 | }, 15 | "@types/execa": { 16 | "version": "0.9.0", 17 | "resolved": "https://registry.npmjs.org/@types/execa/-/execa-0.9.0.tgz", 18 | "integrity": "sha512-mgfd93RhzjYBUHHV532turHC2j4l/qxsF/PbfDmprHDEUHmNZGlDn1CEsulGK3AfsPdhkWzZQT/S/k0UGhLGsA==", 19 | "requires": { 20 | "@types/node": "*" 21 | } 22 | }, 23 | "@types/node": { 24 | "version": "11.13.10", 25 | "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.10.tgz", 26 | "integrity": "sha512-leUNzbFTMX94TWaIKz8N15Chu55F9QSH+INKayQr5xpkasBQBRF3qQXfo3/dOnMU/dEIit+Y/SU8HyOjq++GwA==" 27 | }, 28 | "ansi-escapes": { 29 | "version": "3.2.0", 30 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", 31 | "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" 32 | }, 33 | "ansi-regex": { 34 | "version": "3.0.0", 35 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 36 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" 37 | }, 38 | "ansi-styles": { 39 | "version": "3.2.1", 40 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 41 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 42 | "requires": { 43 | "color-convert": "^1.9.0" 44 | } 45 | }, 46 | "any-observable": { 47 | "version": "0.3.0", 48 | "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", 49 | "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==" 50 | }, 51 | "arg": { 52 | "version": "4.1.0", 53 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz", 54 | "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==" 55 | }, 56 | "chalk": { 57 | "version": "2.4.2", 58 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 59 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 60 | "requires": { 61 | "ansi-styles": "^3.2.1", 62 | "escape-string-regexp": "^1.0.5", 63 | "supports-color": "^5.3.0" 64 | } 65 | }, 66 | "chardet": { 67 | "version": "0.7.0", 68 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", 69 | "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" 70 | }, 71 | "cli-cursor": { 72 | "version": "2.1.0", 73 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", 74 | "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", 75 | "requires": { 76 | "restore-cursor": "^2.0.0" 77 | } 78 | }, 79 | "cli-truncate": { 80 | "version": "0.2.1", 81 | "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", 82 | "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", 83 | "requires": { 84 | "slice-ansi": "0.0.4", 85 | "string-width": "^1.0.1" 86 | }, 87 | "dependencies": { 88 | "ansi-regex": { 89 | "version": "2.1.1", 90 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 91 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 92 | }, 93 | "is-fullwidth-code-point": { 94 | "version": "1.0.0", 95 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", 96 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 97 | "requires": { 98 | "number-is-nan": "^1.0.0" 99 | } 100 | }, 101 | "string-width": { 102 | "version": "1.0.2", 103 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", 104 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 105 | "requires": { 106 | "code-point-at": "^1.0.0", 107 | "is-fullwidth-code-point": "^1.0.0", 108 | "strip-ansi": "^3.0.0" 109 | } 110 | }, 111 | "strip-ansi": { 112 | "version": "3.0.1", 113 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 114 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 115 | "requires": { 116 | "ansi-regex": "^2.0.0" 117 | } 118 | } 119 | } 120 | }, 121 | "cli-width": { 122 | "version": "2.2.0", 123 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", 124 | "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" 125 | }, 126 | "code-point-at": { 127 | "version": "1.1.0", 128 | "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", 129 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" 130 | }, 131 | "color-convert": { 132 | "version": "1.9.3", 133 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 134 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 135 | "requires": { 136 | "color-name": "1.1.3" 137 | } 138 | }, 139 | "color-name": { 140 | "version": "1.1.3", 141 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 142 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 143 | }, 144 | "cross-spawn": { 145 | "version": "6.0.5", 146 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", 147 | "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", 148 | "requires": { 149 | "nice-try": "^1.0.4", 150 | "path-key": "^2.0.1", 151 | "semver": "^5.5.0", 152 | "shebang-command": "^1.2.0", 153 | "which": "^1.2.9" 154 | } 155 | }, 156 | "date-fns": { 157 | "version": "1.30.1", 158 | "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", 159 | "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==" 160 | }, 161 | "elegant-spinner": { 162 | "version": "1.0.1", 163 | "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", 164 | "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=" 165 | }, 166 | "end-of-stream": { 167 | "version": "1.4.1", 168 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", 169 | "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", 170 | "requires": { 171 | "once": "^1.4.0" 172 | } 173 | }, 174 | "escape-string-regexp": { 175 | "version": "1.0.5", 176 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 177 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 178 | }, 179 | "esm": { 180 | "version": "3.2.22", 181 | "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.22.tgz", 182 | "integrity": "sha512-z8YG7U44L82j1XrdEJcqZOLUnjxco8pO453gKOlaMD1/md1n/5QrscAmYG+oKUspsmDLuBFZrpbxI6aQ67yRxA==" 183 | }, 184 | "execa": { 185 | "version": "1.0.0", 186 | "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", 187 | "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", 188 | "requires": { 189 | "cross-spawn": "^6.0.0", 190 | "get-stream": "^4.0.0", 191 | "is-stream": "^1.1.0", 192 | "npm-run-path": "^2.0.0", 193 | "p-finally": "^1.0.0", 194 | "signal-exit": "^3.0.0", 195 | "strip-eof": "^1.0.0" 196 | } 197 | }, 198 | "external-editor": { 199 | "version": "3.0.3", 200 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", 201 | "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", 202 | "requires": { 203 | "chardet": "^0.7.0", 204 | "iconv-lite": "^0.4.24", 205 | "tmp": "^0.0.33" 206 | } 207 | }, 208 | "figures": { 209 | "version": "2.0.0", 210 | "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", 211 | "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", 212 | "requires": { 213 | "escape-string-regexp": "^1.0.5" 214 | } 215 | }, 216 | "get-stream": { 217 | "version": "4.1.0", 218 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", 219 | "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", 220 | "requires": { 221 | "pump": "^3.0.0" 222 | } 223 | }, 224 | "has-ansi": { 225 | "version": "2.0.0", 226 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 227 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 228 | "requires": { 229 | "ansi-regex": "^2.0.0" 230 | }, 231 | "dependencies": { 232 | "ansi-regex": { 233 | "version": "2.1.1", 234 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 235 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 236 | } 237 | } 238 | }, 239 | "has-flag": { 240 | "version": "3.0.0", 241 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 242 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 243 | }, 244 | "iconv-lite": { 245 | "version": "0.4.24", 246 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 247 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 248 | "requires": { 249 | "safer-buffer": ">= 2.1.2 < 3" 250 | } 251 | }, 252 | "indent-string": { 253 | "version": "3.2.0", 254 | "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", 255 | "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=" 256 | }, 257 | "inquirer": { 258 | "version": "6.3.1", 259 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.3.1.tgz", 260 | "integrity": "sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA==", 261 | "requires": { 262 | "ansi-escapes": "^3.2.0", 263 | "chalk": "^2.4.2", 264 | "cli-cursor": "^2.1.0", 265 | "cli-width": "^2.0.0", 266 | "external-editor": "^3.0.3", 267 | "figures": "^2.0.0", 268 | "lodash": "^4.17.11", 269 | "mute-stream": "0.0.7", 270 | "run-async": "^2.2.0", 271 | "rxjs": "^6.4.0", 272 | "string-width": "^2.1.0", 273 | "strip-ansi": "^5.1.0", 274 | "through": "^2.3.6" 275 | } 276 | }, 277 | "is-fullwidth-code-point": { 278 | "version": "2.0.0", 279 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 280 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" 281 | }, 282 | "is-observable": { 283 | "version": "1.1.0", 284 | "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", 285 | "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", 286 | "requires": { 287 | "symbol-observable": "^1.1.0" 288 | } 289 | }, 290 | "is-promise": { 291 | "version": "2.1.0", 292 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 293 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" 294 | }, 295 | "is-stream": { 296 | "version": "1.1.0", 297 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 298 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" 299 | }, 300 | "isexe": { 301 | "version": "2.0.0", 302 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 303 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" 304 | }, 305 | "listr": { 306 | "version": "0.14.3", 307 | "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", 308 | "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", 309 | "requires": { 310 | "@samverschueren/stream-to-observable": "^0.3.0", 311 | "is-observable": "^1.1.0", 312 | "is-promise": "^2.1.0", 313 | "is-stream": "^1.1.0", 314 | "listr-silent-renderer": "^1.1.1", 315 | "listr-update-renderer": "^0.5.0", 316 | "listr-verbose-renderer": "^0.5.0", 317 | "p-map": "^2.0.0", 318 | "rxjs": "^6.3.3" 319 | } 320 | }, 321 | "listr-silent-renderer": { 322 | "version": "1.1.1", 323 | "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", 324 | "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=" 325 | }, 326 | "listr-update-renderer": { 327 | "version": "0.5.0", 328 | "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", 329 | "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", 330 | "requires": { 331 | "chalk": "^1.1.3", 332 | "cli-truncate": "^0.2.1", 333 | "elegant-spinner": "^1.0.1", 334 | "figures": "^1.7.0", 335 | "indent-string": "^3.0.0", 336 | "log-symbols": "^1.0.2", 337 | "log-update": "^2.3.0", 338 | "strip-ansi": "^3.0.1" 339 | }, 340 | "dependencies": { 341 | "ansi-regex": { 342 | "version": "2.1.1", 343 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 344 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 345 | }, 346 | "ansi-styles": { 347 | "version": "2.2.1", 348 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 349 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" 350 | }, 351 | "chalk": { 352 | "version": "1.1.3", 353 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 354 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 355 | "requires": { 356 | "ansi-styles": "^2.2.1", 357 | "escape-string-regexp": "^1.0.2", 358 | "has-ansi": "^2.0.0", 359 | "strip-ansi": "^3.0.0", 360 | "supports-color": "^2.0.0" 361 | } 362 | }, 363 | "figures": { 364 | "version": "1.7.0", 365 | "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", 366 | "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", 367 | "requires": { 368 | "escape-string-regexp": "^1.0.5", 369 | "object-assign": "^4.1.0" 370 | } 371 | }, 372 | "strip-ansi": { 373 | "version": "3.0.1", 374 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 375 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 376 | "requires": { 377 | "ansi-regex": "^2.0.0" 378 | } 379 | }, 380 | "supports-color": { 381 | "version": "2.0.0", 382 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 383 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" 384 | } 385 | } 386 | }, 387 | "listr-verbose-renderer": { 388 | "version": "0.5.0", 389 | "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", 390 | "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", 391 | "requires": { 392 | "chalk": "^2.4.1", 393 | "cli-cursor": "^2.1.0", 394 | "date-fns": "^1.27.2", 395 | "figures": "^2.0.0" 396 | } 397 | }, 398 | "lodash": { 399 | "version": "4.17.15", 400 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 401 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" 402 | }, 403 | "log-symbols": { 404 | "version": "1.0.2", 405 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", 406 | "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", 407 | "requires": { 408 | "chalk": "^1.0.0" 409 | }, 410 | "dependencies": { 411 | "ansi-regex": { 412 | "version": "2.1.1", 413 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 414 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 415 | }, 416 | "ansi-styles": { 417 | "version": "2.2.1", 418 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 419 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" 420 | }, 421 | "chalk": { 422 | "version": "1.1.3", 423 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 424 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 425 | "requires": { 426 | "ansi-styles": "^2.2.1", 427 | "escape-string-regexp": "^1.0.2", 428 | "has-ansi": "^2.0.0", 429 | "strip-ansi": "^3.0.0", 430 | "supports-color": "^2.0.0" 431 | } 432 | }, 433 | "strip-ansi": { 434 | "version": "3.0.1", 435 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 436 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 437 | "requires": { 438 | "ansi-regex": "^2.0.0" 439 | } 440 | }, 441 | "supports-color": { 442 | "version": "2.0.0", 443 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 444 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" 445 | } 446 | } 447 | }, 448 | "log-update": { 449 | "version": "2.3.0", 450 | "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", 451 | "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", 452 | "requires": { 453 | "ansi-escapes": "^3.0.0", 454 | "cli-cursor": "^2.0.0", 455 | "wrap-ansi": "^3.0.1" 456 | } 457 | }, 458 | "mimic-fn": { 459 | "version": "1.2.0", 460 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", 461 | "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" 462 | }, 463 | "mute-stream": { 464 | "version": "0.0.7", 465 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", 466 | "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" 467 | }, 468 | "ncp": { 469 | "version": "2.0.0", 470 | "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", 471 | "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=" 472 | }, 473 | "nice-try": { 474 | "version": "1.0.5", 475 | "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", 476 | "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" 477 | }, 478 | "npm-run-path": { 479 | "version": "2.0.2", 480 | "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", 481 | "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", 482 | "requires": { 483 | "path-key": "^2.0.0" 484 | } 485 | }, 486 | "number-is-nan": { 487 | "version": "1.0.1", 488 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", 489 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" 490 | }, 491 | "object-assign": { 492 | "version": "4.1.1", 493 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 494 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 495 | }, 496 | "once": { 497 | "version": "1.4.0", 498 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 499 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 500 | "requires": { 501 | "wrappy": "1" 502 | } 503 | }, 504 | "onetime": { 505 | "version": "2.0.1", 506 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", 507 | "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", 508 | "requires": { 509 | "mimic-fn": "^1.0.0" 510 | } 511 | }, 512 | "os-tmpdir": { 513 | "version": "1.0.2", 514 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 515 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" 516 | }, 517 | "p-finally": { 518 | "version": "1.0.0", 519 | "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", 520 | "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" 521 | }, 522 | "p-map": { 523 | "version": "2.1.0", 524 | "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", 525 | "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==" 526 | }, 527 | "path-key": { 528 | "version": "2.0.1", 529 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", 530 | "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" 531 | }, 532 | "pkg-install": { 533 | "version": "1.0.0", 534 | "resolved": "https://registry.npmjs.org/pkg-install/-/pkg-install-1.0.0.tgz", 535 | "integrity": "sha512-UGI8bfhrDb1KN01RZ7Bq08GRQc8rmVjxQ2up0g4mUHPCYDTK1FzQ0PMmLOBCHg3yaIijZ2U3Fn9ofLa4N392Ug==", 536 | "requires": { 537 | "@types/execa": "^0.9.0", 538 | "@types/node": "^11.9.4", 539 | "execa": "^1.0.0" 540 | } 541 | }, 542 | "pump": { 543 | "version": "3.0.0", 544 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 545 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 546 | "requires": { 547 | "end-of-stream": "^1.1.0", 548 | "once": "^1.3.1" 549 | } 550 | }, 551 | "restore-cursor": { 552 | "version": "2.0.0", 553 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", 554 | "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", 555 | "requires": { 556 | "onetime": "^2.0.0", 557 | "signal-exit": "^3.0.2" 558 | } 559 | }, 560 | "run-async": { 561 | "version": "2.3.0", 562 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", 563 | "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", 564 | "requires": { 565 | "is-promise": "^2.1.0" 566 | } 567 | }, 568 | "rxjs": { 569 | "version": "6.5.1", 570 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.1.tgz", 571 | "integrity": "sha512-y0j31WJc83wPu31vS1VlAFW5JGrnGC+j+TtGAa1fRQphy48+fDYiDmX8tjGloToEsMkxnouOg/1IzXGKkJnZMg==", 572 | "requires": { 573 | "tslib": "^1.9.0" 574 | } 575 | }, 576 | "safer-buffer": { 577 | "version": "2.1.2", 578 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 579 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 580 | }, 581 | "semver": { 582 | "version": "5.7.0", 583 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", 584 | "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" 585 | }, 586 | "shebang-command": { 587 | "version": "1.2.0", 588 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 589 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", 590 | "requires": { 591 | "shebang-regex": "^1.0.0" 592 | } 593 | }, 594 | "shebang-regex": { 595 | "version": "1.0.0", 596 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 597 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" 598 | }, 599 | "signal-exit": { 600 | "version": "3.0.2", 601 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 602 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" 603 | }, 604 | "slice-ansi": { 605 | "version": "0.0.4", 606 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", 607 | "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=" 608 | }, 609 | "string-width": { 610 | "version": "2.1.1", 611 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 612 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 613 | "requires": { 614 | "is-fullwidth-code-point": "^2.0.0", 615 | "strip-ansi": "^4.0.0" 616 | }, 617 | "dependencies": { 618 | "strip-ansi": { 619 | "version": "4.0.0", 620 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 621 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 622 | "requires": { 623 | "ansi-regex": "^3.0.0" 624 | } 625 | } 626 | } 627 | }, 628 | "strip-ansi": { 629 | "version": "5.2.0", 630 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 631 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 632 | "requires": { 633 | "ansi-regex": "^4.1.0" 634 | }, 635 | "dependencies": { 636 | "ansi-regex": { 637 | "version": "4.1.0", 638 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 639 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" 640 | } 641 | } 642 | }, 643 | "strip-eof": { 644 | "version": "1.0.0", 645 | "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", 646 | "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" 647 | }, 648 | "supports-color": { 649 | "version": "5.5.0", 650 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 651 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 652 | "requires": { 653 | "has-flag": "^3.0.0" 654 | } 655 | }, 656 | "symbol-observable": { 657 | "version": "1.2.0", 658 | "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", 659 | "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" 660 | }, 661 | "through": { 662 | "version": "2.3.8", 663 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 664 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" 665 | }, 666 | "tmp": { 667 | "version": "0.0.33", 668 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 669 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 670 | "requires": { 671 | "os-tmpdir": "~1.0.2" 672 | } 673 | }, 674 | "tslib": { 675 | "version": "1.9.3", 676 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", 677 | "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" 678 | }, 679 | "which": { 680 | "version": "1.3.1", 681 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 682 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 683 | "requires": { 684 | "isexe": "^2.0.0" 685 | } 686 | }, 687 | "wrap-ansi": { 688 | "version": "3.0.1", 689 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", 690 | "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", 691 | "requires": { 692 | "string-width": "^2.1.1", 693 | "strip-ansi": "^4.0.0" 694 | }, 695 | "dependencies": { 696 | "strip-ansi": { 697 | "version": "4.0.0", 698 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 699 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 700 | "requires": { 701 | "ansi-regex": "^3.0.0" 702 | } 703 | } 704 | } 705 | }, 706 | "wrappy": { 707 | "version": "1.0.2", 708 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 709 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 710 | } 711 | } 712 | } 713 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@simonaco/create-graphless", 3 | "version": "1.0.6", 4 | "description": "A CLI to bootstrap new serverless graphql projects", 5 | "main": "src/index.js", 6 | "bin": { 7 | "@simonaco/create-graphless": "bin/create-graphless", 8 | "create-graphless": "bin/create-graphless" 9 | }, 10 | "publishConfig": { 11 | "access": "public" 12 | }, 13 | "keywords": [ 14 | "cli", 15 | "create-graphless" 16 | ], 17 | "scripts": { 18 | "test": "echo \"Error: no test specified\" && exit 1" 19 | }, 20 | "files": [ 21 | "bin/", 22 | "src/", 23 | "templates/" 24 | ], 25 | "author": "Simona Cotin", 26 | "license": "MIT", 27 | "homepage": "https://github.com/simonaco/create-graphless#readme", 28 | "repository": { 29 | "type": "git", 30 | "url": "https://github.com/simonaco/create-graphless" 31 | }, 32 | "bugs": { 33 | "url": "https://github.com/simonaco/create-graphless/issues", 34 | "email": "simona.cotin@gmail.com" 35 | }, 36 | "dependencies": { 37 | "arg": "^4.1.0", 38 | "chalk": "^2.4.2", 39 | "esm": "^3.2.22", 40 | "execa": "^1.0.0", 41 | "inquirer": "^6.3.1", 42 | "listr": "^0.14.3", 43 | "ncp": "^2.0.0", 44 | "pkg-install": "^1.0.0" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/cli.js: -------------------------------------------------------------------------------- 1 | import arg from 'arg' 2 | import inquirer from 'inquirer' 3 | import { createProject } from './main' 4 | function parseArgumentsIntoOptions(rawArgs) { 5 | const args = arg( 6 | { 7 | '--git': Boolean, 8 | '--yes': Boolean, 9 | '--install': Boolean, 10 | '-g': '--git', 11 | '-y': '--yes', 12 | '-i': '--install', 13 | }, 14 | { 15 | argv: rawArgs.slice(2), 16 | } 17 | ) 18 | return { 19 | skipPrompts: args['--yes'] || false, 20 | git: args['--git'] || false, 21 | template: args._[0], 22 | runInstall: args['--install'] || false, 23 | addDatabase: args['--db'] || false, 24 | } 25 | } 26 | 27 | async function promptForMissingOptions(options) { 28 | const defaultTemplate = 'JavaScript' 29 | if (options.skipPrompts) { 30 | return { 31 | ...options, 32 | template: options.template || defaultTemplate, 33 | } 34 | } 35 | 36 | const questions = [] 37 | if (!options.template) { 38 | questions.push({ 39 | type: 'list', 40 | name: 'template', 41 | message: 'Please choose which project template to use', 42 | choices: ['JavaScript', 'db'], 43 | default: defaultTemplate, 44 | }) 45 | } 46 | 47 | if (!options.git) { 48 | questions.push({ 49 | type: 'confirm', 50 | name: 'git', 51 | message: 'Initialize a git repository?', 52 | default: false, 53 | }) 54 | } 55 | 56 | const answers = await inquirer.prompt(questions) 57 | return { 58 | ...options, 59 | template: options.template || answers.template, 60 | git: options.git || answers.git, 61 | } 62 | } 63 | 64 | export async function cli(args) { 65 | let options = parseArgumentsIntoOptions(args) 66 | options = await promptForMissingOptions(options) 67 | await createProject(options) 68 | } 69 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk' 2 | import fs from 'fs' 3 | import ncp from 'ncp' 4 | import path from 'path' 5 | import { promisify } from 'util' 6 | import execa from 'execa' 7 | import Listr from 'listr' 8 | import { projectInstall } from 'pkg-install' 9 | 10 | const access = promisify(fs.access) 11 | const copy = promisify(ncp) 12 | 13 | async function copyTemplateFiles(options) { 14 | return copy(options.templateDirectory, options.targetDirectory, { 15 | clobber: false, 16 | }) 17 | } 18 | 19 | async function initGit(options) { 20 | const result = await execa('git', ['init'], { 21 | cwd: options.targetDirectory, 22 | }) 23 | if (result.failed) { 24 | return Promise.reject(new Error('Failed to initialize git')) 25 | } 26 | return 27 | } 28 | 29 | export async function createProject(options) { 30 | options = { 31 | ...options, 32 | targetDirectory: options.targetDirectory || process.cwd(), 33 | } 34 | 35 | const currentFileUrl = import.meta.url 36 | const templateDir = 37 | __dirname + 38 | '/../templates/'+ 39 | options.template.toLowerCase() 40 | 41 | options.templateDirectory = templateDir 42 | 43 | try { 44 | await access(templateDir, fs.constants.R_OK) 45 | } catch (err) { 46 | console.error('%s Invalid template name', chalk.red.bold('ERROR')) 47 | process.exit(1) 48 | } 49 | 50 | const tasks = new Listr([ 51 | { 52 | title: 'Copy project files', 53 | task: () => copyTemplateFiles(options), 54 | }, 55 | { 56 | title: 'Initialize git', 57 | task: () => initGit(options), 58 | enabled: () => options.git, 59 | }, 60 | { 61 | title: 'Install dependencies', 62 | task: () => 63 | projectInstall({ 64 | cwd: options.targetDirectory, 65 | }), 66 | skip: () => 67 | !options.runInstall 68 | ? 'Pass --install to automatically install dependencies' 69 | : undefined, 70 | }, 71 | ]) 72 | 73 | await tasks.run() 74 | 75 | console.log('%s Project ready', chalk.green.bold('DONE')) 76 | return true 77 | } 78 | -------------------------------------------------------------------------------- /templates/db/.funcignore: -------------------------------------------------------------------------------- 1 | *.js.map 2 | *.ts 3 | .git* 4 | .vscode 5 | local.settings.json 6 | test 7 | tsconfig.json -------------------------------------------------------------------------------- /templates/db/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | 24 | # nyc test coverage 25 | .nyc_output 26 | 27 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 28 | .grunt 29 | 30 | # Bower dependency directory (https://bower.io/) 31 | bower_components 32 | 33 | # node-waf configuration 34 | .lock-wscript 35 | 36 | # Compiled binary addons (https://nodejs.org/api/addons.html) 37 | build/Release 38 | 39 | # Dependency directories 40 | node_modules/ 41 | jspm_packages/ 42 | 43 | # TypeScript v1 declaration files 44 | typings/ 45 | 46 | # Optional npm cache directory 47 | .npm 48 | 49 | # Optional eslint cache 50 | .eslintcache 51 | 52 | # Optional REPL history 53 | .node_repl_history 54 | 55 | # Output of 'npm pack' 56 | *.tgz 57 | 58 | # Yarn Integrity file 59 | .yarn-integrity 60 | 61 | # dotenv environment variables file 62 | .env 63 | .env.test 64 | 65 | # parcel-bundler cache (https://parceljs.org/) 66 | .cache 67 | 68 | # next.js build output 69 | .next 70 | 71 | # nuxt.js build output 72 | .nuxt 73 | 74 | # vuepress build output 75 | .vuepress/dist 76 | 77 | # Serverless directories 78 | .serverless/ 79 | 80 | # FuseBox cache 81 | .fusebox/ 82 | 83 | # DynamoDB Local files 84 | .dynamodb/ 85 | 86 | # TypeScript output 87 | dist 88 | out 89 | 90 | # Azure Functions artifacts 91 | bin 92 | obj 93 | appsettings.json 94 | 95 | local.settings.json -------------------------------------------------------------------------------- /templates/db/azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | pool: 2 | vmImage: 'Ubuntu 16.04' 3 | steps: 4 | - task: NodeTool@0 5 | inputs: 6 | versionSpec: "8.x" 7 | displayName: "Installing Node.js" 8 | - task: Npm@1 9 | inputs: 10 | command: "install" 11 | - task: ArchiveFiles@2 12 | displayName: 'Archive files' 13 | inputs: 14 | rootFolderOrFile: '$(System.DefaultWorkingDirectory)' 15 | includeRootFolder: false 16 | archiveFile: '$(System.DefaultWorkingDirectory)/$(Build.BuildId).zip' 17 | - task: PublishBuildArtifacts@1 18 | displayName: 'Publish files' 19 | inputs: 20 | PathtoPublish: '$(System.DefaultWorkingDirectory)' 21 | name: 'drop' 22 | - task: AzureRmWebAppDeployment@4 23 | displayName: 'Deploy Azure App Service' 24 | inputs: 25 | azureSubscription: '$(Parameters.ConnectedServiceName)' 26 | appType: 'functionapp' 27 | WebAppName: '$(Parameters.WebAppName)' -------------------------------------------------------------------------------- /templates/db/db-utils/db.js: -------------------------------------------------------------------------------- 1 | const MongoClient = require('mongodb').MongoClient 2 | const auth = { 3 | user: process.env.user, 4 | password: process.env.password, 5 | } 6 | let db = null 7 | const loadDB = async () => { 8 | if (db) { 9 | return db 10 | } 11 | const client = await MongoClient.connect( 12 | `mongodb://${process.env.user}.documents.azure.com:${ 13 | process.env.port 14 | }/?ssl=true`, 15 | { 16 | auth: auth, 17 | } 18 | ) 19 | db = client.db(process.env.database) 20 | return db 21 | } 22 | 23 | module.exports.loadDB = loadDB -------------------------------------------------------------------------------- /templates/db/extensions.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.0 4 | 5 | ** 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /templates/db/graphiql/env.js: -------------------------------------------------------------------------------- 1 | env = { 2 | WEBSITE_NAME: 'http://localhost:7071/api/graphql', 3 | WEBSITE_URL: 'http://localhost:7071/api/graphql', 4 | } 5 | -------------------------------------------------------------------------------- /templates/db/graphiql/index.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 23 | 24 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 42 | 46 | 47 | 48 | 49 | 50 |
Loading...
51 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /templates/db/graphless/function.json: -------------------------------------------------------------------------------- 1 | { 2 | "bindings": [ 3 | { 4 | "authLevel": "anonymous", 5 | "type": "httpTrigger", 6 | "direction": "in", 7 | "name": "req", 8 | "methods": ["get", "post"], 9 | "route": "graphql" 10 | }, 11 | { 12 | "type": "http", 13 | "direction": "out", 14 | "name": "res" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /templates/db/graphless/index.js: -------------------------------------------------------------------------------- 1 | const { typeDefs } = require('../graphql-utils/schema') 2 | const { resolvers } = require('../graphql-utils/resolvers') 3 | const { graphql } = require('graphql') 4 | const { loadDB } = require('../db-utils/db') 5 | 6 | module.exports = async function(context, req) { 7 | const body = req.body 8 | const database = await loadDB() 9 | try { 10 | const response = await graphql( 11 | typeDefs, 12 | body.query, 13 | resolvers, 14 | { 15 | client: database, 16 | }, 17 | body.variables, 18 | body.operationName 19 | ) 20 | context.res = { 21 | body: response, 22 | } 23 | } catch (error) { 24 | context.log(`Error code: ${error.code} message: ${error.message}`) 25 | context.res = { 26 | status: 500, 27 | body: { message: 'An error has occured, please try again later' }, 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /templates/db/graphql-utils/resolvers.js: -------------------------------------------------------------------------------- 1 | const resolvers = { 2 | hello: async obj => { 3 | return `Hello ${obj.name}` 4 | }, 5 | } 6 | 7 | module.exports.resolvers = resolvers 8 | -------------------------------------------------------------------------------- /templates/db/graphql-utils/schema.js: -------------------------------------------------------------------------------- 1 | const { buildSchema } = require('graphql') 2 | const typeDefs = buildSchema(` 3 | type Query { 4 | hello(name:String):String 5 | } 6 | `) 7 | 8 | module.exports.typeDefs = typeDefs 9 | -------------------------------------------------------------------------------- /templates/db/host.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0" 3 | } 4 | -------------------------------------------------------------------------------- /templates/db/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "graphless", 3 | "version": "1.0.0", 4 | "description": "", 5 | "scripts": { 6 | "test": "echo \"No tests yet...\"", 7 | "start": "concurrently --kill-others \"http-server ./graphiql \" \"func host start\"" 8 | }, 9 | "dependencies": { 10 | "axios": "^0.18.0", 11 | "graphql": "^14.2.1", 12 | "mongodb": "^3.2.3" 13 | }, 14 | "devDependencies": { 15 | "concurrently": "^4.1.0", 16 | "http-server": "^0.11.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /templates/db/proxies.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/proxies", 3 | "proxies": {} 4 | } 5 | -------------------------------------------------------------------------------- /templates/db/scripts/deployment: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | APP_NAME=$1 3 | REPO_URL=https://github.com/simonaco/graphless 4 | 5 | # create resource group 6 | az group create --location westus --name $APP_NAME 7 | 8 | # enable static storage 9 | az extension add --name storage-preview 10 | 11 | # deploy resource: az function, storage account 12 | az group deployment create \ 13 | --name $APP_NAME \ 14 | --resource-group $APP_NAME \ 15 | --template-file template/azuredeploy.json \ 16 | --parameters appName=$APP_NAME repoURL=$REPO_URL 17 | 18 | # generate dynamic url part for az functions enpoint 19 | ./env > graphiql/env.js "$APP_NAME" 20 | 21 | # update static storage config for index and 404 files 22 | az storage blob service-properties update --account-name "$APP_NAME" --static-website --404-document index.html --index-document index.html 23 | 24 | # upload graphiql page & env file 25 | az storage blob upload-batch -s graphiql -d \$web --account-name "$APP_NAME" 26 | 27 | # fetch static website url 28 | STATIC_WEBSITE_URL=$(az storage account show -n "$APP_NAME" -g "$APP_NAME" --query "primaryEndpoints.web" --output tsv) 29 | 30 | # remove trailing slash from static storage endpoint url 31 | CORS_URL=$(echo $STATIC_WEBSITE_URL | sed 's/.$//') 32 | 33 | # add static storage endpoint url to cors rules 34 | az webapp cors add -g $APP_NAME -n $APP_NAME --allowed-origins $CORS_URL -------------------------------------------------------------------------------- /templates/db/scripts/env: -------------------------------------------------------------------------------- 1 | 2 | #!/bin/bash 3 | STORAGE_ACC=$1 4 | echo "env = {" 5 | echo " WEBSITE_NAME: '$STORAGE_ACC'," 6 | echo "}" -------------------------------------------------------------------------------- /templates/db/scripts/graphiql/env.js: -------------------------------------------------------------------------------- 1 | env = { 2 | WEBSITE_NAME: 'graphless31', 3 | } 4 | -------------------------------------------------------------------------------- /templates/db/scripts/graphiql/index.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 23 | 24 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 42 | 46 | 47 | 48 | 49 | 50 |
Loading...
51 | 169 | 170 | -------------------------------------------------------------------------------- /templates/db/scripts/template/azuredeploy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "appName": { 6 | "type": "string", 7 | "metadata": { 8 | "description": "The name of the function app that you wish to create." 9 | } 10 | }, 11 | "storageAccountType": { 12 | "type": "string", 13 | "defaultValue": "Standard_LRS", 14 | "allowedValues": ["Standard_LRS", "Standard_GRS", "Standard_RAGRS"], 15 | "metadata": { 16 | "description": "Storage Account type" 17 | } 18 | }, 19 | "location": { 20 | "type": "string", 21 | "defaultValue": "[resourceGroup().location]", 22 | "metadata": { 23 | "description": "Location for all resources." 24 | } 25 | }, 26 | "runtime": { 27 | "type": "string", 28 | "defaultValue": "node", 29 | "allowedValues": ["node", "dotnet", "java"], 30 | "metadata": { 31 | "description": "The language worker runtime to load in the function app." 32 | } 33 | }, 34 | "repoURL": { 35 | "type": "string", 36 | "defaultValue": "https://github.com/simonaco/graphless" 37 | }, 38 | "branch": { 39 | "type": "string", 40 | "defaultValue": "master" 41 | }, 42 | "accountType": { 43 | "type": "string", 44 | "defaultValue": "Standard_RAGRS" 45 | }, 46 | "kind": { 47 | "type": "string", 48 | "defaultValue": "StorageV2" 49 | }, 50 | "accessTier": { 51 | "type": "string", 52 | "defaultValue": "Hot" 53 | }, 54 | "supportsHttpsTrafficOnly": { 55 | "type": "bool", 56 | "defaultValue": true 57 | } 58 | }, 59 | "variables": { 60 | "functionAppName": "[parameters('appName')]", 61 | "hostingPlanName": "[parameters('appName')]", 62 | "applicationInsightsName": "[parameters('appName')]", 63 | "storageAccountName": "[concat(uniquestring(resourceGroup().id), 'azfunctions')]", 64 | "storageAccountid": "[concat(resourceGroup().id,'/providers/','Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]", 65 | "functionWorkerRuntime": "[parameters('runtime')]", 66 | "graphiqlStorageName":"[parameters('appName')]" 67 | }, 68 | "resources": [ 69 | { 70 | "type": "Microsoft.Storage/storageAccounts", 71 | "apiVersion": "2018-07-01", 72 | "name": "[variables('graphiqlStorageName')]", 73 | "location": "[parameters('location')]", 74 | "dependsOn": [], 75 | "sku": { 76 | "name": "[parameters('accountType')]" 77 | }, 78 | "kind": "[parameters('kind')]", 79 | "properties": { 80 | "accessTier": "[parameters('accessTier')]", 81 | "supportsHttpsTrafficOnly": "[parameters('supportsHttpsTrafficOnly')]" 82 | } 83 | }, 84 | { 85 | "type": "Microsoft.Storage/storageAccounts", 86 | "name": "[variables('storageAccountName')]", 87 | "apiVersion": "2016-12-01", 88 | "location": "[parameters('location')]", 89 | "kind": "Storage", 90 | "sku": { 91 | "name": "[parameters('storageAccountType')]" 92 | } 93 | }, 94 | { 95 | "type": "Microsoft.Web/serverfarms", 96 | "apiVersion": "2015-04-01", 97 | "name": "[variables('hostingPlanName')]", 98 | "location": "[parameters('location')]", 99 | "properties": { 100 | "name": "[variables('hostingPlanName')]", 101 | "computeMode": "Dynamic", 102 | "sku": "Dynamic" 103 | } 104 | }, 105 | { 106 | "apiVersion": "2016-03-01", 107 | "name": "[variables('functionAppName')]", 108 | "type": "Microsoft.Web/sites", 109 | "location": "[parameters('location')]", 110 | "kind": "functionapp", 111 | "dependsOn": [ 112 | "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]", 113 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]" 114 | ], 115 | "properties": { 116 | "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]", 117 | "siteConfig": { 118 | "appSettings": [ 119 | { 120 | "name": "AzureWebJobsDashboard", 121 | "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2015-05-01-preview').key1)]" 122 | }, 123 | { 124 | "name": "AzureWebJobsStorage", 125 | "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2015-05-01-preview').key1)]" 126 | }, 127 | { 128 | "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING", 129 | "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2015-05-01-preview').key1)]" 130 | }, 131 | { 132 | "name": "WEBSITE_CONTENTSHARE", 133 | "value": "[toLower(variables('functionAppName'))]" 134 | }, 135 | { 136 | "name": "FUNCTIONS_EXTENSION_VERSION", 137 | "value": "~2" 138 | }, 139 | { 140 | "name": "WEBSITE_NODE_DEFAULT_VERSION", 141 | "value": "8.11.1" 142 | }, 143 | { 144 | "name": "APPINSIGHTS_INSTRUMENTATIONKEY", 145 | "value": "[reference(resourceId('microsoft.insights/components/', variables('applicationInsightsName')), '2015-05-01').InstrumentationKey]" 146 | }, 147 | { 148 | "name": "FUNCTIONS_WORKER_RUNTIME", 149 | "value": "[variables('functionWorkerRuntime')]" 150 | } 151 | ] 152 | } 153 | }, 154 | "resources": [ 155 | { 156 | "apiVersion": "2015-08-01", 157 | "name": "web", 158 | "type": "sourcecontrols", 159 | "dependsOn": [ 160 | "[resourceId('Microsoft.Web/Sites', variables('functionAppName'))]" 161 | ], 162 | "properties": { 163 | "RepoUrl": "[parameters('repoURL')]", 164 | "branch": "[parameters('branch')]", 165 | "IsManualIntegration": true 166 | } 167 | } 168 | ] 169 | }, 170 | { 171 | "apiVersion": "2018-05-01-preview", 172 | "name": "[variables('applicationInsightsName')]", 173 | "type": "microsoft.insights/components", 174 | "location": "East US", 175 | "tags": { 176 | "[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/sites/', variables('applicationInsightsName'))]": "Resource" 177 | }, 178 | "properties": { 179 | "ApplicationId": "[variables('applicationInsightsName')]", 180 | "Request_Source": "IbizaWebAppExtensionCreate" 181 | } 182 | } 183 | ] 184 | } -------------------------------------------------------------------------------- /templates/javascript/.funcignore: -------------------------------------------------------------------------------- 1 | *.js.map 2 | *.ts 3 | .git* 4 | .vscode 5 | local.settings.json 6 | test 7 | tsconfig.json -------------------------------------------------------------------------------- /templates/javascript/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | 24 | # nyc test coverage 25 | .nyc_output 26 | 27 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 28 | .grunt 29 | 30 | # Bower dependency directory (https://bower.io/) 31 | bower_components 32 | 33 | # node-waf configuration 34 | .lock-wscript 35 | 36 | # Compiled binary addons (https://nodejs.org/api/addons.html) 37 | build/Release 38 | 39 | # Dependency directories 40 | node_modules/ 41 | jspm_packages/ 42 | 43 | # TypeScript v1 declaration files 44 | typings/ 45 | 46 | # Optional npm cache directory 47 | .npm 48 | 49 | # Optional eslint cache 50 | .eslintcache 51 | 52 | # Optional REPL history 53 | .node_repl_history 54 | 55 | # Output of 'npm pack' 56 | *.tgz 57 | 58 | # Yarn Integrity file 59 | .yarn-integrity 60 | 61 | # dotenv environment variables file 62 | .env 63 | .env.test 64 | 65 | # parcel-bundler cache (https://parceljs.org/) 66 | .cache 67 | 68 | # next.js build output 69 | .next 70 | 71 | # nuxt.js build output 72 | .nuxt 73 | 74 | # vuepress build output 75 | .vuepress/dist 76 | 77 | # Serverless directories 78 | .serverless/ 79 | 80 | # FuseBox cache 81 | .fusebox/ 82 | 83 | # DynamoDB Local files 84 | .dynamodb/ 85 | 86 | # TypeScript output 87 | dist 88 | out 89 | 90 | # Azure Functions artifacts 91 | bin 92 | obj 93 | appsettings.json 94 | 95 | local.settings.json -------------------------------------------------------------------------------- /templates/javascript/azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | pool: 2 | vmImage: 'Ubuntu 16.04' 3 | steps: 4 | - task: NodeTool@0 5 | inputs: 6 | versionSpec: "8.x" 7 | displayName: "Installing Node.js" 8 | - task: Npm@1 9 | inputs: 10 | command: "install" 11 | - task: ArchiveFiles@2 12 | displayName: 'Archive files' 13 | inputs: 14 | rootFolderOrFile: '$(System.DefaultWorkingDirectory)' 15 | includeRootFolder: false 16 | archiveFile: '$(System.DefaultWorkingDirectory)/$(Build.BuildId).zip' 17 | - task: PublishBuildArtifacts@1 18 | displayName: 'Publish files' 19 | inputs: 20 | PathtoPublish: '$(System.DefaultWorkingDirectory)' 21 | name: 'drop' 22 | - task: AzureRmWebAppDeployment@4 23 | displayName: 'Deploy Azure App Service' 24 | inputs: 25 | azureSubscription: '$(Parameters.ConnectedServiceName)' 26 | appType: 'functionapp' 27 | WebAppName: '$(Parameters.WebAppName)' -------------------------------------------------------------------------------- /templates/javascript/extensions.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.0 4 | 5 | ** 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /templates/javascript/graphiql/env.js: -------------------------------------------------------------------------------- 1 | env = { 2 | WEBSITE_NAME: 'http://localhost:7071/api/graphql', 3 | WEBSITE_URL: 'http://localhost:7071/api/graphql', 4 | } 5 | -------------------------------------------------------------------------------- /templates/javascript/graphiql/index.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 23 | 24 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 42 | 46 | 47 | 48 | 49 | 50 |
Loading...
51 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /templates/javascript/graphless/function.json: -------------------------------------------------------------------------------- 1 | { 2 | "bindings": [ 3 | { 4 | "authLevel": "anonymous", 5 | "type": "httpTrigger", 6 | "direction": "in", 7 | "name": "req", 8 | "methods": ["get", "post"], 9 | "route": "graphql" 10 | }, 11 | { 12 | "type": "http", 13 | "direction": "out", 14 | "name": "res" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /templates/javascript/graphless/index.js: -------------------------------------------------------------------------------- 1 | const { typeDefs } = require('../graphql-utils/schema') 2 | const { resolvers } = require('../graphql-utils/resolvers') 3 | const { graphql } = require('graphql') 4 | 5 | module.exports = async function(context, req) { 6 | const body = req.body 7 | try { 8 | const response = await graphql( 9 | typeDefs, 10 | body.query, 11 | resolvers, 12 | null, 13 | body.variables, 14 | body.operationName 15 | ) 16 | context.res = { 17 | body: response, 18 | } 19 | } catch (error) { 20 | context.log(`Error code: ${error.code} message: ${error.message}`) 21 | context.res = { 22 | status: 500, 23 | body: { message: 'An error has occured, please try again later' }, 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /templates/javascript/graphql-utils/resolvers.js: -------------------------------------------------------------------------------- 1 | const resolvers = { 2 | hello: async obj => { 3 | return `Hello ${obj.name}` 4 | }, 5 | } 6 | 7 | module.exports.resolvers = resolvers 8 | -------------------------------------------------------------------------------- /templates/javascript/graphql-utils/schema.js: -------------------------------------------------------------------------------- 1 | const { buildSchema } = require('graphql') 2 | const typeDefs = buildSchema(` 3 | type Query { 4 | hello(name:String):String 5 | } 6 | `) 7 | 8 | module.exports.typeDefs = typeDefs 9 | -------------------------------------------------------------------------------- /templates/javascript/host.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0" 3 | } 4 | -------------------------------------------------------------------------------- /templates/javascript/local.settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "IsEncrypted": false, 3 | "Values": { 4 | "AzureWebJobsStorage": "", 5 | "FUNCTIONS_WORKER_RUNTIME": "node" 6 | }, 7 | "Host":{ 8 | "CORS":"*" 9 | } 10 | } -------------------------------------------------------------------------------- /templates/javascript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "graphless", 3 | "version": "1.0.0", 4 | "description": "", 5 | "scripts": { 6 | "test": "echo \"No tests yet...\"", 7 | "start": "concurrently --kill-others \"http-server ./graphiql \" \"func host start\"" 8 | }, 9 | "dependencies": { 10 | "graphql": "^14.2.1" 11 | }, 12 | "devDependencies": { 13 | "concurrently": "^4.1.0", 14 | "http-server": "^0.11.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /templates/javascript/proxies.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/proxies", 3 | "proxies": {} 4 | } 5 | -------------------------------------------------------------------------------- /templates/javascript/scripts/deployment: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | APP_NAME=$1 3 | REPO_URL=https://github.com/simonaco/graphless-hello 4 | 5 | # create resource group 6 | az group create --location westus --name $APP_NAME 7 | 8 | # enable static storage 9 | az extension add --name storage-preview 10 | 11 | # deploy resource: az function, storage account 12 | az group deployment create \ 13 | --name $APP_NAME \ 14 | --resource-group $APP_NAME \ 15 | --template-file template/azuredeploy.json \ 16 | --parameters appName=$APP_NAME repoURL=$REPO_URL 17 | 18 | # generate dynamic url part for az functions enpoint 19 | ./env > graphiql/env.js "$APP_NAME" 20 | 21 | # update static storage config for index and 404 files 22 | az storage blob service-properties update --account-name "$APP_NAME" --static-website --404-document index.html --index-document index.html 23 | 24 | # upload graphiql page & env file 25 | az storage blob upload-batch -s graphiql -d \$web --account-name "$APP_NAME" 26 | 27 | # fetch static website url 28 | STATIC_WEBSITE_URL=$(az storage account show -n "$APP_NAME" -g "$APP_NAME" --query "primaryEndpoints.web" --output tsv) 29 | 30 | # remove trailing slash from static storage endpoint url 31 | CORS_URL=$(echo $STATIC_WEBSITE_URL | sed 's/.$//') 32 | 33 | # add static storage endpoint url to cors rules 34 | az webapp cors add -g $APP_NAME -n $APP_NAME --allowed-origins $CORS_URL -------------------------------------------------------------------------------- /templates/javascript/scripts/env: -------------------------------------------------------------------------------- 1 | 2 | #!/bin/bash 3 | STORAGE_ACC=$1 4 | echo "env = {" 5 | echo " WEBSITE_NAME: '$STORAGE_ACC'," 6 | echo "}" -------------------------------------------------------------------------------- /templates/javascript/scripts/graphiql/env.js: -------------------------------------------------------------------------------- 1 | env = { 2 | WEBSITE_NAME: 'graphless31', 3 | } 4 | -------------------------------------------------------------------------------- /templates/javascript/scripts/graphiql/index.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 23 | 24 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 42 | 46 | 47 | 48 | 49 | 50 |
Loading...
51 | 169 | 170 | -------------------------------------------------------------------------------- /templates/javascript/scripts/template/azuredeploy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "appName": { 6 | "type": "string", 7 | "metadata": { 8 | "description": "The name of the function app that you wish to create." 9 | } 10 | }, 11 | "storageAccountType": { 12 | "type": "string", 13 | "defaultValue": "Standard_LRS", 14 | "allowedValues": ["Standard_LRS", "Standard_GRS", "Standard_RAGRS"], 15 | "metadata": { 16 | "description": "Storage Account type" 17 | } 18 | }, 19 | "location": { 20 | "type": "string", 21 | "defaultValue": "[resourceGroup().location]", 22 | "metadata": { 23 | "description": "Location for all resources." 24 | } 25 | }, 26 | "runtime": { 27 | "type": "string", 28 | "defaultValue": "node", 29 | "allowedValues": ["node", "dotnet", "java"], 30 | "metadata": { 31 | "description": "The language worker runtime to load in the function app." 32 | } 33 | }, 34 | "repoURL": { 35 | "type": "string", 36 | "defaultValue": "https://github.com/simonaco/graphless" 37 | }, 38 | "branch": { 39 | "type": "string", 40 | "defaultValue": "master" 41 | }, 42 | "accountType": { 43 | "type": "string", 44 | "defaultValue": "Standard_RAGRS" 45 | }, 46 | "kind": { 47 | "type": "string", 48 | "defaultValue": "StorageV2" 49 | }, 50 | "accessTier": { 51 | "type": "string", 52 | "defaultValue": "Hot" 53 | }, 54 | "supportsHttpsTrafficOnly": { 55 | "type": "bool", 56 | "defaultValue": true 57 | } 58 | }, 59 | "variables": { 60 | "functionAppName": "[parameters('appName')]", 61 | "hostingPlanName": "[parameters('appName')]", 62 | "applicationInsightsName": "[parameters('appName')]", 63 | "storageAccountName": "[concat(uniquestring(resourceGroup().id), 'azfunctions')]", 64 | "storageAccountid": "[concat(resourceGroup().id,'/providers/','Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]", 65 | "functionWorkerRuntime": "[parameters('runtime')]", 66 | "graphiqlStorageName":"[parameters('appName')]" 67 | }, 68 | "resources": [ 69 | { 70 | "type": "Microsoft.Storage/storageAccounts", 71 | "apiVersion": "2018-07-01", 72 | "name": "[variables('graphiqlStorageName')]", 73 | "location": "[parameters('location')]", 74 | "dependsOn": [], 75 | "sku": { 76 | "name": "[parameters('accountType')]" 77 | }, 78 | "kind": "[parameters('kind')]", 79 | "properties": { 80 | "accessTier": "[parameters('accessTier')]", 81 | "supportsHttpsTrafficOnly": "[parameters('supportsHttpsTrafficOnly')]" 82 | } 83 | }, 84 | { 85 | "type": "Microsoft.Storage/storageAccounts", 86 | "name": "[variables('storageAccountName')]", 87 | "apiVersion": "2016-12-01", 88 | "location": "[parameters('location')]", 89 | "kind": "Storage", 90 | "sku": { 91 | "name": "[parameters('storageAccountType')]" 92 | } 93 | }, 94 | { 95 | "type": "Microsoft.Web/serverfarms", 96 | "apiVersion": "2015-04-01", 97 | "name": "[variables('hostingPlanName')]", 98 | "location": "[parameters('location')]", 99 | "properties": { 100 | "name": "[variables('hostingPlanName')]", 101 | "computeMode": "Dynamic", 102 | "sku": "Dynamic" 103 | } 104 | }, 105 | { 106 | "apiVersion": "2016-03-01", 107 | "name": "[variables('functionAppName')]", 108 | "type": "Microsoft.Web/sites", 109 | "location": "[parameters('location')]", 110 | "kind": "functionapp", 111 | "dependsOn": [ 112 | "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]", 113 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]" 114 | ], 115 | "properties": { 116 | "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]", 117 | "siteConfig": { 118 | "appSettings": [ 119 | { 120 | "name": "AzureWebJobsDashboard", 121 | "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2015-05-01-preview').key1)]" 122 | }, 123 | { 124 | "name": "AzureWebJobsStorage", 125 | "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2015-05-01-preview').key1)]" 126 | }, 127 | { 128 | "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING", 129 | "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2015-05-01-preview').key1)]" 130 | }, 131 | { 132 | "name": "WEBSITE_CONTENTSHARE", 133 | "value": "[toLower(variables('functionAppName'))]" 134 | }, 135 | { 136 | "name": "FUNCTIONS_EXTENSION_VERSION", 137 | "value": "~2" 138 | }, 139 | { 140 | "name": "WEBSITE_NODE_DEFAULT_VERSION", 141 | "value": "8.11.1" 142 | }, 143 | { 144 | "name": "APPINSIGHTS_INSTRUMENTATIONKEY", 145 | "value": "[reference(resourceId('microsoft.insights/components/', variables('applicationInsightsName')), '2015-05-01').InstrumentationKey]" 146 | }, 147 | { 148 | "name": "FUNCTIONS_WORKER_RUNTIME", 149 | "value": "[variables('functionWorkerRuntime')]" 150 | } 151 | ] 152 | } 153 | }, 154 | "resources": [ 155 | { 156 | "apiVersion": "2015-08-01", 157 | "name": "web", 158 | "type": "sourcecontrols", 159 | "dependsOn": [ 160 | "[resourceId('Microsoft.Web/Sites', variables('functionAppName'))]" 161 | ], 162 | "properties": { 163 | "RepoUrl": "[parameters('repoURL')]", 164 | "branch": "[parameters('branch')]", 165 | "IsManualIntegration": true 166 | } 167 | } 168 | ] 169 | }, 170 | { 171 | "apiVersion": "2018-05-01-preview", 172 | "name": "[variables('applicationInsightsName')]", 173 | "type": "microsoft.insights/components", 174 | "location": "East US", 175 | "tags": { 176 | "[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/sites/', variables('applicationInsightsName'))]": "Resource" 177 | }, 178 | "properties": { 179 | "ApplicationId": "[variables('applicationInsightsName')]", 180 | "Request_Source": "IbizaWebAppExtensionCreate" 181 | } 182 | } 183 | ] 184 | } --------------------------------------------------------------------------------