Repository: adonisjs/adonis-cli Branch: develop Commit: 5e64ac7a871f Files: 75 Total size: 143.4 KB Directory structure: gitextract_r83ys1rm/ ├── .editorconfig ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.md │ │ └── feature_request.md │ └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .npmignore ├── .snyk ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── appveyor.yml ├── config.json ├── index.js ├── japaFile.js ├── lib/ │ ├── Steps.js │ └── ace.js ├── package.json ├── src/ │ ├── Commands/ │ │ ├── Addon/ │ │ │ └── index.js │ │ ├── Base/ │ │ │ └── index.js │ │ ├── Install/ │ │ │ └── index.js │ │ ├── Instructions/ │ │ │ ├── Context.js │ │ │ └── index.js │ │ ├── KeyGenerate/ │ │ │ └── index.js │ │ ├── Make/ │ │ │ ├── Base.js │ │ │ ├── Command.js │ │ │ ├── Controller.js │ │ │ ├── Exception.js │ │ │ ├── ExceptionHandler.js │ │ │ ├── Hook.js │ │ │ ├── Listener.js │ │ │ ├── Middleware.js │ │ │ ├── Migration.js │ │ │ ├── Model.js │ │ │ ├── Provider.js │ │ │ ├── Seed.js │ │ │ ├── Trait.js │ │ │ └── View.js │ │ ├── New/ │ │ │ └── index.js │ │ ├── Repl/ │ │ │ └── index.js │ │ ├── RouteList/ │ │ │ └── index.js │ │ ├── Serve/ │ │ │ └── index.js │ │ └── index.js │ ├── Generators/ │ │ ├── index.js │ │ └── templates/ │ │ ├── command.mustache │ │ ├── exception.mustache │ │ ├── exceptionHandler.mustache │ │ ├── hook.mustache │ │ ├── httpController.mustache │ │ ├── listener.mustache │ │ ├── middleware.mustache │ │ ├── model.mustache │ │ ├── provider.mustache │ │ ├── schema.mustache │ │ ├── seed.mustache │ │ ├── trait.mustache │ │ ├── view.mustache │ │ └── wsController.mustache │ └── Services/ │ ├── check-node-version.js │ ├── clone.js │ ├── copy-env-file.js │ ├── exec.js │ ├── generate-app-key.js │ ├── install.js │ ├── render-instructions-md.js │ ├── run-instructions.js │ └── verify-existing-folder.js └── test/ ├── clone.spec.js ├── copy-env-file.spec.js ├── generators.spec.js ├── install.spec.js ├── new.spec.js ├── run-instructions.spec.js └── verify-existing-folder.spec.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ # http://editorconfig.org root = true [*] indent_size = 2 indent_style = space end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true [*.json] insert_final_newline = ignore [**.min.js] indent_style = ignore insert_final_newline = ignore [MakeFile] indent_style = tab [*.md] trim_trailing_whitespace = false ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- name: Bug report about: Report identified bugs --- ## Prerequisites We do our best to reply to all the issues on time. If you will follow the given guidelines, the turn around time will be faster. - Lots of raised issues are directly not bugs but instead are design decisions taken by us. - Make use of our [forum](https://forum.adonisjs.com/), or [discord server](https://discord.me/adonisjs), if you are not sure that you are reporting a bug. - Ensure the issue isn't already reported. - Ensure you are reporting the bug in the correct repo. *Delete the above section and the instructions in the sections below before submitting* ## Package version ## Node.js and npm version ## Sample Code (to reproduce the issue) ## BONUS (a sample repo to reproduce the issue) ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.md ================================================ --- name: Feature request about: Propose changes for adding a new feature --- ## Prerequisites We do our best to reply to all the issues on time. If you will follow the given guidelines, the turn around time will be faster. ## Consider an RFC Please create an [RFC](https://github.com/adonisjs/rfcs) instead, if - Feature introduces a breaking change - Demands lots of time and changes in the current code base. *Delete the above section and the instructions in the sections below before submitting* ## Why this feature is required (specific use-cases will be appreciated)? ## Have you tried any other work arounds? ## Are you willing to work on it with little guidance? ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ ## Proposed changes Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request. If it fixes a bug or resolves a feature request, be sure to link to that issue. ## Types of changes What types of changes does your code introduce? _Put an `x` in the boxes that apply_ - [ ] Bugfix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) ## Checklist _Put an `x` in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code._ - [ ] I have read the [CONTRIBUTING](https://github.com/adonisjs/adonis-cli/blob/develop/CONTRIBUTING.md) doc - [ ] Lint and unit tests pass locally with my changes - [ ] I have added tests that prove my fix is effective or that my feature works. - [ ] I have added necessary documentation (if appropriate) ## Further comments If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc... ================================================ FILE: .gitignore ================================================ !.gitkeep node_modules npm-debug.log .nyc_output coverage test/yardstick test/yardstick-app .DS_STORE .idea .vscode/ *.sublime-project *.sublime-workspace *.log build dist yarn.lock shrinkwrap.yaml package-lock.json ================================================ FILE: .npmignore ================================================ .editorconfig .gitignore test .nyc_output coverage ================================================ FILE: .snyk ================================================ # Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. version: v1.13.5 ignore: {} # patches apply the minimum changes required to fix a vulnerability patch: SNYK-JS-LODASH-450202: - lodash: patched: '2019-07-04T02:19:04.709Z' - '@adonisjs/ace > lodash': patched: '2019-07-04T02:19:04.709Z' SNYK-JS-HTTPSPROXYAGENT-469131: - snyk > proxy-agent > https-proxy-agent: patched: '2019-10-05T02:19:18.739Z' - snyk > proxy-agent > pac-proxy-agent > https-proxy-agent: patched: '2019-10-05T02:19:18.739Z' ================================================ FILE: .travis.yml ================================================ language: node_js node_js: - node - 8.0.0 sudo: false install: - npm install after_script: - npm run coverage notifications: slack: secure: >- m91zkX2cLVDRDMBAUnR1d+hbZqtSHXLkuPencHadhJ3C3wm53Box8U25co/goAmjnW5HNJ1SMSIg+DojtgDhqTbReSh5gSbU0uU8YaF8smbvmUv3b2Q8PRCA7f6hQiea+a8+jAb7BOvwh66dV4Al/1DJ2b4tCjPuVuxQ96Wll7Pnj1S7yW/Hb8fQlr9wc+INXUZOe8erFin+508r5h1L4Xv0N5ZmNw+Gqvn2kPJD8f/YBPpx0AeZdDssTL0IOcol1+cDtDzMw5PAkGnqwamtxhnsw+i8OW4avFt1GrRNlz3eci5Cb3NQGjHxJf+JIALvBeSqkOEFJIFGqwAXMctJ9q8/7XyXk7jVFUg5+0Z74HIkBwdtLwi/BTyXMZAgsnDjndmR9HsuBP7OSTJF5/V7HCJZAaO9shEgS8DwR78owv9Fr5er5m9IMI+EgSH3qtb8iuuQaPtflbk+cPD3nmYbDqmPwkSCXcXRfq3IxdcV9hkiaAw52AIqqhnAXJWZfL6+Ct32i2mtSaov9FYtp/G0xb4tjrUAsDUd/AGmMJNEBVoHtP7mKjrVQ35cEtFwJr/8SmZxGvOaJXPaLs43dhXKa2tAGl11wF02d+Rz1HhbOoq9pJvJuqkLAVvRdBHUJrB4/hnTta5B0W5pe3mIgLw3AmOpk+s/H4hAP4Hp0gOWlPA= ================================================ FILE: CHANGELOG.md ================================================ ## [4.0.12](https://github.com/adonisjs/adonis-cli/compare/4.0.11...4.0.12) (2019-04-11) ### Bug Fixes * package.json to reduce vulnerabilities ([#130](https://github.com/adonisjs/adonis-cli/issues/130)) ([57b5520](https://github.com/adonisjs/adonis-cli/commit/57b5520)) ### Features * **serve:** merge --ext with default in development mode ([#126](https://github.com/adonisjs/adonis-cli/issues/126)) ([a6fa0dd](https://github.com/adonisjs/adonis-cli/commit/a6fa0dd)) ## [4.0.11](https://github.com/adonisjs/adonis-cli/compare/v4.0.10...v4.0.11) (2019-01-18) ### Bug Fixes * **new:** correctly verify the versionn of npm ([1ceef76](https://github.com/adonisjs/adonis-cli/commit/1ceef76)) ### Features * **new:** add api flag as alternative to api-only ([fb88973](https://github.com/adonisjs/adonis-cli/commit/fb88973)) * **new:** remove dev flag ([3f8394b](https://github.com/adonisjs/adonis-cli/commit/3f8394b)) ## [4.0.10](https://github.com/adonisjs/adonis-cli/compare/v4.0.9...v4.0.10) (2018-11-27) ### Bug Fixes * **deps:** upgrade `nodemon` ([#117](https://github.com/adonisjs/adonis-cli/issues/117)) ([8a77564](https://github.com/adonisjs/adonis-cli/commit/8a77564)) ## [4.0.9](https://github.com/adonisjs/adonis-cli/compare/v4.0.8...v4.0.9) (2018-10-02) ### Bug Fixes * use bgGreen vs bgGreenBright coz of kleur over chalk ([56eaba2](https://github.com/adonisjs/adonis-cli/commit/56eaba2)) ## [4.0.8](https://github.com/adonisjs/adonis-cli/compare/v4.0.7...v4.0.8) (2018-10-01) ### Features * **intellisense:** add type comments to templates ([878154a](https://github.com/adonisjs/adonis-cli/commit/878154a)) * **template:** add typedoc to middleware template ([9920b4a](https://github.com/adonisjs/adonis-cli/commit/9920b4a)) ## [4.0.7](https://github.com/adonisjs/adonis-cli/compare/v4.0.6...v4.0.7) (2018-09-05) ### Features * **serve:** add ignore options ([#115](https://github.com/adonisjs/adonis-cli/issues/115)) ([876d13e](https://github.com/adonisjs/adonis-cli/commit/876d13e)) ## [4.0.6](https://github.com/adonisjs/adonis-cli/compare/v4.0.5...v4.0.6) (2018-08-03) ### Bug Fixes * **commands:** support prereleases of Node.js ([#114](https://github.com/adonisjs/adonis-cli/issues/114)) ([f28cdd6](https://github.com/adonisjs/adonis-cli/commit/f28cdd6)) ### Features * **new:** add support for complete git urls ([64ca4e4](https://github.com/adonisjs/adonis-cli/commit/64ca4e4)), closes [prividers#109](https://github.com/prividers/issues/109) * **serve:** add support for defining ext for watch & remove domain ([f6ec54c](https://github.com/adonisjs/adonis-cli/commit/f6ec54c)), closes [#96](https://github.com/adonisjs/adonis-cli/issues/96) ## [4.0.5](https://github.com/adonisjs/adonis-cli/compare/v4.0.4...v4.0.5) (2018-06-04) ### Bug Fixes * **package:** update marked to version 0.4.0 ([#105](https://github.com/adonisjs/adonis-cli/issues/105)) ([8b7b190](https://github.com/adonisjs/adonis-cli/commit/8b7b190)) ### Features * **install:** use cnpm flag for install ([71ae975](https://github.com/adonisjs/adonis-cli/commit/71ae975)) * **make:** add docblocks & params to resource controller ([#92](https://github.com/adonisjs/adonis-cli/issues/92)) ([d7cf77f](https://github.com/adonisjs/adonis-cli/commit/d7cf77f)) * **make:** add make:provider command ([#94](https://github.com/adonisjs/adonis-cli/issues/94)) ([3344066](https://github.com/adonisjs/adonis-cli/commit/3344066)) * **new:** add cnpm flag ([d64cb7f](https://github.com/adonisjs/adonis-cli/commit/d64cb7f)) * **serve:** add option to specify debug port ([c0735ff](https://github.com/adonisjs/adonis-cli/commit/c0735ff)) ## [4.0.4](https://github.com/adonisjs/adonis-cli/compare/v4.0.3...v4.0.4) (2018-02-14) ### Bug Fixes * **serve:** boxen has been removed ([97890a2](https://github.com/adonisjs/adonis-cli/commit/97890a2)), closes [#93](https://github.com/adonisjs/adonis-cli/issues/93) ## [4.0.3](https://github.com/adonisjs/adonis-cli/compare/v4.0.2...v4.0.3) (2018-02-09) ## [4.0.2](https://github.com/adonisjs/adonis-cli/compare/v4.0.0...v4.0.2) (2018-02-07) ### Bug Fixes * **package:** update [@adonisjs](https://github.com/adonisjs)/ignitor to version 2.0.0 ([#90](https://github.com/adonisjs/adonis-cli/issues/90)) ([a24bc49](https://github.com/adonisjs/adonis-cli/commit/a24bc49)) ## [4.0.1](https://github.com/adonisjs/adonis-cli/compare/v4.0.0...v4.0.1) (2018-02-07) # [4.0.0](https://github.com/adonisjs/adonis-cli/compare/v3.0.17...v4.0.0) (2018-01-31) ### Bug Fixes * **package:** update dotenv to version 5.0.0 ([#89](https://github.com/adonisjs/adonis-cli/issues/89)) ([454a8bf](https://github.com/adonisjs/adonis-cli/commit/454a8bf)) * **package:** update dotenv to version 5.0.0 ([#89](https://github.com/adonisjs/adonis-cli/issues/89)) ([e655cb7](https://github.com/adonisjs/adonis-cli/commit/e655cb7)) * **package:** update shelljs to version 0.8.0 ([#82](https://github.com/adonisjs/adonis-cli/issues/82)) ([05f0919](https://github.com/adonisjs/adonis-cli/commit/05f0919)) * **serve:** add root directory to ignore files nodemon ([#76](https://github.com/adonisjs/adonis-cli/issues/76)) ([11d8b5c](https://github.com/adonisjs/adonis-cli/commit/11d8b5c)) ### Features * **new:** re-design new command output & add raw option ([db4c5d9](https://github.com/adonisjs/adonis-cli/commit/db4c5d9)) ## [3.0.17](https://github.com/adonisjs/adonis-cli/compare/v3.0.16...v3.0.17) (2017-11-08) ### Features * **generators:** add traits generator ([16bebfb](https://github.com/adonisjs/adonis-cli/commit/16bebfb)) ## [3.0.16](https://github.com/adonisjs/adonis-cli/compare/v3.0.15...v3.0.16) (2017-10-30) ### Bug Fixes * **serve:** exit process on close everytime ([f1b6c77](https://github.com/adonisjs/adonis-cli/commit/f1b6c77)) ## [3.0.15](https://github.com/adonisjs/adonis-cli/compare/v3.0.14...v3.0.15) (2017-10-29) ### Features * **model:** add the possibility to generate a resourceful controller ([#63](https://github.com/adonisjs/adonis-cli/issues/63)) ([c8cdbc0](https://github.com/adonisjs/adonis-cli/commit/c8cdbc0)) * **serve:** add .dev domains support via hotel ([b3c7bdd](https://github.com/adonisjs/adonis-cli/commit/b3c7bdd)) * **serve:** add polling option for legacy watch ([695b7df](https://github.com/adonisjs/adonis-cli/commit/695b7df)) * **serve:** allow user to register `.dev` domain ([14fc1e8](https://github.com/adonisjs/adonis-cli/commit/14fc1e8)) * **setup:** add `setup` command to allow projects define setup process ([4954433](https://github.com/adonisjs/adonis-cli/commit/4954433)) ### Reverts * **commands:** remove setup command ([15258e8](https://github.com/adonisjs/adonis-cli/commit/15258e8)) ## [3.0.14](https://github.com/adonisjs/adonis-cli/compare/v3.0.12...v3.0.14) (2017-10-10) ### Bug Fixes * **clone:** allow white space ([dd2b551](https://github.com/adonisjs/adonis-cli/commit/dd2b551)) * **make:controller:** entertain the resource flag ([977b160](https://github.com/adonisjs/adonis-cli/commit/977b160)) * **repl:** create history file if doesn't exists ([#58](https://github.com/adonisjs/adonis-cli/issues/58)) ([3fb526b](https://github.com/adonisjs/adonis-cli/commit/3fb526b)) * **watch:** ignore public directory ([67ca54d](https://github.com/adonisjs/adonis-cli/commit/67ca54d)) ## [3.0.13](https://github.com/adonisjs/adonis-cli/compare/v3.0.12...v3.0.13) (2017-10-03) ## [3.0.12](https://github.com/adonisjs/adonis-cli/compare/v3.0.11...v3.0.12) (2017-08-22) ### Features * **new:** add --dev flag to the new command ([4282267](https://github.com/adonisjs/adonis-cli/commit/4282267)) ## [3.0.11](https://github.com/adonisjs/adonis-cli/compare/v3.0.10...v3.0.11) (2017-08-22) ### Bug Fixes * **install:** do not require app ace file ([ab536d5](https://github.com/adonisjs/adonis-cli/commit/ab536d5)) * **package:** update pluralize to version 7.0.0 ([#53](https://github.com/adonisjs/adonis-cli/issues/53)) ([0e46de1](https://github.com/adonisjs/adonis-cli/commit/0e46de1)) ### Features * **make:** add make:exception command ([a9b2c3c](https://github.com/adonisjs/adonis-cli/commit/a9b2c3c)) * **new:** install fullstack app by default ([e07860c](https://github.com/adonisjs/adonis-cli/commit/e07860c)) ## [3.0.10](https://github.com/adonisjs/adonis-cli/compare/v3.0.9...v3.0.10) (2017-08-18) ### Features * **serve:** add --debug flag to run in debug mode ([d6197b8](https://github.com/adonisjs/adonis-cli/commit/d6197b8)) ## [3.0.9](https://github.com/adonisjs/adonis-cli/compare/v3.0.8...v3.0.9) (2017-08-16) ### Bug Fixes * **generators:** add WsController template ([#51](https://github.com/adonisjs/adonis-cli/issues/51)) ([a10e1e4](https://github.com/adonisjs/adonis-cli/commit/a10e1e4)) * **generators:** generate proper paths to nested folders ([6cae861](https://github.com/adonisjs/adonis-cli/commit/6cae861)) * **install:** pass `--save` flag to npm install ([9b39aa7](https://github.com/adonisjs/adonis-cli/commit/9b39aa7)) * **wsController:** make proper path for subdirs ([28f7af0](https://github.com/adonisjs/adonis-cli/commit/28f7af0)) ### Features * **serve:** remove forever for nodemon ([23f1798](https://github.com/adonisjs/adonis-cli/commit/23f1798)) ## [3.0.8](https://github.com/adonisjs/adonis-cli/compare/v3.0.7...v3.0.8) (2017-08-08) ### Bug Fixes * **template:** fix command template ([cb3bb86](https://github.com/adonisjs/adonis-cli/commit/cb3bb86)) ## [3.0.7](https://github.com/adonisjs/adonis-cli/compare/v3.0.6...v3.0.7) (2017-08-04) ### Bug Fixes * **context:** cli.copy should not overwrite the existing file ([8fc3bd1](https://github.com/adonisjs/adonis-cli/commit/8fc3bd1)) * **instructions:** make sure instruction fn is a function ([acc7e82](https://github.com/adonisjs/adonis-cli/commit/acc7e82)) * **serve:** fix glob pattern for ignore dirs ([4860502](https://github.com/adonisjs/adonis-cli/commit/4860502)) ## [3.0.6](https://github.com/adonisjs/adonis-cli/compare/v3.0.5...v3.0.6) (2017-08-02) ## [3.0.5](https://github.com/adonisjs/adonis-cli/compare/v3.0.4...v3.0.5) (2017-08-01) ### Bug Fixes * **commands:** use as flag over name ([e11ae80](https://github.com/adonisjs/adonis-cli/commit/e11ae80)) ## [3.0.4](https://github.com/adonisjs/adonis-cli/compare/v3.0.3...v3.0.4) (2017-08-01) ### Features * **commands:** add install command ([56834a8](https://github.com/adonisjs/adonis-cli/commit/56834a8)) * **commands:** add run:instructions command ([459d7c9](https://github.com/adonisjs/adonis-cli/commit/459d7c9)) ## [3.0.3](https://github.com/adonisjs/adonis-cli/compare/v3.0.2...v3.0.3) (2017-07-28) ### Features * **commands:** add make:ehandler command ([8703159](https://github.com/adonisjs/adonis-cli/commit/8703159)) * **commands:** add make:seed command ([c7898da](https://github.com/adonisjs/adonis-cli/commit/c7898da)) * **commands:** add repl command ([e0c0f7f](https://github.com/adonisjs/adonis-cli/commit/e0c0f7f)) * **commands:** add route:list command ([a0b63ed](https://github.com/adonisjs/adonis-cli/commit/a0b63ed)) ## [3.0.2](https://github.com/adonisjs/adonis-cli/compare/v3.0.1...v3.0.2) (2017-07-27) ### Features * **serve:** add ignore patterns to serve command ([eb132ef](https://github.com/adonisjs/adonis-cli/commit/eb132ef)) ## [3.0.1](https://github.com/adonisjs/adonis-cli/compare/v3.0.0...v3.0.1) (2017-07-27) ### Bug Fixes * **bin:** remove --harmony flag ([a814d45](https://github.com/adonisjs/adonis-cli/commit/a814d45)) # [3.0.0](https://github.com/adonisjs/adonis-cli/compare/v2.1.9...v3.0.0) (2017-07-27) ### Bug Fixes * **test:** add hack for windows ([5ee5071](https://github.com/adonisjs/adonis-cli/commit/5ee5071)) * **test:** another attempt for window ([5a98518](https://github.com/adonisjs/adonis-cli/commit/5a98518)) * **test:** fix breaking tests ([525312a](https://github.com/adonisjs/adonis-cli/commit/525312a)) * **test:** fs.remove doesn't work in windows ([c4539cf](https://github.com/adonisjs/adonis-cli/commit/c4539cf)) ### Features * **command:** cleanup & add `new` command ([5844ef6](https://github.com/adonisjs/adonis-cli/commit/5844ef6)) * **commands:** add key:generate ([e4d105e](https://github.com/adonisjs/adonis-cli/commit/e4d105e)) * **commands:** add make commands ([c4d21d4](https://github.com/adonisjs/adonis-cli/commit/c4d21d4)) * **commands:** add make:listener command ([6e276d6](https://github.com/adonisjs/adonis-cli/commit/6e276d6)) * **commands:** add migration make command ([d13b2f7](https://github.com/adonisjs/adonis-cli/commit/d13b2f7)) * **commands:** add serve command ([34ee502](https://github.com/adonisjs/adonis-cli/commit/34ee502)) ## [2.1.9](https://github.com/adonisjs/adonis-cli/compare/v2.1.8...v2.1.9) (2017-03-14) ### Bug Fixes * **new:** change process directory ([#26](https://github.com/adonisjs/adonis-cli/issues/26)) ([35afe17](https://github.com/adonisjs/adonis-cli/commit/35afe17)) ## [2.1.8](https://github.com/adonisjs/adonis-cli/compare/v2.1.7...v2.1.8) (2017-01-30) ### Bug Fixes * **fs:** fs.constants is undefined across versions ([b0d8841](https://github.com/adonisjs/adonis-cli/commit/b0d8841)) ## [2.1.7](https://github.com/adonisjs/adonis-cli/compare/v2.1.6...v2.1.7) (2017-01-28) ### Bug Fixes * **dependencies:** install adonis-fold as main dependency ([dbf9e21](https://github.com/adonisjs/adonis-cli/commit/dbf9e21)) ## [2.1.6](https://github.com/adonisjs/adonis-cli/compare/v2.1.5...v2.1.6) (2017-01-28) ### Bug Fixes * closes [#3](https://github.com/adonisjs/adonis-cli/issues/3) ([25d2edd](https://github.com/adonisjs/adonis-cli/commit/25d2edd)) * use the requiredNodeVersion and requiredNpmVersion const ([246dde6](https://github.com/adonisjs/adonis-cli/commit/246dde6)) * **install:** install using --no-optional flag ([0426fa3](https://github.com/adonisjs/adonis-cli/commit/0426fa3)) ### Features * add check node.js and npm required versions to the new command. ([7493ee6](https://github.com/adonisjs/adonis-cli/commit/7493ee6)) * check node.js and npm required versions ([954f3e8](https://github.com/adonisjs/adonis-cli/commit/954f3e8)) ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing AdonisJs is a community driven project. You are free to contribute in any of the following ways. - [Coding style](coding-style) - [Fix bugs by creating PR's](fix-bugs-by-creating-prs) - [Share an RFC for new features or big changes](share-an-rfc-for-new-features-or-big-changes) - [Report security issues](report-security-issues) - [Be a part of the community](be-a-part-of-community) ## Coding style Majority of AdonisJs core packages are written in Typescript. Having a brief knowledge of Typescript is required to contribute to the core. [Learn more](https://adonisjs.com/coding-style) about the same. ## Fix bugs by creating PR's We appreciate every time you report a bug in the framework or related libraries. However, taking time to submit a PR can help us in fixing bugs quickly and ensure a healthy and stable eco-system. Go through the following points, before creating a new PR. 1. Create an issue discussing the bug or short-coming in the framework. 2. Once approved, go ahead and fork the REPO. 3. Make sure to start from the `develop`, since this is the upto date branch. 4. Make sure to keep commits small and relevant. 5. We follow [conventional-commits](https://github.com/conventional-changelog/conventional-changelog) to structure our commit messages. Instead of running `git commit`, you must run `npm commit`, which will show you prompts to create a valid commit message. 6. Once done with all the changes, create a PR against the `develop` branch. ## Share an RFC for new features or big changes Sharing PR's for small changes works great. However, when contributing big features to the framework, it is required to go through the RFC process. ### What is an RFC? RFC stands for **Request for Commits**, a standard process followed by many other frameworks including [Ember](https://github.com/emberjs/rfcs), [yarn](https://github.com/yarnpkg/rfcs) and [rust](https://github.com/rust-lang/rfcs). In brief, RFC process allows you to talk about the changes with everyone in the community and get a view of the core team before dedicating your time to work on the feature. The RFC proposals are created as issues on [adonisjs/rfcs](https://github.com/adonisjs/rfcs) repo. Make sure to read the README to learn about the process in depth. ## Report security issues All of the security issues, must be reported via [email](mailto:virk@adonisjs.com) and not using any of the public channels. [Learn more](https://adonisjs.com/security) about the security policy ## Be a part of community We welcome you to participate in the [forum](https://forum.adonisjs.com/) and the AdonisJs [discord server](https://discord.me/adonisjs). You are free to ask your questions and share your work or contributions made to AdonisJs eco-system. We follow a strict [Code of Conduct](https://adonisjs.com/community-guidelines) to make sure everyone is respectful to each other. ================================================ FILE: LICENSE.md ================================================ # The MIT License Copyright 2018 Harminder Virk, contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # AdonisJs Cli 🍺 > Scaffolding tool for Adonisjs [![NPM Version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Appveyor][appveyor-image]][appveyor-url] [![Coveralls][coveralls-image]][coveralls-url] Adonis cli is built on top of [Adonis ace](https://github.com/adonisjs/ace) and helps you scaffold new Adonisjs projects. Also it can proxy all the ace commands for a project, so that you can run them using the global `adonis` command. ## Installation You can install the package from npm. ```bash npm i --global @adonisjs/cli ``` ## Usage ```bash adonis new yardstick # start http server adonis serve --dev ``` ## Moving Forward Checkout the [official documentation](https://adonisjs.com/docs/4.1/installation) at the AdonisJs website for more info. ## Tests Tests are written using [japa](http://github.com/thetutlage/japa). Run the following commands to run tests. ```bash npm run test:local # report coverage npm run test # on windows npm run test:win ``` ## Release History Checkout [CHANGELOG.md](CHANGELOG.md) file for release history. ## Meta AdonisJs – [@adonisframework](https://twitter.com/adonisframework) – virk@adonisjs.com Checkout [LICENSE.txt](LICENSE.txt) for license information Harminder Virk (Aman) - [https://github.com/thetutlage](https://github.com/thetutlage) [appveyor-image]: https://img.shields.io/appveyor/ci/thetutlage/adonis-cli/master.svg?style=flat-square [appveyor-url]: https://ci.appveyor.com/project/thetutlage/adonis-cli [npm-image]: https://img.shields.io/npm/v/@adonisjs/cli.svg?style=flat-square [npm-url]: https://npmjs.org/package/@adonisjs/cli [travis-image]: https://img.shields.io/travis/adonisjs/adonis-cli/master.svg?style=flat-square [travis-url]: https://travis-ci.org/adonisjs/adonis-cli [coveralls-image]: https://img.shields.io/coveralls/adonisjs/adonis-cli/develop.svg?style=flat-square [coveralls-url]: https://coveralls.io/github/adonisjs/adonis-cli ================================================ FILE: appveyor.yml ================================================ environment: matrix: - nodejs_version: Stable - nodejs_version: 8.0.0 init: git config --global core.autocrlf true install: - ps: 'Install-Product node $env:nodejs_version' - npm install test_script: - node --version - npm --version - npm run test build: 'off' clone_depth: 1 matrix: fast_finish: true ================================================ FILE: config.json ================================================ { "core": true, "ts": false, "license": "MIT", "services": [ "travis", "appveyor", "coveralls" ], "appveyorUsername": "thetutlage", "minNodeVersion": "8.0.0" } ================================================ FILE: index.js ================================================ #!/usr/bin/env node 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const path = require('path') const debug = require('debug')('adonis:cli') const Commands = require('./src/Commands') const commandNames = [] const needProviders = ['repl', 'route:list', 'run:instructions'] const ace = require('./lib/ace') // register internal commands Object.keys(Commands).forEach((name) => { commandNames.push(name) ace.addCommand(Commands[name]) }) // require user project .ace file try { const command = process.argv[2] if (commandNames.indexOf(command) > -1 && needProviders.indexOf(command) <= -1) { debug('loading ace from cli') ace.wireUpWithCommander() ace.invoke(require('./package')) } else { debug('loading ace from project') require(path.join(process.cwd(), 'ace')) } } catch (error) { if (error.code !== 'ENOENT' && error.code !== 'MODULE_NOT_FOUND') { throw error } debug('loading ace as fallback from cli') ace.wireUpWithCommander() ace.invoke(require('./package')) } ================================================ FILE: japaFile.js ================================================ const { configure } = require('japa') configure({ files: ['test/**/*.spec.js'] }) ================================================ FILE: lib/Steps.js ================================================ 'use strict' /** * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const Steps = require('cli-step') /** * Raw steps are used when user want to disable all animations. * * @class RawStep */ class RawStep { constructor (total, counter, text, helpText) { this.total = total this.stepCounter = counter this.text = text this.helpText = helpText || '' } /** * Start step * * @method start * * @chainable */ start () { console.log(`Step ${this.stepCounter}/${this.total}`) console.log(` ├── ${this.text} (${this.helpText})`) return this } /** * Mark step as successful * * @method success * * @param {String} text * * @return {void} */ success (text) { console.log(` ├── SUCCESS: ${text || this.text} (${this.helpText})`) } /** * Mark step as errored * * @method error * * @param {String} text * * @return {void} */ error (text) { console.log(` ├── ERROR: ${text || this.text} (${this.helpText})`) } } /** * Raw steps is a collection of Raw step. The API has to be * compatible with `cli-step`. * * @class RawSteps */ class RawSteps { constructor (total) { this.counter = 0 this.total = total } /** * Move to next step. Also the icon param is swalled, since raw output * doesn't display emojis. * * @method advance * * @param {String} text * @param {String} icon * @param {String} helpText * * @return {void} */ advance (text, icon, helpText) { this.counter++ return new RawStep(this.total, this.counter, text, helpText) } } module.exports = { RawSteps, Steps } ================================================ FILE: lib/ace.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const path = require('path') let ace = null /** * Give preference to the user ace module if * command is executed in project root. */ try { ace = require(path.join(process.cwd(), 'node_modules/@adonisjs/ace')) } catch (error) { ace = require('@adonisjs/ace') } module.exports = ace ================================================ FILE: package.json ================================================ { "name": "@adonisjs/cli", "version": "4.0.13", "description": "Command line tool for Adonisjs", "keywords": [ "adonis", "adonisjs", "cli", "installer" ], "author": "Harminder Virk ", "contributors": [ "Romain Lanz " ], "license": "MIT", "main": "src/Commands/index.js", "bin": { "adonis": "index.js" }, "scripts": { "mrm": "mrm --preset=@adonisjs/mrm-preset", "pretest": "npm run lint", "test:local": "FORCE_COLOR=true node bin/index.js --local", "test": "nyc node japaFile.js", "coverage": "nyc report --reporter=text-lcov | coveralls", "commit": "git-cz", "lint": "standard", "snyk-protect": "snyk protect", "prepublish": "npm run snyk-protect" }, "dependencies": { "@adonisjs/ace": "^5.0.8", "@adonisjs/ignitor": "^2.0.8", "adonis-await-outside": "^1.0.0", "cli-step": "^1.0.2", "debug": "^4.1.0", "dotenv": "^8.0.0", "gradient-string": "^1.2.0", "is-git-url": "^1.0.0", "lodash": "^4.17.11", "marked": "^1.1.1", "nodemon": "^2.0.3", "opn": "^5.4.0", "pluralize": "^8.0.0", "randomstring": "^1.1.5", "semver": "^5.6.0", "snyk": "^1.231.0" }, "devDependencies": { "@adonisjs/fold": "^4.0.9", "@adonisjs/mrm-preset": "^2.0.3", "@adonisjs/sink": "^1.0.17", "clear-require": "^3.0.0", "commitizen": "^3.0.4", "coveralls": "^3.0.2", "cz-conventional-changelog": "^2.1.0", "fs-extra": "^8.1.0", "japa": "^2.0.6", "japa-cli": "^1.0.1", "mrm": "^1.2.1", "nyc": "^14.1.1", "pkg-ok": "^2.3.1", "standard": "^12.0.1" }, "repository": { "type": "git", "url": "git+https://github.com/adonisjs/adonis-cli.git" }, "bugs": { "url": "https://github.com/adonisjs/adonis-cli/issues" }, "config": { "commitizen": { "path": "cz-conventional-changelog" } }, "nyc": { "exclude": [ "test" ] }, "homepage": "https://github.com/adonisjs/adonis-cli#readme", "directories": { "lib": "lib", "test": "test" }, "snyk": true } ================================================ FILE: src/Commands/Addon/index.js ================================================ 'use strict' /** * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const path = require('path') const BaseCommand = require('../Base') /** * This command performs a series of operations * to be create a new addon folder. * * @class NewAddon */ class NewAddon extends BaseCommand { /** * The command signature required by ace * * @attribute signature * @static * * @return {String} */ static get signature () { return ` addon { name : Name of the addon directory } { --skip-install : Do not install modules from npm } { --yarn : Use yarn over npm for modules installation } { --raw : Disable animations and colored output } { --dev: Install the dev blueprint } ` } /** * The command description required by ace * * @attribute description * * @return {String} */ static get description () { return 'Create a new AdonisJs addon' } /** * Ensure node version is correct, then make sure app path is * empty and finally clone the repo and remove `.git` dir. * * @method _setupProjectDirectory * * @param {Object} stepsCounter * @param {String} blueprint * @param {String} appPath * @param {Object} options * * @return {void} * * @private */ async _setupProjectDirectory (stepsCounter, blueprint, appPath, options) { await require('../../Services/check-node-version')(stepsCounter) await require('../../Services/verify-existing-folder')(appPath, stepsCounter) await require('../../Services/clone')(blueprint, appPath, stepsCounter, options.branch) await this.removeDir(path.join(appPath, '.git')) } /** * Prints a message after a new project has been created * * @method _onBoardForNewAddon * * @return {void} * * @private */ _onBoardForNewAddon () { const lines = [ '', '🚀 Addon created successfully', '👉 Get started by clicking the following link', '', `${this.chalk.blue('https://adonisjs.com/recipes/creating-addons')}`, '' ] lines.forEach((line) => (console.log(line))) } /** * Install dependencies when `skip-install` flag has not been * passed * * @method _installDependencies * * @param {Object} stepsCounter * @param {String} appPath * @param {Object} options * * @return {void} * * @private */ async _installDependencies (stepsCounter, appPath, options) { if (options.skipInstall) { return } await require('../../Services/install')(options.yarn ? 'yarn' : 'npm', stepsCounter) } /** * Invoked by ace * * @method handle * * @param {Object} args * @param {Object} options * * @return {void} */ async handle ({ name }, options) { const blueprint = 'adonisjs/adonis-addon' const addonPath = path.join(process.cwd(), name) const stepsCounter = this.initiateSteps(options.skipInstall ? 3 : 4, options) if (options.dev) { options.branch = 'develop' } await this.invoke(async () => { this.dumpAsciiLogo() await this._setupProjectDirectory(stepsCounter, blueprint, addonPath, options) process.chdir(addonPath) await this._installDependencies(stepsCounter, addonPath, options) this._onBoardForNewAddon() }) } } module.exports = NewAddon ================================================ FILE: src/Commands/Base/index.js ================================================ 'use strict' /** * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const gradient = require('gradient-string') const path = require('path') const ace = require('../../../lib/ace') class BaseCommand extends ace.Command { /** * Returns an instance of steps counter, based upon * command line flags * * @method initiateSteps * * @param {Number} count * @param {Object} options * * @return {Object} */ initiateSteps (count, options) { const { RawSteps, Steps } = require('../../../lib/Steps') return options.raw || process.env.DEBUG ? new RawSteps(count) : new Steps(count) } /** * Prints AdonisJs ascii art to the console * * @method dumpAsciiLogo * * @return {void} */ dumpAsciiLogo () { console.log(gradient.rainbow(" _ _ _ _ \n / \\ __| | ___ _ __ (_)___ | |___ \n / _ \\ / _` |/ _ \\| '_ \\| / __|_ | / __|\n / ___ \\ (_| | (_) | | | | \\__ \\ |_| \\__ \\\n/_/ \\_\\__,_|\\___/|_| |_|_|___/\\___/|___/\n")) } /** * Invokes a function, by automatically catching for errors * and printing them in a standard way * * @method invoke * * @param {Function} callback * * @return {void} */ async invoke (callback) { try { await callback() } catch (error) { this.printError(error) process.exit(1) } } /** * Prints error object to the console * * @method printError * * @param {Object} error * * @return {void} */ printError (error) { console.log(`\n ${this.chalk.bgRed(' ERROR ')} ${error.message}\n`) if (error.hint) { console.log(`\n ${this.chalk.bgRed(' HELP ')} ${error.hint}\n`) } } /** * Throws exception when user is not inside the project root * * @method ensureInProjectRoot * * @return {void} */ async ensureInProjectRoot () { const exists = await this.pathExists(path.join(process.cwd(), 'ace')) if (!exists) { throw new Error(`Make sure you are inside an adonisjs app to run the ${this.constructor.commandName} command`) } } /** * Throws error when NODE_ENV = production and `--force` flag * has not been passed. * * @method ensureCanRunInProduction * * @param {Object} options * * @return {void} */ ensureCanRunInProduction (options) { if (process.env.NODE_ENV === 'production' && !options.force) { throw new Error(`Cannot run ${this.constructor.commandName} command in production. Pass --force flag to continue`) } } /** * Calls a command registered with ace * * @method call * * @param {String} command * @param {Object} options * @param {Object} flags * * @return {void} */ call (command, options, flags) { return ace.call(command, options, flags) } } module.exports = BaseCommand ================================================ FILE: src/Commands/Install/index.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const path = require('path') const BaseCommand = require('../Base') class Install extends BaseCommand { constructor () { super() const FakeHelpers = require('@adonisjs/ignitor/src/Helpers') this.Helpers = new FakeHelpers(process.cwd()) } /** * The command signature * * @method signature * * @return {String} */ static get signature () { return ` install { module : Npm module name } { --as=@value : Name of the module, required when installing from github or local file system } { --yarn: Use yarn over npm for installation } { --cnpm: Use cnpm over npm for installation } { -s, --skip-instructions: Do not run post install instructions } { --raw : Disable animations and colored output } ` } /** * The command description * * @method description * * @return {String} */ static get description () { return 'Install Adonisjs provider from npm/yarn and run post install instructions' } async handle ({ module: packageName }, options) { const name = options.as || packageName const stepsCounter = this.initiateSteps(1, options) await this.invoke(async () => { await this.ensureInProjectRoot() await require('../../Services/install')(options.yarn ? 'yarn' : (options.cnpm ? 'cnpm' : 'npm'), stepsCounter, packageName) if (options.skipInstructions) { return } const directory = path.join(process.cwd(), 'node_modules', name) await this.call('run:instructions', { directory }, { name }) }) } } module.exports = Install ================================================ FILE: src/Commands/Instructions/Context.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const path = require('path') const _ = require('lodash') const ace = require('../../../lib/ace') class Context { constructor (command, helpers) { this.command = command this.helpers = helpers this.appDir = path.join(this.helpers.appRoot(), 'app') } /** * Make config file using a template * * @method makeConfig * @async * * @param {String} fileName * @param {String} templatePath * @param {Object} data * * @return {void} */ async makeConfig (fileName, templatePath, data) { const configFile = path.join(this.helpers.configPath(), fileName) const template = await this.command.readFile(templatePath, 'utf-8') await this.command.generateFile(configFile, template, data) } /** * Calls ace command * * @method callCommand * @async * * @param {String} name * @param {Object} args * @param {Object} options * * @return {void} */ callCommand (name, args, options) { return ace.call(name, args, options) } /** * Copy file from one destination to other * * @method copy * * @param {String} fromFile * @param {String} toFile * @param {Object} [options] * * @return {void} */ copy (fromFile, toFile, options) { return this.command.copy(fromFile, toFile, _.merge({}, { overwrite: false, errorOnExist: true }, options)) } } module.exports = Context ================================================ FILE: src/Commands/Instructions/index.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const path = require('path') const BaseCommand = require('../Base') class Instructions extends BaseCommand { constructor (Helpers) { super() const FakeHelpers = require('@adonisjs/ignitor/src/Helpers') this.Helpers = Helpers || new FakeHelpers(process.cwd()) } /** * Injecting dependencies * * @method inject * * @return {Array} */ static get inject () { return ['Adonis/Src/Helpers'] } /** * The command signature * * @method signature * * @return {String} */ static get signature () { return ` run:instructions { directory : Directory path for which to run instructions } { --as=@value: Name of the module } ` } /** * The command description * * @method description * * @return {String} */ static get description () { return 'Run instructions for a given module' } /** * Handle method executed by ace when command runs. It will * install a module and run post install instructions * * @method handle * * @return {void} */ async handle ({ directory }, options) { await this.invoke(async () => { const modulePath = path.isAbsolute(directory) ? directory : path.join(process.cwd(), directory) const name = options.name || path.basename(modulePath) const Context = require('./Context') const ctx = new Context(this, this.Helpers) await require('../../Services/run-instructions')(ctx, modulePath) await require('../../Services/render-instructions-md')(modulePath, name) }) } } module.exports = Instructions ================================================ FILE: src/Commands/KeyGenerate/index.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const path = require('path') const BaseCommand = require('../Base') /** * Generate unique application key * * @class KeyGenerate * @constructor */ class KeyGenerate extends BaseCommand { /** * The command signature used by ace * * @method signature * * @return {String} */ static get signature () { return ` key:generate { -f, --force: Forcefully generate the key in production environment } { --env=@value: .env file location } { -s, --size=@value: The key size which defaults to 32 characters } { --echo: Echo the key instead of writing to the file } ` } /** * The command description used by ace * * @method description * * @return {String} */ static get description () { return 'Generate secret key for the app' } /** * Reads the content of `.env` file and returns it as * an object * * @method getEnvContent * * @param {String} envPath * * @return {Object} */ async getEnvContent (envPath) { const dotEnvContents = await this.readFile(envPath) return require('dotenv').parse(dotEnvContents) } /** * Updates the `.env` file by converting the object back * to a valid string * * @method updateEnvContents * * @param {String} envPath * @param {Object} envHash * * @return {void} */ async updateEnvContents (envPath, envHash) { const updatedContents = Object.keys(envHash).map((key) => { return `${key}=${envHash[key]}` }).join('\n') await this.writeFile(envPath, updatedContents) } /** * Invoked by ace * * @method handle * * @param {Object} args * @param {Object} options * * @return {void} */ async handle (args, options) { const size = options.size ? Number(options.size) : 32 const key = require('randomstring').generate(size) /** * Echo key to console when echo is set to true * and return */ if (options.echo) { console.log(`APP_KEY=${key}`) return } await this.invoke(async () => { this.ensureCanRunInProduction(options) await this.ensureInProjectRoot() const env = options.env || '.env' const pathToEnv = path.isAbsolute(env) ? env : path.join(process.cwd(), env) const envHash = await this.getEnvContent(pathToEnv) await this.updateEnvContents(pathToEnv, Object.assign(envHash, { APP_KEY: key })) this.completed('generated', 'unique APP_KEY') }) } } module.exports = KeyGenerate ================================================ FILE: src/Commands/Make/Base.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const path = require('path') const BaseCommand = require('../Base') const debug = require('debug')('adonis:cli') const options = { appDir: 'app', dirs: { httpControllers: 'Controllers/Http', wsControllers: 'Controllers/Ws', models: 'Models', traits: 'Models/Traits', hooks: 'Models/Hooks', listeners: 'Listeners', exceptions: 'Exceptions', middleware: 'Middleware', commands: 'Commands', views: 'resources/views', migrations: 'database/migrations', seeds: 'database/seeds', providers: 'providers' } } class MakeBase extends BaseCommand { /** * Generates the blueprint for a given resources * using pre-defined template * * @method generateBlueprint * * @param {String} templateFor * @param {String} name * @param {Object} flags * * @return {void} */ async generateBlueprint (templateFor, name, flags) { const generators = require('../../Generators') options.appRoot = options.appRoot || process.cwd() debug('blueprint options %j', options) const templateFile = path.join(__dirname, '../../Generators/templates', `${templateFor}.mustache`) const filePath = generators[templateFor].getFilePath(name, options) const data = generators[templateFor].getData(path.basename(name), flags) debug('blueprint file path %s', filePath) debug('blueprint data %j', data) const templateContents = await this.readFile(templateFile, 'utf-8') await this.generateFile(filePath, templateContents, data) const createdFile = filePath.replace(process.cwd(), '').replace(path.sep, '') console.log(`${this.icon('success')} ${this.chalk.green('create')} ${createdFile}`) return { file: createdFile, namespace: this.getNamespace(createdFile, templateFor) } } /** * Returns namespace for a given resource * * @method getNamespace * * @param {String} filePath * @param {String} namespaceFor * * @return {String} */ getNamespace (filePath, namespaceFor) { const dir = options.dirs[namespaceFor] || options.dirs[`${namespaceFor}s`] return `App/${dir}/${path.basename(filePath).replace('.js', '')}` } /** * Print lines to the console * * @method printInstructions * * @param {Array} lines * * @return {void} */ printInstructions (heading, steps) { console.log( ['', `👉 ${heading}`, ''] .concat(steps.map((line) => `${this.chalk.dim('→')} ${line}`)) .concat(['']) .join('\n') ) } } module.exports = MakeBase ================================================ FILE: src/Commands/Make/Command.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const BaseCommand = require('./Base') /** * Creates a new ace command * * @class MakeCommand * @constructor */ class MakeCommand extends BaseCommand { /** * The command signature * * @method signature * * @return {String} */ static get signature () { return ` make:command { name: Name of the command } ` } /** * The command description * * @method description * * @return {String} */ static get description () { return 'Make a new ace command' } /** * Handle method executed by ace * * @method handle * * @param {String} options.name * @param {String} options.type * * @return {void} */ async handle ({ name }) { await this.invoke(async () => { await this.ensureInProjectRoot() const { namespace } = await this.generateBlueprint('command', name, {}) const steps = [ `Open ${this.chalk.cyan('start/app.js')}`, `Add ${this.chalk.cyan(namespace)} to commands array` ] this.printInstructions('Register command as follows', steps) }) } } module.exports = MakeCommand ================================================ FILE: src/Commands/Make/Controller.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const BaseCommand = require('./Base') /** * Make a new HTTP or Ws controller * * @class MakeController * @constructor */ class MakeController extends BaseCommand { /** * The command signature * * @method signature * * @return {String} */ static get signature () { return ` make:controller { name: Name of the controller } { --resource: Create resourceful methods on the controller } { --type=@value: The type can be http or ws } ` } /** * The command description * * @method description * * @return {String} */ static get description () { return 'Make a new HTTP or Websocket channel controller' } /** * Returns the resource type for the controller * * @method _getResourceType * * @param {String} type * * @return {String} * * @private */ async _getResourceType (type) { if (!type || ['ws', 'http'].indexOf(type) <= -1) { type = await this .on('validate', (value) => !!value) .choice('Select controller type', [ { value: 'http', name: 'For HTTP requests' }, { value: 'ws', name: 'For Websocket channel' } ]) } return type === 'ws' ? 'wsController' : 'httpController' } /** * Handle method executed by ace * * @method handle * * @param {String} options.name * @param {String} options.type * * @return {void} */ async handle ({ name }, { type, resource }) { await this.invoke(async () => { await this.ensureInProjectRoot() const resourceType = await this._getResourceType(type) await this.generateBlueprint(resourceType, name, { resource }) }) } } module.exports = MakeController ================================================ FILE: src/Commands/Make/Exception.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const BaseCommand = require('./Base') /** * Make a new exception class * * @class MakeException * @constructor */ class MakeException extends BaseCommand { /** * The command signature * * @method signature * * @return {String} */ static get signature () { return ` make:exception { name: Name of the exception } ` } /** * The command description * * @method description * * @return {String} */ static get description () { return 'Make a new exception' } /** * Handle method executed by ace * * @method handle * * @param {String} options.name * @param {String} options.type * * @return {void} */ async handle ({ name }) { await this.invoke(async () => { await this.ensureInProjectRoot() await this.generateBlueprint('exception', name, {}) }) } } module.exports = MakeException ================================================ FILE: src/Commands/Make/ExceptionHandler.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const path = require('path') const BaseCommand = require('./Base') /** * Make a new global exception handler * * @class MakeExceptionHandler * @constructor */ class MakeExceptionHandler extends BaseCommand { /** * The command signature * * @method signature * * @return {String} */ static get signature () { return 'make:ehandler' } /** * The command description * * @method description * * @return {String} */ static get description () { return 'Make a new global exception handler' } /** * Handle method executed by ace * * @method handle * * @return {void} */ async handle () { await this.invoke(async () => { await this.ensureInProjectRoot() const packageFile = require(path.join(process.cwd(), 'package.json')) const version = packageFile['adonis-version'] || packageFile['version'] /** * The exceptions template is different for 4.0 and newer * versions. */ await this.generateBlueprint('exceptionHandler', '', { new: version !== '4.0.0' }) }) } } module.exports = MakeExceptionHandler ================================================ FILE: src/Commands/Make/Hook.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const BaseCommand = require('./Base') /** * Make a new lucid model hook * * @class MakeModelHook * @constructor */ class MakeModelHook extends BaseCommand { /** * The command signature * * @method signature * * @return {String} */ static get signature () { return ` make:hook { name: Name of the hook } { -m, --method=@value : The method to be created on hook } ` } /** * The command description * * @method description * * @return {String} */ static get description () { return 'Make a new lucid model hook' } /** * Handle method executed by ace * * @method handle * * @param {String} options.name * @param {String} options.type * * @return {void} */ async handle ({ name }, { method }) { await this.invoke(async () => { await this.ensureInProjectRoot() await this.generateBlueprint('hook', name, { method }) }) } } module.exports = MakeModelHook ================================================ FILE: src/Commands/Make/Listener.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const BaseCommand = require('./Base') /** * Make a new redis or event listener * * @class MakeListener * @constructor */ class MakeListener extends BaseCommand { /** * The command signature * * @method signature * * @return {String} */ static get signature () { return ` make:listener { name: Name of the listener } { -m, --method=@value : The method to be created on listener } ` } /** * The command description * * @method description * * @return {String} */ static get description () { return 'Make a new event or redis listener' } /** * Handle method executed by ace * * @method handle * * @param {String} options.name * @param {String} options.type * * @return {void} */ async handle ({ name }, { method }) { await this.invoke(async () => { await this.ensureInProjectRoot() await this.generateBlueprint('listener', name, { method }) }) } } module.exports = MakeListener ================================================ FILE: src/Commands/Make/Middleware.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const BaseCommand = require('./Base') /** * Make a new HTTP or Ws middleware * * @class MakeMiddleware * @constructor */ class MakeMiddleware extends BaseCommand { /** * The command signature * * @method signature * * @return {String} */ static get signature () { return ` make:middleware { name: Name of the middleware } { --type=@value: The type can be http, ws or both } ` } /** * The command description * * @method description * * @return {String} */ static get description () { return 'Make a new HTTP or Ws Middleware' } /** * Returns the resource type for the middleware * * @method _getResourceType * * @param {String} type * * @return {String} * * @private */ async _getResourceType (type) { if (!type || ['ws', 'http', 'both'].indexOf(type) <= -1) { type = await this .on('validate', (value) => !!value) .choice('Select middleware type', [ { name: 'For HTTP requests', value: 'http' }, { name: 'For Websocket requests', value: 'ws' }, { name: 'For both HTTP and Websocket requests', value: 'both' } ]) } return type } /** * Handle method executed by ace * * @method handle * * @param {String} options.name * @param {String} options.type * * @return {void} */ async handle ({ name }, { type }) { await this.invoke(async () => { await this.ensureInProjectRoot() const resourceType = await this._getResourceType(type) const { namespace } = await this.generateBlueprint('middleware', name, { type: resourceType }) const steps = [] /** * Push instructions for http if resource type was * http or both */ if (resourceType === 'both' || resourceType === 'http') { steps.push(`Open ${this.chalk.cyan('start/kernel.js')} file`) steps.push(`Register ${this.chalk.cyan(namespace)} under global or named middleware`) } /** * Push instructions for ws if resource type was * ws or both */ if (resourceType === 'both' || resourceType === 'ws') { steps.push(`Open ${this.chalk.cyan('start/ws.js')} file`) steps.push(`Register ${this.chalk.cyan(namespace)} under global or named middleware`) } this.printInstructions('Register middleware as follows', steps) }) } } module.exports = MakeMiddleware ================================================ FILE: src/Commands/Make/Migration.js ================================================ 'use strict' /* * adonis-lucid * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const BaseCommand = require('./Base') /** * Make a new migration file * * @class MakeMigration * @constructor */ class MakeMigration extends BaseCommand { /** * Command signature required by ace * * @method signature * * @return {String} */ static get signature () { return ` make:migration { name: Name of migration file, current timestamp will be prepended to the name } { --action?=@value : Choose an action to \`create\` or \`select\` a table } ` } /** * Command description * * @method description * * @return {String} */ static get description () { return 'Create a new migration file' } /** * Returns the migration action * * @method _getActionType * * @param {String} action * * @return {String} */ async _getActionType (action) { if (!action || ['create', 'select'].indexOf(action) <= -1) { action = await this.choice('Choose an action', [ { value: 'create', name: 'Create table' }, { value: 'select', name: 'Select table' } ]) } return action } /** * Method to be called when this command is executed * * @method handle * * @param {String} options.name * @param {String} options.action * * @return {void|String} - Returns abs path to created file when command * is not executed by ace. */ async handle ({ name }, { action }) { await this.invoke(async () => { await this.ensureInProjectRoot() const actionType = await this._getActionType(action) await this.generateBlueprint('schema', name, { action: actionType }) }) } } module.exports = MakeMigration ================================================ FILE: src/Commands/Make/Model.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const BaseCommand = require('./Base') /** * Make a new lucid model * * @class MakeModel * @constructor */ class MakeModel extends BaseCommand { /** * The command signature * * @method signature * * @return {String} */ static get signature () { return ` make:model { name: Name of the model } { -m, --migration: Generate migration for the model } { -c, --controller: Generate resourceful controller for the model } ` } /** * The command description * * @method description * * @return {String} */ static get description () { return 'Make a new lucid model' } /** * Handle method executed by ace * * @method handle * * @param {String} options.name * @param {String} options.type * * @return {void} */ async handle ({ name }, { migration, controller }) { await this.invoke(async () => { await this.ensureInProjectRoot() await this.generateBlueprint('model', name, {}) if (migration) { await this.generateBlueprint('schema', name, { action: 'create' }) } if (controller) { await this.generateBlueprint('httpController', name, { resource: controller }) } }) } } module.exports = MakeModel ================================================ FILE: src/Commands/Make/Provider.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const BaseCommand = require('./Base') /** * Make a new provider * * @class MakeProvider * @constructor */ class MakeProvider extends BaseCommand { /** * The command signature * * @method signature * * @return {String} */ static get signature () { return ` make:provider { name: Name of the provider } ` } /** * The command description * * @method description * * @return {String} */ static get description () { return 'Make a new provider' } /** * Handle method executed by ace * * @method handle * * @param {String} options.name * @param {String} options.type * * @return {void} */ async handle ({ name }) { await this.invoke(async () => { await this.ensureInProjectRoot() await this.generateBlueprint('provider', name, {}) }) } } module.exports = MakeProvider ================================================ FILE: src/Commands/Make/Seed.js ================================================ 'use strict' /* * adonis-lucid * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const BaseCommand = require('./Base') /** * Make a new seed file * * @class MakeSeed * @constructor */ class MakeSeed extends BaseCommand { /** * Command signature required by ace * * @method signature * * @return {String} */ static get signature () { return ` make:seed { name?=Database: Name of the seed file } ` } /** * Command description * * @method description * * @return {String} */ static get description () { return 'Create a database seeder' } /** * Method to be called when this command is executed * * @method handle * * @param {String} options.name */ async handle ({ name }) { await this.invoke(async () => { await this.ensureInProjectRoot() await this.generateBlueprint('seed', name) }) } } module.exports = MakeSeed ================================================ FILE: src/Commands/Make/Trait.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const BaseCommand = require('./Base') /** * Make a new lucid trait * * @class MakeTrait * @constructor */ class MakeTrait extends BaseCommand { /** * The command signature * * @method signature * * @return {String} */ static get signature () { return ` make:trait { name: Name of the trait } ` } /** * The command description * * @method description * * @return {String} */ static get description () { return 'Make a new lucid trait' } /** * Handle method executed by ace * * @method handle * * @param {String} options.name * * @return {void} */ async handle ({ name }) { await this.invoke(async () => { await this.ensureInProjectRoot() await this.generateBlueprint('trait', name, {}) }) } } module.exports = MakeTrait ================================================ FILE: src/Commands/Make/View.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const BaseCommand = require('./Base') /** * Make a new edge view * * @class MakeView * @constructor */ class MakeView extends BaseCommand { /** * The command signature * * @method signature * * @return {String} */ static get signature () { return ` make:view { name: Name of the view } { -l, --layout=@value: Define a layout to extend } ` } /** * The command description * * @method description * * @return {String} */ static get description () { return 'Make a view file' } /** * Handle method executed by ace * * @method handle * * @param {String} options.name * @param {String} options.type * * @return {void} */ async handle ({ name }, { layout }) { await this.invoke(async () => { await this.ensureInProjectRoot() await this.generateBlueprint('view', name, { layout }) }) } } module.exports = MakeView ================================================ FILE: src/Commands/New/index.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const path = require('path') const BaseCommand = require('../Base') /** * This command performs a series of operations * to be create a new Adonisjs application. * * @class NewApp */ class NewApp extends BaseCommand { /** * The command signature required by ace * * @attribute signature * @static * * @return {String} */ static get signature () { return ` new { name : Name of the project directory } { --api-only : Scaffold project for api server } { --api: Scaffold project for api server } { --slim : Scaffold smallest possible Adonisjs application } { --blueprint?=@value : Path to github project blueprint } { --branch?=@value : Specify git branch for project blueprint } { --skip-install : Do not install modules from npm } { --yarn : Use yarn over npm for modules installation } { --cnpm: Use cnpm over npm for installation } { --raw : Disable animations and colored output } ` } /** * The command description required by ace * * @attribute description * * @return {String} */ static get description () { return 'Create a new AdonisJs application' } /** * Returns the actual blueprint to be used for * cloning the repo. It will go over the cli * options and returns the most appropriate * one. * * @method _getBluePrint * * @param {Object} options * * @return {String} * * @private */ _getBluePrint (options) { /** * Use the explicitly defined blueprint * over any other options. */ if (options.blueprint) { return options.blueprint } /** * If we used the flag --api-only or --api we want * to fetch the API blueprint. */ if (options.apiOnly || options.api) { return 'adonisjs/adonis-api-app' } /** * If we used the flag --slim we want to fetch * the SLIM blueprint. */ if (options.slim) { return 'adonisjs/adonis-slim-app' } /** * If none flag has been defiend we fallbacke * to the Fullstack blueprint. */ return 'adonisjs/adonis-fullstack-app' } /** * Ensure node version is correct, then make sure app path is * empty and finally clone the repo and remove `.git` dir. * * @method _setupProjectDirectory * * @param {Object} stepsCounter * @param {String} appPath * @param {Object} options * * @return {void} * * @private */ async _setupProjectDirectory (stepsCounter, appPath, options) { await require('../../Services/check-node-version')(stepsCounter) await require('../../Services/verify-existing-folder')(appPath, stepsCounter) await require('../../Services/clone')(this._getBluePrint(options), appPath, stepsCounter, options.branch) await this.removeDir(path.join(appPath, '.git')) } /** * Install dependencies when `skip-install` flag has not been * passed * * @method _installDependencies * * @param {Object} stepsCounter * @param {String} appPath * @param {Object} options * * @return {void} * * @private */ async _installDependencies (stepsCounter, appPath, options) { if (options.skipInstall) { return } await require('../../Services/install')(options.yarn ? 'yarn' : (options.cnpm ? 'cnpm' : 'npm'), stepsCounter) } /** * Copy the `.env` file and generate the app key after installation * of modules have been done. * * @method _postInstallation * * @param {Object} stepsCounter * @param {String} appPath * * @return {void} * * @private */ async _postInstallation (stepsCounter, appPath) { await require('../../Services/copy-env-file')(appPath, stepsCounter) await require('../../Services/generate-app-key')(stepsCounter) } /** * Prints a message after a new project has been created * * @method _onBoardForNewProject * * @param {String} appName * * @return {void} * * @private */ _onBoardForNewProject (appName) { const lines = [ '', '🚀 Successfully created project', '👉 Get started with the following commands', '', `${this.chalk.dim('$')} ${this.chalk.cyan(`cd ${appName}`)}`, `${this.chalk.dim('$')} ${this.chalk.cyan('adonis serve --dev')}`, '' ] lines.forEach((line) => { console.log(line) }) } /** * Handle method executed by ace to setup a new app * * @method handle * * @param {String} options.name * @param {Object} options * * @return {void} */ async handle ({ name }, options) { const appPath = path.join(process.cwd(), name) const stepsCounter = this.initiateSteps(options.skipInstall ? 5 : 6, options) this.invoke(async () => { this.dumpAsciiLogo() await this._setupProjectDirectory(stepsCounter, appPath, options) process.chdir(appPath) await this._installDependencies(stepsCounter, appPath, options) await this._postInstallation(stepsCounter, appPath) this._onBoardForNewProject(name) }) } } module.exports = NewApp ================================================ FILE: src/Commands/Repl/index.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const fs = require('fs') const os = require('os') const path = require('path') const { Command } = require('../../../lib/ace') const historyFile = path.join(os.homedir(), '/.adonis_repl_history') /** * Start the repl server session * * @class Repl * @constructor */ class Repl extends Command { /** * The command signature used by ace * * @method signature * * @return {String} */ static get signature () { return 'repl' } /** * The command description used by ace * * @method description * * @return {String} */ static get description () { return 'Start a new repl session' } /** * Reads the history file * * @param {Object} repl * * @private */ _readHistoryFile (repl) { try { fs.statSync(historyFile) } catch (error) { fs.closeSync(fs.openSync(historyFile, 'w')) } repl.rli.history = fs.readFileSync(historyFile, 'utf-8').split('\n').reverse() repl.rli.history.shift() repl.rli.historyIndex = -1 } /** * Save the history to the history file. * * @param {Object} repl * * @private */ _addHistorySaveListener (repl) { const fd = fs.openSync(historyFile, 'a') repl.rli.addListener('line', (code) => { if (code && code !== '.history') { fs.write(fd, `${code}\n`, (error) => { if (error) console.log(error) }) return } repl.rli.historyIndex++ repl.rli.history.pop() }) process.on('exit', function () { fs.closeSync(fd) }) } /** * Method executed by ace to start the command line * repl * * @method handle * * @return {void} */ async handle () { const awaitOutside = require('adonis-await-outside') const server = require('repl').start() if (typeof (global.use) === 'undefined') { this.info('You are running repl outside of Adonisjs app') } else { server.context.use = global.use server.context.make = global.make } this._readHistoryFile(server) this._addHistorySaveListener(server) awaitOutside.addAwaitOutsideToReplServer(server) } } module.exports = Repl ================================================ FILE: src/Commands/RouteList/index.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const BaseCommand = require('../Base') /** * Start the repl server session * * @class RouteList * @constructor */ class RouteList extends BaseCommand { static get inject () { return ['Adonis/Src/Route'] } /** * The command signature used by ace * * @method signature * * @return {String} */ static get signature () { return 'route:list' } /** * The command description used by ace * * @method description * * @return {String} */ static get description () { return 'List all registered routes' } constructor (Route) { super() this.Route = Route } /** * Returns stringfied version of a function * * @method _toString * * @param {Function} fn * * @return {String} * * @private */ _toString (fn) { return typeof (fn) === 'string' ? fn : 'Closure' } /** * Returns the route row for the table * * @method _getRow * * @param {Object} route * * @return {Array} */ _getRow (route) { const routeJson = route.toJSON() return [ routeJson.route, routeJson.verbs.join(','), this._toString(routeJson.handler), routeJson.middleware.map((middleware) => this._toString(middleware)).join(','), routeJson.name, routeJson.domain || '' ] } /** * Method executed by ace to list all routes * * @method handle * * @return {void} */ async handle () { this.invoke(async () => { await this.ensureInProjectRoot() this.table( ['Route', 'Verb(s)', 'Handler', 'Middleware', 'Name', 'Domain'], this.Route.list().map(this._getRow.bind(this)) ) }) } } module.exports = RouteList ================================================ FILE: src/Commands/Serve/index.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const path = require('path') const { Command } = require('../../../lib/ace') /** * Serve the application using forever * * @class Serve * @constructor */ class Serve extends Command { /** * The command signature used by ace * * @method signature * * @return {String} */ static get signature () { return ` serve { --dev : Start development server } { -w, --watch=@value : A custom set of only files to watch }, { -e, --ext=@value : A custom set of extensions to watch. In development, they will be merged with the default .js and .json }, { -i, --ignore=@value : A custom set of folders to ignore watching }, { -p, --polling : Use polling to find file changes. Also required when using Docker } { --debug?=@value: Start server in debug mode } ` } /** * The command description used by ace * * @method description * * @return {String} */ static get description () { return 'Start Http server' } /** * Console message when server started * * @method started * * @package {Boolean} dev * * @return {void} */ started (dev, debug) { console.log('') console.log(`${this.chalk.bgGreen.black(' SERVER STARTED ')}`) if (debug) { console.log(`> Visit chrome://inspect to debug your app`) } if (dev) { console.log(`> Watching files for changes...`) } console.log('') } /** * This method is executed when nodemon restarts * * @method onRestart * * @param {Array} files * * @return {void} */ onRestart (files) { if (files.length > 1) { console.log(this.chalk.magenta('File(s) changed')) files.forEach((file) => console.log(file.replace(process.cwd(), '').replace(path.sep, ''))) } else { const fileName = files[0].replace(process.cwd(), '').replace(path.sep, '') console.log(`${this.chalk.magenta('changed')} ${fileName}`) } } /** * Message to log on crash * * @method onCrash * * @return {void} */ onCrash () { this.error('Application crashed, make sure to kill all related running process, fix the issue and re-run the app') } /** * Listening for on quite event * * @method onQuit * * @param {String} domain * * @return {void} */ onQuit () { process.exit(0) } /** * Method executed by ace to start the HTTP server * * @method handle * * @param {Object} args * @param {Boolean} options.dev * * @return {void} */ async handle (args, { dev, watch, debug, ignore, polling, ext }) { const acePath = path.join(process.cwd(), 'ace') const appFile = path.join(process.cwd(), 'server.js') const exists = await this.pathExists(acePath) if (!exists) { this.error('Make sure you are inside an adonisjs app to start the server') return } /** * If user has defined files to watch, then switch to * dev version automatically */ if (watch && typeof (watch) === 'string') { watch = watch.split(',').map((item) => item.trim()) dev = true } /** * The file extensions only when dev mode * is true */ if (dev) { ext = `${ext || ''} js json` } else { ext = ext || 'null' } /** * Directories to watch */ const watchDirs = watch || (dev ? [process.cwd(), '.env'] : []) /** * Custom debug port */ let execJsCommand = 'node' if (debug) { execJsCommand += ' --inspect' if (typeof (debug) === 'string') { execJsCommand += '=' + debug } } const nodemon = require('nodemon') nodemon({ script: appFile, execMap: { js: execJsCommand }, ext: ext, legacyWatch: !!polling, ignore: ['/tmp/*', '/resources/*', '/public/*'].concat(ignore || []).map((folder) => `${process.cwd()}/${folder}`), watch: watchDirs, stdin: false }) this.started(dev, debug) /** * Listeners */ nodemon .on('restart', this.onRestart.bind(this)) .on('crash', this.onCrash.bind(this)) .on('quit', () => (this.onQuit())) } } module.exports = Serve ================================================ FILE: src/Commands/index.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /** * Exporting a list of internal commands * * @type {Array} */ module.exports = { new: require('./New'), addon: require('./Addon'), install: require('./Install'), serve: require('./Serve'), 'key:generate': require('./KeyGenerate'), 'make:controller': require('./Make/Controller'), 'make:model': require('./Make/Model'), 'make:trait': require('./Make/Trait'), 'make:view': require('./Make/View'), 'make:middleware': require('./Make/Middleware'), 'make:command': require('./Make/Command'), 'make:exception': require('./Make/Exception'), 'make:hook': require('./Make/Hook'), 'make:migration': require('./Make/Migration'), 'make:listener': require('./Make/Listener'), 'make:provider': require('./Make/Provider'), 'repl': require('./Repl'), 'make:ehandler': require('./Make/ExceptionHandler'), 'make:seed': require('./Make/Seed'), 'route:list': require('./RouteList'), 'run:instructions': require('./Instructions') } ================================================ FILE: src/Generators/index.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const path = require('path') const _ = require('lodash') const pluralize = require('pluralize') const generators = exports = module.exports = {} generators.provider = { /** * Returns the data to be sent to the provider * template * * @method getData * * @param {String} name * @param {Object} flags * * @return {Object} */ getData (name, flags) { return { name: this.getFileName(name) } }, /** * Returns file name for provider. * * @method getFileName * * @param {String} name * * @return {String} */ getFileName (name) { name = name.replace(/provider/ig, '') return `${pluralize.singular(_.upperFirst(_.camelCase(name)))}Provider` }, /** * Returns path to the provider file * * @method getFilePath * * @param {String} name * @param {Object} options * * @return {String} */ getFilePath (name, options) { const baseName = path.basename(name) const normalizedName = name.replace(baseName, this.getFileName(baseName)) return path.join(options.appRoot, options.dirs.providers, normalizedName) + '.js' } } generators.httpController = { /** * Returns the data to be sent to the controller * template * * @method getData * * @param {String} name * @param {Object} flags * * @return {Object} */ getData (name, flags) { return { name: this.getFileName(name), resource: !!flags.resource, resourceName: this.getResourceName(name), resourceNamePlural: pluralize(this.getResourceName(name)) } }, /** * Returns file name for controller. * * @method getFileName * * @param {String} name * * @return {String} */ getFileName (name) { name = name.replace(/controller/ig, '') return `${pluralize.singular(_.upperFirst(_.camelCase(name)))}Controller` }, /** * Returns name of resource from controller name. * * @method getResourceName * * @param {String} name * * @return {String} */ getResourceName (name) { return this.getFileName(name).replace('Controller', '').toLowerCase() }, /** * Returns path to the controller file * * @method getFilePath * * @param {String} name * @param {Object} options * * @return {String} */ getFilePath (name, options) { const baseName = path.basename(name) const normalizedName = name.replace(baseName, this.getFileName(baseName)) return path.join(options.appRoot, options.appDir, options.dirs.httpControllers, normalizedName) + '.js' } } generators.model = { /** * Returns data object for the model * template file * * @method getData * * @param {String} name * * @return {Object} */ getData (name) { return { name: this.getFileName(name) } }, /** * Returns the model file name * * @method getFileName * * @param {String} name * * @return {String} */ getFileName (name, appPath) { name = name.replace(/model/ig, '') return `${pluralize.singular(_.upperFirst(_.camelCase(name)))}` }, /** * Returns file path to the model file * * @method getFilePath * * @param {String} name * @param {Object} options * * @return {String} */ getFilePath (name, options) { const baseName = path.basename(name) const normalizedName = name.replace(baseName, this.getFileName(baseName)) return path.join(options.appRoot, options.appDir, options.dirs.models, normalizedName) + '.js' } } generators.trait = { /** * Returns data object for the trait * template file * * @method getData * * @param {String} name * * @return {Object} */ getData (name) { return { name: this.getFileName(name) } }, /** * Returns the trait file name * * @method getFileName * * @param {String} name * * @return {String} */ getFileName (name, appPath) { name = name.replace(/trait/ig, '') return `${pluralize.singular(_.upperFirst(_.camelCase(name)))}` }, /** * Returns file path to the trait file * * @method getFilePath * * @param {String} name * @param {Object} options * * @return {String} */ getFilePath (name, options) { const baseName = path.basename(name) const normalizedName = name.replace(baseName, this.getFileName(baseName)) return path.join(options.appRoot, options.appDir, options.dirs.traits, normalizedName) + '.js' } } generators.middleware = { /** * Returns data for the middleware template * * @method getData * * @param {String} name * * @return {Object} */ getData (name, flags) { return { name: this.getFileName(name), http: flags.type === 'http' || flags.type === 'both', ws: flags.type === 'ws' || flags.type === 'both' } }, /** * Returns file name for the middleware file * * @method getFileName * * @param {String} name * * @return {String} */ getFileName (name, appPath) { name = name.replace(/middleware/ig, '') return `${pluralize.singular(_.upperFirst(_.camelCase(name)))}` }, /** * Returns file path for the middleware file * * @method getFilePath * * @param {String} name * @param {Object} options * * @return {String} */ getFilePath (name, options) { const baseName = path.basename(name) const normalizedName = name.replace(baseName, this.getFileName(baseName)) return path.join(options.appRoot, options.appDir, options.dirs.middleware, normalizedName) + '.js' } } generators.hook = { /** * Returns data for the hook template * * @method getData * * @param {String} name * @param {Object} flags * * @return {Object} */ getData (name, flags) { return { name: this.getFileName(name), method: flags.method && typeof (flags.method) === 'string' ? flags.method : 'method' } }, /** * Returns file name for the hook file * * @method getFileName * * @param {String} name * * @return {String} */ getFileName (name, appPath) { name = name.replace(/hook/ig, '') return `${pluralize.singular(_.upperFirst(_.camelCase(name)))}Hook` }, /** * Returns file path for the hook file * * @method getFilePath * * @param {String} name * @param {Object} options * * @return {String} */ getFilePath (name, options) { const baseName = path.basename(name) const normalizedName = name.replace(baseName, this.getFileName(baseName)) return path.join(options.appRoot, options.appDir, options.dirs.hooks, normalizedName) + '.js' } } generators.view = { /** * Returns data for the view template * * @method getData * * @param {String} name * @param {Object} flags * * @return {Object} */ getData (name, flags) { return { layout: flags.layout && typeof (flags.layout) === 'string' ? flags.layout : null } }, /** * Returns file name for the view file * * @method getFileName * * @param {String} name * * @return {String} */ getFileName (name, appPath) { return _.toLower(name).replace(/view/ig, '').replace(/\./g, '/') }, /** * Returns file path for the hook file * * @method getFilePath * * @param {String} name * @param {Object} options * * @return {String} */ getFilePath (name, options) { return path.join(options.appRoot, options.dirs.views, this.getFileName(name)) + '.edge' } } generators.command = { /** * Returns data for the command template * * @method getData * * @param {String} name * @param {Object} flags * * @return {Object} */ getData (name, flags) { return { name: this.getFileName(name), commandName: _.snakeCase(this.getFileName(name)).replace(/_/g, ':') } }, /** * Returns file name for the command file * * @method getFileName * * @param {String} name * * @return {String} */ getFileName (name, appPath) { name = name.replace(/command/ig, '') return pluralize.singular(_.upperFirst(_.camelCase(name))) }, /** * Returns file path for the command file * * @method getFilePath * * @param {String} name * @param {Object} options * * @return {String} */ getFilePath (name, options) { const baseName = path.basename(name) const normalizedName = name.replace(baseName, this.getFileName(baseName)) return path.join(options.appRoot, options.appDir, options.dirs.commands, normalizedName) + '.js' } } generators.schema = { /** * Returns data for the migration schema template * * @method getData * * @param {String} name * @param {Object} flags * * @return {Object} */ getData (name, flags) { name = this.getFileName(name) return { create: flags.action === 'create', table: _.snakeCase(pluralize(name.replace('Schema', ''))), name: name } }, /** * Returns file name for the schema migration file * * @method getFileName * * @param {String} name * * @return {String} */ getFileName (name, appPath) { name = name.replace(/schema|table/ig, '') return `${_.upperFirst(_.camelCase(name))}Schema` }, /** * Returns file path for the schema migration file * * @method getFilePath * * @param {String} name * @param {Object} options * * @return {String} */ getFilePath (name, options) { const fileName = `${new Date().getTime()}_${_.snakeCase(this.getFileName(name))}` return path.join(options.appRoot, options.dirs.migrations, fileName) + '.js' } } generators.listener = { /** * Returns data for the listener template * * @method getData * * @param {String} name * @param {Object} flags * * @return {Object} */ getData (name, flags) { return { name: this.getFileName(name), method: flags.method && typeof (flags.method) === 'string' ? flags.method : 'method' } }, /** * Returns file name for the listener file * * @method getFileName * * @param {String} name * * @return {String} */ getFileName (name, appPath) { name = name.replace(/listener/ig, '') return `${_.upperFirst(_.camelCase(name))}` }, /** * Returns file path for the hook file * * @method getFilePath * * @param {String} name * @param {Object} options * * @return {String} */ getFilePath (name, options) { const baseName = path.basename(name) const normalizedName = name.replace(baseName, this.getFileName(baseName)) return path.join(options.appRoot, options.appDir, options.dirs.listeners, normalizedName) + '.js' } } generators.exceptionHandler = { /** * Returns data for the exception handler template * * @method getData * * @return {Object} */ getData (name, flags) { return flags || {} }, /** * Returns file name for the exception handler file * * @return {String} */ getFileName () { return 'Handler' }, /** * Returns file path for the exception handler file * * @method getFilePath * * @param {String} name * @param {Object} options * * @return {String} */ getFilePath (name, options) { const baseName = path.basename(name) const normalizedName = name.replace(baseName, this.getFileName(baseName)) return path.join(options.appRoot, options.appDir, options.dirs.exceptions, normalizedName) + '.js' } } generators.seed = { /** * Returns data object for the seed * template file * * @method getData * * @param {String} name * * @return {Object} */ getData (name) { return { name: this.getFileName(name) } }, /** * Returns the seed file name * * @method getFileName * * @param {String} name * * @return {String} */ getFileName (name, appPath) { name = name.replace(/seed(er)?/ig, '') return `${pluralize.singular(_.upperFirst(_.camelCase(name)))}Seeder` }, /** * Returns file path to the model file * * @method getFilePath * * @param {String} name * @param {Object} options * * @return {String} */ getFilePath (name, options) { const baseName = path.basename(name) const normalizedName = name.replace(baseName, this.getFileName(baseName)) return path.join(options.appRoot, options.dirs.seeds, normalizedName) + '.js' } } generators.wsController = { /** * Returns the data to be sent to the controller * template * * @method getData * * @param {String} name * * @return {Object} */ getData (name) { return { name: this.getFileName(name) } }, /** * Returns file name for controller. * * @method getFileName * * @param {String} name * * @return {String} */ getFileName (name) { name = name.replace(/controller/ig, '') return `${pluralize.singular(_.upperFirst(_.camelCase(name)))}Controller` }, /** * Returns path to the controller file * * @method getFilePath * * @param {String} name * @param {Object} options * * @return {String} */ getFilePath (name, options) { const baseName = path.basename(name) const normalizedName = name.replace(baseName, this.getFileName(baseName)) return path.join(options.appRoot, options.appDir, options.dirs.wsControllers, normalizedName) + '.js' } } generators.exception = { /** * Returns the data to be sent to the exception * template * * @method getData * * @param {String} name * @param {Object} flags * * @return {Object} */ getData (name, flags) { return { name: this.getFileName(name) } }, /** * Returns file name for exception class. * * @method getFileName * * @param {String} name * * @return {String} */ getFileName (name) { name = name.replace(/exception/ig, '') return `${pluralize.singular(_.upperFirst(_.camelCase(name)))}Exception` }, /** * Returns path to the exception file * * @method getFilePath * * @param {String} name * @param {Object} options * * @return {String} */ getFilePath (name, options) { const baseName = path.basename(name) const normalizedName = name.replace(baseName, this.getFileName(baseName)) return path.join(options.appRoot, options.appDir, options.dirs.exceptions, normalizedName) + '.js' } } ================================================ FILE: src/Generators/templates/command.mustache ================================================ 'use strict' const { Command } = require('@adonisjs/ace') class {{name}} extends Command { static get signature () { return '{{commandName}}' } static get description () { return 'Tell something helpful about this command' } async handle (args, options) { this.info('Dummy implementation for {{commandName}} command') } } module.exports = {{name}} ================================================ FILE: src/Generators/templates/exception.mustache ================================================ 'use strict' const { LogicalException } = require('@adonisjs/generic-exceptions') class {{ name }} extends LogicalException { /** * Handle this exception by itself */ // handle () {} } module.exports = {{ name }} ================================================ FILE: src/Generators/templates/exceptionHandler.mustache ================================================ 'use strict' {{#new}} const BaseExceptionHandler = use('BaseExceptionHandler') /** * This class handles all exceptions thrown during * the HTTP request lifecycle. * * @class ExceptionHandler */ class ExceptionHandler extends BaseExceptionHandler { /** * Handle exception thrown during the HTTP lifecycle * * @method handle * * @param {Object} error * @param {Object} options.request * @param {Object} options.response * * @return {void} */ async handle (error, { request, response }) { response.status(error.status).send(error.message) } /** * Report exception for logging or debugging. * * @method report * * @param {Object} error * @param {Object} options.request * * @return {void} */ async report (error, { request }) { } } {{/new}} {{^new}} /** * This class handles all exceptions thrown during * the HTTP request lifecycle. * * @class ExceptionHandler */ class ExceptionHandler { /** * Handle exception thrown during the HTTP lifecycle * * @method handle * * @param {Object} error * @param {Object} options.request * @param {Object} options.response * * @return {void} */ async handle (error, { request, response }) { response.status(error.status).send(error.message) } /** * Report exception for logging or debugging. * * @method report * * @param {Object} error * @param {Object} options.request * * @return {void} */ async report (error, { request }) { } } {{/new}} module.exports = ExceptionHandler ================================================ FILE: src/Generators/templates/hook.mustache ================================================ 'use strict' const {{name}} = exports = module.exports = {} {{name}}.{{method}} = async (modelInstance) => { } ================================================ FILE: src/Generators/templates/httpController.mustache ================================================ 'use strict' {{#resource}} /** @typedef {import('@adonisjs/framework/src/Request')} Request */ /** @typedef {import('@adonisjs/framework/src/Response')} Response */ /** @typedef {import('@adonisjs/framework/src/View')} View */ /** * Resourceful controller for interacting with {{resourceNamePlural}} */ {{/resource}} class {{name}} { {{#resource}} /** * Show a list of all {{resourceNamePlural}}. * GET {{resourceNamePlural}} * * @param {object} ctx * @param {Request} ctx.request * @param {Response} ctx.response * @param {View} ctx.view */ async index ({ request, response, view }) { } /** * Render a form to be used for creating a new {{resourceName}}. * GET {{resourceNamePlural}}/create * * @param {object} ctx * @param {Request} ctx.request * @param {Response} ctx.response * @param {View} ctx.view */ async create ({ request, response, view }) { } /** * Create/save a new {{resourceName}}. * POST {{resourceNamePlural}} * * @param {object} ctx * @param {Request} ctx.request * @param {Response} ctx.response */ async store ({ request, response }) { } /** * Display a single {{resourceName}}. * GET {{resourceNamePlural}}/:id * * @param {object} ctx * @param {Request} ctx.request * @param {Response} ctx.response * @param {View} ctx.view */ async show ({ params, request, response, view }) { } /** * Render a form to update an existing {{resourceName}}. * GET {{resourceNamePlural}}/:id/edit * * @param {object} ctx * @param {Request} ctx.request * @param {Response} ctx.response * @param {View} ctx.view */ async edit ({ params, request, response, view }) { } /** * Update {{resourceName}} details. * PUT or PATCH {{resourceNamePlural}}/:id * * @param {object} ctx * @param {Request} ctx.request * @param {Response} ctx.response */ async update ({ params, request, response }) { } /** * Delete a {{resourceName}} with id. * DELETE {{resourceNamePlural}}/:id * * @param {object} ctx * @param {Request} ctx.request * @param {Response} ctx.response */ async destroy ({ params, request, response }) { } {{/resource}} } module.exports = {{name}} ================================================ FILE: src/Generators/templates/listener.mustache ================================================ 'use strict' const {{name}} = exports = module.exports = {} {{name}}.{{method}} = async () => { } ================================================ FILE: src/Generators/templates/middleware.mustache ================================================ 'use strict' /** @typedef {import('@adonisjs/framework/src/Request')} Request */ /** @typedef {import('@adonisjs/framework/src/Response')} Response */ /** @typedef {import('@adonisjs/framework/src/View')} View */ class {{name}} { {{#http}} /** * @param {object} ctx * @param {Request} ctx.request * @param {Function} next */ async handle ({ request }, next) { // call next to advance the request await next() } {{/http}} {{#ws}} /** * @param {object} ctx * @param {Request} ctx.request * @param {Function} next */ async wsHandle ({ request }, next) { // call next to advance the request await next() } {{/ws}} } module.exports = {{name}} ================================================ FILE: src/Generators/templates/model.mustache ================================================ 'use strict' /** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */ const Model = use('Model') class {{name}} extends Model { } module.exports = {{name}} ================================================ FILE: src/Generators/templates/provider.mustache ================================================ 'use strict' const { ServiceProvider } = require('@adonisjs/fold') class {{name}} extends ServiceProvider { /** * Register namespaces to the IoC container * * @method register * * @return {void} */ register () { // } /** * Attach context getter when all providers have * been registered * * @method boot * * @return {void} */ boot () { // } } module.exports = {{name}} ================================================ FILE: src/Generators/templates/schema.mustache ================================================ 'use strict' /** @type {import('@adonisjs/lucid/src/Schema')} */ const Schema = use('Schema') class {{ name }} extends Schema { {{#create}} up () { this.create('{{ table }}', (table) => { table.increments() table.timestamps() }) } down () { this.drop('{{ table }}') } {{/create}} {{^create}} up () { this.table('{{ table }}', (table) => { // alter table }) } down () { this.table('{{ table }}', (table) => { // reverse alternations }) } {{/create}} } module.exports = {{ name }} ================================================ FILE: src/Generators/templates/seed.mustache ================================================ 'use strict' /* |-------------------------------------------------------------------------- | {{name}} |-------------------------------------------------------------------------- | | Make use of the Factory instance to seed database with dummy data or | make use of Lucid models directly. | */ /** @type {import('@adonisjs/lucid/src/Factory')} */ const Factory = use('Factory') class {{name}} { async run () { } } module.exports = {{name}} ================================================ FILE: src/Generators/templates/trait.mustache ================================================ 'use strict' class {{name}} { register (Model, customOptions = {}) { const defaultOptions = {} const options = Object.assign(defaultOptions, customOptions) } } module.exports = {{name}} ================================================ FILE: src/Generators/templates/view.mustache ================================================ {{#layout}} @layout('{{layout}}') {{/layout}} ================================================ FILE: src/Generators/templates/wsController.mustache ================================================ 'use strict' class {{name}} { constructor ({ socket, request }) { this.socket = socket this.request = request } } module.exports = {{name}} ================================================ FILE: src/Services/check-node-version.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const semver = require('semver') const requiredNodeVersion = '>=8.0.0' const requiredNodeVersionNumber = 8 const requiredNpmVersion = '>=3.0.0' const requiredNpmVersionNumber = 3 /** * This step checks the Node.js and npm version * installed on user machine. It will print * some messages on the console but also * throws an exception to abort the * process * * @async * * @param {Object} stepsCounter * * @return {void} */ module.exports = async function (stepsCounter) { const step = stepsCounter.advance('Verifying requirements', 'microscope', 'node & npm') step.start() /** * Verify Node.js version. * * Uses `semver.parse` instead of `semver.satisfies` to support prereleases * version of Node.js. */ const nodeVersion = process.version if (semver.parse(nodeVersion).major < requiredNodeVersionNumber) { step.error('Unsupported Node.js version', 'x') throw new Error(`Unsatisfied Node.js version ${nodeVersion}. Please update Node.js to ${requiredNodeVersion} before you continue`) } /** * Verify npm version. * * Uses `semver.parse` instead of `semver.satisfies` to support prereleases * version of npm. */ const npmVersion = (await require('./exec')('npm -v')).trim() if (semver.parse(npmVersion).major < requiredNpmVersionNumber) { step.error('Unsupported npm version', 'x') throw new Error(`Unsatisfied npm version ${npmVersion}. Please update npm to ${requiredNpmVersion} before you continue`) } step.success('Requirements matched') } ================================================ FILE: src/Services/clone.js ================================================ 'use strict' /** * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const debug = require('debug')('adonis:cli') const isGitUrl = require('is-git-url') /** * This module clones a given github repo and branch. * * @method * * @param {String} blueprint * @param {String} appPath * @param {Object} stepsCounter * @param {String} [branch = null] * * @return {void} */ module.exports = async function (blueprint, appPath, stepsCounter, branch = null) { const step = stepsCounter.advance('Cloning project blueprint', 'inbox_tray', blueprint) step.start() let cloneCommand = 'git clone --depth=1' /** * Add branch flag when branch is defined */ if (branch) { cloneCommand = `${cloneCommand} --branch ${branch}` } // complete the clone command // check if ths a full .git path if (isGitUrl(blueprint)) { cloneCommand = `${cloneCommand} ${blueprint} "${appPath}"` } else { cloneCommand = `${cloneCommand} https://github.com/${blueprint}.git "${appPath}"` } debug('clone command %s', cloneCommand) try { await require('./exec')(cloneCommand) step.success('Cloned') } catch (error) { step.error('Unable to clone repo', 'x') throw error } } ================================================ FILE: src/Services/copy-env-file.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const path = require('path') const fs = require('fs-extra') /** * This module copies the `.env.example` file to `.env`. * * @method * * @param {String} appPath * @param {Function} copy * @param {Object} stepsCounter * * @return {void} */ module.exports = async function (appPath, stepsCounter) { const step = stepsCounter.advance('Copying default environment variables', 'open_book', '.env') step.start() try { await fs.copy(path.join(appPath, '.env.example'), path.join(appPath, '.env')) step.success('Environment variables copied') } catch (error) { step.error('Unable to copy environment variables', 'x') throw error } } ================================================ FILE: src/Services/exec.js ================================================ 'use strict' /** * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const exec = require('util').promisify(require('child_process').exec) module.exports = async function (command) { const { stdout } = await exec(command) return stdout } ================================================ FILE: src/Services/generate-app-key.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /** * Generates the app key by executing key:generate * ace comamnd. * * @method * * @param {Object} stepsCounter * * @return {void} */ module.exports = async function (stepsCounter) { const step = stepsCounter.advance('Generating APP_KEY', 'key', 'adonis key:generate') step.start() try { await require('./exec')('adonis key:generate') step.success('Key generated') } catch (error) { step.error('Unable to generate key', 'x') error.hint = 'You can continue manually by running adonis key:generate' throw error } } ================================================ FILE: src/Services/install.js ================================================ 'use strict' /** * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /** * Install dependencies from npm or yarn. The installation * tool must be installed on user machine * * @method * * @param {String} via * @param {Object} stepsCounter * @param {String} [packageName = ''] * * @return {void} */ module.exports = async function (via, stepsCounter, packageName) { const command = via === 'npm' ? (packageName ? `npm i --save ${packageName}@legacy` : 'npm install') : (packageName ? `yarn add ${packageName}@legacy` : 'yarn') const message = packageName ? `${via}: Installing` : `${via}: Installing project dependencies` const step = stepsCounter.advance(message, 'package', packageName) step.start() try { await require('./exec')(command) step.success('Dependencies installed') } catch (error) { step.error('Installation failed', 'x') error.hint = `You can manually install dependencies by running ${command}` throw error } } ================================================ FILE: src/Services/render-instructions-md.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const path = require('path') const os = require('os') const opn = require('opn') const fs = require('fs-extra') const marked = require('marked') const debug = require('debug')('adonis:cli') const css = `.markdown-body hr::after,.markdown-body::after{clear:both}body{box-sizing:border-box;min-width:200px;max-width:980px;margin:0 auto;padding:45px}.markdown-body{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;color:#24292e;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:16px;line-height:1.5;word-wrap:break-word}.markdown-body .pl-c{color:#6a737d}.markdown-body .pl-c1,.markdown-body .pl-s .pl-v{color:#005cc5}.markdown-body .pl-e,.markdown-body .pl-en{color:#6f42c1}.markdown-body .pl-s .pl-s1,.markdown-body .pl-smi{color:#24292e}.markdown-body .pl-ent{color:#22863a}.markdown-body .pl-k{color:#d73a49}.markdown-body .pl-pds,.markdown-body .pl-s,.markdown-body .pl-s .pl-pse .pl-s1,.markdown-body .pl-sr,.markdown-body .pl-sr .pl-cce,.markdown-body .pl-sr .pl-sra,.markdown-body .pl-sr .pl-sre{color:#032f62}.markdown-body .pl-smw,.markdown-body .pl-v{color:#e36209}.markdown-body .pl-bu{color:#b31d28}.markdown-body .pl-ii{color:#fafbfc;background-color:#b31d28}.markdown-body .pl-c2{color:#fafbfc;background-color:#d73a49}.markdown-body .pl-sr .pl-cce{font-weight:700;color:#22863a}.markdown-body .pl-ml{color:#735c0f}.markdown-body .pl-mh,.markdown-body .pl-mh .pl-en,.markdown-body .pl-ms{font-weight:700;color:#005cc5}.markdown-body .pl-mi{font-style:italic;color:#24292e}.markdown-body .pl-mb{font-weight:700;color:#24292e}.markdown-body .pl-md{color:#b31d28;background-color:#ffeef0}.markdown-body .pl-mi1{color:#22863a;background-color:#f0fff4}.markdown-body .pl-mc{color:#e36209;background-color:#ffebda}.markdown-body .pl-mi2{color:#f6f8fa;background-color:#005cc5}.markdown-body .pl-mdr{font-weight:700;color:#6f42c1}.markdown-body .pl-ba{color:#586069}.markdown-body .pl-sg{color:#959da5}.markdown-body .pl-corl{text-decoration:underline;color:#032f62}.markdown-body .octicon{display:inline-block;fill:currentColor;vertical-align:text-bottom}.markdown-body hr::after,.markdown-body hr::before,.markdown-body::after,.markdown-body::before{display:table;content:""}.markdown-body a{background-color:transparent;-webkit-text-decoration-skip:objects;color:#0366d6;text-decoration:none}.markdown-body a:active,.markdown-body a:hover{outline-width:0}.markdown-body h1{margin:.67em 0}.markdown-body img{border-style:none}.markdown-body svg:not(:root){overflow:hidden}.markdown-body hr{box-sizing:content-box}.markdown-body input{font:inherit;margin:0;overflow:visible;font-family:inherit;font-size:inherit;line-height:inherit}.markdown-body [type=checkbox]{box-sizing:border-box;padding:0}.markdown-body *{box-sizing:border-box}.markdown-body a:hover{text-decoration:underline}.markdown-body strong{font-weight:600}.markdown-body td,.markdown-body th{padding:0}.markdown-body blockquote{margin:0}.markdown-body ol ol,.markdown-body ul ol{list-style-type:lower-roman}.markdown-body ol ol ol,.markdown-body ol ul ol,.markdown-body ul ol ol,.markdown-body ul ul ol{list-style-type:lower-alpha}.markdown-body dd{margin-left:0}.markdown-body code{font-family:SFMono-Regular,Consolas,"Liberation Mono",Menlo,Courier,monospace}.markdown-body pre{font:12px SFMono-Regular,Consolas,"Liberation Mono",Menlo,Courier,monospace;word-wrap:normal}.markdown-body .pl-0{padding-left:0!important}.markdown-body .pl-1{padding-left:4px!important}.markdown-body .pl-2{padding-left:8px!important}.markdown-body .pl-3{padding-left:16px!important}.markdown-body .pl-4{padding-left:24px!important}.markdown-body .pl-5{padding-left:32px!important}.markdown-body .pl-6{padding-left:40px!important}.markdown-body>:first-child{margin-top:0!important}.markdown-body>:last-child{margin-bottom:0!important}.markdown-body a:not([href]){color:inherit;text-decoration:none}.markdown-body .anchor{float:left;padding-right:4px;margin-left:-20px;line-height:1}.markdown-body .anchor:focus{outline:0}.markdown-body blockquote,.markdown-body dl,.markdown-body ol,.markdown-body p,.markdown-body pre,.markdown-body table,.markdown-body ul{margin-top:0;margin-bottom:16px}.markdown-body hr{overflow:hidden;background:#e1e4e8;height:.25em;padding:0;margin:24px 0;border:0}.markdown-body blockquote{padding:0 1em;color:#6a737d;border-left:.25em solid #dfe2e5}.markdown-body h1,.markdown-body h2{padding-bottom:.3em;border-bottom:1px solid #eaecef}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:24px;margin-bottom:16px;font-weight:600;line-height:1.25}.markdown-body h1 .octicon-link,.markdown-body h2 .octicon-link,.markdown-body h3 .octicon-link,.markdown-body h4 .octicon-link,.markdown-body h5 .octicon-link,.markdown-body h6 .octicon-link{color:#1b1f23;vertical-align:middle;visibility:hidden}.markdown-body h1:hover .anchor,.markdown-body h2:hover .anchor,.markdown-body h3:hover .anchor,.markdown-body h4:hover .anchor,.markdown-body h5:hover .anchor,.markdown-body h6:hover .anchor{text-decoration:none}.markdown-body h1:hover .anchor .octicon-link,.markdown-body h2:hover .anchor .octicon-link,.markdown-body h3:hover .anchor .octicon-link,.markdown-body h4:hover .anchor .octicon-link,.markdown-body h5:hover .anchor .octicon-link,.markdown-body h6:hover .anchor .octicon-link{visibility:visible}.markdown-body h1{font-size:2em}.markdown-body h2{font-size:1.5em}.markdown-body h3{font-size:1.25em}.markdown-body h4{font-size:1em}.markdown-body h5{font-size:.875em}.markdown-body h6{font-size:.85em;color:#6a737d}.markdown-body ol,.markdown-body ul{padding-left:2em}.markdown-body ol ol,.markdown-body ol ul,.markdown-body ul ol,.markdown-body ul ul{margin-top:0;margin-bottom:0}.markdown-body li>p{margin-top:16px}.markdown-body li+li{margin-top:.25em}.markdown-body dl{padding:0}.markdown-body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:600}.markdown-body dl dd{padding:0 16px;margin-bottom:16px}.markdown-body table{border-spacing:0;border-collapse:collapse;display:block;width:100%;overflow:auto}.markdown-body table th{font-weight:600}.markdown-body table td,.markdown-body table th{padding:6px 13px;border:1px solid #dfe2e5}.markdown-body table tr{background-color:#fff;border-top:1px solid #c6cbd1}.markdown-body table tr:nth-child(2n){background-color:#f6f8fa}.markdown-body img{max-width:100%;box-sizing:content-box;background-color:#fff}.markdown-body code{padding:.2em 0;margin:0;font-size:85%;background-color:rgba(27,31,35,.05);border-radius:3px}.markdown-body code::after,.markdown-body code::before{letter-spacing:-.2em}.markdown-body pre>code{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;background:0 0;border:0}.markdown-body .highlight{margin-bottom:16px}.markdown-body .highlight pre{margin-bottom:0;word-break:normal}.markdown-body .highlight pre,.markdown-body pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f6f8fa;border-radius:3px}.markdown-body pre code{display:inline;max-width:auto;padding:0;margin:0;overflow:visible;line-height:inherit;word-wrap:normal;background-color:transparent;border:0}.markdown-body pre code::after,.markdown-body pre code::before{content:normal}.markdown-body .full-commit .btn-outline:not(:disabled):hover{color:#005cc5;border-color:#005cc5}.markdown-body kbd{display:inline-block;padding:3px 5px;font:11px SFMono-Regular,Consolas,"Liberation Mono",Menlo,Courier,monospace;line-height:10px;color:#444d56;vertical-align:middle;background-color:#fafbfc;border:1px solid #d1d5da;border-bottom-color:#c6cbd1;border-radius:3px;box-shadow:inset 0 -1px 0 #c6cbd1}.markdown-body :checked+.radio-label{position:relative;z-index:1;border-color:#0366d6}.markdown-body .task-list-item{list-style-type:none}.markdown-body .task-list-item+.task-list-item{margin-top:3px}.markdown-body .task-list-item input{margin:0 .2em .25em -1.6em;vertical-align:middle}.markdown-body hr{border-bottom-color:#eee}` /** * Returns the html to be saved inside tmp file * and show it to the user * * @method html * * @param {String} css * @param {String} moduleName * @param {String} content * * @return {String} */ const html = function (css, moduleName, content) { return ` ` } /** * Render instructions.md file by converting it to * HTML and serving by tmp dir. * * @method * * @param {String} modulePath * @param {String} moduleName * * @return {void} */ module.exports = async function (modulePath, moduleName) { try { const instructions = await fs.readFile(path.join(modulePath, 'instructions.md'), 'utf-8') debug('found instructions.md file for %s', modulePath) /** * Converting instructions markdown to html */ const content = marked(instructions) /** * Creating html document */ const htmlDocument = html(css, moduleName, content) /** * Generating path to tmp file */ const tmpFile = path.join(os.tmpdir(), `${new Date().getTime()}.html`) /** * Writing to tmp file */ await fs.outputFile(tmpFile, htmlDocument) /** * Opening file */ await opn(tmpFile, { wait: false }) } catch (error) { // ignore error since it's not helpful for enduser } } ================================================ FILE: src/Services/run-instructions.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const path = require('path') const fs = require('fs-extra') const debug = require('debug')('adonis:cli') /** * Executes the instructions file only if it * exists * * @method * @async * * @param {Object} ctx * @param {String} modulePath * * @return {void} */ module.exports = async function (ctx, modulePath) { const instructionsFilePath = path.join(modulePath, 'instructions.js') const hasInstructionsFile = await fs.pathExists(instructionsFilePath) if (!hasInstructionsFile) { return } try { debug('found instructions.js file for %s', modulePath) const instructions = require(instructionsFilePath) if (typeof (instructions) === 'function') { await instructions(ctx) } } catch (error) { error.message = `instructions.js: ${error.message}` throw error } } ================================================ FILE: src/Services/verify-existing-folder.js ================================================ 'use strict' /** * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const path = require('path') const readDir = require('util').promisify(require('fs').readdir) /** * Verifies that the installation folder is empty * or should not exists. Otherwise throws an * exception * * @method * * @param {String} appPath * @param {Object} stepsCounter * * @return {void} */ module.exports = async function (appPath, stepsCounter) { const name = path.basename(appPath) const step = stepsCounter.advance('Ensuring project directory is clean', 'flashlight', name) step.start() try { const files = await readDir(appPath) if (files.length > 0) { step.error('Directory is not empty', 'x') throw new Error(`Cannot override contents of [${name}]. Make sure to delete it or specify a new path`) } } catch (error) { if (error.code !== 'ENOENT') { throw error } } step.success() } ================================================ FILE: test/clone.spec.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const test = require('japa') const path = require('path') const fs = require('fs-extra') const Steps = require('cli-step') const clone = require('../src/Services/clone') test.group('New | Steps | clone', (group) => { group.after(async () => { await fs.remove(path.join(__dirname, './yardstick-app')) await fs.remove(path.join(__dirname, './yardstick')) }) test('throw error when cannot clone repo', async (assert) => { const appPath = path.join(__dirname, './yardstick') assert.plan(1) const stepsCounter = new Steps(1) try { process.env.GIT_TERMINAL_PROMPT = 0 await clone('adonisjs/foo-app', appPath, stepsCounter) } catch ({ message }) { assert.isDefined(message) } }).timeout(0) test('clone repo when it exists', async (assert) => { const appPath = path.join(__dirname, './yardstick') const stepsCounter = new Steps(1) await clone('adonisjs/adonis-app', appPath, stepsCounter) await fs.pathExists(appPath) await fs.remove(appPath) }).timeout(0) test('clone repo with specific branch', async (assert) => { const appPath = path.join(__dirname, './yardstick-app') const stepsCounter = new Steps(1) await clone('adonisjs/adonis-app', appPath, stepsCounter, 'develop') await fs.pathExists(appPath) process.chdir(appPath) const branch = await require('../src/Services/exec')('git branch') assert.equal(branch.replace('*', '').trim(), 'develop') process.chdir(__dirname) }).timeout(0) }) ================================================ FILE: test/copy-env-file.spec.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const test = require('japa') const path = require('path') const fs = require('fs-extra') const Steps = require('cli-step') const copyEnvFile = require('../src/Services/copy-env-file') test.group('New | Steps | copy env file', (group) => { group.after(async () => { await fs.remove(path.join(__dirname, './yardstick-app')) await fs.remove(path.join(__dirname, './yardstick')) }) test('Copy env.example to .env', async (assert) => { const appPath = path.join(__dirname, './yardstick') await fs.ensureFile(path.join(appPath, '.env.example')) const stepsCounter = new Steps(1) process.chdir(appPath) await copyEnvFile(appPath, stepsCounter) await fs.pathExists(path.join(appPath, '.env')) await fs.remove(path.join(appPath, '.env')) await fs.remove(path.join(appPath, '.env.example')) process.chdir(__dirname) }).timeout(0) }) ================================================ FILE: test/generators.spec.js ================================================ 'use strict' /* * adonis-auth * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const path = require('path') const test = require('japa') const generators = require('../src/Generators') const OPTS = { appRoot: __dirname, appDir: 'app', dirs: { httpControllers: 'Controllers/Http', wsControllers: 'Controllers/Ws', models: 'Models', traits: 'Models/Traits', hooks: 'Models/Hooks', listeners: 'Listeners', exceptions: 'Exceptions', middleware: 'Middleware', commands: 'Commands', views: 'resources/views', migrations: 'database/migrations', seeds: 'database/seeds', providers: 'providers' } } test.group('Generators', () => { test('get path to the provider file', (assert) => { const filePath = generators.provider.getFilePath('Event', OPTS) assert.equal(filePath, path.join(__dirname, 'providers', 'EventProvider.js')) }) test('make provider file singular', (assert) => { const filePath = generators.provider.getFilePath('Events', OPTS) assert.equal(filePath, path.join(__dirname, 'providers', 'EventProvider.js')) }) test('normalize provider keyword', (assert) => { const filePath = generators.provider.getFilePath('EventProvider', OPTS) assert.equal(filePath, path.join(__dirname, 'providers', 'EventProvider.js')) }) test('get path to the controller file', (assert) => { const filePath = generators.httpController.getFilePath('User', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Controllers/Http', 'UserController.js')) }) test('make controller file singular', (assert) => { const filePath = generators.httpController.getFilePath('Users', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Controllers/Http', 'UserController.js')) }) test('normalize controller keyword', (assert) => { const filePath = generators.httpController.getFilePath('UsersController', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Controllers/Http', 'UserController.js')) }) test('get data for the controller', (assert) => { const data = generators.httpController.getData('User', {}) assert.deepEqual(data, { name: 'UserController', resource: false, resourceName: 'user', resourceNamePlural: 'users' }) }) test('get path to the model file', (assert) => { const filePath = generators.model.getFilePath('User', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Models', 'User.js')) }) test('singularize model name', (assert) => { const filePath = generators.model.getFilePath('Users', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Models', 'User.js')) }) test('normalize model name', (assert) => { const filePath = generators.model.getFilePath('UsersModel', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Models', 'User.js')) }) test('get data for model', (assert) => { const data = generators.model.getData('UsersModel', {}) assert.deepEqual(data, { name: 'User' }) }) test('get path to the trait file', (assert) => { const filePath = generators.trait.getFilePath('Attachable', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Models/Traits', 'Attachable.js')) }) test('singularize trait name', (assert) => { const filePath = generators.trait.getFilePath('Attachables', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Models/Traits', 'Attachable.js')) }) test('normalize trait name', (assert) => { const filePath = generators.trait.getFilePath('AttachablesTrait', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Models/Traits', 'Attachable.js')) }) test('get data for trait', (assert) => { const data = generators.trait.getData('AttachablesTrait', {}) assert.deepEqual(data, { name: 'Attachable' }) }) test('get path to the middleware file', (assert) => { const filePath = generators.middleware.getFilePath('User', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Middleware', 'User.js')) }) test('keep middleware singular', (assert) => { const filePath = generators.middleware.getFilePath('Users', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Middleware', 'User.js')) }) test('normalize middleware name', (assert) => { const filePath = generators.middleware.getFilePath('UsersMiddleware', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Middleware', 'User.js')) }) test('get middleware data', (assert) => { const data = generators.middleware.getData('UsersMiddleware', {}) assert.deepEqual(data, { name: 'User', http: false, ws: false }) }) test('get path to the hooks file', (assert) => { const filePath = generators.hook.getFilePath('User', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Models/Hooks', 'UserHook.js')) }) test('keep hook name singular', (assert) => { const filePath = generators.hook.getFilePath('Users', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Models/Hooks', 'UserHook.js')) }) test('normalize hook name', (assert) => { const filePath = generators.hook.getFilePath('Users_Hook', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Models/Hooks', 'UserHook.js')) }) test('get data for hook', (assert) => { const data = generators.hook.getData('Users_Hook', {}) assert.deepEqual(data, { name: 'UserHook', method: 'method' }) }) test('use method name passed to flags', (assert) => { const data = generators.hook.getData('Users_Hook', { method: 'validatePassword' }) assert.deepEqual(data, { name: 'UserHook', method: 'validatePassword' }) }) test('get path to the view file', (assert) => { const filePath = generators.view.getFilePath('User', OPTS) assert.equal(filePath, path.join(__dirname, 'resources/views', 'user.edge')) }) test('get path to nested view file', (assert) => { const filePath = generators.view.getFilePath('users.list', OPTS) assert.equal(filePath, path.join(__dirname, 'resources/views', 'users/list.edge')) }) test('get data for the view', (assert) => { const data = generators.view.getData('users.list', {}) assert.deepEqual(data, { layout: null }) }) test('set layout on data', (assert) => { const data = generators.view.getData('users.list', { layout: 'master' }) assert.deepEqual(data, { layout: 'master' }) }) test('get path to the command file', (assert) => { const filePath = generators.command.getFilePath('makeTemplate', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Commands', 'MakeTemplate.js')) }) test('keep command name singular', (assert) => { const filePath = generators.command.getFilePath('makeTemplates', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Commands', 'MakeTemplate.js')) }) test('normalize command name', (assert) => { const filePath = generators.command.getFilePath('makeTemplateCommand', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Commands', 'MakeTemplate.js')) }) test('get data for command', (assert) => { const data = generators.command.getData('makeTemplate', {}) assert.deepEqual(data, { name: 'MakeTemplate', commandName: 'make:template' }) }) test('get path to the schema file', (assert) => { const filePath = generators.schema.getFilePath('users', OPTS) assert.include(filePath, '_users_schema.js') }) test('get data for schema', (assert) => { const data = generators.schema.getData('users', {}) assert.deepEqual(data, { create: false, table: 'users', name: 'UsersSchema' }) }) test('pluralize table name', (assert) => { const data = generators.schema.getData('user', {}) assert.deepEqual(data, { create: false, table: 'users', name: 'UserSchema' }) }) test('snake case table name', (assert) => { const data = generators.schema.getData('UserProfile', {}) assert.deepEqual(data, { create: false, table: 'user_profiles', name: 'UserProfileSchema' }) }) test('get path to the listener file', (assert) => { const filePath = generators.listener.getFilePath('Http', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Listeners', 'Http.js')) }) test('normalize listener name', (assert) => { const filePath = generators.listener.getFilePath('on_http', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Listeners', 'OnHttp.js')) }) test('get data for listener', (assert) => { const data = generators.listener.getData('on_http', { method: 'start' }) assert.deepEqual(data, { name: 'OnHttp', method: 'start' }) }) test('get path to the seed file', (assert) => { const filePath = generators.seed.getFilePath('Database', OPTS) assert.equal(filePath, path.join(__dirname, 'database/seeds', 'DatabaseSeeder.js')) }) test('normalize seeder name', (assert) => { const filePath = generators.seed.getFilePath('DatabaseSeeder', OPTS) assert.equal(filePath, path.join(__dirname, 'database/seeds', 'DatabaseSeeder.js')) }) test('get data for seed', (assert) => { const data = generators.seed.getData('DatabaseSeeder', {}) assert.deepEqual(data, { name: 'DatabaseSeeder' }) }) test('get path to nested controller file', (assert) => { const filePath = generators.httpController.getFilePath('Admin/UserController', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Controllers/Http/Admin', 'UserController.js')) }) test('get path to exception file', (assert) => { const filePath = generators.exception.getFilePath('Validation', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Exceptions', 'ValidationException.js')) }) test('normalize exception file path', (assert) => { const filePath = generators.exception.getFilePath('ValidationException', OPTS) assert.equal(filePath, path.join(__dirname, 'app/Exceptions', 'ValidationException.js')) }) }) ================================================ FILE: test/install.spec.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const test = require('japa') const path = require('path') const fs = require('fs-extra') const Steps = require('cli-step') const BASE_PATH = path.join(__dirname, 'dummyProject') if (process.platform !== 'win32') { test.group('Install | Command', (group) => { group.before(async () => { await fs.ensureDir(BASE_PATH) await fs.outputJSON(path.join(BASE_PATH, 'package.json'), { name: 'dummy-project' }) }) group.afterEach(async () => { await fs.emptyDir(BASE_PATH) }) group.after(async () => { await fs.remove(BASE_PATH) }) test('install a package from npm', async (assert) => { process.chdir(BASE_PATH) const stepsCounter = new Steps(1) await require('../src/Services/install')('npm', stepsCounter, '@adonisjs/session') const exists = await fs.exists(path.join(BASE_PATH, 'node_modules/@adonisjs/session')) assert.isTrue(exists) }).timeout(0) test('throw exception when unable to install package', async (assert) => { assert.plan(2) process.chdir(BASE_PATH) const stepsCounter = new Steps(1) try { await require('../src/Services/install')('npm', stepsCounter, '@adonisjs/foo') } catch (error) { const exists = await fs.exists(path.join(BASE_PATH, 'node_modules/@adonisjs/foo')) assert.isFalse(exists) assert.include(error.message, 'npm ERR! code E404') } }).timeout(0) }) } ================================================ FILE: test/new.spec.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const test = require('japa') const path = require('path') const ace = require('@adonisjs/ace') const fs = require('fs-extra') const NewCommand = require('../src/Commands/New') /** * Ignoring tests in windows, since appveyor has * weird file permission issues */ test.group('New | Command', (group) => { group.before(() => { process.chdir(__dirname) }) group.after(async () => { await fs.remove(path.join(__dirname, './yardstick-app')) await fs.remove(path.join(__dirname, './yardstick')) }) group.beforeEach(() => { ace.commands = {} }) test('set default blueprint to fullstack app', async (assert) => { const newCommand = new NewCommand() assert.equal(newCommand._getBluePrint({}), 'adonisjs/adonis-fullstack-app') }) test('update blueprint when --api-only flag is defined', async (assert) => { const newCommand = new NewCommand() assert.equal(newCommand._getBluePrint({ apiOnly: true }), 'adonisjs/adonis-api-app') }) test('update blueprint when --slim flag is defined', async (assert) => { const newCommand = new NewCommand() assert.equal(newCommand._getBluePrint({ slim: true }), 'adonisjs/adonis-slim-app') }) test('give priority to api-only over slim', async (assert) => { const newCommand = new NewCommand() assert.equal(newCommand._getBluePrint({ slim: true, apiOnly: true }), 'adonisjs/adonis-api-app') }) test('give priority to blueprint over everything', async (assert) => { const newCommand = new NewCommand() assert.equal(newCommand._getBluePrint({ slim: true, apiOnly: true, 'blueprint': 'adonuxt' }), 'adonuxt') }) }) ================================================ FILE: test/run-instructions.spec.js ================================================ /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const test = require('japa') const path = require('path') const ace = require('../lib/ace') const { Helpers, setupResolver } = require('@adonisjs/sink') const fs = require('fs-extra') const clearRequire = require('clear-require') const BASE_PATH = path.join(__dirname, 'dummyProject') const Context = require('../src/Commands/Instructions/Context') /** * Writes the instructions file to the `BASE_PATH`. * @param {String} contents */ const writeInstructionsJs = function (contents) { return fs.writeFile(path.join(BASE_PATH, 'instructions.js'), contents) } /** * Gives a new instance of contents * * @returns Context */ const getContext = function () { const command = new ace.Command() return new Context(command, new Helpers(BASE_PATH)) } if (process.platform !== 'win32') { test.group('Run instructions', (group) => { group.before(async () => { setupResolver() await fs.ensureDir(BASE_PATH) }) group.afterEach(async () => { clearRequire(path.join(BASE_PATH, 'instructions.js')) await fs.emptyDir(BASE_PATH) }) group.after(async () => { await fs.remove(BASE_PATH) }) group.beforeEach(() => { process.chdir(BASE_PATH) ace.commands = {} }) test('run instructions', async (assert) => { await writeInstructionsJs(` module.exports = async function (cli) { cli.executed = true }`) const ctx = getContext() await require('../src/Services/run-instructions')(ctx, BASE_PATH) assert.isTrue(ctx.executed) }).timeout(0) test('save config file via instructions', async (assert) => { const sessionTemplate = ` module.exports = { driver: 'cookie' } ` await fs.writeFile(path.join(BASE_PATH, 'session.mustache'), sessionTemplate) await writeInstructionsJs(` const path = require('path') module.exports = async function (cli) { await cli.makeConfig('session.js', path.join(__dirname, './session.mustache')) } `) await require('../src/Services/run-instructions')(getContext(), BASE_PATH) require(path.join(BASE_PATH, 'config/session.js')) }).timeout(0) test('throw exceptions of instructions file', async (assert) => { assert.plan(1) await writeInstructionsJs(` const path = require('path') module.exports = async function (cli) { cli.foo() }`) try { await require('../src/Services/run-instructions')(getContext(), BASE_PATH) } catch ({ message }) { assert.equal(message, 'instructions.js: cli.foo is not a function') } }).timeout(0) test('instructions call ace commands', async (assert) => { await writeInstructionsJs(` module.exports = async function (cli) { await cli.callCommand('make:model', { name: 'User' }) } `) await fs.writeFile(path.join(BASE_PATH, 'ace'), '') ace.addCommand(require('../src/Commands')['make:model']) await require('../src/Services/run-instructions')(getContext(), BASE_PATH) const exists = await fs.exists(path.join(BASE_PATH, 'app/Models/User.js')) assert.isTrue(exists) }).timeout(0) test('instructions copy files', async (assert) => { await writeInstructionsJs(` const path = require('path') module.exports = async function (cli) { await cli.copy(path.join(__dirname, './foo.js'), cli.helpers.tmpPath('./foo.js')) }`) await fs.writeFile(path.join(BASE_PATH, 'foo.js'), '') await require('../src/Services/run-instructions')(getContext(), BASE_PATH) require(path.join(BASE_PATH, 'tmp/foo.js')) }).timeout(0) test('ignore when instructions.js file does not exists', async (assert) => { await require('../src/Services/run-instructions')(getContext(), BASE_PATH) }).timeout(0) test('ignore when instructions.md file does not exists', async (assert) => { await require('../src/Services/render-instructions-md')(BASE_PATH, '@adonisjs/session') }).timeout(0) }) } ================================================ FILE: test/verify-existing-folder.spec.js ================================================ 'use strict' /* * adonis-cli * * (c) Harminder Virk * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const test = require('japa') const path = require('path') const fs = require('fs-extra') const Steps = require('cli-step') const verifyExistingFolder = require('../src/Services/verify-existing-folder') test.group('Verify Existing Folder', (group) => { group.after(async () => { await fs.remove(path.join(__dirname, './yardstick-app')) await fs.remove(path.join(__dirname, './yardstick')) }) test('throw error when app dir exists and not empty', async (assert) => { const appPath = path.join(__dirname, './yardstick') await fs.ensureFile(path.join(appPath, 'package.json')) const stepsCounter = new Steps(1) assert.plan(1) try { await verifyExistingFolder(appPath, stepsCounter) } catch ({ message }) { assert.include(message, 'Cannot override contents of [yardstick]') await fs.remove(appPath) } }) test('work fine with directory exists but is empty', async (assert) => { const appPath = path.join(__dirname, './yardstick') await fs.ensureDir(appPath) const stepsCounter = new Steps(1) await verifyExistingFolder(appPath, stepsCounter) await fs.remove(appPath) }) test('ignore when directory doesn\'t exists', async (assert) => { const appPath = path.join(__dirname, './yardstick') const stepsCounter = new Steps(1) await verifyExistingFolder(appPath, stepsCounter) }) })