├── .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
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_size = 2
6 | indent_style = space
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.json]
13 | insert_final_newline = ignore
14 |
15 | [**.min.js]
16 | indent_style = ignore
17 | insert_final_newline = ignore
18 |
19 | [MakeFile]
20 | indent_style = tab
21 |
22 | [*.md]
23 | trim_trailing_whitespace = false
24 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Report identified bugs
4 | ---
5 |
6 |
7 |
8 | ## Prerequisites
9 |
10 | 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.
11 |
12 | - Lots of raised issues are directly not bugs but instead are design decisions taken by us.
13 | - 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.
14 | - Ensure the issue isn't already reported.
15 | - Ensure you are reporting the bug in the correct repo.
16 |
17 | *Delete the above section and the instructions in the sections below before submitting*
18 |
19 | ## Package version
20 |
21 |
22 | ## Node.js and npm version
23 |
24 |
25 | ## Sample Code (to reproduce the issue)
26 |
27 |
28 | ## BONUS (a sample repo to reproduce the issue)
29 |
30 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Propose changes for adding a new feature
4 | ---
5 |
6 |
7 |
8 | ## Prerequisites
9 |
10 | 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.
11 |
12 | ## Consider an RFC
13 |
14 | Please create an [RFC](https://github.com/adonisjs/rfcs) instead, if
15 |
16 | - Feature introduces a breaking change
17 | - Demands lots of time and changes in the current code base.
18 |
19 | *Delete the above section and the instructions in the sections below before submitting*
20 |
21 | ## Why this feature is required (specific use-cases will be appreciated)?
22 |
23 |
24 | ## Have you tried any other work arounds?
25 |
26 |
27 | ## Are you willing to work on it with little guidance?
28 |
29 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Proposed changes
4 |
5 | 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.
6 |
7 | ## Types of changes
8 |
9 | What types of changes does your code introduce?
10 |
11 | _Put an `x` in the boxes that apply_
12 |
13 | - [ ] Bugfix (non-breaking change which fixes an issue)
14 | - [ ] New feature (non-breaking change which adds functionality)
15 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
16 |
17 | ## Checklist
18 |
19 | _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._
20 |
21 | - [ ] I have read the [CONTRIBUTING](https://github.com/adonisjs/adonis-cli/blob/develop/CONTRIBUTING.md) doc
22 | - [ ] Lint and unit tests pass locally with my changes
23 | - [ ] I have added tests that prove my fix is effective or that my feature works.
24 | - [ ] I have added necessary documentation (if appropriate)
25 |
26 | ## Further comments
27 |
28 | 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...
29 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | !.gitkeep
2 | node_modules
3 | npm-debug.log
4 | .nyc_output
5 | coverage
6 | test/yardstick
7 | test/yardstick-app
8 | .DS_STORE
9 | .idea
10 | .vscode/
11 | *.sublime-project
12 | *.sublime-workspace
13 | *.log
14 | build
15 | dist
16 | yarn.lock
17 | shrinkwrap.yaml
18 | package-lock.json
19 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .editorconfig
2 | .gitignore
3 | test
4 | .nyc_output
5 | coverage
6 |
--------------------------------------------------------------------------------
/.snyk:
--------------------------------------------------------------------------------
1 | # Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
2 | version: v1.13.5
3 | ignore: {}
4 | # patches apply the minimum changes required to fix a vulnerability
5 | patch:
6 | SNYK-JS-LODASH-450202:
7 | - lodash:
8 | patched: '2019-07-04T02:19:04.709Z'
9 | - '@adonisjs/ace > lodash':
10 | patched: '2019-07-04T02:19:04.709Z'
11 | SNYK-JS-HTTPSPROXYAGENT-469131:
12 | - snyk > proxy-agent > https-proxy-agent:
13 | patched: '2019-10-05T02:19:18.739Z'
14 | - snyk > proxy-agent > pac-proxy-agent > https-proxy-agent:
15 | patched: '2019-10-05T02:19:18.739Z'
16 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - node
4 | - 8.0.0
5 | sudo: false
6 | install:
7 | - npm install
8 | after_script:
9 | - npm run coverage
10 | notifications:
11 | slack:
12 | secure: >-
13 | 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=
14 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [4.0.12](https://github.com/adonisjs/adonis-cli/compare/4.0.11...4.0.12) (2019-04-11)
2 |
3 |
4 | ### Bug Fixes
5 |
6 | * package.json to reduce vulnerabilities ([#130](https://github.com/adonisjs/adonis-cli/issues/130)) ([57b5520](https://github.com/adonisjs/adonis-cli/commit/57b5520))
7 |
8 |
9 | ### Features
10 |
11 | * **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))
12 |
13 |
14 |
15 |
16 | ## [4.0.11](https://github.com/adonisjs/adonis-cli/compare/v4.0.10...v4.0.11) (2019-01-18)
17 |
18 |
19 | ### Bug Fixes
20 |
21 | * **new:** correctly verify the versionn of npm ([1ceef76](https://github.com/adonisjs/adonis-cli/commit/1ceef76))
22 |
23 |
24 | ### Features
25 |
26 | * **new:** add api flag as alternative to api-only ([fb88973](https://github.com/adonisjs/adonis-cli/commit/fb88973))
27 | * **new:** remove dev flag ([3f8394b](https://github.com/adonisjs/adonis-cli/commit/3f8394b))
28 |
29 |
30 |
31 |
32 | ## [4.0.10](https://github.com/adonisjs/adonis-cli/compare/v4.0.9...v4.0.10) (2018-11-27)
33 |
34 |
35 | ### Bug Fixes
36 |
37 | * **deps:** upgrade `nodemon` ([#117](https://github.com/adonisjs/adonis-cli/issues/117)) ([8a77564](https://github.com/adonisjs/adonis-cli/commit/8a77564))
38 |
39 |
40 |
41 |
42 | ## [4.0.9](https://github.com/adonisjs/adonis-cli/compare/v4.0.8...v4.0.9) (2018-10-02)
43 |
44 |
45 | ### Bug Fixes
46 |
47 | * use bgGreen vs bgGreenBright coz of kleur over chalk ([56eaba2](https://github.com/adonisjs/adonis-cli/commit/56eaba2))
48 |
49 |
50 |
51 |
52 | ## [4.0.8](https://github.com/adonisjs/adonis-cli/compare/v4.0.7...v4.0.8) (2018-10-01)
53 |
54 |
55 | ### Features
56 |
57 | * **intellisense:** add type comments to templates ([878154a](https://github.com/adonisjs/adonis-cli/commit/878154a))
58 | * **template:** add typedoc to middleware template ([9920b4a](https://github.com/adonisjs/adonis-cli/commit/9920b4a))
59 |
60 |
61 |
62 |
63 | ## [4.0.7](https://github.com/adonisjs/adonis-cli/compare/v4.0.6...v4.0.7) (2018-09-05)
64 |
65 |
66 | ### Features
67 |
68 | * **serve:** add ignore options ([#115](https://github.com/adonisjs/adonis-cli/issues/115)) ([876d13e](https://github.com/adonisjs/adonis-cli/commit/876d13e))
69 |
70 |
71 |
72 |
73 | ## [4.0.6](https://github.com/adonisjs/adonis-cli/compare/v4.0.5...v4.0.6) (2018-08-03)
74 |
75 |
76 | ### Bug Fixes
77 |
78 | * **commands:** support prereleases of Node.js ([#114](https://github.com/adonisjs/adonis-cli/issues/114)) ([f28cdd6](https://github.com/adonisjs/adonis-cli/commit/f28cdd6))
79 |
80 |
81 | ### Features
82 |
83 | * **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)
84 | * **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)
85 |
86 |
87 |
88 |
89 | ## [4.0.5](https://github.com/adonisjs/adonis-cli/compare/v4.0.4...v4.0.5) (2018-06-04)
90 |
91 |
92 | ### Bug Fixes
93 |
94 | * **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))
95 |
96 |
97 | ### Features
98 |
99 | * **install:** use cnpm flag for install ([71ae975](https://github.com/adonisjs/adonis-cli/commit/71ae975))
100 | * **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))
101 | * **make:** add make:provider command ([#94](https://github.com/adonisjs/adonis-cli/issues/94)) ([3344066](https://github.com/adonisjs/adonis-cli/commit/3344066))
102 | * **new:** add cnpm flag ([d64cb7f](https://github.com/adonisjs/adonis-cli/commit/d64cb7f))
103 | * **serve:** add option to specify debug port ([c0735ff](https://github.com/adonisjs/adonis-cli/commit/c0735ff))
104 |
105 |
106 |
107 |
108 | ## [4.0.4](https://github.com/adonisjs/adonis-cli/compare/v4.0.3...v4.0.4) (2018-02-14)
109 |
110 |
111 | ### Bug Fixes
112 |
113 | * **serve:** boxen has been removed ([97890a2](https://github.com/adonisjs/adonis-cli/commit/97890a2)), closes [#93](https://github.com/adonisjs/adonis-cli/issues/93)
114 |
115 |
116 |
117 |
118 | ## [4.0.3](https://github.com/adonisjs/adonis-cli/compare/v4.0.2...v4.0.3) (2018-02-09)
119 |
120 |
121 |
122 |
123 | ## [4.0.2](https://github.com/adonisjs/adonis-cli/compare/v4.0.0...v4.0.2) (2018-02-07)
124 |
125 |
126 | ### Bug Fixes
127 |
128 | * **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))
129 |
130 |
131 |
132 |
133 | ## [4.0.1](https://github.com/adonisjs/adonis-cli/compare/v4.0.0...v4.0.1) (2018-02-07)
134 |
135 |
136 |
137 |
138 | # [4.0.0](https://github.com/adonisjs/adonis-cli/compare/v3.0.17...v4.0.0) (2018-01-31)
139 |
140 |
141 | ### Bug Fixes
142 |
143 | * **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))
144 | * **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))
145 | * **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))
146 | * **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))
147 |
148 |
149 | ### Features
150 |
151 | * **new:** re-design new command output & add raw option ([db4c5d9](https://github.com/adonisjs/adonis-cli/commit/db4c5d9))
152 |
153 |
154 |
155 |
156 | ## [3.0.17](https://github.com/adonisjs/adonis-cli/compare/v3.0.16...v3.0.17) (2017-11-08)
157 |
158 |
159 | ### Features
160 |
161 | * **generators:** add traits generator ([16bebfb](https://github.com/adonisjs/adonis-cli/commit/16bebfb))
162 |
163 |
164 |
165 |
166 | ## [3.0.16](https://github.com/adonisjs/adonis-cli/compare/v3.0.15...v3.0.16) (2017-10-30)
167 |
168 |
169 | ### Bug Fixes
170 |
171 | * **serve:** exit process on close everytime ([f1b6c77](https://github.com/adonisjs/adonis-cli/commit/f1b6c77))
172 |
173 |
174 |
175 |
176 | ## [3.0.15](https://github.com/adonisjs/adonis-cli/compare/v3.0.14...v3.0.15) (2017-10-29)
177 |
178 |
179 | ### Features
180 |
181 | * **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))
182 | * **serve:** add .dev domains support via hotel ([b3c7bdd](https://github.com/adonisjs/adonis-cli/commit/b3c7bdd))
183 | * **serve:** add polling option for legacy watch ([695b7df](https://github.com/adonisjs/adonis-cli/commit/695b7df))
184 | * **serve:** allow user to register `.dev` domain ([14fc1e8](https://github.com/adonisjs/adonis-cli/commit/14fc1e8))
185 | * **setup:** add `setup` command to allow projects define setup process ([4954433](https://github.com/adonisjs/adonis-cli/commit/4954433))
186 |
187 |
188 | ### Reverts
189 |
190 | * **commands:** remove setup command ([15258e8](https://github.com/adonisjs/adonis-cli/commit/15258e8))
191 |
192 |
193 |
194 |
195 | ## [3.0.14](https://github.com/adonisjs/adonis-cli/compare/v3.0.12...v3.0.14) (2017-10-10)
196 |
197 |
198 | ### Bug Fixes
199 |
200 | * **clone:** allow white space ([dd2b551](https://github.com/adonisjs/adonis-cli/commit/dd2b551))
201 | * **make:controller:** entertain the resource flag ([977b160](https://github.com/adonisjs/adonis-cli/commit/977b160))
202 | * **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))
203 | * **watch:** ignore public directory ([67ca54d](https://github.com/adonisjs/adonis-cli/commit/67ca54d))
204 |
205 |
206 |
207 |
208 | ## [3.0.13](https://github.com/adonisjs/adonis-cli/compare/v3.0.12...v3.0.13) (2017-10-03)
209 |
210 |
211 |
212 |
213 | ## [3.0.12](https://github.com/adonisjs/adonis-cli/compare/v3.0.11...v3.0.12) (2017-08-22)
214 |
215 |
216 | ### Features
217 |
218 | * **new:** add --dev flag to the new command ([4282267](https://github.com/adonisjs/adonis-cli/commit/4282267))
219 |
220 |
221 |
222 |
223 | ## [3.0.11](https://github.com/adonisjs/adonis-cli/compare/v3.0.10...v3.0.11) (2017-08-22)
224 |
225 |
226 | ### Bug Fixes
227 |
228 | * **install:** do not require app ace file ([ab536d5](https://github.com/adonisjs/adonis-cli/commit/ab536d5))
229 | * **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))
230 |
231 |
232 | ### Features
233 |
234 | * **make:** add make:exception command ([a9b2c3c](https://github.com/adonisjs/adonis-cli/commit/a9b2c3c))
235 | * **new:** install fullstack app by default ([e07860c](https://github.com/adonisjs/adonis-cli/commit/e07860c))
236 |
237 |
238 |
239 |
240 | ## [3.0.10](https://github.com/adonisjs/adonis-cli/compare/v3.0.9...v3.0.10) (2017-08-18)
241 |
242 |
243 | ### Features
244 |
245 | * **serve:** add --debug flag to run in debug mode ([d6197b8](https://github.com/adonisjs/adonis-cli/commit/d6197b8))
246 |
247 |
248 |
249 |
250 | ## [3.0.9](https://github.com/adonisjs/adonis-cli/compare/v3.0.8...v3.0.9) (2017-08-16)
251 |
252 |
253 | ### Bug Fixes
254 |
255 | * **generators:** add WsController template ([#51](https://github.com/adonisjs/adonis-cli/issues/51)) ([a10e1e4](https://github.com/adonisjs/adonis-cli/commit/a10e1e4))
256 | * **generators:** generate proper paths to nested folders ([6cae861](https://github.com/adonisjs/adonis-cli/commit/6cae861))
257 | * **install:** pass `--save` flag to npm install ([9b39aa7](https://github.com/adonisjs/adonis-cli/commit/9b39aa7))
258 | * **wsController:** make proper path for subdirs ([28f7af0](https://github.com/adonisjs/adonis-cli/commit/28f7af0))
259 |
260 |
261 | ### Features
262 |
263 | * **serve:** remove forever for nodemon ([23f1798](https://github.com/adonisjs/adonis-cli/commit/23f1798))
264 |
265 |
266 |
267 |
268 | ## [3.0.8](https://github.com/adonisjs/adonis-cli/compare/v3.0.7...v3.0.8) (2017-08-08)
269 |
270 |
271 | ### Bug Fixes
272 |
273 | * **template:** fix command template ([cb3bb86](https://github.com/adonisjs/adonis-cli/commit/cb3bb86))
274 |
275 |
276 |
277 |
278 | ## [3.0.7](https://github.com/adonisjs/adonis-cli/compare/v3.0.6...v3.0.7) (2017-08-04)
279 |
280 |
281 | ### Bug Fixes
282 |
283 | * **context:** cli.copy should not overwrite the existing file ([8fc3bd1](https://github.com/adonisjs/adonis-cli/commit/8fc3bd1))
284 | * **instructions:** make sure instruction fn is a function ([acc7e82](https://github.com/adonisjs/adonis-cli/commit/acc7e82))
285 | * **serve:** fix glob pattern for ignore dirs ([4860502](https://github.com/adonisjs/adonis-cli/commit/4860502))
286 |
287 |
288 |
289 |
290 | ## [3.0.6](https://github.com/adonisjs/adonis-cli/compare/v3.0.5...v3.0.6) (2017-08-02)
291 |
292 |
293 |
294 |
295 | ## [3.0.5](https://github.com/adonisjs/adonis-cli/compare/v3.0.4...v3.0.5) (2017-08-01)
296 |
297 |
298 | ### Bug Fixes
299 |
300 | * **commands:** use as flag over name ([e11ae80](https://github.com/adonisjs/adonis-cli/commit/e11ae80))
301 |
302 |
303 |
304 |
305 | ## [3.0.4](https://github.com/adonisjs/adonis-cli/compare/v3.0.3...v3.0.4) (2017-08-01)
306 |
307 |
308 | ### Features
309 |
310 | * **commands:** add install command ([56834a8](https://github.com/adonisjs/adonis-cli/commit/56834a8))
311 | * **commands:** add run:instructions command ([459d7c9](https://github.com/adonisjs/adonis-cli/commit/459d7c9))
312 |
313 |
314 |
315 |
316 | ## [3.0.3](https://github.com/adonisjs/adonis-cli/compare/v3.0.2...v3.0.3) (2017-07-28)
317 |
318 |
319 | ### Features
320 |
321 | * **commands:** add make:ehandler command ([8703159](https://github.com/adonisjs/adonis-cli/commit/8703159))
322 | * **commands:** add make:seed command ([c7898da](https://github.com/adonisjs/adonis-cli/commit/c7898da))
323 | * **commands:** add repl command ([e0c0f7f](https://github.com/adonisjs/adonis-cli/commit/e0c0f7f))
324 | * **commands:** add route:list command ([a0b63ed](https://github.com/adonisjs/adonis-cli/commit/a0b63ed))
325 |
326 |
327 |
328 |
329 | ## [3.0.2](https://github.com/adonisjs/adonis-cli/compare/v3.0.1...v3.0.2) (2017-07-27)
330 |
331 |
332 | ### Features
333 |
334 | * **serve:** add ignore patterns to serve command ([eb132ef](https://github.com/adonisjs/adonis-cli/commit/eb132ef))
335 |
336 |
337 |
338 |
339 | ## [3.0.1](https://github.com/adonisjs/adonis-cli/compare/v3.0.0...v3.0.1) (2017-07-27)
340 |
341 |
342 | ### Bug Fixes
343 |
344 | * **bin:** remove --harmony flag ([a814d45](https://github.com/adonisjs/adonis-cli/commit/a814d45))
345 |
346 |
347 |
348 |
349 | # [3.0.0](https://github.com/adonisjs/adonis-cli/compare/v2.1.9...v3.0.0) (2017-07-27)
350 |
351 |
352 | ### Bug Fixes
353 |
354 | * **test:** add hack for windows ([5ee5071](https://github.com/adonisjs/adonis-cli/commit/5ee5071))
355 | * **test:** another attempt for window ([5a98518](https://github.com/adonisjs/adonis-cli/commit/5a98518))
356 | * **test:** fix breaking tests ([525312a](https://github.com/adonisjs/adonis-cli/commit/525312a))
357 | * **test:** fs.remove doesn't work in windows ([c4539cf](https://github.com/adonisjs/adonis-cli/commit/c4539cf))
358 |
359 |
360 | ### Features
361 |
362 | * **command:** cleanup & add `new` command ([5844ef6](https://github.com/adonisjs/adonis-cli/commit/5844ef6))
363 | * **commands:** add key:generate ([e4d105e](https://github.com/adonisjs/adonis-cli/commit/e4d105e))
364 | * **commands:** add make commands ([c4d21d4](https://github.com/adonisjs/adonis-cli/commit/c4d21d4))
365 | * **commands:** add make:listener command ([6e276d6](https://github.com/adonisjs/adonis-cli/commit/6e276d6))
366 | * **commands:** add migration make command ([d13b2f7](https://github.com/adonisjs/adonis-cli/commit/d13b2f7))
367 | * **commands:** add serve command ([34ee502](https://github.com/adonisjs/adonis-cli/commit/34ee502))
368 |
369 |
370 |
371 |
372 | ## [2.1.9](https://github.com/adonisjs/adonis-cli/compare/v2.1.8...v2.1.9) (2017-03-14)
373 |
374 |
375 | ### Bug Fixes
376 |
377 | * **new:** change process directory ([#26](https://github.com/adonisjs/adonis-cli/issues/26)) ([35afe17](https://github.com/adonisjs/adonis-cli/commit/35afe17))
378 |
379 |
380 |
381 |
382 | ## [2.1.8](https://github.com/adonisjs/adonis-cli/compare/v2.1.7...v2.1.8) (2017-01-30)
383 |
384 |
385 | ### Bug Fixes
386 |
387 | * **fs:** fs.constants is undefined across versions ([b0d8841](https://github.com/adonisjs/adonis-cli/commit/b0d8841))
388 |
389 |
390 |
391 |
392 | ## [2.1.7](https://github.com/adonisjs/adonis-cli/compare/v2.1.6...v2.1.7) (2017-01-28)
393 |
394 |
395 | ### Bug Fixes
396 |
397 | * **dependencies:** install adonis-fold as main dependency ([dbf9e21](https://github.com/adonisjs/adonis-cli/commit/dbf9e21))
398 |
399 |
400 |
401 |
402 | ## [2.1.6](https://github.com/adonisjs/adonis-cli/compare/v2.1.5...v2.1.6) (2017-01-28)
403 |
404 |
405 | ### Bug Fixes
406 |
407 | * closes [#3](https://github.com/adonisjs/adonis-cli/issues/3) ([25d2edd](https://github.com/adonisjs/adonis-cli/commit/25d2edd))
408 | * use the requiredNodeVersion and requiredNpmVersion const ([246dde6](https://github.com/adonisjs/adonis-cli/commit/246dde6))
409 | * **install:** install using --no-optional flag ([0426fa3](https://github.com/adonisjs/adonis-cli/commit/0426fa3))
410 |
411 |
412 | ### Features
413 |
414 | * add check node.js and npm required versions to the new command. ([7493ee6](https://github.com/adonisjs/adonis-cli/commit/7493ee6))
415 | * check node.js and npm required versions ([954f3e8](https://github.com/adonisjs/adonis-cli/commit/954f3e8))
416 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | AdonisJs is a community driven project. You are free to contribute in any of the following ways.
4 |
5 | - [Coding style](coding-style)
6 | - [Fix bugs by creating PR's](fix-bugs-by-creating-prs)
7 | - [Share an RFC for new features or big changes](share-an-rfc-for-new-features-or-big-changes)
8 | - [Report security issues](report-security-issues)
9 | - [Be a part of the community](be-a-part-of-community)
10 |
11 | ## Coding style
12 |
13 | 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.
14 |
15 | ## Fix bugs by creating PR's
16 |
17 | 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.
18 |
19 | Go through the following points, before creating a new PR.
20 |
21 | 1. Create an issue discussing the bug or short-coming in the framework.
22 | 2. Once approved, go ahead and fork the REPO.
23 | 3. Make sure to start from the `develop`, since this is the upto date branch.
24 | 4. Make sure to keep commits small and relevant.
25 | 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.
26 | 6. Once done with all the changes, create a PR against the `develop` branch.
27 |
28 | ## Share an RFC for new features or big changes
29 |
30 | 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.
31 |
32 | ### What is an RFC?
33 |
34 | 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).
35 |
36 | 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.
37 |
38 | 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.
39 |
40 | ## Report security issues
41 |
42 | 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
43 |
44 | ## Be a part of community
45 |
46 | 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.
47 |
48 | We follow a strict [Code of Conduct](https://adonisjs.com/community-guidelines) to make sure everyone is respectful to each other.
49 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # The MIT License
2 |
3 | Copyright 2018 Harminder Virk, contributors
4 |
5 | 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:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | 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.
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AdonisJs Cli 🍺
2 | > Scaffolding tool for Adonisjs
3 |
4 | [![NPM Version][npm-image]][npm-url]
5 | [![Build Status][travis-image]][travis-url]
6 | [![Appveyor][appveyor-image]][appveyor-url]
7 | [![Coveralls][coveralls-image]][coveralls-url]
8 |
9 | Adonis cli is built on top of [Adonis ace](https://github.com/adonisjs/ace) and helps you scaffold new Adonisjs projects.
10 |
11 | Also it can proxy all the ace commands for a project, so that you can run them using the global `adonis` command.
12 |
13 |
14 |
15 | ## Installation
16 | You can install the package from npm.
17 | ```bash
18 | npm i --global @adonisjs/cli
19 | ```
20 |
21 | ## Usage
22 |
23 | ```bash
24 | adonis new yardstick
25 |
26 | # start http server
27 | adonis serve --dev
28 | ```
29 |
30 | ## Moving Forward
31 | Checkout the [official documentation](https://adonisjs.com/docs/4.1/installation) at the AdonisJs website for more info.
32 |
33 | ## Tests
34 | Tests are written using [japa](http://github.com/thetutlage/japa). Run the following commands to run tests.
35 |
36 | ```bash
37 | npm run test:local
38 |
39 | # report coverage
40 | npm run test
41 |
42 | # on windows
43 | npm run test:win
44 | ```
45 |
46 | ## Release History
47 |
48 | Checkout [CHANGELOG.md](CHANGELOG.md) file for release history.
49 |
50 | ## Meta
51 |
52 | AdonisJs – [@adonisframework](https://twitter.com/adonisframework) – virk@adonisjs.com
53 |
54 | Checkout [LICENSE.txt](LICENSE.txt) for license information
55 |
56 | Harminder Virk (Aman) - [https://github.com/thetutlage](https://github.com/thetutlage)
57 |
58 | [appveyor-image]: https://img.shields.io/appveyor/ci/thetutlage/adonis-cli/master.svg?style=flat-square
59 |
60 | [appveyor-url]: https://ci.appveyor.com/project/thetutlage/adonis-cli
61 |
62 | [npm-image]: https://img.shields.io/npm/v/@adonisjs/cli.svg?style=flat-square
63 | [npm-url]: https://npmjs.org/package/@adonisjs/cli
64 |
65 | [travis-image]: https://img.shields.io/travis/adonisjs/adonis-cli/master.svg?style=flat-square
66 | [travis-url]: https://travis-ci.org/adonisjs/adonis-cli
67 |
68 | [coveralls-image]: https://img.shields.io/coveralls/adonisjs/adonis-cli/develop.svg?style=flat-square
69 |
70 | [coveralls-url]: https://coveralls.io/github/adonisjs/adonis-cli
71 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | environment:
2 | matrix:
3 | - nodejs_version: Stable
4 | - nodejs_version: 8.0.0
5 | init: git config --global core.autocrlf true
6 | install:
7 | - ps: 'Install-Product node $env:nodejs_version'
8 | - npm install
9 | test_script:
10 | - node --version
11 | - npm --version
12 | - npm run test
13 | build: 'off'
14 | clone_depth: 1
15 | matrix:
16 | fast_finish: true
17 |
--------------------------------------------------------------------------------
/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "core": true,
3 | "ts": false,
4 | "license": "MIT",
5 | "services": [
6 | "travis",
7 | "appveyor",
8 | "coveralls"
9 | ],
10 | "appveyorUsername": "thetutlage",
11 | "minNodeVersion": "8.0.0"
12 | }
13 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | 'use strict'
3 |
4 | /*
5 | * adonis-cli
6 | *
7 | * (c) Harminder Virk
8 | *
9 | * For the full copyright and license information, please view the LICENSE
10 | * file that was distributed with this source code.
11 | */
12 |
13 | const path = require('path')
14 | const debug = require('debug')('adonis:cli')
15 |
16 | const Commands = require('./src/Commands')
17 | const commandNames = []
18 | const needProviders = ['repl', 'route:list', 'run:instructions']
19 |
20 | const ace = require('./lib/ace')
21 |
22 | // register internal commands
23 | Object.keys(Commands).forEach((name) => {
24 | commandNames.push(name)
25 | ace.addCommand(Commands[name])
26 | })
27 |
28 | // require user project .ace file
29 | try {
30 | const command = process.argv[2]
31 | if (commandNames.indexOf(command) > -1 && needProviders.indexOf(command) <= -1) {
32 | debug('loading ace from cli')
33 | ace.wireUpWithCommander()
34 | ace.invoke(require('./package'))
35 | } else {
36 | debug('loading ace from project')
37 | require(path.join(process.cwd(), 'ace'))
38 | }
39 | } catch (error) {
40 | if (error.code !== 'ENOENT' && error.code !== 'MODULE_NOT_FOUND') {
41 | throw error
42 | }
43 |
44 | debug('loading ace as fallback from cli')
45 | ace.wireUpWithCommander()
46 | ace.invoke(require('./package'))
47 | }
48 |
--------------------------------------------------------------------------------
/japaFile.js:
--------------------------------------------------------------------------------
1 | const { configure } = require('japa')
2 | configure({
3 | files: ['test/**/*.spec.js']
4 | })
5 |
--------------------------------------------------------------------------------
/lib/Steps.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /**
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const Steps = require('cli-step')
13 |
14 | /**
15 | * Raw steps are used when user want to disable all animations.
16 | *
17 | * @class RawStep
18 | */
19 | class RawStep {
20 | constructor (total, counter, text, helpText) {
21 | this.total = total
22 | this.stepCounter = counter
23 | this.text = text
24 | this.helpText = helpText || ''
25 | }
26 |
27 | /**
28 | * Start step
29 | *
30 | * @method start
31 | *
32 | * @chainable
33 | */
34 | start () {
35 | console.log(`Step ${this.stepCounter}/${this.total}`)
36 | console.log(` ├── ${this.text} (${this.helpText})`)
37 | return this
38 | }
39 |
40 | /**
41 | * Mark step as successful
42 | *
43 | * @method success
44 | *
45 | * @param {String} text
46 | *
47 | * @return {void}
48 | */
49 | success (text) {
50 | console.log(` ├── SUCCESS: ${text || this.text} (${this.helpText})`)
51 | }
52 |
53 | /**
54 | * Mark step as errored
55 | *
56 | * @method error
57 | *
58 | * @param {String} text
59 | *
60 | * @return {void}
61 | */
62 | error (text) {
63 | console.log(` ├── ERROR: ${text || this.text} (${this.helpText})`)
64 | }
65 | }
66 |
67 | /**
68 | * Raw steps is a collection of Raw step. The API has to be
69 | * compatible with `cli-step`.
70 | *
71 | * @class RawSteps
72 | */
73 | class RawSteps {
74 | constructor (total) {
75 | this.counter = 0
76 | this.total = total
77 | }
78 |
79 | /**
80 | * Move to next step. Also the icon param is swalled, since raw output
81 | * doesn't display emojis.
82 | *
83 | * @method advance
84 | *
85 | * @param {String} text
86 | * @param {String} icon
87 | * @param {String} helpText
88 | *
89 | * @return {void}
90 | */
91 | advance (text, icon, helpText) {
92 | this.counter++
93 | return new RawStep(this.total, this.counter, text, helpText)
94 | }
95 | }
96 |
97 | module.exports = { RawSteps, Steps }
98 |
--------------------------------------------------------------------------------
/lib/ace.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const path = require('path')
13 | let ace = null
14 |
15 | /**
16 | * Give preference to the user ace module if
17 | * command is executed in project root.
18 | */
19 | try {
20 | ace = require(path.join(process.cwd(), 'node_modules/@adonisjs/ace'))
21 | } catch (error) {
22 | ace = require('@adonisjs/ace')
23 | }
24 |
25 | module.exports = ace
26 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@adonisjs/cli",
3 | "version": "4.0.13",
4 | "description": "Command line tool for Adonisjs",
5 | "keywords": [
6 | "adonis",
7 | "adonisjs",
8 | "cli",
9 | "installer"
10 | ],
11 | "author": "Harminder Virk ",
12 | "contributors": [
13 | "Romain Lanz "
14 | ],
15 | "license": "MIT",
16 | "main": "src/Commands/index.js",
17 | "bin": {
18 | "adonis": "index.js"
19 | },
20 | "scripts": {
21 | "mrm": "mrm --preset=@adonisjs/mrm-preset",
22 | "pretest": "npm run lint",
23 | "test:local": "FORCE_COLOR=true node bin/index.js --local",
24 | "test": "nyc node japaFile.js",
25 | "coverage": "nyc report --reporter=text-lcov | coveralls",
26 | "commit": "git-cz",
27 | "lint": "standard",
28 | "snyk-protect": "snyk protect",
29 | "prepublish": "npm run snyk-protect"
30 | },
31 | "dependencies": {
32 | "@adonisjs/ace": "^5.0.8",
33 | "@adonisjs/ignitor": "^2.0.8",
34 | "adonis-await-outside": "^1.0.0",
35 | "cli-step": "^1.0.2",
36 | "debug": "^4.1.0",
37 | "dotenv": "^8.0.0",
38 | "gradient-string": "^1.2.0",
39 | "is-git-url": "^1.0.0",
40 | "lodash": "^4.17.11",
41 | "marked": "^1.1.1",
42 | "nodemon": "^2.0.3",
43 | "opn": "^5.4.0",
44 | "pluralize": "^8.0.0",
45 | "randomstring": "^1.1.5",
46 | "semver": "^5.6.0",
47 | "snyk": "^1.231.0"
48 | },
49 | "devDependencies": {
50 | "@adonisjs/fold": "^4.0.9",
51 | "@adonisjs/mrm-preset": "^2.0.3",
52 | "@adonisjs/sink": "^1.0.17",
53 | "clear-require": "^3.0.0",
54 | "commitizen": "^3.0.4",
55 | "coveralls": "^3.0.2",
56 | "cz-conventional-changelog": "^2.1.0",
57 | "fs-extra": "^8.1.0",
58 | "japa": "^2.0.6",
59 | "japa-cli": "^1.0.1",
60 | "mrm": "^1.2.1",
61 | "nyc": "^14.1.1",
62 | "pkg-ok": "^2.3.1",
63 | "standard": "^12.0.1"
64 | },
65 | "repository": {
66 | "type": "git",
67 | "url": "git+https://github.com/adonisjs/adonis-cli.git"
68 | },
69 | "bugs": {
70 | "url": "https://github.com/adonisjs/adonis-cli/issues"
71 | },
72 | "config": {
73 | "commitizen": {
74 | "path": "cz-conventional-changelog"
75 | }
76 | },
77 | "nyc": {
78 | "exclude": [
79 | "test"
80 | ]
81 | },
82 | "homepage": "https://github.com/adonisjs/adonis-cli#readme",
83 | "directories": {
84 | "lib": "lib",
85 | "test": "test"
86 | },
87 | "snyk": true
88 | }
89 |
--------------------------------------------------------------------------------
/src/Commands/Addon/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /**
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const path = require('path')
13 | const BaseCommand = require('../Base')
14 |
15 | /**
16 | * This command performs a series of operations
17 | * to be create a new addon folder.
18 | *
19 | * @class NewAddon
20 | */
21 | class NewAddon extends BaseCommand {
22 | /**
23 | * The command signature required by ace
24 | *
25 | * @attribute signature
26 | * @static
27 | *
28 | * @return {String}
29 | */
30 | static get signature () {
31 | return `
32 | addon
33 | { name : Name of the addon directory }
34 | { --skip-install : Do not install modules from npm }
35 | { --yarn : Use yarn over npm for modules installation }
36 | { --raw : Disable animations and colored output }
37 | { --dev: Install the dev blueprint }
38 | `
39 | }
40 |
41 | /**
42 | * The command description required by ace
43 | *
44 | * @attribute description
45 | *
46 | * @return {String}
47 | */
48 | static get description () {
49 | return 'Create a new AdonisJs addon'
50 | }
51 |
52 | /**
53 | * Ensure node version is correct, then make sure app path is
54 | * empty and finally clone the repo and remove `.git` dir.
55 | *
56 | * @method _setupProjectDirectory
57 | *
58 | * @param {Object} stepsCounter
59 | * @param {String} blueprint
60 | * @param {String} appPath
61 | * @param {Object} options
62 | *
63 | * @return {void}
64 | *
65 | * @private
66 | */
67 | async _setupProjectDirectory (stepsCounter, blueprint, appPath, options) {
68 | await require('../../Services/check-node-version')(stepsCounter)
69 | await require('../../Services/verify-existing-folder')(appPath, stepsCounter)
70 | await require('../../Services/clone')(blueprint, appPath, stepsCounter, options.branch)
71 | await this.removeDir(path.join(appPath, '.git'))
72 | }
73 |
74 | /**
75 | * Prints a message after a new project has been created
76 | *
77 | * @method _onBoardForNewAddon
78 | *
79 | * @return {void}
80 | *
81 | * @private
82 | */
83 | _onBoardForNewAddon () {
84 | const lines = [
85 | '',
86 | '🚀 Addon created successfully',
87 | '👉 Get started by clicking the following link',
88 | '',
89 | `${this.chalk.blue('https://adonisjs.com/recipes/creating-addons')}`,
90 | ''
91 | ]
92 | lines.forEach((line) => (console.log(line)))
93 | }
94 |
95 | /**
96 | * Install dependencies when `skip-install` flag has not been
97 | * passed
98 | *
99 | * @method _installDependencies
100 | *
101 | * @param {Object} stepsCounter
102 | * @param {String} appPath
103 | * @param {Object} options
104 | *
105 | * @return {void}
106 | *
107 | * @private
108 | */
109 | async _installDependencies (stepsCounter, appPath, options) {
110 | if (options.skipInstall) {
111 | return
112 | }
113 | await require('../../Services/install')(options.yarn ? 'yarn' : 'npm', stepsCounter)
114 | }
115 |
116 | /**
117 | * Invoked by ace
118 | *
119 | * @method handle
120 | *
121 | * @param {Object} args
122 | * @param {Object} options
123 | *
124 | * @return {void}
125 | */
126 | async handle ({ name }, options) {
127 | const blueprint = 'adonisjs/adonis-addon'
128 | const addonPath = path.join(process.cwd(), name)
129 | const stepsCounter = this.initiateSteps(options.skipInstall ? 3 : 4, options)
130 |
131 | if (options.dev) {
132 | options.branch = 'develop'
133 | }
134 |
135 | await this.invoke(async () => {
136 | this.dumpAsciiLogo()
137 |
138 | await this._setupProjectDirectory(stepsCounter, blueprint, addonPath, options)
139 | process.chdir(addonPath)
140 |
141 | await this._installDependencies(stepsCounter, addonPath, options)
142 | this._onBoardForNewAddon()
143 | })
144 | }
145 | }
146 |
147 | module.exports = NewAddon
148 |
--------------------------------------------------------------------------------
/src/Commands/Base/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /**
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const gradient = require('gradient-string')
13 | const path = require('path')
14 |
15 | const ace = require('../../../lib/ace')
16 |
17 | class BaseCommand extends ace.Command {
18 | /**
19 | * Returns an instance of steps counter, based upon
20 | * command line flags
21 | *
22 | * @method initiateSteps
23 | *
24 | * @param {Number} count
25 | * @param {Object} options
26 | *
27 | * @return {Object}
28 | */
29 | initiateSteps (count, options) {
30 | const { RawSteps, Steps } = require('../../../lib/Steps')
31 | return options.raw || process.env.DEBUG ? new RawSteps(count) : new Steps(count)
32 | }
33 |
34 | /**
35 | * Prints AdonisJs ascii art to the console
36 | *
37 | * @method dumpAsciiLogo
38 | *
39 | * @return {void}
40 | */
41 | dumpAsciiLogo () {
42 | console.log(gradient.rainbow(" _ _ _ _ \n / \\ __| | ___ _ __ (_)___ | |___ \n / _ \\ / _` |/ _ \\| '_ \\| / __|_ | / __|\n / ___ \\ (_| | (_) | | | | \\__ \\ |_| \\__ \\\n/_/ \\_\\__,_|\\___/|_| |_|_|___/\\___/|___/\n"))
43 | }
44 |
45 | /**
46 | * Invokes a function, by automatically catching for errors
47 | * and printing them in a standard way
48 | *
49 | * @method invoke
50 | *
51 | * @param {Function} callback
52 | *
53 | * @return {void}
54 | */
55 | async invoke (callback) {
56 | try {
57 | await callback()
58 | } catch (error) {
59 | this.printError(error)
60 | process.exit(1)
61 | }
62 | }
63 |
64 | /**
65 | * Prints error object to the console
66 | *
67 | * @method printError
68 | *
69 | * @param {Object} error
70 | *
71 | * @return {void}
72 | */
73 | printError (error) {
74 | console.log(`\n ${this.chalk.bgRed(' ERROR ')} ${error.message}\n`)
75 |
76 | if (error.hint) {
77 | console.log(`\n ${this.chalk.bgRed(' HELP ')} ${error.hint}\n`)
78 | }
79 | }
80 |
81 | /**
82 | * Throws exception when user is not inside the project root
83 | *
84 | * @method ensureInProjectRoot
85 | *
86 | * @return {void}
87 | */
88 | async ensureInProjectRoot () {
89 | const exists = await this.pathExists(path.join(process.cwd(), 'ace'))
90 | if (!exists) {
91 | throw new Error(`Make sure you are inside an adonisjs app to run the ${this.constructor.commandName} command`)
92 | }
93 | }
94 |
95 | /**
96 | * Throws error when NODE_ENV = production and `--force` flag
97 | * has not been passed.
98 | *
99 | * @method ensureCanRunInProduction
100 | *
101 | * @param {Object} options
102 | *
103 | * @return {void}
104 | */
105 | ensureCanRunInProduction (options) {
106 | if (process.env.NODE_ENV === 'production' && !options.force) {
107 | throw new Error(`Cannot run ${this.constructor.commandName} command in production. Pass --force flag to continue`)
108 | }
109 | }
110 |
111 | /**
112 | * Calls a command registered with ace
113 | *
114 | * @method call
115 | *
116 | * @param {String} command
117 | * @param {Object} options
118 | * @param {Object} flags
119 | *
120 | * @return {void}
121 | */
122 | call (command, options, flags) {
123 | return ace.call(command, options, flags)
124 | }
125 | }
126 |
127 | module.exports = BaseCommand
128 |
--------------------------------------------------------------------------------
/src/Commands/Install/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const path = require('path')
13 | const BaseCommand = require('../Base')
14 |
15 | class Install extends BaseCommand {
16 | constructor () {
17 | super()
18 | const FakeHelpers = require('@adonisjs/ignitor/src/Helpers')
19 | this.Helpers = new FakeHelpers(process.cwd())
20 | }
21 |
22 | /**
23 | * The command signature
24 | *
25 | * @method signature
26 | *
27 | * @return {String}
28 | */
29 | static get signature () {
30 | return `
31 | install
32 | { module : Npm module name }
33 | { --as=@value : Name of the module, required when installing from github or local file system }
34 | { --yarn: Use yarn over npm for installation }
35 | { --cnpm: Use cnpm over npm for installation }
36 | { -s, --skip-instructions: Do not run post install instructions }
37 | { --raw : Disable animations and colored output }
38 | `
39 | }
40 |
41 | /**
42 | * The command description
43 | *
44 | * @method description
45 | *
46 | * @return {String}
47 | */
48 | static get description () {
49 | return 'Install Adonisjs provider from npm/yarn and run post install instructions'
50 | }
51 |
52 | async handle ({ module: packageName }, options) {
53 | const name = options.as || packageName
54 | const stepsCounter = this.initiateSteps(1, options)
55 |
56 | await this.invoke(async () => {
57 | await this.ensureInProjectRoot()
58 | await require('../../Services/install')(options.yarn ? 'yarn' : (options.cnpm ? 'cnpm' : 'npm'), stepsCounter, packageName)
59 |
60 | if (options.skipInstructions) {
61 | return
62 | }
63 |
64 | const directory = path.join(process.cwd(), 'node_modules', name)
65 | await this.call('run:instructions', { directory }, { name })
66 | })
67 | }
68 | }
69 |
70 | module.exports = Install
71 |
--------------------------------------------------------------------------------
/src/Commands/Instructions/Context.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const path = require('path')
13 | const _ = require('lodash')
14 | const ace = require('../../../lib/ace')
15 |
16 | class Context {
17 | constructor (command, helpers) {
18 | this.command = command
19 | this.helpers = helpers
20 | this.appDir = path.join(this.helpers.appRoot(), 'app')
21 | }
22 |
23 | /**
24 | * Make config file using a template
25 | *
26 | * @method makeConfig
27 | * @async
28 | *
29 | * @param {String} fileName
30 | * @param {String} templatePath
31 | * @param {Object} data
32 | *
33 | * @return {void}
34 | */
35 | async makeConfig (fileName, templatePath, data) {
36 | const configFile = path.join(this.helpers.configPath(), fileName)
37 | const template = await this.command.readFile(templatePath, 'utf-8')
38 | await this.command.generateFile(configFile, template, data)
39 | }
40 |
41 | /**
42 | * Calls ace command
43 | *
44 | * @method callCommand
45 | * @async
46 | *
47 | * @param {String} name
48 | * @param {Object} args
49 | * @param {Object} options
50 | *
51 | * @return {void}
52 | */
53 | callCommand (name, args, options) {
54 | return ace.call(name, args, options)
55 | }
56 |
57 | /**
58 | * Copy file from one destination to other
59 | *
60 | * @method copy
61 | *
62 | * @param {String} fromFile
63 | * @param {String} toFile
64 | * @param {Object} [options]
65 | *
66 | * @return {void}
67 | */
68 | copy (fromFile, toFile, options) {
69 | return this.command.copy(fromFile, toFile, _.merge({}, { overwrite: false, errorOnExist: true }, options))
70 | }
71 | }
72 |
73 | module.exports = Context
74 |
--------------------------------------------------------------------------------
/src/Commands/Instructions/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const path = require('path')
13 | const BaseCommand = require('../Base')
14 |
15 | class Instructions extends BaseCommand {
16 | constructor (Helpers) {
17 | super()
18 | const FakeHelpers = require('@adonisjs/ignitor/src/Helpers')
19 | this.Helpers = Helpers || new FakeHelpers(process.cwd())
20 | }
21 |
22 | /**
23 | * Injecting dependencies
24 | *
25 | * @method inject
26 | *
27 | * @return {Array}
28 | */
29 | static get inject () {
30 | return ['Adonis/Src/Helpers']
31 | }
32 |
33 | /**
34 | * The command signature
35 | *
36 | * @method signature
37 | *
38 | * @return {String}
39 | */
40 | static get signature () {
41 | return `
42 | run:instructions
43 | { directory : Directory path for which to run instructions }
44 | { --as=@value: Name of the module }
45 | `
46 | }
47 |
48 | /**
49 | * The command description
50 | *
51 | * @method description
52 | *
53 | * @return {String}
54 | */
55 | static get description () {
56 | return 'Run instructions for a given module'
57 | }
58 |
59 | /**
60 | * Handle method executed by ace when command runs. It will
61 | * install a module and run post install instructions
62 | *
63 | * @method handle
64 | *
65 | * @return {void}
66 | */
67 | async handle ({ directory }, options) {
68 | await this.invoke(async () => {
69 | const modulePath = path.isAbsolute(directory) ? directory : path.join(process.cwd(), directory)
70 | const name = options.name || path.basename(modulePath)
71 | const Context = require('./Context')
72 | const ctx = new Context(this, this.Helpers)
73 |
74 | await require('../../Services/run-instructions')(ctx, modulePath)
75 | await require('../../Services/render-instructions-md')(modulePath, name)
76 | })
77 | }
78 | }
79 |
80 | module.exports = Instructions
81 |
--------------------------------------------------------------------------------
/src/Commands/KeyGenerate/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const path = require('path')
13 | const BaseCommand = require('../Base')
14 |
15 | /**
16 | * Generate unique application key
17 | *
18 | * @class KeyGenerate
19 | * @constructor
20 | */
21 | class KeyGenerate extends BaseCommand {
22 | /**
23 | * The command signature used by ace
24 | *
25 | * @method signature
26 | *
27 | * @return {String}
28 | */
29 | static get signature () {
30 | return `
31 | key:generate
32 | { -f, --force: Forcefully generate the key in production environment }
33 | { --env=@value: .env file location }
34 | { -s, --size=@value: The key size which defaults to 32 characters }
35 | { --echo: Echo the key instead of writing to the file }
36 | `
37 | }
38 |
39 | /**
40 | * The command description used by ace
41 | *
42 | * @method description
43 | *
44 | * @return {String}
45 | */
46 | static get description () {
47 | return 'Generate secret key for the app'
48 | }
49 |
50 | /**
51 | * Reads the content of `.env` file and returns it as
52 | * an object
53 | *
54 | * @method getEnvContent
55 | *
56 | * @param {String} envPath
57 | *
58 | * @return {Object}
59 | */
60 | async getEnvContent (envPath) {
61 | const dotEnvContents = await this.readFile(envPath)
62 | return require('dotenv').parse(dotEnvContents)
63 | }
64 |
65 | /**
66 | * Updates the `.env` file by converting the object back
67 | * to a valid string
68 | *
69 | * @method updateEnvContents
70 | *
71 | * @param {String} envPath
72 | * @param {Object} envHash
73 | *
74 | * @return {void}
75 | */
76 | async updateEnvContents (envPath, envHash) {
77 | const updatedContents = Object.keys(envHash).map((key) => {
78 | return `${key}=${envHash[key]}`
79 | }).join('\n')
80 |
81 | await this.writeFile(envPath, updatedContents)
82 | }
83 |
84 | /**
85 | * Invoked by ace
86 | *
87 | * @method handle
88 | *
89 | * @param {Object} args
90 | * @param {Object} options
91 | *
92 | * @return {void}
93 | */
94 | async handle (args, options) {
95 | const size = options.size ? Number(options.size) : 32
96 | const key = require('randomstring').generate(size)
97 |
98 | /**
99 | * Echo key to console when echo is set to true
100 | * and return
101 | */
102 | if (options.echo) {
103 | console.log(`APP_KEY=${key}`)
104 | return
105 | }
106 |
107 | await this.invoke(async () => {
108 | this.ensureCanRunInProduction(options)
109 | await this.ensureInProjectRoot()
110 |
111 | const env = options.env || '.env'
112 | const pathToEnv = path.isAbsolute(env) ? env : path.join(process.cwd(), env)
113 |
114 | const envHash = await this.getEnvContent(pathToEnv)
115 | await this.updateEnvContents(pathToEnv, Object.assign(envHash, { APP_KEY: key }))
116 |
117 | this.completed('generated', 'unique APP_KEY')
118 | })
119 | }
120 | }
121 |
122 | module.exports = KeyGenerate
123 |
--------------------------------------------------------------------------------
/src/Commands/Make/Base.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const path = require('path')
13 | const BaseCommand = require('../Base')
14 | const debug = require('debug')('adonis:cli')
15 |
16 | const options = {
17 | appDir: 'app',
18 | dirs: {
19 | httpControllers: 'Controllers/Http',
20 | wsControllers: 'Controllers/Ws',
21 | models: 'Models',
22 | traits: 'Models/Traits',
23 | hooks: 'Models/Hooks',
24 | listeners: 'Listeners',
25 | exceptions: 'Exceptions',
26 | middleware: 'Middleware',
27 | commands: 'Commands',
28 | views: 'resources/views',
29 | migrations: 'database/migrations',
30 | seeds: 'database/seeds',
31 | providers: 'providers'
32 | }
33 | }
34 |
35 | class MakeBase extends BaseCommand {
36 | /**
37 | * Generates the blueprint for a given resources
38 | * using pre-defined template
39 | *
40 | * @method generateBlueprint
41 | *
42 | * @param {String} templateFor
43 | * @param {String} name
44 | * @param {Object} flags
45 | *
46 | * @return {void}
47 | */
48 | async generateBlueprint (templateFor, name, flags) {
49 | const generators = require('../../Generators')
50 |
51 | options.appRoot = options.appRoot || process.cwd()
52 |
53 | debug('blueprint options %j', options)
54 |
55 | const templateFile = path.join(__dirname, '../../Generators/templates', `${templateFor}.mustache`)
56 |
57 | const filePath = generators[templateFor].getFilePath(name, options)
58 | const data = generators[templateFor].getData(path.basename(name), flags)
59 |
60 | debug('blueprint file path %s', filePath)
61 | debug('blueprint data %j', data)
62 |
63 | const templateContents = await this.readFile(templateFile, 'utf-8')
64 | await this.generateFile(filePath, templateContents, data)
65 |
66 | const createdFile = filePath.replace(process.cwd(), '').replace(path.sep, '')
67 | console.log(`${this.icon('success')} ${this.chalk.green('create')} ${createdFile}`)
68 |
69 | return { file: createdFile, namespace: this.getNamespace(createdFile, templateFor) }
70 | }
71 |
72 | /**
73 | * Returns namespace for a given resource
74 | *
75 | * @method getNamespace
76 | *
77 | * @param {String} filePath
78 | * @param {String} namespaceFor
79 | *
80 | * @return {String}
81 | */
82 | getNamespace (filePath, namespaceFor) {
83 | const dir = options.dirs[namespaceFor] || options.dirs[`${namespaceFor}s`]
84 | return `App/${dir}/${path.basename(filePath).replace('.js', '')}`
85 | }
86 |
87 | /**
88 | * Print lines to the console
89 | *
90 | * @method printInstructions
91 | *
92 | * @param {Array} lines
93 | *
94 | * @return {void}
95 | */
96 | printInstructions (heading, steps) {
97 | console.log(
98 | ['', `👉 ${heading}`, '']
99 | .concat(steps.map((line) => `${this.chalk.dim('→')} ${line}`))
100 | .concat([''])
101 | .join('\n')
102 | )
103 | }
104 | }
105 |
106 | module.exports = MakeBase
107 |
--------------------------------------------------------------------------------
/src/Commands/Make/Command.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const BaseCommand = require('./Base')
13 |
14 | /**
15 | * Creates a new ace command
16 | *
17 | * @class MakeCommand
18 | * @constructor
19 | */
20 | class MakeCommand extends BaseCommand {
21 | /**
22 | * The command signature
23 | *
24 | * @method signature
25 | *
26 | * @return {String}
27 | */
28 | static get signature () {
29 | return `
30 | make:command
31 | { name: Name of the command }
32 | `
33 | }
34 |
35 | /**
36 | * The command description
37 | *
38 | * @method description
39 | *
40 | * @return {String}
41 | */
42 | static get description () {
43 | return 'Make a new ace command'
44 | }
45 |
46 | /**
47 | * Handle method executed by ace
48 | *
49 | * @method handle
50 | *
51 | * @param {String} options.name
52 | * @param {String} options.type
53 | *
54 | * @return {void}
55 | */
56 | async handle ({ name }) {
57 | await this.invoke(async () => {
58 | await this.ensureInProjectRoot()
59 | const { namespace } = await this.generateBlueprint('command', name, {})
60 |
61 | const steps = [
62 | `Open ${this.chalk.cyan('start/app.js')}`,
63 | `Add ${this.chalk.cyan(namespace)} to commands array`
64 | ]
65 |
66 | this.printInstructions('Register command as follows', steps)
67 | })
68 | }
69 | }
70 |
71 | module.exports = MakeCommand
72 |
--------------------------------------------------------------------------------
/src/Commands/Make/Controller.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const BaseCommand = require('./Base')
13 |
14 | /**
15 | * Make a new HTTP or Ws controller
16 | *
17 | * @class MakeController
18 | * @constructor
19 | */
20 | class MakeController extends BaseCommand {
21 | /**
22 | * The command signature
23 | *
24 | * @method signature
25 | *
26 | * @return {String}
27 | */
28 | static get signature () {
29 | return `
30 | make:controller
31 | { name: Name of the controller }
32 | { --resource: Create resourceful methods on the controller }
33 | { --type=@value: The type can be http or ws }
34 | `
35 | }
36 |
37 | /**
38 | * The command description
39 | *
40 | * @method description
41 | *
42 | * @return {String}
43 | */
44 | static get description () {
45 | return 'Make a new HTTP or Websocket channel controller'
46 | }
47 |
48 | /**
49 | * Returns the resource type for the controller
50 | *
51 | * @method _getResourceType
52 | *
53 | * @param {String} type
54 | *
55 | * @return {String}
56 | *
57 | * @private
58 | */
59 | async _getResourceType (type) {
60 | if (!type || ['ws', 'http'].indexOf(type) <= -1) {
61 | type = await this
62 | .on('validate', (value) => !!value)
63 | .choice('Select controller type', [
64 | {
65 | value: 'http',
66 | name: 'For HTTP requests'
67 | },
68 | {
69 | value: 'ws',
70 | name: 'For Websocket channel'
71 | }
72 | ])
73 | }
74 |
75 | return type === 'ws' ? 'wsController' : 'httpController'
76 | }
77 |
78 | /**
79 | * Handle method executed by ace
80 | *
81 | * @method handle
82 | *
83 | * @param {String} options.name
84 | * @param {String} options.type
85 | *
86 | * @return {void}
87 | */
88 | async handle ({ name }, { type, resource }) {
89 | await this.invoke(async () => {
90 | await this.ensureInProjectRoot()
91 | const resourceType = await this._getResourceType(type)
92 | await this.generateBlueprint(resourceType, name, { resource })
93 | })
94 | }
95 | }
96 |
97 | module.exports = MakeController
98 |
--------------------------------------------------------------------------------
/src/Commands/Make/Exception.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const BaseCommand = require('./Base')
13 |
14 | /**
15 | * Make a new exception class
16 | *
17 | * @class MakeException
18 | * @constructor
19 | */
20 | class MakeException extends BaseCommand {
21 | /**
22 | * The command signature
23 | *
24 | * @method signature
25 | *
26 | * @return {String}
27 | */
28 | static get signature () {
29 | return `
30 | make:exception
31 | { name: Name of the exception }
32 | `
33 | }
34 |
35 | /**
36 | * The command description
37 | *
38 | * @method description
39 | *
40 | * @return {String}
41 | */
42 | static get description () {
43 | return 'Make a new exception'
44 | }
45 |
46 | /**
47 | * Handle method executed by ace
48 | *
49 | * @method handle
50 | *
51 | * @param {String} options.name
52 | * @param {String} options.type
53 | *
54 | * @return {void}
55 | */
56 | async handle ({ name }) {
57 | await this.invoke(async () => {
58 | await this.ensureInProjectRoot()
59 | await this.generateBlueprint('exception', name, {})
60 | })
61 | }
62 | }
63 |
64 | module.exports = MakeException
65 |
--------------------------------------------------------------------------------
/src/Commands/Make/ExceptionHandler.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const path = require('path')
13 | const BaseCommand = require('./Base')
14 |
15 | /**
16 | * Make a new global exception handler
17 | *
18 | * @class MakeExceptionHandler
19 | * @constructor
20 | */
21 | class MakeExceptionHandler extends BaseCommand {
22 | /**
23 | * The command signature
24 | *
25 | * @method signature
26 | *
27 | * @return {String}
28 | */
29 | static get signature () {
30 | return 'make:ehandler'
31 | }
32 |
33 | /**
34 | * The command description
35 | *
36 | * @method description
37 | *
38 | * @return {String}
39 | */
40 | static get description () {
41 | return 'Make a new global exception handler'
42 | }
43 |
44 | /**
45 | * Handle method executed by ace
46 | *
47 | * @method handle
48 | *
49 | * @return {void}
50 | */
51 | async handle () {
52 | await this.invoke(async () => {
53 | await this.ensureInProjectRoot()
54 |
55 | const packageFile = require(path.join(process.cwd(), 'package.json'))
56 | const version = packageFile['adonis-version'] || packageFile['version']
57 |
58 | /**
59 | * The exceptions template is different for 4.0 and newer
60 | * versions.
61 | */
62 | await this.generateBlueprint('exceptionHandler', '', {
63 | new: version !== '4.0.0'
64 | })
65 | })
66 | }
67 | }
68 |
69 | module.exports = MakeExceptionHandler
70 |
--------------------------------------------------------------------------------
/src/Commands/Make/Hook.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const BaseCommand = require('./Base')
13 |
14 | /**
15 | * Make a new lucid model hook
16 | *
17 | * @class MakeModelHook
18 | * @constructor
19 | */
20 | class MakeModelHook extends BaseCommand {
21 | /**
22 | * The command signature
23 | *
24 | * @method signature
25 | *
26 | * @return {String}
27 | */
28 | static get signature () {
29 | return `
30 | make:hook
31 | { name: Name of the hook }
32 | { -m, --method=@value : The method to be created on hook }
33 | `
34 | }
35 |
36 | /**
37 | * The command description
38 | *
39 | * @method description
40 | *
41 | * @return {String}
42 | */
43 | static get description () {
44 | return 'Make a new lucid model hook'
45 | }
46 |
47 | /**
48 | * Handle method executed by ace
49 | *
50 | * @method handle
51 | *
52 | * @param {String} options.name
53 | * @param {String} options.type
54 | *
55 | * @return {void}
56 | */
57 | async handle ({ name }, { method }) {
58 | await this.invoke(async () => {
59 | await this.ensureInProjectRoot()
60 | await this.generateBlueprint('hook', name, { method })
61 | })
62 | }
63 | }
64 |
65 | module.exports = MakeModelHook
66 |
--------------------------------------------------------------------------------
/src/Commands/Make/Listener.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const BaseCommand = require('./Base')
13 |
14 | /**
15 | * Make a new redis or event listener
16 | *
17 | * @class MakeListener
18 | * @constructor
19 | */
20 | class MakeListener extends BaseCommand {
21 | /**
22 | * The command signature
23 | *
24 | * @method signature
25 | *
26 | * @return {String}
27 | */
28 | static get signature () {
29 | return `
30 | make:listener
31 | { name: Name of the listener }
32 | { -m, --method=@value : The method to be created on listener }
33 | `
34 | }
35 |
36 | /**
37 | * The command description
38 | *
39 | * @method description
40 | *
41 | * @return {String}
42 | */
43 | static get description () {
44 | return 'Make a new event or redis listener'
45 | }
46 |
47 | /**
48 | * Handle method executed by ace
49 | *
50 | * @method handle
51 | *
52 | * @param {String} options.name
53 | * @param {String} options.type
54 | *
55 | * @return {void}
56 | */
57 | async handle ({ name }, { method }) {
58 | await this.invoke(async () => {
59 | await this.ensureInProjectRoot()
60 | await this.generateBlueprint('listener', name, { method })
61 | })
62 | }
63 | }
64 |
65 | module.exports = MakeListener
66 |
--------------------------------------------------------------------------------
/src/Commands/Make/Middleware.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const BaseCommand = require('./Base')
13 |
14 | /**
15 | * Make a new HTTP or Ws middleware
16 | *
17 | * @class MakeMiddleware
18 | * @constructor
19 | */
20 | class MakeMiddleware extends BaseCommand {
21 | /**
22 | * The command signature
23 | *
24 | * @method signature
25 | *
26 | * @return {String}
27 | */
28 | static get signature () {
29 | return `
30 | make:middleware
31 | { name: Name of the middleware }
32 | { --type=@value: The type can be http, ws or both }
33 | `
34 | }
35 |
36 | /**
37 | * The command description
38 | *
39 | * @method description
40 | *
41 | * @return {String}
42 | */
43 | static get description () {
44 | return 'Make a new HTTP or Ws Middleware'
45 | }
46 |
47 | /**
48 | * Returns the resource type for the middleware
49 | *
50 | * @method _getResourceType
51 | *
52 | * @param {String} type
53 | *
54 | * @return {String}
55 | *
56 | * @private
57 | */
58 | async _getResourceType (type) {
59 | if (!type || ['ws', 'http', 'both'].indexOf(type) <= -1) {
60 | type = await this
61 | .on('validate', (value) => !!value)
62 | .choice('Select middleware type', [
63 | {
64 | name: 'For HTTP requests',
65 | value: 'http'
66 | },
67 | {
68 | name: 'For Websocket requests',
69 | value: 'ws'
70 | },
71 | {
72 | name: 'For both HTTP and Websocket requests',
73 | value: 'both'
74 | }
75 | ])
76 | }
77 |
78 | return type
79 | }
80 |
81 | /**
82 | * Handle method executed by ace
83 | *
84 | * @method handle
85 | *
86 | * @param {String} options.name
87 | * @param {String} options.type
88 | *
89 | * @return {void}
90 | */
91 | async handle ({ name }, { type }) {
92 | await this.invoke(async () => {
93 | await this.ensureInProjectRoot()
94 |
95 | const resourceType = await this._getResourceType(type)
96 | const { namespace } = await this.generateBlueprint('middleware', name, { type: resourceType })
97 |
98 | const steps = []
99 |
100 | /**
101 | * Push instructions for http if resource type was
102 | * http or both
103 | */
104 | if (resourceType === 'both' || resourceType === 'http') {
105 | steps.push(`Open ${this.chalk.cyan('start/kernel.js')} file`)
106 | steps.push(`Register ${this.chalk.cyan(namespace)} under global or named middleware`)
107 | }
108 |
109 | /**
110 | * Push instructions for ws if resource type was
111 | * ws or both
112 | */
113 | if (resourceType === 'both' || resourceType === 'ws') {
114 | steps.push(`Open ${this.chalk.cyan('start/ws.js')} file`)
115 | steps.push(`Register ${this.chalk.cyan(namespace)} under global or named middleware`)
116 | }
117 |
118 | this.printInstructions('Register middleware as follows', steps)
119 | })
120 | }
121 | }
122 |
123 | module.exports = MakeMiddleware
124 |
--------------------------------------------------------------------------------
/src/Commands/Make/Migration.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-lucid
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const BaseCommand = require('./Base')
13 |
14 | /**
15 | * Make a new migration file
16 | *
17 | * @class MakeMigration
18 | * @constructor
19 | */
20 | class MakeMigration extends BaseCommand {
21 | /**
22 | * Command signature required by ace
23 | *
24 | * @method signature
25 | *
26 | * @return {String}
27 | */
28 | static get signature () {
29 | return `
30 | make:migration
31 | { name: Name of migration file, current timestamp will be prepended to the name }
32 | { --action?=@value : Choose an action to \`create\` or \`select\` a table }
33 | `
34 | }
35 |
36 | /**
37 | * Command description
38 | *
39 | * @method description
40 | *
41 | * @return {String}
42 | */
43 | static get description () {
44 | return 'Create a new migration file'
45 | }
46 |
47 | /**
48 | * Returns the migration action
49 | *
50 | * @method _getActionType
51 | *
52 | * @param {String} action
53 | *
54 | * @return {String}
55 | */
56 | async _getActionType (action) {
57 | if (!action || ['create', 'select'].indexOf(action) <= -1) {
58 | action = await this.choice('Choose an action', [
59 | {
60 | value: 'create',
61 | name: 'Create table'
62 | },
63 | {
64 | value: 'select',
65 | name: 'Select table'
66 | }
67 | ])
68 | }
69 |
70 | return action
71 | }
72 |
73 | /**
74 | * Method to be called when this command is executed
75 | *
76 | * @method handle
77 | *
78 | * @param {String} options.name
79 | * @param {String} options.action
80 | *
81 | * @return {void|String} - Returns abs path to created file when command
82 | * is not executed by ace.
83 | */
84 | async handle ({ name }, { action }) {
85 | await this.invoke(async () => {
86 | await this.ensureInProjectRoot()
87 |
88 | const actionType = await this._getActionType(action)
89 | await this.generateBlueprint('schema', name, { action: actionType })
90 | })
91 | }
92 | }
93 |
94 | module.exports = MakeMigration
95 |
--------------------------------------------------------------------------------
/src/Commands/Make/Model.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const BaseCommand = require('./Base')
13 |
14 | /**
15 | * Make a new lucid model
16 | *
17 | * @class MakeModel
18 | * @constructor
19 | */
20 | class MakeModel extends BaseCommand {
21 | /**
22 | * The command signature
23 | *
24 | * @method signature
25 | *
26 | * @return {String}
27 | */
28 | static get signature () {
29 | return `
30 | make:model
31 | { name: Name of the model }
32 | { -m, --migration: Generate migration for the model }
33 | { -c, --controller: Generate resourceful controller for the model }
34 | `
35 | }
36 |
37 | /**
38 | * The command description
39 | *
40 | * @method description
41 | *
42 | * @return {String}
43 | */
44 | static get description () {
45 | return 'Make a new lucid model'
46 | }
47 |
48 | /**
49 | * Handle method executed by ace
50 | *
51 | * @method handle
52 | *
53 | * @param {String} options.name
54 | * @param {String} options.type
55 | *
56 | * @return {void}
57 | */
58 | async handle ({ name }, { migration, controller }) {
59 | await this.invoke(async () => {
60 | await this.ensureInProjectRoot()
61 | await this.generateBlueprint('model', name, {})
62 |
63 | if (migration) {
64 | await this.generateBlueprint('schema', name, { action: 'create' })
65 | }
66 |
67 | if (controller) {
68 | await this.generateBlueprint('httpController', name, { resource: controller })
69 | }
70 | })
71 | }
72 | }
73 |
74 | module.exports = MakeModel
75 |
--------------------------------------------------------------------------------
/src/Commands/Make/Provider.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const BaseCommand = require('./Base')
13 |
14 | /**
15 | * Make a new provider
16 | *
17 | * @class MakeProvider
18 | * @constructor
19 | */
20 | class MakeProvider extends BaseCommand {
21 | /**
22 | * The command signature
23 | *
24 | * @method signature
25 | *
26 | * @return {String}
27 | */
28 | static get signature () {
29 | return `
30 | make:provider
31 | { name: Name of the provider }
32 | `
33 | }
34 |
35 | /**
36 | * The command description
37 | *
38 | * @method description
39 | *
40 | * @return {String}
41 | */
42 | static get description () {
43 | return 'Make a new provider'
44 | }
45 |
46 | /**
47 | * Handle method executed by ace
48 | *
49 | * @method handle
50 | *
51 | * @param {String} options.name
52 | * @param {String} options.type
53 | *
54 | * @return {void}
55 | */
56 | async handle ({ name }) {
57 | await this.invoke(async () => {
58 | await this.ensureInProjectRoot()
59 | await this.generateBlueprint('provider', name, {})
60 | })
61 | }
62 | }
63 |
64 | module.exports = MakeProvider
65 |
--------------------------------------------------------------------------------
/src/Commands/Make/Seed.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-lucid
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const BaseCommand = require('./Base')
13 |
14 | /**
15 | * Make a new seed file
16 | *
17 | * @class MakeSeed
18 | * @constructor
19 | */
20 | class MakeSeed extends BaseCommand {
21 | /**
22 | * Command signature required by ace
23 | *
24 | * @method signature
25 | *
26 | * @return {String}
27 | */
28 | static get signature () {
29 | return `
30 | make:seed
31 | { name?=Database: Name of the seed file }
32 | `
33 | }
34 |
35 | /**
36 | * Command description
37 | *
38 | * @method description
39 | *
40 | * @return {String}
41 | */
42 | static get description () {
43 | return 'Create a database seeder'
44 | }
45 |
46 | /**
47 | * Method to be called when this command is executed
48 | *
49 | * @method handle
50 | *
51 | * @param {String} options.name
52 | */
53 | async handle ({ name }) {
54 | await this.invoke(async () => {
55 | await this.ensureInProjectRoot()
56 | await this.generateBlueprint('seed', name)
57 | })
58 | }
59 | }
60 |
61 | module.exports = MakeSeed
62 |
--------------------------------------------------------------------------------
/src/Commands/Make/Trait.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const BaseCommand = require('./Base')
13 |
14 | /**
15 | * Make a new lucid trait
16 | *
17 | * @class MakeTrait
18 | * @constructor
19 | */
20 | class MakeTrait extends BaseCommand {
21 | /**
22 | * The command signature
23 | *
24 | * @method signature
25 | *
26 | * @return {String}
27 | */
28 | static get signature () {
29 | return `
30 | make:trait
31 | { name: Name of the trait }
32 | `
33 | }
34 |
35 | /**
36 | * The command description
37 | *
38 | * @method description
39 | *
40 | * @return {String}
41 | */
42 | static get description () {
43 | return 'Make a new lucid trait'
44 | }
45 |
46 | /**
47 | * Handle method executed by ace
48 | *
49 | * @method handle
50 | *
51 | * @param {String} options.name
52 | *
53 | * @return {void}
54 | */
55 | async handle ({ name }) {
56 | await this.invoke(async () => {
57 | await this.ensureInProjectRoot()
58 | await this.generateBlueprint('trait', name, {})
59 | })
60 | }
61 | }
62 |
63 | module.exports = MakeTrait
64 |
--------------------------------------------------------------------------------
/src/Commands/Make/View.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const BaseCommand = require('./Base')
13 |
14 | /**
15 | * Make a new edge view
16 | *
17 | * @class MakeView
18 | * @constructor
19 | */
20 | class MakeView extends BaseCommand {
21 | /**
22 | * The command signature
23 | *
24 | * @method signature
25 | *
26 | * @return {String}
27 | */
28 | static get signature () {
29 | return `
30 | make:view
31 | { name: Name of the view }
32 | { -l, --layout=@value: Define a layout to extend }
33 | `
34 | }
35 |
36 | /**
37 | * The command description
38 | *
39 | * @method description
40 | *
41 | * @return {String}
42 | */
43 | static get description () {
44 | return 'Make a view file'
45 | }
46 |
47 | /**
48 | * Handle method executed by ace
49 | *
50 | * @method handle
51 | *
52 | * @param {String} options.name
53 | * @param {String} options.type
54 | *
55 | * @return {void}
56 | */
57 | async handle ({ name }, { layout }) {
58 | await this.invoke(async () => {
59 | await this.ensureInProjectRoot()
60 | await this.generateBlueprint('view', name, { layout })
61 | })
62 | }
63 | }
64 |
65 | module.exports = MakeView
66 |
--------------------------------------------------------------------------------
/src/Commands/New/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const path = require('path')
13 | const BaseCommand = require('../Base')
14 |
15 | /**
16 | * This command performs a series of operations
17 | * to be create a new Adonisjs application.
18 | *
19 | * @class NewApp
20 | */
21 | class NewApp extends BaseCommand {
22 | /**
23 | * The command signature required by ace
24 | *
25 | * @attribute signature
26 | * @static
27 | *
28 | * @return {String}
29 | */
30 | static get signature () {
31 | return `
32 | new
33 | { name : Name of the project directory }
34 | { --api-only : Scaffold project for api server }
35 | { --api: Scaffold project for api server }
36 | { --slim : Scaffold smallest possible Adonisjs application }
37 | { --blueprint?=@value : Path to github project blueprint }
38 | { --branch?=@value : Specify git branch for project blueprint }
39 | { --skip-install : Do not install modules from npm }
40 | { --yarn : Use yarn over npm for modules installation }
41 | { --cnpm: Use cnpm over npm for installation }
42 | { --raw : Disable animations and colored output }
43 | `
44 | }
45 |
46 | /**
47 | * The command description required by ace
48 | *
49 | * @attribute description
50 | *
51 | * @return {String}
52 | */
53 | static get description () {
54 | return 'Create a new AdonisJs application'
55 | }
56 |
57 | /**
58 | * Returns the actual blueprint to be used for
59 | * cloning the repo. It will go over the cli
60 | * options and returns the most appropriate
61 | * one.
62 | *
63 | * @method _getBluePrint
64 | *
65 | * @param {Object} options
66 | *
67 | * @return {String}
68 | *
69 | * @private
70 | */
71 | _getBluePrint (options) {
72 | /**
73 | * Use the explicitly defined blueprint
74 | * over any other options.
75 | */
76 | if (options.blueprint) {
77 | return options.blueprint
78 | }
79 |
80 | /**
81 | * If we used the flag --api-only or --api we want
82 | * to fetch the API blueprint.
83 | */
84 | if (options.apiOnly || options.api) {
85 | return 'adonisjs/adonis-api-app'
86 | }
87 |
88 | /**
89 | * If we used the flag --slim we want to fetch
90 | * the SLIM blueprint.
91 | */
92 | if (options.slim) {
93 | return 'adonisjs/adonis-slim-app'
94 | }
95 |
96 | /**
97 | * If none flag has been defiend we fallbacke
98 | * to the Fullstack blueprint.
99 | */
100 | return 'adonisjs/adonis-fullstack-app'
101 | }
102 |
103 | /**
104 | * Ensure node version is correct, then make sure app path is
105 | * empty and finally clone the repo and remove `.git` dir.
106 | *
107 | * @method _setupProjectDirectory
108 | *
109 | * @param {Object} stepsCounter
110 | * @param {String} appPath
111 | * @param {Object} options
112 | *
113 | * @return {void}
114 | *
115 | * @private
116 | */
117 | async _setupProjectDirectory (stepsCounter, appPath, options) {
118 | await require('../../Services/check-node-version')(stepsCounter)
119 | await require('../../Services/verify-existing-folder')(appPath, stepsCounter)
120 | await require('../../Services/clone')(this._getBluePrint(options), appPath, stepsCounter, options.branch)
121 | await this.removeDir(path.join(appPath, '.git'))
122 | }
123 |
124 | /**
125 | * Install dependencies when `skip-install` flag has not been
126 | * passed
127 | *
128 | * @method _installDependencies
129 | *
130 | * @param {Object} stepsCounter
131 | * @param {String} appPath
132 | * @param {Object} options
133 | *
134 | * @return {void}
135 | *
136 | * @private
137 | */
138 | async _installDependencies (stepsCounter, appPath, options) {
139 | if (options.skipInstall) {
140 | return
141 | }
142 | await require('../../Services/install')(options.yarn ? 'yarn' : (options.cnpm ? 'cnpm' : 'npm'), stepsCounter)
143 | }
144 |
145 | /**
146 | * Copy the `.env` file and generate the app key after installation
147 | * of modules have been done.
148 | *
149 | * @method _postInstallation
150 | *
151 | * @param {Object} stepsCounter
152 | * @param {String} appPath
153 | *
154 | * @return {void}
155 | *
156 | * @private
157 | */
158 | async _postInstallation (stepsCounter, appPath) {
159 | await require('../../Services/copy-env-file')(appPath, stepsCounter)
160 | await require('../../Services/generate-app-key')(stepsCounter)
161 | }
162 |
163 | /**
164 | * Prints a message after a new project has been created
165 | *
166 | * @method _onBoardForNewProject
167 | *
168 | * @param {String} appName
169 | *
170 | * @return {void}
171 | *
172 | * @private
173 | */
174 | _onBoardForNewProject (appName) {
175 | const lines = [
176 | '',
177 | '🚀 Successfully created project',
178 | '👉 Get started with the following commands',
179 | '',
180 | `${this.chalk.dim('$')} ${this.chalk.cyan(`cd ${appName}`)}`,
181 | `${this.chalk.dim('$')} ${this.chalk.cyan('adonis serve --dev')}`,
182 | ''
183 | ]
184 |
185 | lines.forEach((line) => {
186 | console.log(line)
187 | })
188 | }
189 |
190 | /**
191 | * Handle method executed by ace to setup a new app
192 | *
193 | * @method handle
194 | *
195 | * @param {String} options.name
196 | * @param {Object} options
197 | *
198 | * @return {void}
199 | */
200 | async handle ({ name }, options) {
201 | const appPath = path.join(process.cwd(), name)
202 | const stepsCounter = this.initiateSteps(options.skipInstall ? 5 : 6, options)
203 |
204 | this.invoke(async () => {
205 | this.dumpAsciiLogo()
206 | await this._setupProjectDirectory(stepsCounter, appPath, options)
207 |
208 | process.chdir(appPath)
209 |
210 | await this._installDependencies(stepsCounter, appPath, options)
211 | await this._postInstallation(stepsCounter, appPath)
212 | this._onBoardForNewProject(name)
213 | })
214 | }
215 | }
216 |
217 | module.exports = NewApp
218 |
--------------------------------------------------------------------------------
/src/Commands/Repl/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const fs = require('fs')
13 | const os = require('os')
14 | const path = require('path')
15 | const { Command } = require('../../../lib/ace')
16 |
17 | const historyFile = path.join(os.homedir(), '/.adonis_repl_history')
18 |
19 | /**
20 | * Start the repl server session
21 | *
22 | * @class Repl
23 | * @constructor
24 | */
25 | class Repl extends Command {
26 | /**
27 | * The command signature used by ace
28 | *
29 | * @method signature
30 | *
31 | * @return {String}
32 | */
33 | static get signature () {
34 | return 'repl'
35 | }
36 |
37 | /**
38 | * The command description used by ace
39 | *
40 | * @method description
41 | *
42 | * @return {String}
43 | */
44 | static get description () {
45 | return 'Start a new repl session'
46 | }
47 |
48 | /**
49 | * Reads the history file
50 | *
51 | * @param {Object} repl
52 | *
53 | * @private
54 | */
55 | _readHistoryFile (repl) {
56 | try {
57 | fs.statSync(historyFile)
58 | } catch (error) {
59 | fs.closeSync(fs.openSync(historyFile, 'w'))
60 | }
61 |
62 | repl.rli.history = fs.readFileSync(historyFile, 'utf-8').split('\n').reverse()
63 | repl.rli.history.shift()
64 | repl.rli.historyIndex = -1
65 | }
66 |
67 | /**
68 | * Save the history to the history file.
69 | *
70 | * @param {Object} repl
71 | *
72 | * @private
73 | */
74 | _addHistorySaveListener (repl) {
75 | const fd = fs.openSync(historyFile, 'a')
76 | repl.rli.addListener('line', (code) => {
77 | if (code && code !== '.history') {
78 | fs.write(fd, `${code}\n`, (error) => { if (error) console.log(error) })
79 | return
80 | }
81 | repl.rli.historyIndex++
82 | repl.rli.history.pop()
83 | })
84 |
85 | process.on('exit', function () {
86 | fs.closeSync(fd)
87 | })
88 | }
89 |
90 | /**
91 | * Method executed by ace to start the command line
92 | * repl
93 | *
94 | * @method handle
95 | *
96 | * @return {void}
97 | */
98 | async handle () {
99 | const awaitOutside = require('adonis-await-outside')
100 | const server = require('repl').start()
101 |
102 | if (typeof (global.use) === 'undefined') {
103 | this.info('You are running repl outside of Adonisjs app')
104 | } else {
105 | server.context.use = global.use
106 | server.context.make = global.make
107 | }
108 |
109 | this._readHistoryFile(server)
110 | this._addHistorySaveListener(server)
111 | awaitOutside.addAwaitOutsideToReplServer(server)
112 | }
113 | }
114 |
115 | module.exports = Repl
116 |
--------------------------------------------------------------------------------
/src/Commands/RouteList/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const BaseCommand = require('../Base')
13 |
14 | /**
15 | * Start the repl server session
16 | *
17 | * @class RouteList
18 | * @constructor
19 | */
20 | class RouteList extends BaseCommand {
21 | static get inject () {
22 | return ['Adonis/Src/Route']
23 | }
24 |
25 | /**
26 | * The command signature used by ace
27 | *
28 | * @method signature
29 | *
30 | * @return {String}
31 | */
32 | static get signature () {
33 | return 'route:list'
34 | }
35 |
36 | /**
37 | * The command description used by ace
38 | *
39 | * @method description
40 | *
41 | * @return {String}
42 | */
43 | static get description () {
44 | return 'List all registered routes'
45 | }
46 |
47 | constructor (Route) {
48 | super()
49 | this.Route = Route
50 | }
51 |
52 | /**
53 | * Returns stringfied version of a function
54 | *
55 | * @method _toString
56 | *
57 | * @param {Function} fn
58 | *
59 | * @return {String}
60 | *
61 | * @private
62 | */
63 | _toString (fn) {
64 | return typeof (fn) === 'string' ? fn : 'Closure'
65 | }
66 |
67 | /**
68 | * Returns the route row for the table
69 | *
70 | * @method _getRow
71 | *
72 | * @param {Object} route
73 | *
74 | * @return {Array}
75 | */
76 | _getRow (route) {
77 | const routeJson = route.toJSON()
78 |
79 | return [
80 | routeJson.route,
81 | routeJson.verbs.join(','),
82 | this._toString(routeJson.handler),
83 | routeJson.middleware.map((middleware) => this._toString(middleware)).join(','),
84 | routeJson.name,
85 | routeJson.domain || ''
86 | ]
87 | }
88 |
89 | /**
90 | * Method executed by ace to list all routes
91 | *
92 | * @method handle
93 | *
94 | * @return {void}
95 | */
96 | async handle () {
97 | this.invoke(async () => {
98 | await this.ensureInProjectRoot()
99 |
100 | this.table(
101 | ['Route', 'Verb(s)', 'Handler', 'Middleware', 'Name', 'Domain'],
102 | this.Route.list().map(this._getRow.bind(this))
103 | )
104 | })
105 | }
106 | }
107 |
108 | module.exports = RouteList
109 |
--------------------------------------------------------------------------------
/src/Commands/Serve/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const path = require('path')
13 | const { Command } = require('../../../lib/ace')
14 |
15 | /**
16 | * Serve the application using forever
17 | *
18 | * @class Serve
19 | * @constructor
20 | */
21 | class Serve extends Command {
22 | /**
23 | * The command signature used by ace
24 | *
25 | * @method signature
26 | *
27 | * @return {String}
28 | */
29 | static get signature () {
30 | return `
31 | serve
32 | { --dev : Start development server }
33 | { -w, --watch=@value : A custom set of only files to watch },
34 | { -e, --ext=@value : A custom set of extensions to watch. In development, they will be merged with the default .js and .json },
35 | { -i, --ignore=@value : A custom set of folders to ignore watching },
36 | { -p, --polling : Use polling to find file changes. Also required when using Docker }
37 | { --debug?=@value: Start server in debug mode }
38 | `
39 | }
40 |
41 | /**
42 | * The command description used by ace
43 | *
44 | * @method description
45 | *
46 | * @return {String}
47 | */
48 | static get description () {
49 | return 'Start Http server'
50 | }
51 |
52 | /**
53 | * Console message when server started
54 | *
55 | * @method started
56 | *
57 | * @package {Boolean} dev
58 | *
59 | * @return {void}
60 | */
61 | started (dev, debug) {
62 | console.log('')
63 | console.log(`${this.chalk.bgGreen.black(' SERVER STARTED ')}`)
64 | if (debug) {
65 | console.log(`> Visit chrome://inspect to debug your app`)
66 | }
67 | if (dev) {
68 | console.log(`> Watching files for changes...`)
69 | }
70 | console.log('')
71 | }
72 |
73 | /**
74 | * This method is executed when nodemon restarts
75 | *
76 | * @method onRestart
77 | *
78 | * @param {Array} files
79 | *
80 | * @return {void}
81 | */
82 | onRestart (files) {
83 | if (files.length > 1) {
84 | console.log(this.chalk.magenta('File(s) changed'))
85 | files.forEach((file) => console.log(file.replace(process.cwd(), '').replace(path.sep, '')))
86 | } else {
87 | const fileName = files[0].replace(process.cwd(), '').replace(path.sep, '')
88 | console.log(`${this.chalk.magenta('changed')} ${fileName}`)
89 | }
90 | }
91 |
92 | /**
93 | * Message to log on crash
94 | *
95 | * @method onCrash
96 | *
97 | * @return {void}
98 | */
99 | onCrash () {
100 | this.error('Application crashed, make sure to kill all related running process, fix the issue and re-run the app')
101 | }
102 |
103 | /**
104 | * Listening for on quite event
105 | *
106 | * @method onQuit
107 | *
108 | * @param {String} domain
109 | *
110 | * @return {void}
111 | */
112 | onQuit () {
113 | process.exit(0)
114 | }
115 |
116 | /**
117 | * Method executed by ace to start the HTTP server
118 | *
119 | * @method handle
120 | *
121 | * @param {Object} args
122 | * @param {Boolean} options.dev
123 | *
124 | * @return {void}
125 | */
126 | async handle (args, { dev, watch, debug, ignore, polling, ext }) {
127 | const acePath = path.join(process.cwd(), 'ace')
128 | const appFile = path.join(process.cwd(), 'server.js')
129 | const exists = await this.pathExists(acePath)
130 |
131 | if (!exists) {
132 | this.error('Make sure you are inside an adonisjs app to start the server')
133 | return
134 | }
135 |
136 | /**
137 | * If user has defined files to watch, then switch to
138 | * dev version automatically
139 | */
140 | if (watch && typeof (watch) === 'string') {
141 | watch = watch.split(',').map((item) => item.trim())
142 | dev = true
143 | }
144 |
145 | /**
146 | * The file extensions only when dev mode
147 | * is true
148 | */
149 | if (dev) {
150 | ext = `${ext || ''} js json`
151 | } else {
152 | ext = ext || 'null'
153 | }
154 |
155 | /**
156 | * Directories to watch
157 | */
158 | const watchDirs = watch || (dev ? [process.cwd(), '.env'] : [])
159 |
160 | /**
161 | * Custom debug port
162 | */
163 | let execJsCommand = 'node'
164 | if (debug) {
165 | execJsCommand += ' --inspect'
166 | if (typeof (debug) === 'string') {
167 | execJsCommand += '=' + debug
168 | }
169 | }
170 |
171 | const nodemon = require('nodemon')
172 |
173 | nodemon({
174 | script: appFile,
175 | execMap: {
176 | js: execJsCommand
177 | },
178 | ext: ext,
179 | legacyWatch: !!polling,
180 | ignore: ['/tmp/*', '/resources/*', '/public/*'].concat(ignore || []).map((folder) => `${process.cwd()}/${folder}`),
181 | watch: watchDirs,
182 | stdin: false
183 | })
184 |
185 | this.started(dev, debug)
186 |
187 | /**
188 | * Listeners
189 | */
190 | nodemon
191 | .on('restart', this.onRestart.bind(this))
192 | .on('crash', this.onCrash.bind(this))
193 | .on('quit', () => (this.onQuit()))
194 | }
195 | }
196 |
197 | module.exports = Serve
198 |
--------------------------------------------------------------------------------
/src/Commands/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | /**
13 | * Exporting a list of internal commands
14 | *
15 | * @type {Array}
16 | */
17 | module.exports = {
18 | new: require('./New'),
19 | addon: require('./Addon'),
20 | install: require('./Install'),
21 | serve: require('./Serve'),
22 | 'key:generate': require('./KeyGenerate'),
23 | 'make:controller': require('./Make/Controller'),
24 | 'make:model': require('./Make/Model'),
25 | 'make:trait': require('./Make/Trait'),
26 | 'make:view': require('./Make/View'),
27 | 'make:middleware': require('./Make/Middleware'),
28 | 'make:command': require('./Make/Command'),
29 | 'make:exception': require('./Make/Exception'),
30 | 'make:hook': require('./Make/Hook'),
31 | 'make:migration': require('./Make/Migration'),
32 | 'make:listener': require('./Make/Listener'),
33 | 'make:provider': require('./Make/Provider'),
34 | 'repl': require('./Repl'),
35 | 'make:ehandler': require('./Make/ExceptionHandler'),
36 | 'make:seed': require('./Make/Seed'),
37 | 'route:list': require('./RouteList'),
38 | 'run:instructions': require('./Instructions')
39 | }
40 |
--------------------------------------------------------------------------------
/src/Generators/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const path = require('path')
13 | const _ = require('lodash')
14 | const pluralize = require('pluralize')
15 | const generators = exports = module.exports = {}
16 |
17 | generators.provider = {
18 | /**
19 | * Returns the data to be sent to the provider
20 | * template
21 | *
22 | * @method getData
23 | *
24 | * @param {String} name
25 | * @param {Object} flags
26 | *
27 | * @return {Object}
28 | */
29 | getData (name, flags) {
30 | return {
31 | name: this.getFileName(name)
32 | }
33 | },
34 |
35 | /**
36 | * Returns file name for provider.
37 | *
38 | * @method getFileName
39 | *
40 | * @param {String} name
41 | *
42 | * @return {String}
43 | */
44 | getFileName (name) {
45 | name = name.replace(/provider/ig, '')
46 | return `${pluralize.singular(_.upperFirst(_.camelCase(name)))}Provider`
47 | },
48 |
49 | /**
50 | * Returns path to the provider file
51 | *
52 | * @method getFilePath
53 | *
54 | * @param {String} name
55 | * @param {Object} options
56 | *
57 | * @return {String}
58 | */
59 | getFilePath (name, options) {
60 | const baseName = path.basename(name)
61 | const normalizedName = name.replace(baseName, this.getFileName(baseName))
62 | return path.join(options.appRoot, options.dirs.providers, normalizedName) + '.js'
63 | }
64 | }
65 |
66 | generators.httpController = {
67 | /**
68 | * Returns the data to be sent to the controller
69 | * template
70 | *
71 | * @method getData
72 | *
73 | * @param {String} name
74 | * @param {Object} flags
75 | *
76 | * @return {Object}
77 | */
78 | getData (name, flags) {
79 | return {
80 | name: this.getFileName(name),
81 | resource: !!flags.resource,
82 | resourceName: this.getResourceName(name),
83 | resourceNamePlural: pluralize(this.getResourceName(name))
84 | }
85 | },
86 |
87 | /**
88 | * Returns file name for controller.
89 | *
90 | * @method getFileName
91 | *
92 | * @param {String} name
93 | *
94 | * @return {String}
95 | */
96 | getFileName (name) {
97 | name = name.replace(/controller/ig, '')
98 | return `${pluralize.singular(_.upperFirst(_.camelCase(name)))}Controller`
99 | },
100 |
101 | /**
102 | * Returns name of resource from controller name.
103 | *
104 | * @method getResourceName
105 | *
106 | * @param {String} name
107 | *
108 | * @return {String}
109 | */
110 | getResourceName (name) {
111 | return this.getFileName(name).replace('Controller', '').toLowerCase()
112 | },
113 |
114 | /**
115 | * Returns path to the controller file
116 | *
117 | * @method getFilePath
118 | *
119 | * @param {String} name
120 | * @param {Object} options
121 | *
122 | * @return {String}
123 | */
124 | getFilePath (name, options) {
125 | const baseName = path.basename(name)
126 | const normalizedName = name.replace(baseName, this.getFileName(baseName))
127 | return path.join(options.appRoot, options.appDir, options.dirs.httpControllers, normalizedName) + '.js'
128 | }
129 | }
130 |
131 | generators.model = {
132 | /**
133 | * Returns data object for the model
134 | * template file
135 | *
136 | * @method getData
137 | *
138 | * @param {String} name
139 | *
140 | * @return {Object}
141 | */
142 | getData (name) {
143 | return {
144 | name: this.getFileName(name)
145 | }
146 | },
147 |
148 | /**
149 | * Returns the model file name
150 | *
151 | * @method getFileName
152 | *
153 | * @param {String} name
154 | *
155 | * @return {String}
156 | */
157 | getFileName (name, appPath) {
158 | name = name.replace(/model/ig, '')
159 | return `${pluralize.singular(_.upperFirst(_.camelCase(name)))}`
160 | },
161 |
162 | /**
163 | * Returns file path to the model file
164 | *
165 | * @method getFilePath
166 | *
167 | * @param {String} name
168 | * @param {Object} options
169 | *
170 | * @return {String}
171 | */
172 | getFilePath (name, options) {
173 | const baseName = path.basename(name)
174 | const normalizedName = name.replace(baseName, this.getFileName(baseName))
175 | return path.join(options.appRoot, options.appDir, options.dirs.models, normalizedName) + '.js'
176 | }
177 | }
178 |
179 | generators.trait = {
180 | /**
181 | * Returns data object for the trait
182 | * template file
183 | *
184 | * @method getData
185 | *
186 | * @param {String} name
187 | *
188 | * @return {Object}
189 | */
190 | getData (name) {
191 | return {
192 | name: this.getFileName(name)
193 | }
194 | },
195 |
196 | /**
197 | * Returns the trait file name
198 | *
199 | * @method getFileName
200 | *
201 | * @param {String} name
202 | *
203 | * @return {String}
204 | */
205 | getFileName (name, appPath) {
206 | name = name.replace(/trait/ig, '')
207 | return `${pluralize.singular(_.upperFirst(_.camelCase(name)))}`
208 | },
209 |
210 | /**
211 | * Returns file path to the trait file
212 | *
213 | * @method getFilePath
214 | *
215 | * @param {String} name
216 | * @param {Object} options
217 | *
218 | * @return {String}
219 | */
220 | getFilePath (name, options) {
221 | const baseName = path.basename(name)
222 | const normalizedName = name.replace(baseName, this.getFileName(baseName))
223 | return path.join(options.appRoot, options.appDir, options.dirs.traits, normalizedName) + '.js'
224 | }
225 | }
226 |
227 | generators.middleware = {
228 | /**
229 | * Returns data for the middleware template
230 | *
231 | * @method getData
232 | *
233 | * @param {String} name
234 | *
235 | * @return {Object}
236 | */
237 | getData (name, flags) {
238 | return {
239 | name: this.getFileName(name),
240 | http: flags.type === 'http' || flags.type === 'both',
241 | ws: flags.type === 'ws' || flags.type === 'both'
242 | }
243 | },
244 |
245 | /**
246 | * Returns file name for the middleware file
247 | *
248 | * @method getFileName
249 | *
250 | * @param {String} name
251 | *
252 | * @return {String}
253 | */
254 | getFileName (name, appPath) {
255 | name = name.replace(/middleware/ig, '')
256 | return `${pluralize.singular(_.upperFirst(_.camelCase(name)))}`
257 | },
258 |
259 | /**
260 | * Returns file path for the middleware file
261 | *
262 | * @method getFilePath
263 | *
264 | * @param {String} name
265 | * @param {Object} options
266 | *
267 | * @return {String}
268 | */
269 | getFilePath (name, options) {
270 | const baseName = path.basename(name)
271 | const normalizedName = name.replace(baseName, this.getFileName(baseName))
272 | return path.join(options.appRoot, options.appDir, options.dirs.middleware, normalizedName) + '.js'
273 | }
274 | }
275 |
276 | generators.hook = {
277 | /**
278 | * Returns data for the hook template
279 | *
280 | * @method getData
281 | *
282 | * @param {String} name
283 | * @param {Object} flags
284 | *
285 | * @return {Object}
286 | */
287 | getData (name, flags) {
288 | return {
289 | name: this.getFileName(name),
290 | method: flags.method && typeof (flags.method) === 'string' ? flags.method : 'method'
291 | }
292 | },
293 |
294 | /**
295 | * Returns file name for the hook file
296 | *
297 | * @method getFileName
298 | *
299 | * @param {String} name
300 | *
301 | * @return {String}
302 | */
303 | getFileName (name, appPath) {
304 | name = name.replace(/hook/ig, '')
305 | return `${pluralize.singular(_.upperFirst(_.camelCase(name)))}Hook`
306 | },
307 |
308 | /**
309 | * Returns file path for the hook file
310 | *
311 | * @method getFilePath
312 | *
313 | * @param {String} name
314 | * @param {Object} options
315 | *
316 | * @return {String}
317 | */
318 | getFilePath (name, options) {
319 | const baseName = path.basename(name)
320 | const normalizedName = name.replace(baseName, this.getFileName(baseName))
321 | return path.join(options.appRoot, options.appDir, options.dirs.hooks, normalizedName) + '.js'
322 | }
323 | }
324 |
325 | generators.view = {
326 | /**
327 | * Returns data for the view template
328 | *
329 | * @method getData
330 | *
331 | * @param {String} name
332 | * @param {Object} flags
333 | *
334 | * @return {Object}
335 | */
336 | getData (name, flags) {
337 | return {
338 | layout: flags.layout && typeof (flags.layout) === 'string' ? flags.layout : null
339 | }
340 | },
341 |
342 | /**
343 | * Returns file name for the view file
344 | *
345 | * @method getFileName
346 | *
347 | * @param {String} name
348 | *
349 | * @return {String}
350 | */
351 | getFileName (name, appPath) {
352 | return _.toLower(name).replace(/view/ig, '').replace(/\./g, '/')
353 | },
354 |
355 | /**
356 | * Returns file path for the hook file
357 | *
358 | * @method getFilePath
359 | *
360 | * @param {String} name
361 | * @param {Object} options
362 | *
363 | * @return {String}
364 | */
365 | getFilePath (name, options) {
366 | return path.join(options.appRoot, options.dirs.views, this.getFileName(name)) + '.edge'
367 | }
368 | }
369 |
370 | generators.command = {
371 | /**
372 | * Returns data for the command template
373 | *
374 | * @method getData
375 | *
376 | * @param {String} name
377 | * @param {Object} flags
378 | *
379 | * @return {Object}
380 | */
381 | getData (name, flags) {
382 | return {
383 | name: this.getFileName(name),
384 | commandName: _.snakeCase(this.getFileName(name)).replace(/_/g, ':')
385 | }
386 | },
387 |
388 | /**
389 | * Returns file name for the command file
390 | *
391 | * @method getFileName
392 | *
393 | * @param {String} name
394 | *
395 | * @return {String}
396 | */
397 | getFileName (name, appPath) {
398 | name = name.replace(/command/ig, '')
399 | return pluralize.singular(_.upperFirst(_.camelCase(name)))
400 | },
401 |
402 | /**
403 | * Returns file path for the command file
404 | *
405 | * @method getFilePath
406 | *
407 | * @param {String} name
408 | * @param {Object} options
409 | *
410 | * @return {String}
411 | */
412 | getFilePath (name, options) {
413 | const baseName = path.basename(name)
414 | const normalizedName = name.replace(baseName, this.getFileName(baseName))
415 | return path.join(options.appRoot, options.appDir, options.dirs.commands, normalizedName) + '.js'
416 | }
417 | }
418 |
419 | generators.schema = {
420 | /**
421 | * Returns data for the migration schema template
422 | *
423 | * @method getData
424 | *
425 | * @param {String} name
426 | * @param {Object} flags
427 | *
428 | * @return {Object}
429 | */
430 | getData (name, flags) {
431 | name = this.getFileName(name)
432 | return {
433 | create: flags.action === 'create',
434 | table: _.snakeCase(pluralize(name.replace('Schema', ''))),
435 | name: name
436 | }
437 | },
438 |
439 | /**
440 | * Returns file name for the schema migration file
441 | *
442 | * @method getFileName
443 | *
444 | * @param {String} name
445 | *
446 | * @return {String}
447 | */
448 | getFileName (name, appPath) {
449 | name = name.replace(/schema|table/ig, '')
450 | return `${_.upperFirst(_.camelCase(name))}Schema`
451 | },
452 |
453 | /**
454 | * Returns file path for the schema migration file
455 | *
456 | * @method getFilePath
457 | *
458 | * @param {String} name
459 | * @param {Object} options
460 | *
461 | * @return {String}
462 | */
463 | getFilePath (name, options) {
464 | const fileName = `${new Date().getTime()}_${_.snakeCase(this.getFileName(name))}`
465 | return path.join(options.appRoot, options.dirs.migrations, fileName) + '.js'
466 | }
467 | }
468 |
469 | generators.listener = {
470 | /**
471 | * Returns data for the listener template
472 | *
473 | * @method getData
474 | *
475 | * @param {String} name
476 | * @param {Object} flags
477 | *
478 | * @return {Object}
479 | */
480 | getData (name, flags) {
481 | return {
482 | name: this.getFileName(name),
483 | method: flags.method && typeof (flags.method) === 'string' ? flags.method : 'method'
484 | }
485 | },
486 |
487 | /**
488 | * Returns file name for the listener file
489 | *
490 | * @method getFileName
491 | *
492 | * @param {String} name
493 | *
494 | * @return {String}
495 | */
496 | getFileName (name, appPath) {
497 | name = name.replace(/listener/ig, '')
498 | return `${_.upperFirst(_.camelCase(name))}`
499 | },
500 |
501 | /**
502 | * Returns file path for the hook file
503 | *
504 | * @method getFilePath
505 | *
506 | * @param {String} name
507 | * @param {Object} options
508 | *
509 | * @return {String}
510 | */
511 | getFilePath (name, options) {
512 | const baseName = path.basename(name)
513 | const normalizedName = name.replace(baseName, this.getFileName(baseName))
514 | return path.join(options.appRoot, options.appDir, options.dirs.listeners, normalizedName) + '.js'
515 | }
516 | }
517 |
518 | generators.exceptionHandler = {
519 | /**
520 | * Returns data for the exception handler template
521 | *
522 | * @method getData
523 | *
524 | * @return {Object}
525 | */
526 | getData (name, flags) {
527 | return flags || {}
528 | },
529 |
530 | /**
531 | * Returns file name for the exception handler file
532 | *
533 | * @return {String}
534 | */
535 | getFileName () {
536 | return 'Handler'
537 | },
538 |
539 | /**
540 | * Returns file path for the exception handler file
541 | *
542 | * @method getFilePath
543 | *
544 | * @param {String} name
545 | * @param {Object} options
546 | *
547 | * @return {String}
548 | */
549 | getFilePath (name, options) {
550 | const baseName = path.basename(name)
551 | const normalizedName = name.replace(baseName, this.getFileName(baseName))
552 | return path.join(options.appRoot, options.appDir, options.dirs.exceptions, normalizedName) + '.js'
553 | }
554 | }
555 |
556 | generators.seed = {
557 | /**
558 | * Returns data object for the seed
559 | * template file
560 | *
561 | * @method getData
562 | *
563 | * @param {String} name
564 | *
565 | * @return {Object}
566 | */
567 | getData (name) {
568 | return {
569 | name: this.getFileName(name)
570 | }
571 | },
572 |
573 | /**
574 | * Returns the seed file name
575 | *
576 | * @method getFileName
577 | *
578 | * @param {String} name
579 | *
580 | * @return {String}
581 | */
582 | getFileName (name, appPath) {
583 | name = name.replace(/seed(er)?/ig, '')
584 | return `${pluralize.singular(_.upperFirst(_.camelCase(name)))}Seeder`
585 | },
586 |
587 | /**
588 | * Returns file path to the model file
589 | *
590 | * @method getFilePath
591 | *
592 | * @param {String} name
593 | * @param {Object} options
594 | *
595 | * @return {String}
596 | */
597 | getFilePath (name, options) {
598 | const baseName = path.basename(name)
599 | const normalizedName = name.replace(baseName, this.getFileName(baseName))
600 | return path.join(options.appRoot, options.dirs.seeds, normalizedName) + '.js'
601 | }
602 | }
603 |
604 | generators.wsController = {
605 | /**
606 | * Returns the data to be sent to the controller
607 | * template
608 | *
609 | * @method getData
610 | *
611 | * @param {String} name
612 | *
613 | * @return {Object}
614 | */
615 | getData (name) {
616 | return {
617 | name: this.getFileName(name)
618 | }
619 | },
620 |
621 | /**
622 | * Returns file name for controller.
623 | *
624 | * @method getFileName
625 | *
626 | * @param {String} name
627 | *
628 | * @return {String}
629 | */
630 | getFileName (name) {
631 | name = name.replace(/controller/ig, '')
632 | return `${pluralize.singular(_.upperFirst(_.camelCase(name)))}Controller`
633 | },
634 |
635 | /**
636 | * Returns path to the controller file
637 | *
638 | * @method getFilePath
639 | *
640 | * @param {String} name
641 | * @param {Object} options
642 | *
643 | * @return {String}
644 | */
645 | getFilePath (name, options) {
646 | const baseName = path.basename(name)
647 | const normalizedName = name.replace(baseName, this.getFileName(baseName))
648 | return path.join(options.appRoot, options.appDir, options.dirs.wsControllers, normalizedName) + '.js'
649 | }
650 | }
651 |
652 | generators.exception = {
653 | /**
654 | * Returns the data to be sent to the exception
655 | * template
656 | *
657 | * @method getData
658 | *
659 | * @param {String} name
660 | * @param {Object} flags
661 | *
662 | * @return {Object}
663 | */
664 | getData (name, flags) {
665 | return {
666 | name: this.getFileName(name)
667 | }
668 | },
669 |
670 | /**
671 | * Returns file name for exception class.
672 | *
673 | * @method getFileName
674 | *
675 | * @param {String} name
676 | *
677 | * @return {String}
678 | */
679 | getFileName (name) {
680 | name = name.replace(/exception/ig, '')
681 | return `${pluralize.singular(_.upperFirst(_.camelCase(name)))}Exception`
682 | },
683 |
684 | /**
685 | * Returns path to the exception file
686 | *
687 | * @method getFilePath
688 | *
689 | * @param {String} name
690 | * @param {Object} options
691 | *
692 | * @return {String}
693 | */
694 | getFilePath (name, options) {
695 | const baseName = path.basename(name)
696 | const normalizedName = name.replace(baseName, this.getFileName(baseName))
697 | return path.join(options.appRoot, options.appDir, options.dirs.exceptions, normalizedName) + '.js'
698 | }
699 | }
700 |
--------------------------------------------------------------------------------
/src/Generators/templates/command.mustache:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const { Command } = require('@adonisjs/ace')
4 |
5 | class {{name}} extends Command {
6 | static get signature () {
7 | return '{{commandName}}'
8 | }
9 |
10 | static get description () {
11 | return 'Tell something helpful about this command'
12 | }
13 |
14 | async handle (args, options) {
15 | this.info('Dummy implementation for {{commandName}} command')
16 | }
17 | }
18 |
19 | module.exports = {{name}}
20 |
--------------------------------------------------------------------------------
/src/Generators/templates/exception.mustache:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const { LogicalException } = require('@adonisjs/generic-exceptions')
4 |
5 | class {{ name }} extends LogicalException {
6 | /**
7 | * Handle this exception by itself
8 | */
9 | // handle () {}
10 | }
11 |
12 | module.exports = {{ name }}
13 |
--------------------------------------------------------------------------------
/src/Generators/templates/exceptionHandler.mustache:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | {{#new}}
4 | const BaseExceptionHandler = use('BaseExceptionHandler')
5 |
6 | /**
7 | * This class handles all exceptions thrown during
8 | * the HTTP request lifecycle.
9 | *
10 | * @class ExceptionHandler
11 | */
12 | class ExceptionHandler extends BaseExceptionHandler {
13 | /**
14 | * Handle exception thrown during the HTTP lifecycle
15 | *
16 | * @method handle
17 | *
18 | * @param {Object} error
19 | * @param {Object} options.request
20 | * @param {Object} options.response
21 | *
22 | * @return {void}
23 | */
24 | async handle (error, { request, response }) {
25 | response.status(error.status).send(error.message)
26 | }
27 |
28 | /**
29 | * Report exception for logging or debugging.
30 | *
31 | * @method report
32 | *
33 | * @param {Object} error
34 | * @param {Object} options.request
35 | *
36 | * @return {void}
37 | */
38 | async report (error, { request }) {
39 | }
40 | }
41 | {{/new}}
42 | {{^new}}
43 | /**
44 | * This class handles all exceptions thrown during
45 | * the HTTP request lifecycle.
46 | *
47 | * @class ExceptionHandler
48 | */
49 | class ExceptionHandler {
50 | /**
51 | * Handle exception thrown during the HTTP lifecycle
52 | *
53 | * @method handle
54 | *
55 | * @param {Object} error
56 | * @param {Object} options.request
57 | * @param {Object} options.response
58 | *
59 | * @return {void}
60 | */
61 | async handle (error, { request, response }) {
62 | response.status(error.status).send(error.message)
63 | }
64 |
65 | /**
66 | * Report exception for logging or debugging.
67 | *
68 | * @method report
69 | *
70 | * @param {Object} error
71 | * @param {Object} options.request
72 | *
73 | * @return {void}
74 | */
75 | async report (error, { request }) {
76 | }
77 | }
78 | {{/new}}
79 |
80 | module.exports = ExceptionHandler
81 |
--------------------------------------------------------------------------------
/src/Generators/templates/hook.mustache:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const {{name}} = exports = module.exports = {}
4 |
5 | {{name}}.{{method}} = async (modelInstance) => {
6 | }
7 |
--------------------------------------------------------------------------------
/src/Generators/templates/httpController.mustache:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | {{#resource}}
4 | /** @typedef {import('@adonisjs/framework/src/Request')} Request */
5 | /** @typedef {import('@adonisjs/framework/src/Response')} Response */
6 | /** @typedef {import('@adonisjs/framework/src/View')} View */
7 |
8 | /**
9 | * Resourceful controller for interacting with {{resourceNamePlural}}
10 | */
11 | {{/resource}}
12 | class {{name}} {
13 | {{#resource}}
14 | /**
15 | * Show a list of all {{resourceNamePlural}}.
16 | * GET {{resourceNamePlural}}
17 | *
18 | * @param {object} ctx
19 | * @param {Request} ctx.request
20 | * @param {Response} ctx.response
21 | * @param {View} ctx.view
22 | */
23 | async index ({ request, response, view }) {
24 | }
25 |
26 | /**
27 | * Render a form to be used for creating a new {{resourceName}}.
28 | * GET {{resourceNamePlural}}/create
29 | *
30 | * @param {object} ctx
31 | * @param {Request} ctx.request
32 | * @param {Response} ctx.response
33 | * @param {View} ctx.view
34 | */
35 | async create ({ request, response, view }) {
36 | }
37 |
38 | /**
39 | * Create/save a new {{resourceName}}.
40 | * POST {{resourceNamePlural}}
41 | *
42 | * @param {object} ctx
43 | * @param {Request} ctx.request
44 | * @param {Response} ctx.response
45 | */
46 | async store ({ request, response }) {
47 | }
48 |
49 | /**
50 | * Display a single {{resourceName}}.
51 | * GET {{resourceNamePlural}}/:id
52 | *
53 | * @param {object} ctx
54 | * @param {Request} ctx.request
55 | * @param {Response} ctx.response
56 | * @param {View} ctx.view
57 | */
58 | async show ({ params, request, response, view }) {
59 | }
60 |
61 | /**
62 | * Render a form to update an existing {{resourceName}}.
63 | * GET {{resourceNamePlural}}/:id/edit
64 | *
65 | * @param {object} ctx
66 | * @param {Request} ctx.request
67 | * @param {Response} ctx.response
68 | * @param {View} ctx.view
69 | */
70 | async edit ({ params, request, response, view }) {
71 | }
72 |
73 | /**
74 | * Update {{resourceName}} details.
75 | * PUT or PATCH {{resourceNamePlural}}/:id
76 | *
77 | * @param {object} ctx
78 | * @param {Request} ctx.request
79 | * @param {Response} ctx.response
80 | */
81 | async update ({ params, request, response }) {
82 | }
83 |
84 | /**
85 | * Delete a {{resourceName}} with id.
86 | * DELETE {{resourceNamePlural}}/:id
87 | *
88 | * @param {object} ctx
89 | * @param {Request} ctx.request
90 | * @param {Response} ctx.response
91 | */
92 | async destroy ({ params, request, response }) {
93 | }
94 | {{/resource}}
95 | }
96 |
97 | module.exports = {{name}}
98 |
--------------------------------------------------------------------------------
/src/Generators/templates/listener.mustache:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const {{name}} = exports = module.exports = {}
4 |
5 | {{name}}.{{method}} = async () => {
6 | }
7 |
--------------------------------------------------------------------------------
/src/Generators/templates/middleware.mustache:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | /** @typedef {import('@adonisjs/framework/src/Request')} Request */
3 | /** @typedef {import('@adonisjs/framework/src/Response')} Response */
4 | /** @typedef {import('@adonisjs/framework/src/View')} View */
5 |
6 | class {{name}} {
7 | {{#http}}
8 | /**
9 | * @param {object} ctx
10 | * @param {Request} ctx.request
11 | * @param {Function} next
12 | */
13 | async handle ({ request }, next) {
14 | // call next to advance the request
15 | await next()
16 | }
17 | {{/http}}
18 | {{#ws}}
19 |
20 | /**
21 | * @param {object} ctx
22 | * @param {Request} ctx.request
23 | * @param {Function} next
24 | */
25 | async wsHandle ({ request }, next) {
26 | // call next to advance the request
27 | await next()
28 | }
29 | {{/ws}}
30 | }
31 |
32 | module.exports = {{name}}
33 |
--------------------------------------------------------------------------------
/src/Generators/templates/model.mustache:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */
4 | const Model = use('Model')
5 |
6 | class {{name}} extends Model {
7 | }
8 |
9 | module.exports = {{name}}
10 |
--------------------------------------------------------------------------------
/src/Generators/templates/provider.mustache:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const { ServiceProvider } = require('@adonisjs/fold')
4 |
5 | class {{name}} extends ServiceProvider {
6 | /**
7 | * Register namespaces to the IoC container
8 | *
9 | * @method register
10 | *
11 | * @return {void}
12 | */
13 | register () {
14 | //
15 | }
16 |
17 | /**
18 | * Attach context getter when all providers have
19 | * been registered
20 | *
21 | * @method boot
22 | *
23 | * @return {void}
24 | */
25 | boot () {
26 | //
27 | }
28 | }
29 |
30 | module.exports = {{name}}
31 |
--------------------------------------------------------------------------------
/src/Generators/templates/schema.mustache:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /** @type {import('@adonisjs/lucid/src/Schema')} */
4 | const Schema = use('Schema')
5 |
6 | class {{ name }} extends Schema {
7 | {{#create}}
8 | up () {
9 | this.create('{{ table }}', (table) => {
10 | table.increments()
11 | table.timestamps()
12 | })
13 | }
14 |
15 | down () {
16 | this.drop('{{ table }}')
17 | }
18 | {{/create}}
19 | {{^create}}
20 | up () {
21 | this.table('{{ table }}', (table) => {
22 | // alter table
23 | })
24 | }
25 |
26 | down () {
27 | this.table('{{ table }}', (table) => {
28 | // reverse alternations
29 | })
30 | }
31 | {{/create}}
32 | }
33 |
34 | module.exports = {{ name }}
35 |
--------------------------------------------------------------------------------
/src/Generators/templates/seed.mustache:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | |--------------------------------------------------------------------------
5 | | {{name}}
6 | |--------------------------------------------------------------------------
7 | |
8 | | Make use of the Factory instance to seed database with dummy data or
9 | | make use of Lucid models directly.
10 | |
11 | */
12 |
13 | /** @type {import('@adonisjs/lucid/src/Factory')} */
14 | const Factory = use('Factory')
15 |
16 | class {{name}} {
17 | async run () {
18 | }
19 | }
20 |
21 | module.exports = {{name}}
22 |
--------------------------------------------------------------------------------
/src/Generators/templates/trait.mustache:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | class {{name}} {
4 | register (Model, customOptions = {}) {
5 | const defaultOptions = {}
6 | const options = Object.assign(defaultOptions, customOptions)
7 | }
8 | }
9 |
10 | module.exports = {{name}}
11 |
--------------------------------------------------------------------------------
/src/Generators/templates/view.mustache:
--------------------------------------------------------------------------------
1 | {{#layout}}
2 | @layout('{{layout}}')
3 | {{/layout}}
4 |
--------------------------------------------------------------------------------
/src/Generators/templates/wsController.mustache:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | class {{name}} {
4 | constructor ({ socket, request }) {
5 | this.socket = socket
6 | this.request = request
7 | }
8 | }
9 |
10 | module.exports = {{name}}
11 |
--------------------------------------------------------------------------------
/src/Services/check-node-version.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const semver = require('semver')
13 | const requiredNodeVersion = '>=8.0.0'
14 | const requiredNodeVersionNumber = 8
15 | const requiredNpmVersion = '>=3.0.0'
16 | const requiredNpmVersionNumber = 3
17 |
18 | /**
19 | * This step checks the Node.js and npm version
20 | * installed on user machine. It will print
21 | * some messages on the console but also
22 | * throws an exception to abort the
23 | * process
24 | *
25 | * @async
26 | *
27 | * @param {Object} stepsCounter
28 | *
29 | * @return {void}
30 | */
31 | module.exports = async function (stepsCounter) {
32 | const step = stepsCounter.advance('Verifying requirements', 'microscope', 'node & npm')
33 | step.start()
34 |
35 | /**
36 | * Verify Node.js version.
37 | *
38 | * Uses `semver.parse` instead of `semver.satisfies` to support prereleases
39 | * version of Node.js.
40 | */
41 | const nodeVersion = process.version
42 | if (semver.parse(nodeVersion).major < requiredNodeVersionNumber) {
43 | step.error('Unsupported Node.js version', 'x')
44 | throw new Error(`Unsatisfied Node.js version ${nodeVersion}. Please update Node.js to ${requiredNodeVersion} before you continue`)
45 | }
46 |
47 | /**
48 | * Verify npm version.
49 | *
50 | * Uses `semver.parse` instead of `semver.satisfies` to support prereleases
51 | * version of npm.
52 | */
53 | const npmVersion = (await require('./exec')('npm -v')).trim()
54 | if (semver.parse(npmVersion).major < requiredNpmVersionNumber) {
55 | step.error('Unsupported npm version', 'x')
56 | throw new Error(`Unsatisfied npm version ${npmVersion}. Please update npm to ${requiredNpmVersion} before you continue`)
57 | }
58 |
59 | step.success('Requirements matched')
60 | }
61 |
--------------------------------------------------------------------------------
/src/Services/clone.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /**
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const debug = require('debug')('adonis:cli')
13 | const isGitUrl = require('is-git-url')
14 |
15 | /**
16 | * This module clones a given github repo and branch.
17 | *
18 | * @method
19 | *
20 | * @param {String} blueprint
21 | * @param {String} appPath
22 | * @param {Object} stepsCounter
23 | * @param {String} [branch = null]
24 | *
25 | * @return {void}
26 | */
27 | module.exports = async function (blueprint, appPath, stepsCounter, branch = null) {
28 | const step = stepsCounter.advance('Cloning project blueprint', 'inbox_tray', blueprint)
29 | step.start()
30 |
31 | let cloneCommand = 'git clone --depth=1'
32 |
33 | /**
34 | * Add branch flag when branch is defined
35 | */
36 | if (branch) {
37 | cloneCommand = `${cloneCommand} --branch ${branch}`
38 | }
39 |
40 | // complete the clone command
41 | // check if ths a full .git path
42 | if (isGitUrl(blueprint)) {
43 | cloneCommand = `${cloneCommand} ${blueprint} "${appPath}"`
44 | } else {
45 | cloneCommand = `${cloneCommand} https://github.com/${blueprint}.git "${appPath}"`
46 | }
47 | debug('clone command %s', cloneCommand)
48 |
49 | try {
50 | await require('./exec')(cloneCommand)
51 | step.success('Cloned')
52 | } catch (error) {
53 | step.error('Unable to clone repo', 'x')
54 | throw error
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Services/copy-env-file.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const path = require('path')
13 | const fs = require('fs-extra')
14 |
15 | /**
16 | * This module copies the `.env.example` file to `.env`.
17 | *
18 | * @method
19 | *
20 | * @param {String} appPath
21 | * @param {Function} copy
22 | * @param {Object} stepsCounter
23 | *
24 | * @return {void}
25 | */
26 | module.exports = async function (appPath, stepsCounter) {
27 | const step = stepsCounter.advance('Copying default environment variables', 'open_book', '.env')
28 | step.start()
29 |
30 | try {
31 | await fs.copy(path.join(appPath, '.env.example'), path.join(appPath, '.env'))
32 | step.success('Environment variables copied')
33 | } catch (error) {
34 | step.error('Unable to copy environment variables', 'x')
35 | throw error
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Services/exec.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /**
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const exec = require('util').promisify(require('child_process').exec)
13 |
14 | module.exports = async function (command) {
15 | const { stdout } = await exec(command)
16 | return stdout
17 | }
18 |
--------------------------------------------------------------------------------
/src/Services/generate-app-key.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | /**
13 | * Generates the app key by executing key:generate
14 | * ace comamnd.
15 | *
16 | * @method
17 | *
18 | * @param {Object} stepsCounter
19 | *
20 | * @return {void}
21 | */
22 | module.exports = async function (stepsCounter) {
23 | const step = stepsCounter.advance('Generating APP_KEY', 'key', 'adonis key:generate')
24 | step.start()
25 |
26 | try {
27 | await require('./exec')('adonis key:generate')
28 | step.success('Key generated')
29 | } catch (error) {
30 | step.error('Unable to generate key', 'x')
31 | error.hint = 'You can continue manually by running adonis key:generate'
32 | throw error
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Services/install.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /**
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | /**
13 | * Install dependencies from npm or yarn. The installation
14 | * tool must be installed on user machine
15 | *
16 | * @method
17 | *
18 | * @param {String} via
19 | * @param {Object} stepsCounter
20 | * @param {String} [packageName = '']
21 | *
22 | * @return {void}
23 | */
24 | module.exports = async function (via, stepsCounter, packageName) {
25 | const command = via === 'npm'
26 | ? (packageName ? `npm i --save ${packageName}@legacy` : 'npm install')
27 | : (packageName ? `yarn add ${packageName}@legacy` : 'yarn')
28 |
29 | const message = packageName ? `${via}: Installing` : `${via}: Installing project dependencies`
30 | const step = stepsCounter.advance(message, 'package', packageName)
31 |
32 | step.start()
33 |
34 | try {
35 | await require('./exec')(command)
36 | step.success('Dependencies installed')
37 | } catch (error) {
38 | step.error('Installation failed', 'x')
39 | error.hint = `You can manually install dependencies by running ${command}`
40 | throw error
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Services/render-instructions-md.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const path = require('path')
13 | const os = require('os')
14 | const opn = require('opn')
15 | const fs = require('fs-extra')
16 | const marked = require('marked')
17 | const debug = require('debug')('adonis:cli')
18 |
19 | 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}`
20 |
21 | /**
22 | * Returns the html to be saved inside tmp file
23 | * and show it to the user
24 | *
25 | * @method html
26 | *
27 | * @param {String} css
28 | * @param {String} moduleName
29 | * @param {String} content
30 | *
31 | * @return {String}
32 | */
33 | const html = function (css, moduleName, content) {
34 | return `
35 |
36 |
37 |
38 |
39 |
40 | Setup instructions for
41 | ${moduleName}
42 |
43 | ${content}
44 |
45 |
46 |
47 | `
48 | }
49 |
50 | /**
51 | * Render instructions.md file by converting it to
52 | * HTML and serving by tmp dir.
53 | *
54 | * @method
55 | *
56 | * @param {String} modulePath
57 | * @param {String} moduleName
58 | *
59 | * @return {void}
60 | */
61 | module.exports = async function (modulePath, moduleName) {
62 | try {
63 | const instructions = await fs.readFile(path.join(modulePath, 'instructions.md'), 'utf-8')
64 | debug('found instructions.md file for %s', modulePath)
65 |
66 | /**
67 | * Converting instructions markdown to html
68 | */
69 | const content = marked(instructions)
70 |
71 | /**
72 | * Creating html document
73 | */
74 | const htmlDocument = html(css, moduleName, content)
75 |
76 | /**
77 | * Generating path to tmp file
78 | */
79 | const tmpFile = path.join(os.tmpdir(), `${new Date().getTime()}.html`)
80 |
81 | /**
82 | * Writing to tmp file
83 | */
84 | await fs.outputFile(tmpFile, htmlDocument)
85 |
86 | /**
87 | * Opening file
88 | */
89 | await opn(tmpFile, { wait: false })
90 | } catch (error) {
91 | // ignore error since it's not helpful for enduser
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/Services/run-instructions.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const path = require('path')
13 | const fs = require('fs-extra')
14 | const debug = require('debug')('adonis:cli')
15 |
16 | /**
17 | * Executes the instructions file only if it
18 | * exists
19 | *
20 | * @method
21 | * @async
22 | *
23 | * @param {Object} ctx
24 | * @param {String} modulePath
25 | *
26 | * @return {void}
27 | */
28 | module.exports = async function (ctx, modulePath) {
29 | const instructionsFilePath = path.join(modulePath, 'instructions.js')
30 |
31 | const hasInstructionsFile = await fs.pathExists(instructionsFilePath)
32 | if (!hasInstructionsFile) {
33 | return
34 | }
35 |
36 | try {
37 | debug('found instructions.js file for %s', modulePath)
38 | const instructions = require(instructionsFilePath)
39 | if (typeof (instructions) === 'function') {
40 | await instructions(ctx)
41 | }
42 | } catch (error) {
43 | error.message = `instructions.js: ${error.message}`
44 | throw error
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/Services/verify-existing-folder.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /**
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const path = require('path')
13 | const readDir = require('util').promisify(require('fs').readdir)
14 |
15 | /**
16 | * Verifies that the installation folder is empty
17 | * or should not exists. Otherwise throws an
18 | * exception
19 | *
20 | * @method
21 | *
22 | * @param {String} appPath
23 | * @param {Object} stepsCounter
24 | *
25 | * @return {void}
26 | */
27 | module.exports = async function (appPath, stepsCounter) {
28 | const name = path.basename(appPath)
29 |
30 | const step = stepsCounter.advance('Ensuring project directory is clean', 'flashlight', name)
31 | step.start()
32 |
33 | try {
34 | const files = await readDir(appPath)
35 | if (files.length > 0) {
36 | step.error('Directory is not empty', 'x')
37 | throw new Error(`Cannot override contents of [${name}]. Make sure to delete it or specify a new path`)
38 | }
39 | } catch (error) {
40 | if (error.code !== 'ENOENT') {
41 | throw error
42 | }
43 | }
44 |
45 | step.success()
46 | }
47 |
--------------------------------------------------------------------------------
/test/clone.spec.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const test = require('japa')
13 | const path = require('path')
14 | const fs = require('fs-extra')
15 | const Steps = require('cli-step')
16 | const clone = require('../src/Services/clone')
17 |
18 | test.group('New | Steps | clone', (group) => {
19 | group.after(async () => {
20 | await fs.remove(path.join(__dirname, './yardstick-app'))
21 | await fs.remove(path.join(__dirname, './yardstick'))
22 | })
23 |
24 | test('throw error when cannot clone repo', async (assert) => {
25 | const appPath = path.join(__dirname, './yardstick')
26 | assert.plan(1)
27 | const stepsCounter = new Steps(1)
28 |
29 | try {
30 | process.env.GIT_TERMINAL_PROMPT = 0
31 | await clone('adonisjs/foo-app', appPath, stepsCounter)
32 | } catch ({ message }) {
33 | assert.isDefined(message)
34 | }
35 | }).timeout(0)
36 |
37 | test('clone repo when it exists', async (assert) => {
38 | const appPath = path.join(__dirname, './yardstick')
39 | const stepsCounter = new Steps(1)
40 |
41 | await clone('adonisjs/adonis-app', appPath, stepsCounter)
42 | await fs.pathExists(appPath)
43 | await fs.remove(appPath)
44 | }).timeout(0)
45 |
46 | test('clone repo with specific branch', async (assert) => {
47 | const appPath = path.join(__dirname, './yardstick-app')
48 | const stepsCounter = new Steps(1)
49 |
50 | await clone('adonisjs/adonis-app', appPath, stepsCounter, 'develop')
51 |
52 | await fs.pathExists(appPath)
53 | process.chdir(appPath)
54 |
55 | const branch = await require('../src/Services/exec')('git branch')
56 | assert.equal(branch.replace('*', '').trim(), 'develop')
57 | process.chdir(__dirname)
58 | }).timeout(0)
59 | })
60 |
--------------------------------------------------------------------------------
/test/copy-env-file.spec.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const test = require('japa')
13 | const path = require('path')
14 | const fs = require('fs-extra')
15 | const Steps = require('cli-step')
16 | const copyEnvFile = require('../src/Services/copy-env-file')
17 |
18 | test.group('New | Steps | copy env file', (group) => {
19 | group.after(async () => {
20 | await fs.remove(path.join(__dirname, './yardstick-app'))
21 | await fs.remove(path.join(__dirname, './yardstick'))
22 | })
23 |
24 | test('Copy env.example to .env', async (assert) => {
25 | const appPath = path.join(__dirname, './yardstick')
26 | await fs.ensureFile(path.join(appPath, '.env.example'))
27 | const stepsCounter = new Steps(1)
28 |
29 | process.chdir(appPath)
30 | await copyEnvFile(appPath, stepsCounter)
31 |
32 | await fs.pathExists(path.join(appPath, '.env'))
33 | await fs.remove(path.join(appPath, '.env'))
34 | await fs.remove(path.join(appPath, '.env.example'))
35 |
36 | process.chdir(__dirname)
37 | }).timeout(0)
38 | })
39 |
--------------------------------------------------------------------------------
/test/generators.spec.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-auth
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const path = require('path')
13 | const test = require('japa')
14 | const generators = require('../src/Generators')
15 | const OPTS = {
16 | appRoot: __dirname,
17 | appDir: 'app',
18 | dirs: {
19 | httpControllers: 'Controllers/Http',
20 | wsControllers: 'Controllers/Ws',
21 | models: 'Models',
22 | traits: 'Models/Traits',
23 | hooks: 'Models/Hooks',
24 | listeners: 'Listeners',
25 | exceptions: 'Exceptions',
26 | middleware: 'Middleware',
27 | commands: 'Commands',
28 | views: 'resources/views',
29 | migrations: 'database/migrations',
30 | seeds: 'database/seeds',
31 | providers: 'providers'
32 | }
33 | }
34 |
35 | test.group('Generators', () => {
36 | test('get path to the provider file', (assert) => {
37 | const filePath = generators.provider.getFilePath('Event', OPTS)
38 | assert.equal(filePath, path.join(__dirname, 'providers', 'EventProvider.js'))
39 | })
40 |
41 | test('make provider file singular', (assert) => {
42 | const filePath = generators.provider.getFilePath('Events', OPTS)
43 | assert.equal(filePath, path.join(__dirname, 'providers', 'EventProvider.js'))
44 | })
45 |
46 | test('normalize provider keyword', (assert) => {
47 | const filePath = generators.provider.getFilePath('EventProvider', OPTS)
48 | assert.equal(filePath, path.join(__dirname, 'providers', 'EventProvider.js'))
49 | })
50 |
51 | test('get path to the controller file', (assert) => {
52 | const filePath = generators.httpController.getFilePath('User', OPTS)
53 | assert.equal(filePath, path.join(__dirname, 'app/Controllers/Http', 'UserController.js'))
54 | })
55 |
56 | test('make controller file singular', (assert) => {
57 | const filePath = generators.httpController.getFilePath('Users', OPTS)
58 | assert.equal(filePath, path.join(__dirname, 'app/Controllers/Http', 'UserController.js'))
59 | })
60 |
61 | test('normalize controller keyword', (assert) => {
62 | const filePath = generators.httpController.getFilePath('UsersController', OPTS)
63 | assert.equal(filePath, path.join(__dirname, 'app/Controllers/Http', 'UserController.js'))
64 | })
65 |
66 | test('get data for the controller', (assert) => {
67 | const data = generators.httpController.getData('User', {})
68 | assert.deepEqual(data, { name: 'UserController', resource: false, resourceName: 'user', resourceNamePlural: 'users' })
69 | })
70 |
71 | test('get path to the model file', (assert) => {
72 | const filePath = generators.model.getFilePath('User', OPTS)
73 | assert.equal(filePath, path.join(__dirname, 'app/Models', 'User.js'))
74 | })
75 |
76 | test('singularize model name', (assert) => {
77 | const filePath = generators.model.getFilePath('Users', OPTS)
78 | assert.equal(filePath, path.join(__dirname, 'app/Models', 'User.js'))
79 | })
80 |
81 | test('normalize model name', (assert) => {
82 | const filePath = generators.model.getFilePath('UsersModel', OPTS)
83 | assert.equal(filePath, path.join(__dirname, 'app/Models', 'User.js'))
84 | })
85 |
86 | test('get data for model', (assert) => {
87 | const data = generators.model.getData('UsersModel', {})
88 | assert.deepEqual(data, { name: 'User' })
89 | })
90 |
91 | test('get path to the trait file', (assert) => {
92 | const filePath = generators.trait.getFilePath('Attachable', OPTS)
93 | assert.equal(filePath, path.join(__dirname, 'app/Models/Traits', 'Attachable.js'))
94 | })
95 |
96 | test('singularize trait name', (assert) => {
97 | const filePath = generators.trait.getFilePath('Attachables', OPTS)
98 | assert.equal(filePath, path.join(__dirname, 'app/Models/Traits', 'Attachable.js'))
99 | })
100 |
101 | test('normalize trait name', (assert) => {
102 | const filePath = generators.trait.getFilePath('AttachablesTrait', OPTS)
103 | assert.equal(filePath, path.join(__dirname, 'app/Models/Traits', 'Attachable.js'))
104 | })
105 |
106 | test('get data for trait', (assert) => {
107 | const data = generators.trait.getData('AttachablesTrait', {})
108 | assert.deepEqual(data, { name: 'Attachable' })
109 | })
110 |
111 | test('get path to the middleware file', (assert) => {
112 | const filePath = generators.middleware.getFilePath('User', OPTS)
113 | assert.equal(filePath, path.join(__dirname, 'app/Middleware', 'User.js'))
114 | })
115 |
116 | test('keep middleware singular', (assert) => {
117 | const filePath = generators.middleware.getFilePath('Users', OPTS)
118 | assert.equal(filePath, path.join(__dirname, 'app/Middleware', 'User.js'))
119 | })
120 |
121 | test('normalize middleware name', (assert) => {
122 | const filePath = generators.middleware.getFilePath('UsersMiddleware', OPTS)
123 | assert.equal(filePath, path.join(__dirname, 'app/Middleware', 'User.js'))
124 | })
125 |
126 | test('get middleware data', (assert) => {
127 | const data = generators.middleware.getData('UsersMiddleware', {})
128 | assert.deepEqual(data, { name: 'User', http: false, ws: false })
129 | })
130 |
131 | test('get path to the hooks file', (assert) => {
132 | const filePath = generators.hook.getFilePath('User', OPTS)
133 | assert.equal(filePath, path.join(__dirname, 'app/Models/Hooks', 'UserHook.js'))
134 | })
135 |
136 | test('keep hook name singular', (assert) => {
137 | const filePath = generators.hook.getFilePath('Users', OPTS)
138 | assert.equal(filePath, path.join(__dirname, 'app/Models/Hooks', 'UserHook.js'))
139 | })
140 |
141 | test('normalize hook name', (assert) => {
142 | const filePath = generators.hook.getFilePath('Users_Hook', OPTS)
143 | assert.equal(filePath, path.join(__dirname, 'app/Models/Hooks', 'UserHook.js'))
144 | })
145 |
146 | test('get data for hook', (assert) => {
147 | const data = generators.hook.getData('Users_Hook', {})
148 | assert.deepEqual(data, { name: 'UserHook', method: 'method' })
149 | })
150 |
151 | test('use method name passed to flags', (assert) => {
152 | const data = generators.hook.getData('Users_Hook', { method: 'validatePassword' })
153 | assert.deepEqual(data, { name: 'UserHook', method: 'validatePassword' })
154 | })
155 |
156 | test('get path to the view file', (assert) => {
157 | const filePath = generators.view.getFilePath('User', OPTS)
158 | assert.equal(filePath, path.join(__dirname, 'resources/views', 'user.edge'))
159 | })
160 |
161 | test('get path to nested view file', (assert) => {
162 | const filePath = generators.view.getFilePath('users.list', OPTS)
163 | assert.equal(filePath, path.join(__dirname, 'resources/views', 'users/list.edge'))
164 | })
165 |
166 | test('get data for the view', (assert) => {
167 | const data = generators.view.getData('users.list', {})
168 | assert.deepEqual(data, { layout: null })
169 | })
170 |
171 | test('set layout on data', (assert) => {
172 | const data = generators.view.getData('users.list', { layout: 'master' })
173 | assert.deepEqual(data, { layout: 'master' })
174 | })
175 |
176 | test('get path to the command file', (assert) => {
177 | const filePath = generators.command.getFilePath('makeTemplate', OPTS)
178 | assert.equal(filePath, path.join(__dirname, 'app/Commands', 'MakeTemplate.js'))
179 | })
180 |
181 | test('keep command name singular', (assert) => {
182 | const filePath = generators.command.getFilePath('makeTemplates', OPTS)
183 | assert.equal(filePath, path.join(__dirname, 'app/Commands', 'MakeTemplate.js'))
184 | })
185 |
186 | test('normalize command name', (assert) => {
187 | const filePath = generators.command.getFilePath('makeTemplateCommand', OPTS)
188 | assert.equal(filePath, path.join(__dirname, 'app/Commands', 'MakeTemplate.js'))
189 | })
190 |
191 | test('get data for command', (assert) => {
192 | const data = generators.command.getData('makeTemplate', {})
193 | assert.deepEqual(data, { name: 'MakeTemplate', commandName: 'make:template' })
194 | })
195 |
196 | test('get path to the schema file', (assert) => {
197 | const filePath = generators.schema.getFilePath('users', OPTS)
198 | assert.include(filePath, '_users_schema.js')
199 | })
200 |
201 | test('get data for schema', (assert) => {
202 | const data = generators.schema.getData('users', {})
203 | assert.deepEqual(data, { create: false, table: 'users', name: 'UsersSchema' })
204 | })
205 |
206 | test('pluralize table name', (assert) => {
207 | const data = generators.schema.getData('user', {})
208 | assert.deepEqual(data, { create: false, table: 'users', name: 'UserSchema' })
209 | })
210 |
211 | test('snake case table name', (assert) => {
212 | const data = generators.schema.getData('UserProfile', {})
213 | assert.deepEqual(data, { create: false, table: 'user_profiles', name: 'UserProfileSchema' })
214 | })
215 |
216 | test('get path to the listener file', (assert) => {
217 | const filePath = generators.listener.getFilePath('Http', OPTS)
218 | assert.equal(filePath, path.join(__dirname, 'app/Listeners', 'Http.js'))
219 | })
220 |
221 | test('normalize listener name', (assert) => {
222 | const filePath = generators.listener.getFilePath('on_http', OPTS)
223 | assert.equal(filePath, path.join(__dirname, 'app/Listeners', 'OnHttp.js'))
224 | })
225 |
226 | test('get data for listener', (assert) => {
227 | const data = generators.listener.getData('on_http', { method: 'start' })
228 | assert.deepEqual(data, { name: 'OnHttp', method: 'start' })
229 | })
230 |
231 | test('get path to the seed file', (assert) => {
232 | const filePath = generators.seed.getFilePath('Database', OPTS)
233 | assert.equal(filePath, path.join(__dirname, 'database/seeds', 'DatabaseSeeder.js'))
234 | })
235 |
236 | test('normalize seeder name', (assert) => {
237 | const filePath = generators.seed.getFilePath('DatabaseSeeder', OPTS)
238 | assert.equal(filePath, path.join(__dirname, 'database/seeds', 'DatabaseSeeder.js'))
239 | })
240 |
241 | test('get data for seed', (assert) => {
242 | const data = generators.seed.getData('DatabaseSeeder', {})
243 | assert.deepEqual(data, { name: 'DatabaseSeeder' })
244 | })
245 |
246 | test('get path to nested controller file', (assert) => {
247 | const filePath = generators.httpController.getFilePath('Admin/UserController', OPTS)
248 | assert.equal(filePath, path.join(__dirname, 'app/Controllers/Http/Admin', 'UserController.js'))
249 | })
250 |
251 | test('get path to exception file', (assert) => {
252 | const filePath = generators.exception.getFilePath('Validation', OPTS)
253 | assert.equal(filePath, path.join(__dirname, 'app/Exceptions', 'ValidationException.js'))
254 | })
255 |
256 | test('normalize exception file path', (assert) => {
257 | const filePath = generators.exception.getFilePath('ValidationException', OPTS)
258 | assert.equal(filePath, path.join(__dirname, 'app/Exceptions', 'ValidationException.js'))
259 | })
260 | })
261 |
--------------------------------------------------------------------------------
/test/install.spec.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const test = require('japa')
13 | const path = require('path')
14 | const fs = require('fs-extra')
15 | const Steps = require('cli-step')
16 |
17 | const BASE_PATH = path.join(__dirname, 'dummyProject')
18 |
19 | if (process.platform !== 'win32') {
20 | test.group('Install | Command', (group) => {
21 | group.before(async () => {
22 | await fs.ensureDir(BASE_PATH)
23 | await fs.outputJSON(path.join(BASE_PATH, 'package.json'), {
24 | name: 'dummy-project'
25 | })
26 | })
27 |
28 | group.afterEach(async () => {
29 | await fs.emptyDir(BASE_PATH)
30 | })
31 |
32 | group.after(async () => {
33 | await fs.remove(BASE_PATH)
34 | })
35 |
36 | test('install a package from npm', async (assert) => {
37 | process.chdir(BASE_PATH)
38 | const stepsCounter = new Steps(1)
39 |
40 | await require('../src/Services/install')('npm', stepsCounter, '@adonisjs/session')
41 | const exists = await fs.exists(path.join(BASE_PATH, 'node_modules/@adonisjs/session'))
42 | assert.isTrue(exists)
43 | }).timeout(0)
44 |
45 | test('throw exception when unable to install package', async (assert) => {
46 | assert.plan(2)
47 | process.chdir(BASE_PATH)
48 |
49 | const stepsCounter = new Steps(1)
50 |
51 | try {
52 | await require('../src/Services/install')('npm', stepsCounter, '@adonisjs/foo')
53 | } catch (error) {
54 | const exists = await fs.exists(path.join(BASE_PATH, 'node_modules/@adonisjs/foo'))
55 | assert.isFalse(exists)
56 | assert.include(error.message, 'npm ERR! code E404')
57 | }
58 | }).timeout(0)
59 | })
60 | }
61 |
--------------------------------------------------------------------------------
/test/new.spec.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const test = require('japa')
13 | const path = require('path')
14 | const ace = require('@adonisjs/ace')
15 | const fs = require('fs-extra')
16 | const NewCommand = require('../src/Commands/New')
17 |
18 | /**
19 | * Ignoring tests in windows, since appveyor has
20 | * weird file permission issues
21 | */
22 | test.group('New | Command', (group) => {
23 | group.before(() => {
24 | process.chdir(__dirname)
25 | })
26 |
27 | group.after(async () => {
28 | await fs.remove(path.join(__dirname, './yardstick-app'))
29 | await fs.remove(path.join(__dirname, './yardstick'))
30 | })
31 |
32 | group.beforeEach(() => {
33 | ace.commands = {}
34 | })
35 |
36 | test('set default blueprint to fullstack app', async (assert) => {
37 | const newCommand = new NewCommand()
38 | assert.equal(newCommand._getBluePrint({}), 'adonisjs/adonis-fullstack-app')
39 | })
40 |
41 | test('update blueprint when --api-only flag is defined', async (assert) => {
42 | const newCommand = new NewCommand()
43 | assert.equal(newCommand._getBluePrint({ apiOnly: true }), 'adonisjs/adonis-api-app')
44 | })
45 |
46 | test('update blueprint when --slim flag is defined', async (assert) => {
47 | const newCommand = new NewCommand()
48 | assert.equal(newCommand._getBluePrint({ slim: true }), 'adonisjs/adonis-slim-app')
49 | })
50 |
51 | test('give priority to api-only over slim', async (assert) => {
52 | const newCommand = new NewCommand()
53 | assert.equal(newCommand._getBluePrint({ slim: true, apiOnly: true }), 'adonisjs/adonis-api-app')
54 | })
55 |
56 | test('give priority to blueprint over everything', async (assert) => {
57 | const newCommand = new NewCommand()
58 | assert.equal(newCommand._getBluePrint({ slim: true, apiOnly: true, 'blueprint': 'adonuxt' }), 'adonuxt')
59 | })
60 | })
61 |
--------------------------------------------------------------------------------
/test/run-instructions.spec.js:
--------------------------------------------------------------------------------
1 | /*
2 | * adonis-cli
3 | *
4 | * (c) Harminder Virk
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | const test = require('japa')
11 | const path = require('path')
12 | const ace = require('../lib/ace')
13 | const { Helpers, setupResolver } = require('@adonisjs/sink')
14 | const fs = require('fs-extra')
15 | const clearRequire = require('clear-require')
16 |
17 | const BASE_PATH = path.join(__dirname, 'dummyProject')
18 | const Context = require('../src/Commands/Instructions/Context')
19 |
20 | /**
21 | * Writes the instructions file to the `BASE_PATH`.
22 | * @param {String} contents
23 | */
24 | const writeInstructionsJs = function (contents) {
25 | return fs.writeFile(path.join(BASE_PATH, 'instructions.js'), contents)
26 | }
27 |
28 | /**
29 | * Gives a new instance of contents
30 | *
31 | * @returns Context
32 | */
33 | const getContext = function () {
34 | const command = new ace.Command()
35 | return new Context(command, new Helpers(BASE_PATH))
36 | }
37 |
38 | if (process.platform !== 'win32') {
39 | test.group('Run instructions', (group) => {
40 | group.before(async () => {
41 | setupResolver()
42 | await fs.ensureDir(BASE_PATH)
43 | })
44 |
45 | group.afterEach(async () => {
46 | clearRequire(path.join(BASE_PATH, 'instructions.js'))
47 | await fs.emptyDir(BASE_PATH)
48 | })
49 |
50 | group.after(async () => {
51 | await fs.remove(BASE_PATH)
52 | })
53 |
54 | group.beforeEach(() => {
55 | process.chdir(BASE_PATH)
56 | ace.commands = {}
57 | })
58 |
59 | test('run instructions', async (assert) => {
60 | await writeInstructionsJs(`
61 | module.exports = async function (cli) {
62 | cli.executed = true
63 | }`)
64 |
65 | const ctx = getContext()
66 | await require('../src/Services/run-instructions')(ctx, BASE_PATH)
67 | assert.isTrue(ctx.executed)
68 | }).timeout(0)
69 |
70 | test('save config file via instructions', async (assert) => {
71 | const sessionTemplate = `
72 | module.exports = {
73 | driver: 'cookie'
74 | }
75 | `
76 | await fs.writeFile(path.join(BASE_PATH, 'session.mustache'), sessionTemplate)
77 |
78 | await writeInstructionsJs(`
79 | const path = require('path')
80 | module.exports = async function (cli) {
81 | await cli.makeConfig('session.js', path.join(__dirname, './session.mustache'))
82 | }
83 | `)
84 |
85 | await require('../src/Services/run-instructions')(getContext(), BASE_PATH)
86 |
87 | require(path.join(BASE_PATH, 'config/session.js'))
88 | }).timeout(0)
89 |
90 | test('throw exceptions of instructions file', async (assert) => {
91 | assert.plan(1)
92 |
93 | await writeInstructionsJs(`
94 | const path = require('path')
95 | module.exports = async function (cli) {
96 | cli.foo()
97 | }`)
98 |
99 | try {
100 | await require('../src/Services/run-instructions')(getContext(), BASE_PATH)
101 | } catch ({ message }) {
102 | assert.equal(message, 'instructions.js: cli.foo is not a function')
103 | }
104 | }).timeout(0)
105 |
106 | test('instructions call ace commands', async (assert) => {
107 | await writeInstructionsJs(`
108 | module.exports = async function (cli) {
109 | await cli.callCommand('make:model', { name: 'User' })
110 | }
111 | `)
112 |
113 | await fs.writeFile(path.join(BASE_PATH, 'ace'), '')
114 | ace.addCommand(require('../src/Commands')['make:model'])
115 |
116 | await require('../src/Services/run-instructions')(getContext(), BASE_PATH)
117 | const exists = await fs.exists(path.join(BASE_PATH, 'app/Models/User.js'))
118 | assert.isTrue(exists)
119 | }).timeout(0)
120 |
121 | test('instructions copy files', async (assert) => {
122 | await writeInstructionsJs(`
123 | const path = require('path')
124 |
125 | module.exports = async function (cli) {
126 | await cli.copy(path.join(__dirname, './foo.js'), cli.helpers.tmpPath('./foo.js'))
127 | }`)
128 |
129 | await fs.writeFile(path.join(BASE_PATH, 'foo.js'), '')
130 | await require('../src/Services/run-instructions')(getContext(), BASE_PATH)
131 | require(path.join(BASE_PATH, 'tmp/foo.js'))
132 | }).timeout(0)
133 |
134 | test('ignore when instructions.js file does not exists', async (assert) => {
135 | await require('../src/Services/run-instructions')(getContext(), BASE_PATH)
136 | }).timeout(0)
137 |
138 | test('ignore when instructions.md file does not exists', async (assert) => {
139 | await require('../src/Services/render-instructions-md')(BASE_PATH, '@adonisjs/session')
140 | }).timeout(0)
141 | })
142 | }
143 |
--------------------------------------------------------------------------------
/test/verify-existing-folder.spec.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /*
4 | * adonis-cli
5 | *
6 | * (c) Harminder Virk
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | const test = require('japa')
13 | const path = require('path')
14 | const fs = require('fs-extra')
15 | const Steps = require('cli-step')
16 | const verifyExistingFolder = require('../src/Services/verify-existing-folder')
17 |
18 | test.group('Verify Existing Folder', (group) => {
19 | group.after(async () => {
20 | await fs.remove(path.join(__dirname, './yardstick-app'))
21 | await fs.remove(path.join(__dirname, './yardstick'))
22 | })
23 |
24 | test('throw error when app dir exists and not empty', async (assert) => {
25 | const appPath = path.join(__dirname, './yardstick')
26 | await fs.ensureFile(path.join(appPath, 'package.json'))
27 | const stepsCounter = new Steps(1)
28 |
29 | assert.plan(1)
30 |
31 | try {
32 | await verifyExistingFolder(appPath, stepsCounter)
33 | } catch ({ message }) {
34 | assert.include(message, 'Cannot override contents of [yardstick]')
35 | await fs.remove(appPath)
36 | }
37 | })
38 |
39 | test('work fine with directory exists but is empty', async (assert) => {
40 | const appPath = path.join(__dirname, './yardstick')
41 | await fs.ensureDir(appPath)
42 | const stepsCounter = new Steps(1)
43 |
44 | await verifyExistingFolder(appPath, stepsCounter)
45 | await fs.remove(appPath)
46 | })
47 |
48 | test('ignore when directory doesn\'t exists', async (assert) => {
49 | const appPath = path.join(__dirname, './yardstick')
50 | const stepsCounter = new Steps(1)
51 |
52 | await verifyExistingFolder(appPath, stepsCounter)
53 | })
54 | })
55 |
--------------------------------------------------------------------------------