@adonisjs/assembler 6.1.3-9 → 7.0.0-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,27 +2,407 @@
2
2
 
3
3
  <br />
4
4
 
5
- [![gh-workflow-image]][gh-workflow-url] [![npm-image]][npm-url] ![][typescript-image] [![license-image]][license-url] [![snyk-image]][snyk-url]
5
+ [![gh-workflow-image]][gh-workflow-url] [![npm-image]][npm-url] ![][typescript-image] [![license-image]][license-url]
6
6
 
7
7
  ## Introduction
8
- Assembler exports the API for starting the **AdonisJS development server**, **building project for production** and **running tests** in watch mode. Assembler must be used during development only.
8
+ AdonisJS Assembler is a development toolkit used by AdonisJS to perform tasks like **starting the dev server in watch mode**, **running tests in watch mode**, and **applying codemods** to modify source files.
9
9
 
10
- ## Official Documentation
11
- The documentation is available on the official website
10
+ Assembler should always be installed as a development dependency. If your project needs Assembler APIs in production, you must reconsider your approach.
11
+
12
+ ## Goals
13
+ Assembler is built around the following goals.
14
+
15
+ - Expose a coding interface and not a user interface. In other words, Assembler will never expose any CLI commands.
16
+ - Encapsulate tasks under a single API. Instead of providing ten different utilities to run a dev server, Assembler will expose one API to run the dev server.
17
+ - House all development APIs needed by AdonisJS. Therefore, the scope of the Assembler might increase over time.
18
+
19
+ ## Dev server
20
+ You can start the HTTP server of an AdonisJS application using the `node --loader=ts-node/esm bin/server.ts` file. However, this approach has some limitations and may not provide the best DX.
21
+
22
+ ### Using a file watcher
23
+ You might be tempted to use the Node.js built-in file watcher with the `--watch` flag. However, the Node.js file watcher does not integrate with TypeScript. As a result, you will be tweaking its configuration options to get an ideal experience.
24
+
25
+ On the other hand, the Assembler file watcher takes the following approach.
26
+
27
+ - Parses the `tsconfig.json` file to collect the list of files that are part of your TypeScript project. As a result, if you ever want to ignore any file, you do it directly within the `tsconfig.json` file, and the watcher will pick it up.
28
+ - It uses the `metaFiles` array defined inside the `adonisrc.ts` file to watch additional files that are not `.js` or `.ts`. It may be the Edge templates, markdown files, YAML files, etc.
29
+
30
+ ### Starting the asset bundler server
31
+ If you create a full-stack application, the chances of using Webpack or Vite are high. Instead of starting your assets bundler inside a separate process, you can also rely on Assembler to start a parallel process for the assets bundler.
32
+
33
+ The [`node ace serve` command](https://github.com/adonisjs/core/blob/next/commands/serve.ts#L88) detects the assets bundler used by your AdonisJS project and passes it to Assembler.
34
+
35
+ Therefore, if you run the `serve` command with a `vite.config.js` file, you will notice that the Assembler will start both Vite and the AdonisJS HTTP server.
36
+
37
+ ### Picking a random port
38
+ The PORT on which an AdonisJS application should run is configured inside the `.env` file of your AdonisJS application. However, you will often start multiple projects together and have to edit the `.env` file to ensure both projects run on different ports.
39
+
40
+ With Assembler, you do not have to edit the `.env` files since Assembler will pick a random port of your application if the configured one is already in use.
41
+
42
+ ### Usage
43
+ You may import and use the `DevServer` as follows.
44
+
45
+ ```ts
46
+ import ts from 'typescript'
47
+ import { DevServer } from '@adonisjs/assembler'
48
+
49
+ const appRoot = new URL('./', import.meta.url)
50
+
51
+ const devServer = new DevServer(appRoot, {
52
+ /**
53
+ * Arguments to pass to the "bin/server.ts" file
54
+ */
55
+ scriptArgs: [],
56
+
57
+ /**
58
+ * Arguments to pass to the Node.js CLI
59
+ */
60
+ nodeArgs: [],
61
+
62
+ /**
63
+ * An array of metaFiles to watch and re-start the
64
+ * HTTP server only if the "reloadServer" flag is
65
+ * true.
66
+ */
67
+ metaFiles: [
68
+ {
69
+ pattern: 'resources/views/**/*.edge',
70
+ reloadServer: false,
71
+ }
72
+ ],
73
+
74
+ /**
75
+ * The assets bundler process to start
76
+ */
77
+ assets: {
78
+ enabled: true,
79
+ name: 'vite',
80
+ cmd: 'vite',
81
+ args: []
82
+ }
83
+ })
84
+
85
+ devServer.onError((error) => {
86
+ process.exitCode = 1
87
+ })
88
+ devServer.onClose((exitCode) => {
89
+ process.exitCode = exitCode
90
+ })
91
+
92
+ await devServer.runAndWatch(ts)
93
+ ```
94
+
95
+ You may start the dev server and assets bundler dev server using the `start` method.
96
+
97
+ ```ts
98
+ await devServer.start()
99
+ ```
100
+
101
+ ## Test runner
102
+ The `TestRunner` is used to execute the `bin/test.ts` file of your AdonisJS application. Like the `DevServer`, the `TestRunner` allows you to watch for file changes and re-run the tests. The following steps are taken to re-run tests in watch mode.
103
+
104
+ > [!NOTE]
105
+ > Read [Using a file watcher](#using-a-file-watcher) section to understand which files are watched by the file watcher.
106
+
107
+ - If the changed file is a test file, only tests for that file will be re-run.
108
+ - Otherwise, all tests will re-run with respect to the initial filters applied when running the `node ace test` command.
109
+
110
+ ### Usage
111
+
112
+ You may import and use the `TestRunner` as follows.
113
+
114
+ ```ts
115
+ import ts from 'typescript'
116
+ import { TestRunner } from '@adonisjs/assembler'
117
+
118
+ const appRoot = new URL('./', import.meta.url)
119
+
120
+ const runner = new TestRunner(appRoot, {
121
+ /**
122
+ * Arguments to pass to the "bin/test.ts" file
123
+ */
124
+ scriptArgs: [],
125
+
126
+ /**
127
+ * Arguments to pass to the Node.js CLI
128
+ */
129
+ nodeArgs: [],
130
+
131
+ /**
132
+ * An array of suites and their glob patterns
133
+ */
134
+ suites: [
135
+ {
136
+ name: 'unit',
137
+ files: ['tests/unit/**/*.spec.ts']
138
+ },
139
+ {
140
+ name: 'functional',
141
+ files: ['tests/functional/**/*.spec.ts']
142
+ }
143
+ ],
144
+
145
+ /**
146
+ * Initial set of filters to apply. These filters
147
+ * will be re-applied when re-running tests in
148
+ * watch mode
149
+ */
150
+ filters: {
151
+ suites: ['unit'],
152
+ tags: ['@slow']
153
+ }
154
+ })
155
+
156
+ await runner.runAndWatch(ts)
157
+ ```
158
+
159
+ You can run tests without the watcher using the `run` method.
160
+
161
+ ```ts
162
+ await runner.run()
163
+ ```
164
+
165
+ ## Bundler
166
+ The `Bundler` is used to create the production build of an AdonisJS application. The following steps are performed to generate the build.
167
+
168
+ - Clean up the existing build directory.
169
+ - Compile frontend assets (if an assets bundler is configured).
170
+ - Create JavaScript build using `tsc` (The TypeScript's official compiler).
171
+ - Copy the `ace.js` file to the build folder. Since the ace file ends with the `.js` extension, it is not compiled by the TypeScript compiler.
172
+ - Copy `package.json` and the **lock-file of the package manager** you are using to the `build` folder. This operation only supports `bun | npm | yarn | pnpm`. For other bundlers, you will have to copy the lock file manually.
173
+ - The end.
174
+
175
+ ### Usage
176
+ You may import and use the `Bundler` as follows.
177
+
178
+ ```ts
179
+ import ts from 'typescript'
180
+ import { Bundler } from '@adonisjs/assembler'
181
+
182
+ const appRoot = new URL('./', import.meta.url)
183
+
184
+ const bundler = new Bundler(appRoot, ts, {
185
+ /**
186
+ * Metafiles to copy to the build folder
187
+ */
188
+ metaFiles: [
189
+ {
190
+ pattern: 'resources/views/**/*.edge',
191
+ reloadServer: false,
192
+ }
193
+ ],
194
+
195
+ /**
196
+ * The assets bundler to use to bundle the frontend
197
+ * assets
198
+ */
199
+ assets: {
200
+ enabled: true,
201
+ name: 'vite',
202
+ cmd: 'vite',
203
+ args: ['build']
204
+ }
205
+ })
206
+ ```
207
+
208
+ ## Codemods
209
+ Assembler also exports certain codemods to modify the source files of an AdonisJS project to configure packages.
210
+
211
+ The codemods relies on the defaults of AdonisJS and will not work if a project does not follow the defaults. This is an intentional limit since we only have limited time to craft codemods that work with every possible setup.
212
+
213
+ ### Usage
214
+ You may import and use the `Codemods` as follows.
215
+
216
+ ```ts
217
+ import { CodeTransformer } from '@adonisjs/assembler/code_transformer'
218
+
219
+ const appRoot = new URL('./', import.meta.url)
220
+
221
+ const transformer = new CodeTransformer(appRoot)
222
+ ```
223
+
224
+ ### defineEnvValidations
225
+ Define validation rules for environment variables. The method accepts a key-value pair of variables. The `key` is the env variable name, and the `value` is the validation expression as a string.
226
+
227
+ > [!IMPORTANT]
228
+ > This codemod expects the `start/env.ts` file to exist and must have the `export default await Env.create` method call.
229
+ >
230
+ > Also, the codemod does not overwrite the existing validation rule for a given environment variable. This is done to respect in-app modifications.
231
+
232
+ ```ts
233
+ const transformer = new CodeTransformer(appRoot)
234
+
235
+ try {
236
+ await transformer.defineEnvValidations({
237
+ leadingComment: 'App environment variables',
238
+ variables: {
239
+ PORT: 'Env.schema.number()',
240
+ HOST: 'Env.schema.string()',
241
+ }
242
+ })
243
+ } catch (error) {
244
+ console.error('Unable to define env validations')
245
+ console.error(error)
246
+ }
247
+ ```
248
+
249
+ Output
250
+
251
+ ```ts
252
+ import { Env } from '@adonisjs/core/env'
253
+
254
+ export default await Env.create(new URL('../', import.meta.url), {
255
+ PORT: Env.schema.number(),
256
+ HOST: Env.schema.string(),
257
+ })
258
+ ```
259
+
260
+ ### addMiddlewareToStack
261
+ Register AdonisJS middleware to one of the known middleware stacks. The method accepts the middleware stack and an array of middleware to register.
262
+
263
+ The middleware stack could be one of `server | router | named`.
264
+
265
+ > [!IMPORTANT]
266
+ > This codemod expects the `start/kernel.ts` file to exist and must have a function call for the middleware stack for which you are trying to register a middleware.
267
+
268
+ ```ts
269
+ const transformer = new CodeTransformer(appRoot)
270
+
271
+ try {
272
+ await transformer.addMiddlewareToStack('router', [
273
+ {
274
+ path: '@adonisjs/core/bodyparser_middleware'
275
+ }
276
+ ])
277
+ } catch (error) {
278
+ console.error('Unable to register middleware')
279
+ console.error(error)
280
+ }
281
+ ```
282
+
283
+ Output
284
+
285
+ ```ts
286
+ import router from '@adonisjs/core/services/router'
287
+
288
+ router.use([
289
+ () => import('@adonisjs/core/bodyparser_middleware')
290
+ ])
291
+ ```
292
+
293
+ You may define named middleware as follows.
294
+
295
+ ```ts
296
+ const transformer = new CodeTransformer(appRoot)
297
+
298
+ try {
299
+ await transformer.addMiddlewareToStack('named', [
300
+ {
301
+ name: 'auth',
302
+ path: '@adonisjs/auth/auth_middleware'
303
+ }
304
+ ])
305
+ } catch (error) {
306
+ console.error('Unable to register middleware')
307
+ console.error(error)
308
+ }
309
+ ```
310
+
311
+ ### updateRcFile
312
+ Register `providers`, `commands`, define `metaFiles` and `commandAliases` to the `adonisrc.ts` file.
313
+
314
+ > [!IMPORTANT]
315
+ > This codemod expects the `adonisrc.ts` file to exist and must have an `export default defineConfig` function call.
316
+
317
+ ```ts
318
+ const transformer = new CodeTransformer(appRoot)
319
+
320
+ try {
321
+ await transformer.updateRcFile((rcFile) => {
322
+ rcFile
323
+ .addProvider('@adonisjs/lucid/db_provider')
324
+ .addCommand('@adonisjs/lucid/commands'),
325
+ .setCommandAlias('migrate', 'migration:run')
326
+ })
327
+ } catch (error) {
328
+ console.error('Unable to update adonisrc.ts file')
329
+ console.error(error)
330
+ }
331
+ ```
332
+
333
+ Output
334
+
335
+ ```ts
336
+ import { defineConfig } from '@adonisjs/core/app'
337
+
338
+ export default defineConfig({
339
+ commands: [
340
+ () => import('@adonisjs/lucid/commands')
341
+ ],
342
+ providers: [
343
+ () => import('@adonisjs/lucid/db_provider')
344
+ ],
345
+ commandAliases: {
346
+ migrate: 'migration:run'
347
+ }
348
+ })
349
+ ```
350
+
351
+ ### addJapaPlugin
352
+ Register a Japa plugin to the `tests/bootstrap.ts` file.
353
+
354
+ > [!IMPORTANT]
355
+ > This codemod expects the `tests/bootstrap.ts` file to exist and must have the `export const plugins: Config['plugins']` export.
356
+
357
+ ```ts
358
+ const transformer = new CodeTransformer(appRoot)
359
+
360
+ const imports = [
361
+ {
362
+ isNamed: false,
363
+ module: '@adonisjs/core/services/app',
364
+ identifier: 'app'
365
+ },
366
+ {
367
+ isNamed: true,
368
+ module: '@adonisjs/session/plugins/api_client',
369
+ identifier: 'sessionApiClient'
370
+ }
371
+ ]
372
+ const pluginUsage = 'sessionApiClient(app)'
373
+
374
+ try {
375
+ await transformer.addJapaPlugin(pluginUsage, imports)
376
+ } catch (error) {
377
+ console.error('Unable to register japa plugin')
378
+ console.error(error)
379
+ }
380
+ ```
381
+
382
+ Output
383
+
384
+ ```ts
385
+ import app from '@adonisjs/core/services/app'
386
+ import { sessionApiClient } from '@adonisjs/session/plugins/api_client'
387
+
388
+ export const plugins: Config['plugins'] = [
389
+ sessionApiClient(app)
390
+ ]
391
+ ```
12
392
 
13
393
  ## Contributing
14
- One of the primary goals of AdonisJS is to have a vibrant community of users and contributors who believes in the principles of the framework.
394
+ One of the primary goals of AdonisJS is to have a vibrant community of users and contributors who believe in the framework's principles.
15
395
 
16
396
  We encourage you to read the [contribution guide](https://github.com/adonisjs/.github/blob/main/docs/CONTRIBUTING.md) before contributing to the framework.
17
397
 
18
398
  ## Code of Conduct
19
- In order to ensure that the AdonisJS community is welcoming to all, please review and abide by the [Code of Conduct](https://github.com/adonisjs/.github/blob/main/docs/CODE_OF_CONDUCT.md).
399
+ To ensure that the AdonisJS community is welcoming to all, please review and abide by the [Code of Conduct](https://github.com/adonisjs/.github/blob/main/docs/CODE_OF_CONDUCT.md).
20
400
 
21
401
  ## License
22
402
  AdonisJS Assembler is open-sourced software licensed under the [MIT license](LICENSE.md).
23
403
 
24
- [gh-workflow-image]: https://img.shields.io/github/actions/workflow/status/adonisjs/assembler/test.yml?style=for-the-badge
25
- [gh-workflow-url]: https://github.com/adonisjs/assembler/actions/workflows/test.yml "Github action"
404
+ [gh-workflow-image]: https://img.shields.io/github/actions/workflow/status/adonisjs/assembler/checks.yml?style=for-the-badge
405
+ [gh-workflow-url]: https://github.com/adonisjs/assembler/actions/workflows/checks.yml "Github action"
26
406
 
27
407
  [npm-image]: https://img.shields.io/npm/v/@adonisjs/assembler/latest.svg?style=for-the-badge&logo=npm
28
408
  [npm-url]: https://npmjs.org/package/@adonisjs/assembler/v/latest "npm"
@@ -31,6 +411,3 @@ AdonisJS Assembler is open-sourced software licensed under the [MIT license](LIC
31
411
 
32
412
  [license-url]: LICENSE.md
33
413
  [license-image]: https://img.shields.io/github/license/adonisjs/ace?style=for-the-badge
34
-
35
- [snyk-image]: https://img.shields.io/snyk/vulnerabilities/github/adonisjs/assembler?label=snyk%20Vulnerabilities&style=for-the-badge
36
- [snyk-url]: https://snyk.io/test/github/adonisjs/assembler?targetFile=package.json "snyk"