@adonisjs/assembler 8.0.0-next.9 → 8.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.
Files changed (34) hide show
  1. package/README.md +260 -0
  2. package/build/codemod_exception-CzQgXAAf.js +137 -0
  3. package/build/index.d.ts +1 -1
  4. package/build/index.js +927 -1724
  5. package/build/source-dVeugJ0e.js +166 -0
  6. package/build/src/bundler.d.ts +2 -0
  7. package/build/src/code_scanners/routes_scanner/main.d.ts +16 -2
  8. package/build/src/code_scanners/routes_scanner/main.js +168 -441
  9. package/build/src/code_transformer/main.d.ts +14 -1
  10. package/build/src/code_transformer/main.js +502 -622
  11. package/build/src/code_transformer/rc_file_transformer.d.ts +28 -2
  12. package/build/src/debug.d.ts +1 -1
  13. package/build/src/dev_server.d.ts +60 -12
  14. package/build/src/exceptions/codemod_exception.d.ts +178 -0
  15. package/build/src/file_buffer.d.ts +19 -0
  16. package/build/src/file_system.d.ts +2 -2
  17. package/build/src/helpers.js +72 -16
  18. package/build/src/index_generator/main.js +28 -6
  19. package/build/src/paths_resolver.d.ts +2 -1
  20. package/build/src/test_runner.d.ts +3 -2
  21. package/build/src/types/code_scanners.d.ts +29 -13
  22. package/build/src/types/code_transformer.d.ts +127 -0
  23. package/build/src/types/common.d.ts +98 -2
  24. package/build/src/types/hooks.d.ts +4 -1
  25. package/build/src/types/main.js +1 -0
  26. package/build/src/utils.d.ts +9 -3
  27. package/build/src/virtual_file_system.d.ts +1 -1
  28. package/build/validator_extractor-Ccio_Ndi.js +82 -0
  29. package/build/virtual_file_system-bGeoWsK-.js +285 -0
  30. package/package.json +41 -39
  31. package/build/chunk-7XU453QB.js +0 -418
  32. package/build/chunk-PORDZS62.js +0 -391
  33. package/build/chunk-TIKQQRMX.js +0 -116
  34. package/build/src/hooks.d.ts +0 -224
@@ -1,3 +1,4 @@
1
+ import { type ImportInfo } from '@poppinss/utils';
1
2
  /**
2
3
  * Entry to add a middleware to a given middleware stack via the CodeTransformer.
3
4
  * Represents middleware configuration for server, router, or named middleware stacks.
@@ -90,6 +91,132 @@ export type EnvValidationNode = {
90
91
  */
91
92
  variables: Record<string, string>;
92
93
  };
94
+ /**
95
+ * Configuration for creating a new validator file via CodeTransformer.
96
+ * Represents the structure needed to generate validator files.
97
+ *
98
+ * @example
99
+ * const validator: ValidatorNode = {
100
+ * validatorFileName: 'create_user',
101
+ * exportName: 'createUserValidator',
102
+ * contents: 'export const createUserValidator = vine.compile(...)'
103
+ * }
104
+ */
105
+ export type ValidatorNode = {
106
+ /** The filename for the validator (without extension) */
107
+ validatorFileName: string;
108
+ /** The name of the exported validator constant or function */
109
+ exportName: string;
110
+ /** The complete file contents including the validator definition */
111
+ contents: string;
112
+ };
113
+ /**
114
+ * Configuration for creating a new rate limiter file via CodeTransformer.
115
+ * Represents the structure needed to generate limiter files.
116
+ *
117
+ * @example
118
+ * const limiter: LimiterNode = {
119
+ * limiterFileName: 'api_throttle',
120
+ * exportName: 'apiThrottleLimiter',
121
+ * contents: 'export const apiThrottleLimiter = limiter.define(...)'
122
+ * }
123
+ */
124
+ export type LimiterNode = {
125
+ /** The filename for the limiter (without extension) */
126
+ limiterFileName: string;
127
+ /** The name of the exported limiter constant or function */
128
+ exportName: string;
129
+ /** The complete file contents including the limiter definition */
130
+ contents: string;
131
+ };
132
+ /**
133
+ * Definition for applying a mixin to a model class.
134
+ * Mixins extend model functionality by adding methods, properties, or behaviors.
135
+ *
136
+ * @example
137
+ * const mixin: MixinDefinition = {
138
+ * name: 'SoftDeletes',
139
+ * importPath: '@adonisjs/lucid/mixins/soft_deletes',
140
+ * importType: 'named'
141
+ * }
142
+ *
143
+ * @example
144
+ * const mixinWithArgs: MixinDefinition = {
145
+ * name: 'Sluggable',
146
+ * args: ['title', '{ strategy: "dbIncrement" }'],
147
+ * importPath: '#mixins/sluggable',
148
+ * importType: 'default'
149
+ * }
150
+ */
151
+ export type MixinDefinition = {
152
+ /** The name of the mixin function or class */
153
+ name: string;
154
+ /** Optional arguments to pass to the mixin function */
155
+ args?: string[];
156
+ /** The import path to the mixin module */
157
+ importPath: string;
158
+ /** Whether the mixin is exported as named or default export */
159
+ importType: 'named' | 'default';
160
+ };
161
+ /**
162
+ * Configuration for adding a new method to an existing controller class.
163
+ * Used by CodeTransformer to inject methods into controller files.
164
+ *
165
+ * @example
166
+ * const method: ControllerMethodNode = {
167
+ * controllerFileName: 'users_controller',
168
+ * className: 'UsersController',
169
+ * name: 'destroy',
170
+ * contents: 'async destroy({ params, response }: HttpContext) { ... }',
171
+ * imports: [
172
+ * { isType: false, isNamed: true, name: 'HttpContext', path: '@adonisjs/core/http' }
173
+ * ]
174
+ * }
175
+ */
176
+ export type ControllerMethodNode = {
177
+ /** The controller filename (without extension) */
178
+ controllerFileName: string;
179
+ /** The name of the controller class */
180
+ className: string;
181
+ /** The name of the method to add */
182
+ name: string;
183
+ /** The complete method implementation including signature and body */
184
+ contents: string;
185
+ /** Optional imports needed by the method */
186
+ imports?: ImportInfo[];
187
+ };
188
+ /**
189
+ * Configuration for adding hooks to adonisrc.ts file.
190
+ * Hooks can be defined as thunks (lazy imports) or direct imports.
191
+ *
192
+ * @example
193
+ * // Thunk style (lazy import)
194
+ * const thunkHook: HookNode = {
195
+ * type: 'thunk',
196
+ * path: './commands/migrate.js'
197
+ * }
198
+ *
199
+ * @example
200
+ * // Import style with named export
201
+ * const importHook: HookNode = {
202
+ * type: 'import',
203
+ * path: '#hooks/after_build',
204
+ * name: 'afterBuildHook'
205
+ * }
206
+ */
207
+ export type HookNode = {
208
+ /** Hook type: thunk creates a lazy import function */
209
+ type: 'thunk';
210
+ /** Path to the hook module */
211
+ path: string;
212
+ } | {
213
+ /** Hook type: import directly imports the hook */
214
+ type: 'import';
215
+ /** Path to the hook module */
216
+ path: string;
217
+ /** Optional name of the exported hook (for named exports) */
218
+ name?: string;
219
+ };
93
220
  /**
94
221
  * The supported package managers for installing packages and managing lockfiles.
95
222
  * Each package manager has specific lockfiles and install commands.
@@ -4,6 +4,7 @@ import type StringBuilder from '@poppinss/utils/string_builder';
4
4
  import { type AllHooks } from './hooks.ts';
5
5
  import { type FileBuffer } from '../file_buffer.ts';
6
6
  import { type VirtualFileSystem } from '../virtual_file_system.ts';
7
+ import { type FilterPredicate } from 'fdir';
7
8
  /**
8
9
  * Recursive file tree structure for representing nested directory hierarchies
9
10
  */
@@ -15,6 +16,7 @@ export type RecursiveFileTree = {
15
16
  */
16
17
  export type VirtualFileSystemOptions = {
17
18
  glob?: string[];
19
+ filter?: FilterPredicate;
18
20
  };
19
21
  /**
20
22
  * Source configuration accepted by the index generator
@@ -22,6 +24,11 @@ export type VirtualFileSystemOptions = {
22
24
  export type IndexGeneratorSourceConfig = ({
23
25
  exportName: string;
24
26
  as: 'barrelFile';
27
+ /**
28
+ * Disable the use of lazy imports and instead import the
29
+ * files using the import expression
30
+ */
31
+ disableLazyImports?: boolean;
25
32
  } | {
26
33
  as: (vfs: VirtualFileSystem, buffer: FileBuffer, config: IndexGeneratorSourceConfig, helpers: {
27
34
  toImportPath(filePath: string): string;
@@ -30,10 +37,11 @@ export type IndexGeneratorSourceConfig = ({
30
37
  computeBaseName?: (baseName: StringBuilder) => StringBuilder;
31
38
  source: string;
32
39
  output: string;
33
- glob?: string[];
34
40
  importAlias?: string;
35
41
  removeSuffix?: string;
36
- };
42
+ skipSegments?: string[];
43
+ comment?: string | boolean;
44
+ } & VirtualFileSystemOptions;
37
45
  /**
38
46
  * Marks a given optional property as required
39
47
  *
@@ -338,3 +346,91 @@ export interface ShortcutsManagerOptions {
338
346
  /** Callback functions for different shortcut actions */
339
347
  callbacks: KeyboardShortcutsCallbacks;
340
348
  }
349
+ /**
350
+ * Message sent from the dev server child process to the parent when the server is ready.
351
+ * Used for IPC communication to notify when the AdonisJS HTTP server has started.
352
+ *
353
+ * @example
354
+ * const message: AdonisJSServerReadyMessage = {
355
+ * isAdonisJS: true,
356
+ * environment: 'web',
357
+ * port: 3333,
358
+ * host: 'localhost',
359
+ * duration: [0, 150000000] // [seconds, nanoseconds]
360
+ * }
361
+ */
362
+ export type AdonisJSServerReadyMessage = {
363
+ /** Marker to identify AdonisJS-specific messages */
364
+ isAdonisJS: true;
365
+ /** The environment type (always 'web' for HTTP servers) */
366
+ environment: 'web';
367
+ /** The port number the server is listening on */
368
+ port: number;
369
+ /** The host address the server is bound to */
370
+ host: string;
371
+ /** Optional server startup duration as [seconds, nanoseconds] tuple */
372
+ duration?: [number, number];
373
+ };
374
+ /**
375
+ * Message sent from the dev server child process when routes are committed.
376
+ * Contains the file location where routes are defined.
377
+ *
378
+ * @example
379
+ * const message: AdonisJSRoutesSharedMessage = {
380
+ * isAdonisJS: true,
381
+ * routesFileLocation: '/project/start/routes.ts'
382
+ * }
383
+ */
384
+ export type AdonisJSRoutesSharedMessage = {
385
+ /** Marker to identify AdonisJS-specific messages */
386
+ isAdonisJS: true;
387
+ /** Absolute path to the routes definition file */
388
+ routesFileLocation: string;
389
+ };
390
+ /**
391
+ * Messages sent by the hot-hook module for HMR (Hot Module Replacement) communication.
392
+ * These messages notify the dev server about file system changes and module invalidations.
393
+ *
394
+ * @example
395
+ * // Full reload required
396
+ * const fullReload: HotHookMessage = {
397
+ * type: 'hot-hook:full-reload',
398
+ * path: 'app/middleware/auth.ts',
399
+ * shouldBeReloadable: false
400
+ * }
401
+ *
402
+ * @example
403
+ * // Modules invalidated (can be hot-reloaded)
404
+ * const invalidated: HotHookMessage = {
405
+ * type: 'hot-hook:invalidated',
406
+ * paths: ['app/controllers/users_controller.ts', 'app/models/user.ts']
407
+ * }
408
+ *
409
+ * @example
410
+ * // File changed notification
411
+ * const fileChanged: HotHookMessage = {
412
+ * type: 'hot-hook:file-changed',
413
+ * path: 'config/database.ts',
414
+ * action: 'change'
415
+ * }
416
+ */
417
+ export type HotHookMessage = {
418
+ /** Message type indicating a full server reload is required */
419
+ type: 'hot-hook:full-reload';
420
+ /** Path to the file that triggered the full reload */
421
+ path: string;
422
+ /** Whether the file should be hot-reloadable but isn't */
423
+ shouldBeReloadable?: boolean;
424
+ } | {
425
+ /** Message type indicating modules have been invalidated */
426
+ type: 'hot-hook:invalidated';
427
+ /** Array of module paths that were invalidated */
428
+ paths: string[];
429
+ } | {
430
+ /** Message type indicating a file has changed */
431
+ type: 'hot-hook:file-changed';
432
+ /** Path to the file that changed */
433
+ path: string;
434
+ /** The type of file system change */
435
+ action: 'change' | 'add' | 'unlink';
436
+ };
@@ -6,6 +6,7 @@ import { type TestRunner } from '../test_runner.ts';
6
6
  import { type RoutesListItem } from './code_scanners.ts';
7
7
  import { type IndexGenerator } from '../index_generator/main.ts';
8
8
  import { type RoutesScanner } from '../code_scanners/routes_scanner/main.ts';
9
+ import type Hooks from '@poppinss/hooks';
9
10
  /**
10
11
  * Defines a hook that can be either a lazy import or an object with a run method.
11
12
  * This type provides flexibility in how hooks are defined and imported, supporting
@@ -45,7 +46,9 @@ export type CommonHooks = {
45
46
  *
46
47
  * @param parent - The parent instance (DevServer, TestRunner, or Bundler)
47
48
  */
48
- init: DefineHook<(parent: DevServer | TestRunner | Bundler, indexGenerator: IndexGenerator) => AsyncOrSync<void>>[];
49
+ init: DefineHook<(parent: DevServer | TestRunner | Bundler, hooks: Hooks<{
50
+ [P in keyof AllHooks]: [HookParams<P>, HookParams<P>];
51
+ }>, indexGenerator: IndexGenerator) => AsyncOrSync<void>>[];
49
52
  };
50
53
  /**
51
54
  * Hooks executed by the dev server around the router.
@@ -0,0 +1 @@
1
+ export {};
@@ -1,6 +1,7 @@
1
1
  import Hooks from '@poppinss/hooks';
2
2
  import type tsStatic from 'typescript';
3
3
  import { type ChokidarOptions } from 'chokidar';
4
+ import { type TsConfigResult } from 'get-tsconfig';
4
5
  import type { RunScriptOptions } from './types/common.ts';
5
6
  import { type AllHooks, type HookParams } from './types/hooks.ts';
6
7
  /**
@@ -10,11 +11,14 @@ import { type AllHooks, type HookParams } from './types/hooks.ts';
10
11
  * handling diagnostic errors and returning a parsed configuration that can be
11
12
  * used by other TypeScript operations.
12
13
  *
14
+ * @deprecated While we are experimenting with the readTsConfig method
15
+ *
13
16
  * @param cwd - The current working directory URL or string path
14
17
  * @param ts - TypeScript module reference
15
18
  * @returns Parsed TypeScript configuration or undefined if parsing failed
16
19
  */
17
20
  export declare function parseConfig(cwd: URL | string, ts: typeof tsStatic): tsStatic.ParsedCommandLine | undefined;
21
+ export declare function readTsConfig(cwd: string): TsConfigResult | null;
18
22
  /**
19
23
  * Runs a Node.js script as a child process and inherits the stdio streams
20
24
  *
@@ -36,7 +40,7 @@ export declare function runNode(cwd: string | URL, options: RunScriptOptions): i
36
40
  buffer: false;
37
41
  stdio: "pipe" | "inherit";
38
42
  env: {
39
- TZ?: string;
43
+ TZ?: string | undefined;
40
44
  FORCE_COLOR?: string | undefined;
41
45
  };
42
46
  }>;
@@ -58,7 +62,7 @@ export declare function run(cwd: string | URL, options: Omit<RunScriptOptions, '
58
62
  buffer: false;
59
63
  stdio: "pipe" | "inherit";
60
64
  env: {
61
- TZ?: string;
65
+ TZ?: string | undefined;
62
66
  FORCE_COLOR?: string | undefined;
63
67
  };
64
68
  }>;
@@ -144,7 +148,9 @@ export declare function isRelative(pathValue: string): boolean;
144
148
  * @param names - Array of hook names to load
145
149
  * @returns Promise resolving to configured Hooks instance
146
150
  */
147
- export declare function loadHooks<K extends keyof AllHooks>(rcFileHooks: Partial<AllHooks> | undefined, names: K[]): Promise<Hooks<{ [P in K]: [HookParams<P>, HookParams<P>]; }>>;
151
+ export declare function loadHooks<K extends keyof AllHooks>(rcFileHooks: Partial<AllHooks> | undefined, names: K[]): Promise<Hooks<{
152
+ [P in K]: [HookParams<P>, HookParams<P>];
153
+ }>>;
148
154
  /**
149
155
  * Wraps a function inside another function that throttles the concurrent
150
156
  * executions of a function. If the function is called too quickly, then
@@ -65,7 +65,7 @@ export declare class VirtualFileSystem {
65
65
  */
66
66
  asTree(options?: {
67
67
  transformKey?: (key: string) => string;
68
- transformValue?: (filePath: string) => string;
68
+ transformValue?: (filePath: string, key: string) => string;
69
69
  }): RecursiveFileTree;
70
70
  /**
71
71
  * Add a new file to the virtual file system. File is only added when it
@@ -0,0 +1,82 @@
1
+ import { i as isRelative, m as debug_default } from "./virtual_file_system-bGeoWsK-.js";
2
+ import { findImport, inspectClass, inspectClassMethods, inspectMethodArguments, nodeToPlainText, searchValidatorDirectUsage } from "./src/helpers.js";
3
+ import { fileURLToPath, pathToFileURL } from "node:url";
4
+ import string from "@poppinss/utils/string";
5
+ import { join, relative } from "node:path";
6
+ import { resolve } from "import-meta-resolve";
7
+ var PathsResolver = class {
8
+ #appRoot;
9
+ #resolvedPaths = {};
10
+ #resolver = (specifier, parentPath) => resolve(specifier, parentPath);
11
+ constructor(appRoot) {
12
+ this.#appRoot = pathToFileURL(join(appRoot, "index.js")).href;
13
+ }
14
+ use(resolver) {
15
+ this.#resolver = resolver;
16
+ }
17
+ resolve(specifier, rewriteAliasImportExtension = false) {
18
+ if (isRelative(specifier)) throw new Error("Cannot resolve relative paths using PathsResolver");
19
+ const cacheKey = specifier;
20
+ const cached = this.#resolvedPaths[cacheKey];
21
+ if (cached) return cached;
22
+ let resolvedPath = fileURLToPath(this.#resolver(specifier, this.#appRoot));
23
+ if (rewriteAliasImportExtension && specifier.startsWith("#") && resolvedPath.endsWith(".js")) resolvedPath = resolvedPath.replace(/\.js$/, ".ts");
24
+ this.#resolvedPaths[cacheKey] = resolvedPath;
25
+ return this.#resolvedPaths[cacheKey];
26
+ }
27
+ };
28
+ async function extractValidators(appRoot, vfs, controller) {
29
+ const root = await vfs.get(controller.path);
30
+ const fileContents = root.text();
31
+ const controllerClass = inspectClass(root);
32
+ if (!controllerClass) {
33
+ debug_default(`No class defined within the "%s"`, controller.import.specifier);
34
+ return;
35
+ }
36
+ const method = inspectClassMethods(controllerClass).find((methodNode) => {
37
+ return methodNode.find({ rule: { kind: "property_identifier" } })?.text() === controller.method;
38
+ });
39
+ if (!method) {
40
+ debug_default(`Unable to find "%s" method in "%s"`, controller.method, controller.import.specifier);
41
+ return;
42
+ }
43
+ const validationCalls = inspectMethodArguments(method, [
44
+ "request.validateUsing",
45
+ "$CTX.request.validateUsing",
46
+ "vine.validate"
47
+ ]).map((node) => {
48
+ const firstArg = node.find({ rule: { any: [{ kind: "identifier" }, { kind: "member_expression" }] } });
49
+ if (!firstArg) return;
50
+ return nodeToPlainText(firstArg);
51
+ }).filter((node) => node !== void 0).concat(searchValidatorDirectUsage(method).map((node) => nodeToPlainText(node)));
52
+ if (!validationCalls.length) {
53
+ debug_default(`Unable to detect any validation calls in "%s.%s" method`, controller.import.specifier, controller.method);
54
+ return;
55
+ }
56
+ const controllerName = controllerClass.find({ rule: { kind: "type_identifier" } }).text();
57
+ const controllerURL = pathToFileURL(controller.path);
58
+ return (await Promise.all(validationCalls.map(async (validationCall) => {
59
+ if (validationCall.split(".")[0] === controllerName) return {
60
+ name: validationCall,
61
+ import: {
62
+ specifier: controller.import.specifier,
63
+ type: "default",
64
+ value: controllerName
65
+ }
66
+ };
67
+ const importCall = await findImport(fileContents, validationCall);
68
+ if (!importCall) {
69
+ debug_default("Unable to find import for \"%s\" used by \"%s.%s\" method", validationCall, controller.import.specifier, controller.method);
70
+ return null;
71
+ }
72
+ return {
73
+ name: validationCall,
74
+ import: {
75
+ specifier: isRelative(importCall.specifier) ? string.toUnixSlash(relative(appRoot, fileURLToPath(new URL(importCall.specifier, controllerURL)))) : importCall.specifier,
76
+ type: importCall.clause.type,
77
+ value: importCall.clause.value
78
+ }
79
+ };
80
+ }))).filter((value) => !!value);
81
+ }
82
+ export { PathsResolver as n, extractValidators as t };