@adonisjs/assembler 8.0.0-next.8 → 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 +3 -1
  4. package/build/index.js +927 -1720
  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 +22 -2
  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-N6H4XTTC.js +0 -405
  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,445 +1,172 @@
1
- import {
2
- findImport,
3
- inspectClass,
4
- inspectClassMethods,
5
- inspectMethodArguments,
6
- nodeToPlainText,
7
- searchValidatorDirectUsage
8
- } from "../../../chunk-TIKQQRMX.js";
9
- import {
10
- VirtualFileSystem,
11
- debug_default,
12
- isRelative
13
- } from "../../../chunk-PORDZS62.js";
14
-
15
- // src/code_scanners/routes_scanner/main.ts
1
+ import { m as debug_default, t as VirtualFileSystem } from "../../../virtual_file_system-bGeoWsK-.js";
2
+ import { n as PathsResolver, t as extractValidators } from "../../../validator_extractor-Ccio_Ndi.js";
16
3
  import { cliui } from "@poppinss/cliui";
17
- import string2 from "@poppinss/utils/string";
18
- import { parseImports } from "parse-imports";
19
- import StringBuilder from "@poppinss/utils/string_builder";
20
-
21
- // src/paths_resolver.ts
22
- import { fileURLToPath } from "url";
23
- var PathsResolver = class {
24
- /**
25
- * Cache of resolved paths to avoid resolving the same specifier multiple times
26
- */
27
- #resolvedPaths = {};
28
- /**
29
- * The resolver function used to resolve import specifiers
30
- */
31
- #resolver = (specifier) => import.meta.resolve(specifier);
32
- /**
33
- * Define a custom resolver that resolves a path
34
- *
35
- * The custom resolver function will be used instead of the default
36
- * import.meta.resolve() for resolving import specifiers.
37
- *
38
- * @param resolver - Function that takes a specifier and returns resolved path
39
- */
40
- use(resolver) {
41
- this.#resolver = resolver;
42
- }
43
- /**
44
- * Resolve import specifier to an absolute file path
45
- *
46
- * This method caches resolved paths to improve performance on repeated
47
- * resolutions. Relative paths are not supported and will throw an error.
48
- *
49
- * @param specifier - The import specifier to resolve (must not be relative)
50
- * @returns The resolved absolute file path
51
- * @throws Error when attempting to resolve relative paths
52
- *
53
- * @example
54
- * const path = resolver.resolve('#app/models/user')
55
- * const path2 = resolver.resolve('@/utils/helper')
56
- */
57
- resolve(specifier) {
58
- if (isRelative(specifier)) {
59
- throw new Error("Cannot resolve relative paths using PathsResolver");
60
- }
61
- const cacheKey = specifier;
62
- const cached = this.#resolvedPaths[cacheKey];
63
- if (cached) {
64
- return cached;
65
- }
66
- this.#resolvedPaths[cacheKey] = fileURLToPath(this.#resolver(specifier));
67
- return this.#resolvedPaths[cacheKey];
68
- }
69
- };
70
-
71
- // src/code_scanners/routes_scanner/validator_extractor.ts
72
- import { relative } from "path";
73
4
  import string from "@poppinss/utils/string";
74
- import { fileURLToPath as fileURLToPath2, pathToFileURL } from "url";
75
- async function extractValidators(appRoot, vfs, controller) {
76
- const root = await vfs.get(controller.path);
77
- const fileContents = root.text();
78
- const controllerClass = inspectClass(root);
79
- if (!controllerClass) {
80
- debug_default(`No class defined within the "%s"`, controller.import.specifier);
81
- return;
82
- }
83
- const method = inspectClassMethods(controllerClass).find((e) => {
84
- return e.find({
85
- rule: { kind: "property_identifier", regex: `\\b${controller.method}\\b` }
86
- });
87
- });
88
- if (!method) {
89
- debug_default(`Unable to find "%s" method in "%s"`, controller.method, controller.import.specifier);
90
- return;
91
- }
92
- const validationCalls = inspectMethodArguments(method, ["request.validateUsing", "vine.validate"]).map((node) => {
93
- const firstArg = node.find({
94
- rule: { any: [{ kind: "identifier" }, { kind: "member_expression" }] }
95
- });
96
- if (!firstArg) {
97
- return;
98
- }
99
- return nodeToPlainText(firstArg);
100
- }).filter((node) => node !== void 0).concat(searchValidatorDirectUsage(method).map((node) => nodeToPlainText(node)));
101
- if (!validationCalls.length) {
102
- debug_default(
103
- `Unable to detect any validation calls in "%s.%s" method`,
104
- controller.import.specifier,
105
- controller.method
106
- );
107
- return;
108
- }
109
- const controllerName = controllerClass.find({ rule: { kind: "type_identifier" } }).text();
110
- const controllerURL = pathToFileURL(controller.path);
111
- const imports = await Promise.all(
112
- validationCalls.map(async (validationCall) => {
113
- const validatorNamespace = validationCall.split(".")[0];
114
- if (validatorNamespace === controllerName) {
115
- return {
116
- name: validationCall,
117
- import: {
118
- specifier: controller.import.specifier,
119
- type: "default",
120
- value: controllerName
121
- }
122
- };
123
- }
124
- const importCall = await findImport(fileContents, validationCall);
125
- if (!importCall) {
126
- debug_default(
127
- 'Unable to find import for "%s" used by "%s.%s" method',
128
- validationCall,
129
- controller.import.specifier,
130
- controller.method
131
- );
132
- return null;
133
- }
134
- return {
135
- name: validationCall,
136
- import: {
137
- specifier: isRelative(importCall.specifier) ? string.toUnixSlash(
138
- relative(appRoot, fileURLToPath2(new URL(importCall.specifier, controllerURL)))
139
- ) : importCall.specifier,
140
- type: importCall.clause.type,
141
- value: importCall.clause.value
142
- }
143
- };
144
- })
145
- );
146
- return imports.filter((value) => !!value);
147
- }
148
-
149
- // src/code_scanners/routes_scanner/main.ts
5
+ import StringBuilder from "@poppinss/utils/string_builder";
6
+ import { parseImports } from "parse-imports";
150
7
  var RoutesScanner = class {
151
- /**
152
- * The root of the application from where we will resolve
153
- * paths.
154
- */
155
- #appRoot;
156
- /**
157
- * Collection of routes by their controller file path. This helps
158
- * us re-compute request types when the controller is changed.
159
- */
160
- #controllerRoutes = {};
161
- /**
162
- * Collection of scanned routes
163
- */
164
- #scannedRoutes = [];
165
- /**
166
- * A custom method to self compute the response type for a route. Return
167
- * undefined to fallback to the default behavior
168
- */
169
- #computeResponseTypes;
170
- /**
171
- * A custom method to self compute the request type for a route. Return
172
- * undefined to fallback to the default behavior
173
- */
174
- #computeRequestTypes;
175
- /**
176
- * A custom method to self extract the validators from the route controller.
177
- * Return undefined to fallback to the default behavior.
178
- */
179
- #extractValidators;
180
- /**
181
- * CLI UI instance to log colorful messages and progress information
182
- */
183
- ui = cliui();
184
- /**
185
- * The paths resolver is used to convert subpath and package
186
- * imports to absolute paths
187
- */
188
- pathsResolver = new PathsResolver();
189
- /**
190
- * The rules to apply when scanning routes
191
- */
192
- rules = {
193
- skip: [],
194
- request: {},
195
- response: {}
196
- };
197
- /**
198
- * Create a new RoutesScanner instance
199
- *
200
- * @param appRoot - The root directory of the application
201
- * @param rulesCollection - Collection of rules to apply during scanning
202
- */
203
- constructor(appRoot, rulesCollection) {
204
- this.#appRoot = appRoot;
205
- rulesCollection.forEach((rules) => {
206
- this.rules.skip = this.rules.skip.concat(rules.skip);
207
- Object.assign(this.rules.request, rules.request);
208
- Object.assign(this.rules.response, rules.response);
209
- });
210
- this.rules.skip = Array.from(/* @__PURE__ */ new Set([...this.rules.skip]));
211
- }
212
- /**
213
- * Assumes the validators are from VineJS and computes the request types from them
214
- *
215
- * This method generates TypeScript type definitions for request validation
216
- * by analyzing VineJS validators and creating Infer types.
217
- *
218
- * @param route - The scanned route with validators
219
- * @returns Request type definition or undefined
220
- */
221
- #prepareRequestTypes(route) {
222
- if (!route.validators) {
223
- return;
224
- }
225
- const schemas = route.validators.reduce((result, validator) => {
226
- const validatorExport = validator.import.type === "default" ? ".default" : validator.import.type === "named" ? `.${validator.import.value}` : "";
227
- const [, ...segments] = validator.name.split(".");
228
- const namespace = segments.map((segment) => `['${segment}']`).join("");
229
- result.push(
230
- `Infer<(typeof import('${validator.import.specifier}')${validatorExport})${namespace}>`
231
- );
232
- return result;
233
- }, []);
234
- return {
235
- type: schemas.join("|"),
236
- imports: [`import { Infer } from '@vinejs/vine/types'`]
237
- };
238
- }
239
- /**
240
- * Inspects the controller reference and fetches its import specifier
241
- * and the controller name from it.
242
- */
243
- async #inspectControllerSpecifier(importExpression, method) {
244
- const imports = [...await parseImports(importExpression)];
245
- const importedModule = imports.find(
246
- ($import) => $import.isDynamicImport && $import.moduleSpecifier.value
247
- );
248
- if (!importedModule || importedModule.moduleSpecifier.type !== "package" || !importedModule.moduleSpecifier.value) {
249
- return null;
250
- }
251
- const specifier = importedModule.moduleSpecifier.value;
252
- const name = new StringBuilder(specifier.split("/").pop()).removeSuffix("Controller").pascalCase().suffix("Controller").toString();
253
- return {
254
- name,
255
- method: method ?? "handle",
256
- path: string2.toUnixSlash(this.pathsResolver.resolve(specifier)),
257
- import: {
258
- specifier,
259
- type: "default",
260
- value: name
261
- }
262
- };
263
- }
264
- /**
265
- * Defines the response type for the route
266
- */
267
- async #setResponse(route, controller) {
268
- const responseType = await this.#computeResponseTypes?.(route, controller, this);
269
- route.response = responseType ?? {
270
- type: `ReturnType<import('${controller.import.specifier}').default['${controller.method}']>`,
271
- imports: []
272
- };
273
- }
274
- /**
275
- * Defines the request type for the route
276
- */
277
- async #setRequest(route, controller, vfs) {
278
- route.validators = await this.#extractValidators?.(route, controller, this) ?? await extractValidators(this.#appRoot, vfs, controller);
279
- route.request = await this.#computeRequestTypes?.(route, controller, this) ?? this.#prepareRequestTypes(route);
280
- }
281
- /**
282
- * Scans a route that is not using a controller
283
- */
284
- #processRouteWithoutController(route) {
285
- if (!route.name) {
286
- debug_default(`skipping route "%s" scanning. Missing a controller reference`, route.name);
287
- return;
288
- }
289
- const scannedRoute = {
290
- name: route.name,
291
- domain: route.domain,
292
- methods: route.methods,
293
- pattern: route.pattern,
294
- tokens: route.tokens,
295
- request: this.rules.request[route.name],
296
- response: this.rules.response[route.name]
297
- };
298
- this.#scannedRoutes.push(scannedRoute);
299
- }
300
- /**
301
- * Scans a route that is using a controller reference
302
- */
303
- async #processRouteWithController(route, vfs) {
304
- const controller = await this.#inspectControllerSpecifier(
305
- route.controllerReference.importExpression,
306
- route.controllerReference.method
307
- );
308
- if (!controller) {
309
- return this.#processRouteWithoutController(route);
310
- }
311
- const routeName = route.name ?? new StringBuilder(controller.name).removeSuffix("Controller").snakeCase().suffix(`.${string2.snakeCase(controller.method)}`).toString();
312
- if (this.rules.skip.includes(routeName)) {
313
- return;
314
- }
315
- const scannedRoute = {
316
- name: routeName,
317
- domain: route.domain,
318
- methods: route.methods,
319
- pattern: route.pattern,
320
- tokens: route.tokens,
321
- request: this.rules.request[routeName],
322
- response: this.rules.response[routeName],
323
- controller
324
- };
325
- this.#scannedRoutes.push(scannedRoute);
326
- if (!scannedRoute.request || !scannedRoute.response) {
327
- this.#controllerRoutes[controller.path] ??= [];
328
- this.#controllerRoutes[controller.path].push(scannedRoute);
329
- if (!scannedRoute.response) {
330
- await this.#setResponse(scannedRoute, controller);
331
- }
332
- if (!scannedRoute.request) {
333
- await this.#setRequest(scannedRoute, controller, vfs);
334
- }
335
- }
336
- }
337
- /**
338
- * Processing a given route list item and further scan it to
339
- * fetch the controller, request and response types.
340
- */
341
- async #processRoute(route, vfs) {
342
- if (route.name && this.rules.skip.includes(route.name)) {
343
- return;
344
- }
345
- if (!route.controllerReference) {
346
- this.#processRouteWithoutController(route);
347
- return;
348
- }
349
- await this.#processRouteWithController(
350
- route,
351
- vfs
352
- );
353
- }
354
- /**
355
- * Register a callback to self compute the response types for
356
- * a given route. The callback will be executed for all
357
- * the routes and you must return undefined to fallback
358
- * to the default behavior of detecting types
359
- *
360
- * @param callback - Function to compute response types for routes
361
- * @returns This RoutesScanner instance for method chaining
362
- */
363
- defineResponse(callback) {
364
- this.#computeResponseTypes = callback;
365
- return this;
366
- }
367
- /**
368
- * Register a callback to self compute the request types for
369
- * a given route. The callback will be executed for all
370
- * the routes and you must return undefined to fallback
371
- * to the default behavior of detecting types
372
- *
373
- * @param callback - Function to compute request types for routes
374
- * @returns This RoutesScanner instance for method chaining
375
- */
376
- defineRequest(callback) {
377
- this.#computeRequestTypes = callback;
378
- return this;
379
- }
380
- /**
381
- * Register a callback to extract validators from the route controller
382
- *
383
- * @param callback - Function to extract validators from controllers
384
- * @returns This RoutesScanner instance for method chaining
385
- */
386
- extractValidators(callback) {
387
- this.#extractValidators = callback;
388
- return this;
389
- }
390
- /**
391
- * Returns the scanned routes
392
- *
393
- * @returns Array of scanned routes with their metadata
394
- */
395
- getScannedRoutes() {
396
- return this.#scannedRoutes;
397
- }
398
- /**
399
- * Returns an array of controllers bound to the provided
400
- * routes
401
- *
402
- * @returns Array of controller's absolute paths
403
- */
404
- getControllers() {
405
- return Object.keys(this.#controllerRoutes);
406
- }
407
- /**
408
- * Invalidating a controller will trigger computing the validators,
409
- * request types and the response types.
410
- *
411
- * @param controllerPath - Path to the controller file to invalidate
412
- */
413
- async invalidate(controllerPath) {
414
- const controllerRoutes = this.#controllerRoutes[controllerPath];
415
- if (!controllerRoutes) {
416
- return;
417
- }
418
- for (let scannedRoute of controllerRoutes) {
419
- if (scannedRoute.controller) {
420
- const vfs = new VirtualFileSystem(this.#appRoot);
421
- await this.#setResponse(scannedRoute, scannedRoute.controller);
422
- await this.#setRequest(scannedRoute, scannedRoute.controller, vfs);
423
- }
424
- }
425
- }
426
- /**
427
- * Scans an array of Route list items and fetches their validators,
428
- * controllers, and request/response types.
429
- *
430
- * This is the main method that processes all routes and extracts
431
- * their type information for code generation purposes.
432
- *
433
- * @param routes - Array of route list items to scan
434
- */
435
- async scan(routes) {
436
- const vfs = new VirtualFileSystem(this.#appRoot);
437
- for (let route of routes) {
438
- await this.#processRoute(route, vfs);
439
- }
440
- vfs.invalidate();
441
- }
442
- };
443
- export {
444
- RoutesScanner
8
+ #filter;
9
+ #appRoot;
10
+ #controllerRoutes = {};
11
+ #scannedRoutes = [];
12
+ #computeResponseTypes;
13
+ #computeRequestTypes;
14
+ #extractValidators;
15
+ ui = cliui();
16
+ pathsResolver;
17
+ rules = {
18
+ request: {},
19
+ response: {}
20
+ };
21
+ constructor(appRoot, rulesCollection) {
22
+ this.#appRoot = appRoot;
23
+ this.pathsResolver = new PathsResolver(appRoot);
24
+ rulesCollection.forEach((rules) => {
25
+ Object.assign(this.rules.request, rules.request);
26
+ Object.assign(this.rules.response, rules.response);
27
+ });
28
+ }
29
+ #shouldSkipRoute(route) {
30
+ if (this.#filter) return !this.#filter(route);
31
+ return false;
32
+ }
33
+ #prepareRequestTypes(route) {
34
+ if (!route.validators) return;
35
+ return {
36
+ type: route.validators.reduce((result, validator) => {
37
+ const validatorExport = validator.import.type === "default" ? ".default" : validator.import.type === "named" ? `.${validator.import.value}` : "";
38
+ const [, ...segments] = validator.name.split(".");
39
+ const namespace = segments.map((segment) => `['${segment}']`).join("");
40
+ result.push(`InferInput<(typeof import('${validator.import.specifier}')${validatorExport})${namespace}>`);
41
+ return result;
42
+ }, []).join("|"),
43
+ imports: [`import { InferInput } from '@vinejs/vine/types'`]
44
+ };
45
+ }
46
+ async #inspectControllerSpecifier(importExpression, method) {
47
+ const importedModule = [...await parseImports(importExpression)].find(($import) => $import.isDynamicImport && $import.moduleSpecifier.value);
48
+ if (!importedModule || importedModule.moduleSpecifier.type !== "package" || !importedModule.moduleSpecifier.value) return null;
49
+ const specifier = importedModule.moduleSpecifier.value;
50
+ const name = new StringBuilder(specifier.split("/").pop()).removeSuffix("Controller").pascalCase().suffix("Controller").toString();
51
+ return {
52
+ name,
53
+ method: method ?? "handle",
54
+ path: string.toUnixSlash(this.pathsResolver.resolve(specifier, true)),
55
+ import: {
56
+ specifier,
57
+ type: "default",
58
+ value: name
59
+ }
60
+ };
61
+ }
62
+ async #setResponse(route, controller) {
63
+ route.response = await this.#computeResponseTypes?.(route, controller, this) ?? {
64
+ type: `ReturnType<import('${controller.import.specifier}').default['${controller.method}']>`,
65
+ imports: []
66
+ };
67
+ debug_default("computed route \"%s\" response %O", route.name, route.response);
68
+ }
69
+ async #setRequest(route, controller, vfs) {
70
+ route.validators = await this.#extractValidators?.(route, controller, this) ?? await extractValidators(this.#appRoot, vfs, controller);
71
+ debug_default("computed route \"%s\" validators %O", route.name, route.validators);
72
+ route.request = await this.#computeRequestTypes?.(route, controller, this) ?? this.#prepareRequestTypes(route);
73
+ debug_default("computed route \"%s\" request input %O", route.name, route.request);
74
+ }
75
+ #processRouteWithoutController(route) {
76
+ if (!route.name) {
77
+ debug_default(`skipping route "%s" as it does not have a name`, route.pattern);
78
+ return;
79
+ }
80
+ const scannedRoute = {
81
+ name: route.name,
82
+ domain: route.domain,
83
+ methods: route.methods,
84
+ pattern: route.pattern,
85
+ tokens: route.tokens,
86
+ request: this.rules.request[route.name],
87
+ response: this.rules.response[route.name]
88
+ };
89
+ debug_default("scanned route without controller %O", scannedRoute);
90
+ this.#scannedRoutes.push(scannedRoute);
91
+ }
92
+ async #processRouteWithController(route, vfs) {
93
+ if (!route.handler || !route.handler.importExpression) return this.#processRouteWithoutController(route);
94
+ const controller = await this.#inspectControllerSpecifier(route.handler.importExpression, route.handler.method);
95
+ if (!controller) return this.#processRouteWithoutController(route);
96
+ debug_default("processing route \"%s\" with inspected controller %O", route.name, controller);
97
+ route.name = route.name ?? new StringBuilder(controller.name).removeSuffix("Controller").snakeCase().suffix(`.${string.snakeCase(controller.method)}`).toString();
98
+ if (this.#shouldSkipRoute(route)) return;
99
+ const scannedRoute = {
100
+ name: route.name,
101
+ domain: route.domain,
102
+ methods: route.methods,
103
+ pattern: route.pattern,
104
+ tokens: route.tokens,
105
+ request: this.rules.request[route.name],
106
+ response: this.rules.response[route.name],
107
+ controller
108
+ };
109
+ debug_default("scanned route %O", scannedRoute);
110
+ this.#scannedRoutes.push(scannedRoute);
111
+ if (!scannedRoute.request || !scannedRoute.response) {
112
+ debug_default("tracking controller for rescanning %O", scannedRoute);
113
+ this.#controllerRoutes[controller.path] ??= [];
114
+ this.#controllerRoutes[controller.path].push(scannedRoute);
115
+ if (!scannedRoute.response) await this.#setResponse(scannedRoute, controller);
116
+ if (!scannedRoute.request) await this.#setRequest(scannedRoute, controller, vfs);
117
+ }
118
+ }
119
+ async #processRoute(route, vfs) {
120
+ if (route.name && this.#shouldSkipRoute(route)) {
121
+ debug_default("route skipped route: %O, rules: %O", route, this.rules);
122
+ return;
123
+ }
124
+ if (typeof route.handler === "function") {
125
+ this.#processRouteWithoutController(route);
126
+ return;
127
+ }
128
+ await this.#processRouteWithController(route, vfs);
129
+ }
130
+ defineResponse(callback) {
131
+ this.#computeResponseTypes = callback;
132
+ return this;
133
+ }
134
+ defineRequest(callback) {
135
+ this.#computeRequestTypes = callback;
136
+ return this;
137
+ }
138
+ extractValidators(callback) {
139
+ this.#extractValidators = callback;
140
+ return this;
141
+ }
142
+ getScannedRoutes() {
143
+ return this.#scannedRoutes;
144
+ }
145
+ getControllers() {
146
+ return Object.keys(this.#controllerRoutes);
147
+ }
148
+ async invalidate(controllerPath) {
149
+ const controllerRoutes = this.#controllerRoutes[controllerPath];
150
+ if (!controllerRoutes || !controllerRoutes.length) {
151
+ debug_default("\"%s\" controllers is not part of scanned controllers %O", controllerPath, this.#controllerRoutes);
152
+ return false;
153
+ }
154
+ for (let scannedRoute of controllerRoutes) if (scannedRoute.controller) {
155
+ debug_default("invalidating route %O", scannedRoute);
156
+ const vfs = new VirtualFileSystem(this.#appRoot);
157
+ await this.#setResponse(scannedRoute, scannedRoute.controller);
158
+ await this.#setRequest(scannedRoute, scannedRoute.controller, vfs);
159
+ }
160
+ return true;
161
+ }
162
+ filter(filterFn) {
163
+ this.#filter = filterFn;
164
+ return this;
165
+ }
166
+ async scan(routes) {
167
+ const vfs = new VirtualFileSystem(this.#appRoot);
168
+ for (const route of routes) await this.#processRoute(route, vfs);
169
+ vfs.invalidate();
170
+ }
445
171
  };
172
+ export { RoutesScanner };
@@ -1,7 +1,7 @@
1
1
  import { installPackage, detectPackageManager } from '@antfu/install-pkg';
2
2
  import { Project } from 'ts-morph';
3
3
  import { RcFileTransformer } from './rc_file_transformer.ts';
4
- import type { MiddlewareNode, EnvValidationNode, BouncerPolicyNode } from '../types/code_transformer.ts';
4
+ import type { MiddlewareNode, EnvValidationNode, BouncerPolicyNode, ValidatorNode, LimiterNode, MixinDefinition, ControllerMethodNode } from '../types/code_transformer.ts';
5
5
  /**
6
6
  * This class is responsible for transforming AdonisJS project code,
7
7
  * including updating middleware, environment validations, and other
@@ -39,6 +39,15 @@ export declare class CodeTransformer {
39
39
  * @param cwd - The current working directory URL
40
40
  */
41
41
  constructor(cwd: URL);
42
+ /**
43
+ * Get directories configured in adonisrc.ts, with defaults fallback.
44
+ *
45
+ * This method reads the adonisrc.ts file and extracts the directories
46
+ * configuration. If a directory is not configured, the default value is used.
47
+ *
48
+ * @returns Object containing directory paths
49
+ */
50
+ getDirectories(): Record<string, string>;
42
51
  /**
43
52
  * Add new env variable validation in the `env.ts` file
44
53
  *
@@ -91,4 +100,8 @@ export declare class CodeTransformer {
91
100
  * @param policies - Array of bouncer policy entries to add
92
101
  */
93
102
  addPolicies(policies: BouncerPolicyNode[]): Promise<void>;
103
+ addValidator(definition: ValidatorNode): Promise<void>;
104
+ addLimiter(definition: LimiterNode): Promise<void>;
105
+ addModelMixins(modelFileName: string, mixins: MixinDefinition[]): Promise<void>;
106
+ addControllerMethod(definition: ControllerMethodNode): Promise<void>;
94
107
  }