@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.
- package/README.md +260 -0
- package/build/codemod_exception-CzQgXAAf.js +137 -0
- package/build/index.d.ts +1 -1
- package/build/index.js +927 -1724
- package/build/source-dVeugJ0e.js +166 -0
- package/build/src/bundler.d.ts +2 -0
- package/build/src/code_scanners/routes_scanner/main.d.ts +16 -2
- package/build/src/code_scanners/routes_scanner/main.js +168 -441
- package/build/src/code_transformer/main.d.ts +14 -1
- package/build/src/code_transformer/main.js +502 -622
- package/build/src/code_transformer/rc_file_transformer.d.ts +28 -2
- package/build/src/debug.d.ts +1 -1
- package/build/src/dev_server.d.ts +60 -12
- package/build/src/exceptions/codemod_exception.d.ts +178 -0
- package/build/src/file_buffer.d.ts +19 -0
- package/build/src/file_system.d.ts +2 -2
- package/build/src/helpers.js +72 -16
- package/build/src/index_generator/main.js +28 -6
- package/build/src/paths_resolver.d.ts +2 -1
- package/build/src/test_runner.d.ts +3 -2
- package/build/src/types/code_scanners.d.ts +29 -13
- package/build/src/types/code_transformer.d.ts +127 -0
- package/build/src/types/common.d.ts +98 -2
- package/build/src/types/hooks.d.ts +4 -1
- package/build/src/types/main.js +1 -0
- package/build/src/utils.d.ts +9 -3
- package/build/src/virtual_file_system.d.ts +1 -1
- package/build/validator_extractor-Ccio_Ndi.js +82 -0
- package/build/virtual_file_system-bGeoWsK-.js +285 -0
- package/package.json +41 -39
- package/build/chunk-7XU453QB.js +0 -418
- package/build/chunk-PORDZS62.js +0 -391
- package/build/chunk-TIKQQRMX.js +0 -116
- package/build/src/hooks.d.ts +0 -224
|
@@ -1,445 +1,172 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
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
|
|
75
|
-
|
|
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
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
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
|
}
|