@adonisjs/assembler 8.0.0-next.2 → 8.0.0-next.3

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
@@ -50,17 +50,7 @@ const devServer = new DevServer(appRoot, {
50
50
  pattern: 'resources/views/**/*.edge',
51
51
  reloadServer: false,
52
52
  }
53
- ],
54
-
55
- /**
56
- * The assets bundler process to start
57
- */
58
- assets: {
59
- enabled: true,
60
- name: 'vite',
61
- cmd: 'vite',
62
- args: []
63
- }
53
+ ]
64
54
  })
65
55
 
66
56
  devServer.onError((error) => {
@@ -87,9 +77,6 @@ await devServer.start()
87
77
  ## Test runner
88
78
  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.
89
79
 
90
- > [!NOTE]
91
- > Read [Using a file watcher](#using-a-file-watcher) section to understand which files are watched by the file watcher.
92
-
93
80
  - If the changed file is a test file, only tests for that file will be re-run.
94
81
  - Otherwise, all tests will re-run with respect to the initial filters applied when running the `node ace test` command.
95
82
 
@@ -176,17 +163,6 @@ const bundler = new Bundler(appRoot, ts, {
176
163
  reloadServer: false,
177
164
  }
178
165
  ],
179
-
180
- /**
181
- * The assets bundler to use to bundle the frontend
182
- * assets
183
- */
184
- assets: {
185
- enabled: true,
186
- name: 'vite',
187
- cmd: 'vite',
188
- args: ['build']
189
- }
190
166
  })
191
167
  ```
192
168
 
package/build/index.js CHANGED
@@ -609,7 +609,9 @@ var ShortcutsManager = class {
609
609
  * Initialize keyboard shortcuts
610
610
  */
611
611
  setup() {
612
- if (!process.stdin.isTTY) return;
612
+ if (!process.stdin.isTTY) {
613
+ return;
614
+ }
613
615
  process.stdin.setRawMode(true);
614
616
  this.#keyPressHandler = (data) => this.#handleKeyPress(data.toString());
615
617
  process.stdin.on("data", this.#keyPressHandler);
@@ -618,9 +620,13 @@ var ShortcutsManager = class {
618
620
  * Handle key press events
619
621
  */
620
622
  #handleKeyPress(key) {
621
- if (key === "" || key === "") return this.#callbacks.onQuit();
623
+ if (key === "" || key === "") {
624
+ return this.#callbacks.onQuit();
625
+ }
622
626
  const shortcut = this.#shortcuts.find((s) => s.key === key);
623
- if (shortcut) shortcut.handler();
627
+ if (shortcut) {
628
+ shortcut.handler();
629
+ }
624
630
  }
625
631
  /**
626
632
  * Handle opening browser
@@ -643,7 +649,9 @@ var ShortcutsManager = class {
643
649
  * Cleanup keyboard shortcuts
644
650
  */
645
651
  cleanup() {
646
- if (!process.stdin.isTTY) return;
652
+ if (!process.stdin.isTTY) {
653
+ return;
654
+ }
647
655
  process.stdin.setRawMode(false);
648
656
  process.stdin.removeListener("data", this.#keyPressHandler);
649
657
  this.#keyPressHandler = void 0;
@@ -0,0 +1,17 @@
1
+ import { type SgNode } from '@ast-grep/napi';
2
+ /**
3
+ * An abstraction around converting files to an AST and caching
4
+ * them forever. The cache could be cleared manually.
5
+ */
6
+ export declare class AstFileSystem {
7
+ #private;
8
+ /**
9
+ * Returns the file contents as AST-grep node and caches it
10
+ * forever.
11
+ */
12
+ get(filePath: string): Promise<SgNode>;
13
+ /**
14
+ * Clear AST cache for a single file or all the files
15
+ */
16
+ clear(filePath?: string): void;
17
+ }
@@ -0,0 +1,79 @@
1
+ import { type AsyncOrSync } from '@poppinss/utils/types';
2
+ import { PathsResolver } from '../../paths_resolver.ts';
3
+ import { AstFileSystem } from '../../ast_file_system.ts';
4
+ import { type ScannedRoute, type RoutesListItem, type ScannedController, type RoutesScannerRules } from '../../types/code_scanners.ts';
5
+ export declare class RoutesScanner {
6
+ #private;
7
+ /**
8
+ * CLI UI to log colorful messages
9
+ */
10
+ ui: {
11
+ colors: import("@poppinss/colors/types").Colors;
12
+ logger: import("@poppinss/cliui").Logger;
13
+ table: (tableOptions?: Partial<import("@poppinss/cliui/types").TableOptions>) => import("@poppinss/cliui").Table;
14
+ tasks: (tasksOptions?: Partial<import("@poppinss/cliui/types").TaskManagerOptions>) => import("@poppinss/cliui").TaskManager;
15
+ icons: {
16
+ tick: string;
17
+ cross: string;
18
+ bullet: string;
19
+ nodejs: string;
20
+ pointer: string;
21
+ info: string;
22
+ warning: string;
23
+ squareSmallFilled: string;
24
+ };
25
+ sticker: () => import("@poppinss/cliui").Instructions;
26
+ instructions: () => import("@poppinss/cliui").Instructions;
27
+ switchMode(modeToUse: "raw" | "silent" | "normal"): void;
28
+ useRenderer(rendererToUse: import("@poppinss/cliui/types").RendererContract): void;
29
+ useColors(colorsToUse: import("@poppinss/colors/types").Colors): void;
30
+ };
31
+ /**
32
+ * The paths resolver is used to convert subpath and package
33
+ * imports to absolute paths
34
+ */
35
+ pathsResolver: PathsResolver;
36
+ /**
37
+ * The AstFileSystem is used to convert files to AST-grep nodes.
38
+ * The AST is cached to speed up the performance.
39
+ */
40
+ astFileSystem: AstFileSystem;
41
+ /**
42
+ * The rules to apply when scanning routes
43
+ */
44
+ rules: RoutesScannerRules;
45
+ constructor(appRoot: string, rulesCollection: RoutesScannerRules[]);
46
+ /**
47
+ * Register a callback to self compute the response types for
48
+ * a given route. The callback will be executed for all
49
+ * the routes and you must return undefined to fallback
50
+ * to the default behavior of detecting types
51
+ */
52
+ defineResponse(callback: (route: ScannedRoute, controller: ScannedController, scanner: RoutesScanner) => AsyncOrSync<ScannedRoute['response']>): this;
53
+ /**
54
+ * Register a callback to self compute the request types for
55
+ * a given route. The callback will be executed for all
56
+ * the routes and you must return undefined to fallback
57
+ * to the default behavior of detecting types
58
+ */
59
+ defineRequest(callback: (route: ScannedRoute, controller: ScannedController, scanner: RoutesScanner) => AsyncOrSync<ScannedRoute['request']>): this;
60
+ /**
61
+ * Register a callback to extract validators from the route
62
+ * controller.
63
+ */
64
+ extractValidators(callback: (route: ScannedRoute, controller: ScannedController, scanner: RoutesScanner) => AsyncOrSync<ScannedRoute['validators']>): this;
65
+ /**
66
+ * Returns the scanned routes
67
+ */
68
+ getScannedRoutes(): ScannedRoute[];
69
+ /**
70
+ * Invalidating a controller will trigger computing the validators,
71
+ * request types and the response types.
72
+ */
73
+ invalidate(controllerPath: string): Promise<void>;
74
+ /**
75
+ * Scans an array of Route list items and fetches their validators,
76
+ * controllers, and request/response types.
77
+ */
78
+ scan(routes: RoutesListItem[]): Promise<void>;
79
+ }
@@ -0,0 +1,18 @@
1
+ import { type AstFileSystem } from '../../ast_file_system.ts';
2
+ import { type ScannedController, type ScannedRoute } from '../../types/code_scanners.ts';
3
+ /**
4
+ * Extracts the VineJS validator usage from within a controller
5
+ * method. The following syntaxes are supported.
6
+ *
7
+ * - `request.validateUsing(validatorReference)`
8
+ * - `vine.validate(validatorReference)`
9
+ * - `validatorReference.validate(request.all())`
10
+ *
11
+ * - `request.validateUsing(ControllerReference.validator)`
12
+ * - `vine.validate(ControllerReference.validator)`
13
+ * - `ControllerReference.validator.validate(request.all())`
14
+ *
15
+ * The app root is needed to create relative validator imports in case
16
+ * a relative import was used within the controller file.
17
+ */
18
+ export declare function extractValidators(appRoot: string, astFileSystem: AstFileSystem, controller: ScannedController): Promise<ScannedRoute['validators']>;
@@ -0,0 +1,40 @@
1
+ import { type SgNode } from '@ast-grep/napi';
2
+ import type { Import } from './types/common.ts';
3
+ /**
4
+ * Finds an import reference inside a code snippet
5
+ */
6
+ export declare function findImport(code: string, importReference: string): Promise<Import | null>;
7
+ /**
8
+ * Returns a node that represents a TypeScript class or null
9
+ * when unable to find the class.
10
+ */
11
+ export declare function inspectClass(node: SgNode): SgNode | null;
12
+ /**
13
+ * Returns an array of SgNodes for class methods. The input node
14
+ * must represent a class.
15
+ */
16
+ export declare function inspectClassMethods(node: SgNode): SgNode[];
17
+ /**
18
+ * Converts an array of SgNode to plain text by removing whitespaces,
19
+ * identation and comments in between. Tested with the following
20
+ * children nodes only.
21
+ *
22
+ * - MemberExpression
23
+ * - Identifer
24
+ */
25
+ export declare function nodeToPlainText(node: SgNode): string;
26
+ /**
27
+ * Inspects arguments for one or more method calls. If you want to
28
+ * scope the search within a specific context, then make sure to
29
+ * first narrow down the AST and pass a specific SgNode.
30
+ *
31
+ * For example: In case of validators, we will first find the Controller
32
+ * method for which we want the validation method calls.
33
+ */
34
+ export declare function inspectMethodArguments(node: SgNode, methodCalls: string[]): SgNode[];
35
+ /**
36
+ * Inspect the validator direct usage code snippets. A member expression
37
+ * calling the ".validate" method is considered as direct usage of
38
+ * the validator.
39
+ */
40
+ export declare function searchValidatorDirectUsage(node: SgNode): SgNode[];
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Encapsulates the API to resolve import specifiers with the ability
3
+ * to define customer resolver.
4
+ */
5
+ export declare class PathsResolver {
6
+ #private;
7
+ /**
8
+ * Define a custom resolver that resolves a path
9
+ */
10
+ use(resolver: (specifier: string) => string): void;
11
+ /**
12
+ * Resolve import specifier
13
+ */
14
+ resolve(specifier: string): string;
15
+ }
@@ -1,27 +1,4 @@
1
- import type { Logger } from '@poppinss/cliui';
2
- /**
3
- * Keyboard shortcut definition
4
- */
5
- export interface KeyboardShortcut {
6
- key: string;
7
- description: string;
8
- handler: () => void;
9
- }
10
- /**
11
- * Callbacks for keyboard shortcuts actions
12
- */
13
- export interface KeyboardShortcutsCallbacks {
14
- onRestart: () => void;
15
- onClear: () => void;
16
- onQuit: () => void;
17
- }
18
- /**
19
- * Shortcuts manager options
20
- */
21
- export interface ShortcutsManagerOptions {
22
- logger: Logger;
23
- callbacks: KeyboardShortcutsCallbacks;
24
- }
1
+ import { type ShortcutsManagerOptions } from './types/common.ts';
25
2
  /**
26
3
  * Manages keyboard shortcuts for development server
27
4
  */
@@ -0,0 +1,115 @@
1
+ export type ScannedController = {
2
+ name: string;
3
+ path: string;
4
+ method: string;
5
+ import: {
6
+ type: 'default';
7
+ specifier: string;
8
+ value: string;
9
+ };
10
+ };
11
+ export type ScannedValidator = {
12
+ name: string;
13
+ import: {
14
+ type: 'namespace' | 'default' | 'named';
15
+ specifier: string;
16
+ value: string;
17
+ };
18
+ };
19
+ /**
20
+ * Output of scanned route
21
+ */
22
+ export type ScannedRoute = {
23
+ /**
24
+ * A unique name for the route provided by AdonisJS http-server. It
25
+ * could be duplicate across domains.
26
+ */
27
+ name: string;
28
+ /**
29
+ * HTTP methods for which the route is defined
30
+ */
31
+ methods: string[];
32
+ /**
33
+ * HTTP method for which the route is defined
34
+ */
35
+ domain: string;
36
+ /**
37
+ * The route pattern
38
+ */
39
+ pattern: string;
40
+ /**
41
+ * Route tokens could be used for constructing a URI for
42
+ * the route without parsing the pattern
43
+ */
44
+ tokens: {
45
+ val: string;
46
+ old: string;
47
+ type: 0 | 1 | 2 | 3;
48
+ end: string;
49
+ }[];
50
+ /**
51
+ * Inferred request data accepted by the route. By default, the request
52
+ * data type is inferred when route is using a controller with a
53
+ * validator
54
+ */
55
+ request?: {
56
+ type: string;
57
+ imports: string[];
58
+ };
59
+ /**
60
+ * Inferred response for the route. By default, the response is only
61
+ * inferred when the route is using a controller.
62
+ */
63
+ response?: {
64
+ type: string;
65
+ imports: string[];
66
+ };
67
+ /**
68
+ * Extracted validators info, only when using the controller.
69
+ */
70
+ validators?: ScannedValidator[];
71
+ /**
72
+ * Extracted controller info, only when using the controller.
73
+ */
74
+ controller?: ScannedController;
75
+ };
76
+ /**
77
+ * The route accepted by the routes scanner when initiating
78
+ * the scanning process.
79
+ */
80
+ export type RoutesListItem = {
81
+ name?: string;
82
+ pattern: string;
83
+ domain: string;
84
+ methods: string[];
85
+ controllerReference?: {
86
+ importExpression: string;
87
+ method?: string;
88
+ };
89
+ tokens: {
90
+ val: string;
91
+ old: string;
92
+ type: 0 | 1 | 2 | 3;
93
+ end: string;
94
+ }[];
95
+ };
96
+ /**
97
+ * Rules accepted by the route scanner.
98
+ */
99
+ export type RoutesScannerRules = {
100
+ /**
101
+ * An array of route names or controller+method paths to skip from
102
+ * the processing
103
+ */
104
+ skip: string[];
105
+ /**
106
+ * Define custom response type for a route by its name or the
107
+ * controller+method path
108
+ */
109
+ response: Record<string, ScannedRoute['response']>;
110
+ /**
111
+ * Define custom request data type for a route by its name
112
+ * or the controller+method path
113
+ */
114
+ request: Record<string, ScannedRoute['response']>;
115
+ };
@@ -1,4 +1,24 @@
1
+ import type { Logger } from '@poppinss/cliui';
2
+ import { type Prettify } from '@poppinss/utils/types';
1
3
  import { type BundlerHooks, type DevServerHooks, type TestRunnerHooks, type WatcherHooks } from './hooks.ts';
4
+ /**
5
+ * Marks a given optional property as required
6
+ */
7
+ export type AsRequired<T, K extends keyof T> = Prettify<Omit<T, K> & Required<{
8
+ [O in K]: T[K];
9
+ }>>;
10
+ /**
11
+ * Represents an import statement
12
+ */
13
+ export type Import = {
14
+ specifier: string;
15
+ isConstant: boolean;
16
+ clause: {
17
+ type: 'namespace' | 'default' | 'named';
18
+ value: string;
19
+ alias?: string;
20
+ };
21
+ };
2
22
  /**
3
23
  * File inspected by the filesystem based upon the provided globs
4
24
  * and the current file path
@@ -147,3 +167,26 @@ export type TestRunnerOptions = {
147
167
  * Options accepted by the project bundler
148
168
  */
149
169
  export type BundlerOptions = AssemblerRcFile;
170
+ /**
171
+ * Keyboard shortcut definition
172
+ */
173
+ export interface KeyboardShortcut {
174
+ key: string;
175
+ description: string;
176
+ handler: () => void;
177
+ }
178
+ /**
179
+ * Callbacks for keyboard shortcuts actions
180
+ */
181
+ export interface KeyboardShortcutsCallbacks {
182
+ onRestart: () => void;
183
+ onClear: () => void;
184
+ onQuit: () => void;
185
+ }
186
+ /**
187
+ * Shortcuts manager options
188
+ */
189
+ export interface ShortcutsManagerOptions {
190
+ logger: Logger;
191
+ callbacks: KeyboardShortcutsCallbacks;
192
+ }
@@ -72,6 +72,11 @@ export declare function copyFiles(files: string[], cwd: string, outDir: string):
72
72
  * only one argument as a string value.
73
73
  */
74
74
  export declare function memoize<Result>(fn: (input: string) => any, maxKeys?: number): (input: string) => Result;
75
+ /**
76
+ * Returns a boolean telling if the path value is a relative
77
+ * path starting with "./" or "../"
78
+ */
79
+ export declare function isRelative(pathValue: string): boolean;
75
80
  /**
76
81
  * Imports a selected set of lazy hooks and creates an instance of the
77
82
  * Hooks class
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "@adonisjs/assembler",
3
3
  "description": "Provides utilities to run AdonisJS development server and build project for production",
4
- "version": "8.0.0-next.2",
4
+ "version": "8.0.0-next.3",
5
5
  "engines": {
6
6
  "node": ">=24.0.0"
7
7
  },
8
+ "imports": {
9
+ "#tests/*": "./tests/*.ts"
10
+ },
8
11
  "main": "build/index.js",
9
12
  "type": "module",
10
13
  "files": [
@@ -15,6 +18,7 @@
15
18
  "exports": {
16
19
  ".": "./build/index.js",
17
20
  "./code_transformer": "./build/src/code_transformer/main.js",
21
+ "./routes_scanner": "./build/src/code_scanners/routes_scanner/main.js",
18
22
  "./types": "./build/src/types/main.js"
19
23
  },
20
24
  "scripts": {
@@ -30,35 +34,36 @@
30
34
  "release": "release-it",
31
35
  "version": "npm run build",
32
36
  "prepublishOnly": "npm run build",
33
- "quick:test": "cross-env NODE_DEBUG=adonisjs:assembler node --enable-source-maps --import=@poppinss/ts-exec bin/test.ts"
37
+ "quick:test": "cross-env NODE_DEBUG=adonisjs:assembler node --enable-source-maps --import=@poppinss/ts-exec --experimental-import-meta-resolve bin/test.ts"
34
38
  },
35
39
  "devDependencies": {
36
40
  "@adonisjs/eslint-config": "^3.0.0-next.0",
37
41
  "@adonisjs/prettier-config": "^1.4.5",
38
42
  "@adonisjs/tsconfig": "^2.0.0-next.0",
39
- "@japa/assert": "^4.0.1",
43
+ "@japa/assert": "^4.1.1",
40
44
  "@japa/file-system": "^2.3.2",
41
- "@japa/runner": "^4.2.0",
42
- "@japa/snapshot": "^2.0.8",
43
- "@poppinss/ts-exec": "^1.4.0",
45
+ "@japa/runner": "^4.4.0",
46
+ "@japa/snapshot": "^2.0.9",
47
+ "@poppinss/ts-exec": "^1.4.1",
44
48
  "@release-it/conventional-changelog": "^10.0.1",
45
- "@types/node": "^24.0.10",
46
- "@types/picomatch": "^4.0.0",
49
+ "@types/node": "^24.3.0",
50
+ "@types/picomatch": "^4.0.2",
47
51
  "@types/pretty-hrtime": "^1.0.3",
48
52
  "c8": "^10.1.3",
49
- "cross-env": "^7.0.3",
53
+ "cross-env": "^10.0.0",
50
54
  "del-cli": "^6.0.0",
51
- "eslint": "^9.30.1",
55
+ "eslint": "^9.34.0",
52
56
  "hot-hook": "^0.4.1-next.0",
53
57
  "p-event": "^6.0.1",
54
58
  "prettier": "^3.6.2",
55
- "release-it": "^19.0.3",
59
+ "release-it": "^19.0.4",
56
60
  "tsup": "^8.5.0",
57
- "typescript": "^5.8.3"
61
+ "typescript": "^5.9.2"
58
62
  },
59
63
  "dependencies": {
60
64
  "@adonisjs/env": "^6.2.0",
61
65
  "@antfu/install-pkg": "^1.1.0",
66
+ "@ast-grep/napi": "^0.39.4",
62
67
  "@poppinss/cliui": "^6.4.4",
63
68
  "@poppinss/hooks": "^7.2.6",
64
69
  "@poppinss/utils": "^7.0.0-next.3",
@@ -68,8 +73,9 @@
68
73
  "fast-glob": "^3.3.3",
69
74
  "get-port": "^7.1.0",
70
75
  "junk": "^4.0.1",
71
- "open": "^10.1.2",
72
- "picomatch": "^4.0.2",
76
+ "open": "^10.2.0",
77
+ "parse-imports": "^2.2.1",
78
+ "picomatch": "^4.0.3",
73
79
  "pretty-hrtime": "^1.0.3",
74
80
  "tmp-cache": "^1.1.0",
75
81
  "ts-morph": "^26.0.0"