@valkyrjaio/sindri 26.1.3 → 26.3.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/dist/bin/sindri.cjs +580 -309
- package/package.json +2 -2
- package/src/Sindri/Ast/Abstract/AstReader.ts +80 -0
- package/src/Sindri/Ast/CliRouteAttributeReader.ts +11 -11
- package/src/Sindri/Ast/ComponentProviderReader.ts +9 -5
- package/src/Sindri/Ast/ConfigReader.ts +14 -6
- package/src/Sindri/Ast/Contract/HttpRouteMiddlewareReaderContract.ts +1 -1
- package/src/Sindri/Ast/Data/CliRouteData.ts +1 -1
- package/src/Sindri/Ast/Data/Contract/CliRouteDataContract.ts +1 -1
- package/src/Sindri/Ast/Data/Contract/HttpRouteDataContract.ts +1 -1
- package/src/Sindri/Ast/Data/HttpRouteData.ts +1 -1
- package/src/Sindri/Ast/HttpRouteAttributeReader.ts +2 -2
- package/src/Sindri/Ast/HttpRouteMiddlewareReader.ts +9 -9
- package/src/Sindri/Ast/RouteProviderReader.ts +24 -3
- package/src/Sindri/Constant/SindriInfo.ts +2 -2
- package/src/Sindri/Generate/Abstract/GenerateDataFromAst.ts +66 -13
- package/src/Sindri/Generator/Abstract/AstFileGenerator.ts +13 -0
- package/src/Sindri/Generator/Ast/Cli/AstCliDataFileGenerator.ts +47 -11
- package/src/Sindri/Generator/Ast/Container/AstContainerDataFileGenerator.ts +4 -9
- package/src/Sindri/Generator/Ast/Event/AstEventDataFileGenerator.ts +13 -7
- package/src/Sindri/Generator/Ast/Http/AstHttpDataFileGenerator.ts +176 -12
- package/src/Sindri/Generator/Cli/Contract/CliDataFileGeneratorContract.ts +10 -0
- package/src/Sindri/Generator/Container/Contract/ContainerDataFileGeneratorContract.ts +3 -0
- package/src/Sindri/Generator/Http/Contract/HttpDataFileGeneratorContract.ts +10 -0
|
@@ -32,11 +32,7 @@ export class AstCliDataFileGenerator extends AstFileGenerator implements CliData
|
|
|
32
32
|
namespace: string,
|
|
33
33
|
routes: Record<string, ts.Expression>,
|
|
34
34
|
): GenerateStatus {
|
|
35
|
-
const
|
|
36
|
-
.map(([name, specifier]) => `import { ${name} } from '${specifier}';`)
|
|
37
|
-
.join('\n');
|
|
38
|
-
|
|
39
|
-
const userImportsBlock = userImports ? `${userImports}\n` : '';
|
|
35
|
+
const userImportsBlock = this.buildUserImportsBlock(this.classImportMap);
|
|
40
36
|
|
|
41
37
|
const contents = this.generateClassContents(routes);
|
|
42
38
|
|
|
@@ -64,6 +60,36 @@ export class AstCliDataFileGenerator extends AstFileGenerator implements CliData
|
|
|
64
60
|
return this.writeFile(directory, className, data);
|
|
65
61
|
}
|
|
66
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Generate the CLI routing data file from imperative `getRoutes()` route
|
|
65
|
+
* objects — each `new Route(name, description, handler, ...)` is keyed by
|
|
66
|
+
* its command name (the first constructor argument) and emitted verbatim.
|
|
67
|
+
*/
|
|
68
|
+
public generateFileFromRoutes(
|
|
69
|
+
directory: string,
|
|
70
|
+
className: string,
|
|
71
|
+
namespace: string,
|
|
72
|
+
routeExprs: readonly ts.Expression[],
|
|
73
|
+
): GenerateStatus {
|
|
74
|
+
const routes: Record<string, ts.Expression> = {};
|
|
75
|
+
|
|
76
|
+
for (const expr of routeExprs) {
|
|
77
|
+
if (!ts.isNewExpression(expr)) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const nameArg = (expr.arguments ?? [])[0];
|
|
82
|
+
|
|
83
|
+
if (nameArg === undefined || !ts.isStringLiteral(nameArg)) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
routes[nameArg.text] = expr;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return this.generateFile(directory, className, namespace, routes);
|
|
91
|
+
}
|
|
92
|
+
|
|
67
93
|
public generateClassContents(routes: Record<string, ts.Expression>): string {
|
|
68
94
|
const entries = Object.entries(routes);
|
|
69
95
|
|
|
@@ -74,15 +100,25 @@ export class AstCliDataFileGenerator extends AstFileGenerator implements CliData
|
|
|
74
100
|
const lines: string[] = [];
|
|
75
101
|
|
|
76
102
|
for (const [key, valueExpr] of entries) {
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const formattedKey = key.includes('::') ? `[${printedKey}]` : `['${printedKey}']`;
|
|
103
|
+
const printedValue = this.printExpr(valueExpr);
|
|
104
|
+
const formattedKey = key.includes('::')
|
|
105
|
+
? `[${this.printer.printNode(ts.EmitHint.Unspecified, this.buildEnumCaseExpr(key), this.dummySourceFile)}]`
|
|
106
|
+
: `['${key}']`;
|
|
82
107
|
|
|
83
108
|
lines.push(` ${formattedKey}: (): RouteContract => ${printedValue},`);
|
|
84
109
|
}
|
|
85
110
|
|
|
86
|
-
return ['super({',
|
|
111
|
+
return ['super({', ...lines, ' });'].join('\n ');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Print an expression to source. Parsed nodes (from a `getRoutes()` body)
|
|
116
|
+
* are emitted via their original source text; synthesized nodes (which
|
|
117
|
+
* carry no source positions) are emitted through the printer.
|
|
118
|
+
*/
|
|
119
|
+
protected printExpr(expr: ts.Expression): string {
|
|
120
|
+
return expr.pos >= 0
|
|
121
|
+
? expr.getText()
|
|
122
|
+
: this.printer.printNode(ts.EmitHint.Unspecified, expr, this.dummySourceFile);
|
|
87
123
|
}
|
|
88
124
|
}
|
|
@@ -32,11 +32,7 @@ export class AstContainerDataFileGenerator extends AstFileGenerator implements C
|
|
|
32
32
|
namespace: string,
|
|
33
33
|
publishers: Readonly<Record<string, readonly [string, string]>>,
|
|
34
34
|
): GenerateStatus {
|
|
35
|
-
const
|
|
36
|
-
.map(([name, specifier]) => `import { ${name} } from '${specifier}';`)
|
|
37
|
-
.join('\n');
|
|
38
|
-
|
|
39
|
-
const userImportsBlock = userImports ? `${userImports}\n` : '';
|
|
35
|
+
const userImportsBlock = this.buildUserImportsBlock(this.classImportMap);
|
|
40
36
|
|
|
41
37
|
const contents = this.generateClassContents(publishers);
|
|
42
38
|
|
|
@@ -67,12 +63,11 @@ export class AstContainerDataFileGenerator extends AstFileGenerator implements C
|
|
|
67
63
|
const lines: string[] = [];
|
|
68
64
|
|
|
69
65
|
for (const [serviceId, [providerClass, methodName]] of entries) {
|
|
70
|
-
const keyExpr = this.buildEnumCaseExpr(serviceId);
|
|
71
|
-
const printedKey = this.printer.printNode(ts.EmitHint.Unspecified, keyExpr, this.dummySourceFile);
|
|
72
|
-
|
|
73
66
|
const shortProviderClass = providerClass.slice(providerClass.lastIndexOf('\\') + 1);
|
|
74
67
|
|
|
75
|
-
const formattedKey = serviceId.includes('::')
|
|
68
|
+
const formattedKey = serviceId.includes('::')
|
|
69
|
+
? `[${this.printer.printNode(ts.EmitHint.Unspecified, this.buildEnumCaseExpr(serviceId), this.dummySourceFile)}]`
|
|
70
|
+
: `['${serviceId}']`;
|
|
76
71
|
|
|
77
72
|
lines.push(
|
|
78
73
|
` ${formattedKey}: (container: ContainerContract) => ${shortProviderClass}.${methodName}(container),`,
|
|
@@ -32,20 +32,26 @@ export class AstEventDataFileGenerator extends AstFileGenerator implements Event
|
|
|
32
32
|
namespace: string,
|
|
33
33
|
listeners: Record<string, ts.Expression>,
|
|
34
34
|
): GenerateStatus {
|
|
35
|
-
const
|
|
36
|
-
.map(([name, specifier]) => `import { ${name} } from '${specifier}';`)
|
|
37
|
-
.join('\n');
|
|
38
|
-
|
|
39
|
-
const userImportsBlock = userImports ? `${userImports}\n` : '';
|
|
35
|
+
const userImportsBlock = this.buildUserImportsBlock(this.classImportMap);
|
|
40
36
|
|
|
41
37
|
const contents = this.generateClassContents(listeners);
|
|
42
38
|
|
|
39
|
+
// The Listener / ListenerContract imports are only referenced by the
|
|
40
|
+
// generated listener closures — omit them when there are no listeners
|
|
41
|
+
// so empty event data does not carry unused (and unresolved) imports.
|
|
42
|
+
const listenerImports =
|
|
43
|
+
Object.keys(listeners).length > 0
|
|
44
|
+
? [
|
|
45
|
+
`import { Listener } from '@valkyrjaio/valkyrja/Event/Data/Listener.ts';`,
|
|
46
|
+
`import type { ListenerContract } from '@valkyrjaio/valkyrja/Event/Data/Contract/ListenerContract.ts';`,
|
|
47
|
+
]
|
|
48
|
+
: [];
|
|
49
|
+
|
|
43
50
|
const data = [
|
|
44
51
|
'// This file was automatically generated by Sindri.',
|
|
45
52
|
'',
|
|
46
53
|
`import { EventData } from '@valkyrjaio/valkyrja/Event/Data/EventData.ts';`,
|
|
47
|
-
|
|
48
|
-
`import type { ListenerContract } from '@valkyrjaio/valkyrja/Event/Data/Contract/ListenerContract.ts';`,
|
|
54
|
+
...listenerImports,
|
|
49
55
|
userImportsBlock,
|
|
50
56
|
`export class ${className} extends EventData {`,
|
|
51
57
|
` constructor() {`,
|
|
@@ -13,6 +13,7 @@ import { DynamicRoute } from '@valkyrjaio/valkyrja/Http/Routing/Data/DynamicRout
|
|
|
13
13
|
import { Parameter } from '@valkyrjaio/valkyrja/Http/Routing/Data/Parameter.ts';
|
|
14
14
|
import { Regex } from '@valkyrjaio/valkyrja/Http/Routing/Constant/Regex.ts';
|
|
15
15
|
import { Processor } from '@valkyrjaio/valkyrja/Http/Routing/Processor/Processor.ts';
|
|
16
|
+
import { RequestMethod, allRequestMethods } from '@valkyrjaio/valkyrja/Http/Message/Enum/RequestMethod.ts';
|
|
16
17
|
|
|
17
18
|
import { AstFileGenerator } from '../../Abstract/AstFileGenerator.ts';
|
|
18
19
|
import { GeneratorUnreachableException } from '../../Throwable/Exception/GeneratorUnreachableException.ts';
|
|
@@ -22,6 +23,16 @@ import type { HttpParameterData } from '../../../Ast/Data/HttpParameterData.ts';
|
|
|
22
23
|
import type { HttpRouteData } from '../../../Ast/Data/HttpRouteData.ts';
|
|
23
24
|
import type { ProcessorContract } from '@valkyrjaio/valkyrja/Http/Routing/Processor/Contract/ProcessorContract.ts';
|
|
24
25
|
|
|
26
|
+
/** Metadata extracted from an imperative `new Route(...)` / `new DynamicRoute(...)` expression. */
|
|
27
|
+
interface ImperativeRouteMeta {
|
|
28
|
+
readonly expr: ts.Expression;
|
|
29
|
+
readonly name: string;
|
|
30
|
+
readonly path: string;
|
|
31
|
+
readonly isDynamic: boolean;
|
|
32
|
+
readonly regex: string;
|
|
33
|
+
readonly methods: readonly string[];
|
|
34
|
+
}
|
|
35
|
+
|
|
25
36
|
export class AstHttpDataFileGenerator extends AstFileGenerator implements HttpDataFileGeneratorContract {
|
|
26
37
|
public classImportMap: Record<string, string> = {};
|
|
27
38
|
|
|
@@ -49,18 +60,58 @@ export class AstHttpDataFileGenerator extends AstFileGenerator implements HttpDa
|
|
|
49
60
|
routes: Record<string, ts.Expression>,
|
|
50
61
|
routeData: Record<string, HttpRouteData>,
|
|
51
62
|
): GenerateStatus {
|
|
52
|
-
const
|
|
53
|
-
.map(([name, specifier]) => `import { ${name} } from '${specifier}';`)
|
|
54
|
-
.join('\n');
|
|
55
|
-
|
|
56
|
-
const userImportsBlock = userImports ? `${userImports}\n` : '';
|
|
63
|
+
const userImportsBlock = this.buildUserImportsBlock(this.classImportMap);
|
|
57
64
|
|
|
58
65
|
const routesContent = this.getRoutesAsContent(routes, routeData);
|
|
59
66
|
const paths = this.printNestedObject(this.buildPaths(routeData));
|
|
60
67
|
const dynamicPaths = this.printNestedObject(this.buildDynamicPaths(routeData));
|
|
61
68
|
const regexes = this.printNestedObject(this.buildRegexes(routeData));
|
|
62
69
|
|
|
63
|
-
const data =
|
|
70
|
+
const data = this.assembleFile(className, userImportsBlock, routesContent, paths, dynamicPaths, regexes);
|
|
71
|
+
|
|
72
|
+
return this.writeFile(directory, className, data);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Generate the routing data file from imperative `getRoutes()` route
|
|
77
|
+
* objects (as opposed to attribute-scanned routes).
|
|
78
|
+
*
|
|
79
|
+
* Each route expression is emitted verbatim as a route closure and the
|
|
80
|
+
* path/dynamic-path/regex lookup maps are derived from the route objects'
|
|
81
|
+
* own arguments, mirroring the framework's runtime `RouteCollection`
|
|
82
|
+
* (literal path and regex, request methods defaulting to `[HEAD, GET]`).
|
|
83
|
+
*/
|
|
84
|
+
public generateFileFromRoutes(
|
|
85
|
+
directory: string,
|
|
86
|
+
className: string,
|
|
87
|
+
_namespace: string,
|
|
88
|
+
routeExprs: readonly ts.Expression[],
|
|
89
|
+
): GenerateStatus {
|
|
90
|
+
const userImportsBlock = this.buildUserImportsBlock(this.classImportMap);
|
|
91
|
+
|
|
92
|
+
const metas = routeExprs
|
|
93
|
+
.map((expr) => this.extractRouteMeta(expr))
|
|
94
|
+
.filter((meta): meta is ImperativeRouteMeta => meta !== undefined);
|
|
95
|
+
|
|
96
|
+
const routesContent = this.getImperativeRoutesContent(metas);
|
|
97
|
+
const paths = this.printNestedObject(this.buildImperativePaths(metas, false));
|
|
98
|
+
const dynamicPaths = this.printNestedObject(this.buildImperativePaths(metas, true));
|
|
99
|
+
const regexes = this.printNestedObject(this.buildImperativeRegexes(metas));
|
|
100
|
+
|
|
101
|
+
const data = this.assembleFile(className, userImportsBlock, routesContent, paths, dynamicPaths, regexes);
|
|
102
|
+
|
|
103
|
+
return this.writeFile(directory, className, data);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
protected assembleFile(
|
|
107
|
+
className: string,
|
|
108
|
+
userImportsBlock: string,
|
|
109
|
+
routesContent: string,
|
|
110
|
+
paths: string,
|
|
111
|
+
dynamicPaths: string,
|
|
112
|
+
regexes: string,
|
|
113
|
+
): string {
|
|
114
|
+
return [
|
|
64
115
|
'// This file was automatically generated by Sindri.',
|
|
65
116
|
'',
|
|
66
117
|
`import { HttpRoutingData } from '@valkyrjaio/valkyrja/Http/Routing/Data/HttpRoutingData.ts';`,
|
|
@@ -83,8 +134,6 @@ export class AstHttpDataFileGenerator extends AstFileGenerator implements HttpDa
|
|
|
83
134
|
`}`,
|
|
84
135
|
'',
|
|
85
136
|
].join('\n');
|
|
86
|
-
|
|
87
|
-
return this.writeFile(directory, className, data);
|
|
88
137
|
}
|
|
89
138
|
|
|
90
139
|
public generateClassContents(
|
|
@@ -292,15 +341,130 @@ export class AstHttpDataFileGenerator extends AstFileGenerator implements HttpDa
|
|
|
292
341
|
expr = ts.factory.createNewExpression(expr.expression, expr.typeArguments, args);
|
|
293
342
|
}
|
|
294
343
|
|
|
295
|
-
const keyExpr = this.buildEnumCaseExpr(key);
|
|
296
|
-
const printedKey = this.printer.printNode(ts.EmitHint.Unspecified, keyExpr, this.dummySourceFile);
|
|
297
344
|
const printedRoute = this.printer.printNode(ts.EmitHint.Unspecified, expr, this.dummySourceFile);
|
|
298
|
-
|
|
299
|
-
|
|
345
|
+
const formattedKey = key.includes('::')
|
|
346
|
+
? `[${this.printer.printNode(ts.EmitHint.Unspecified, this.buildEnumCaseExpr(key), this.dummySourceFile)}]`
|
|
347
|
+
: `['${key}']`;
|
|
300
348
|
|
|
301
349
|
lines.push(` ${formattedKey}: (): RouteContract => ${printedRoute},`);
|
|
302
350
|
}
|
|
303
351
|
|
|
304
352
|
return ['{', ...lines, ' }'].join('\n ');
|
|
305
353
|
}
|
|
354
|
+
|
|
355
|
+
// -------------------------------------------------------------------------
|
|
356
|
+
// Imperative `getRoutes()` support
|
|
357
|
+
// -------------------------------------------------------------------------
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Extract routing metadata from a `new Route(...)` / `new DynamicRoute(...)`
|
|
361
|
+
* expression, matching the framework constructor argument order:
|
|
362
|
+
* Route(path, name, handler, requestMethods?)
|
|
363
|
+
* DynamicRoute(path, name, regex, parameters, handler, requestMethods?)
|
|
364
|
+
*/
|
|
365
|
+
protected extractRouteMeta(expr: ts.Expression): ImperativeRouteMeta | undefined {
|
|
366
|
+
if (!ts.isNewExpression(expr) || !ts.isIdentifier(expr.expression)) {
|
|
367
|
+
return undefined;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const isDynamic = expr.expression.text === 'DynamicRoute';
|
|
371
|
+
const args = expr.arguments ?? ts.factory.createNodeArray<ts.Expression>();
|
|
372
|
+
|
|
373
|
+
const path = this.stringArg(args[0]);
|
|
374
|
+
const name = this.stringArg(args[1]);
|
|
375
|
+
|
|
376
|
+
if (name === undefined || path === undefined) {
|
|
377
|
+
return undefined;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const regex = isDynamic ? (this.stringArg(args[2]) ?? '') : '';
|
|
381
|
+
const methodsArg = isDynamic ? args[5] : args[3];
|
|
382
|
+
const methods = this.extractMethodNamesFromArg(methodsArg);
|
|
383
|
+
|
|
384
|
+
return { expr, name, path, isDynamic, regex, methods };
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
protected stringArg(node: ts.Expression | undefined): string | undefined {
|
|
388
|
+
return node !== undefined && ts.isStringLiteral(node) ? node.text : undefined;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Resolve a `[RequestMethod.GET, ...]` argument to method-name strings,
|
|
393
|
+
* defaulting to `[HEAD, GET]` (the framework `Route` default) when omitted
|
|
394
|
+
* and expanding `RequestMethod.ANY` to every request method.
|
|
395
|
+
*/
|
|
396
|
+
protected extractMethodNamesFromArg(node: ts.Expression | undefined): string[] {
|
|
397
|
+
if (node === undefined || !ts.isArrayLiteralExpression(node)) {
|
|
398
|
+
return [RequestMethod.HEAD, RequestMethod.GET];
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
const methods: string[] = [];
|
|
402
|
+
|
|
403
|
+
for (const element of node.elements) {
|
|
404
|
+
if (!ts.isPropertyAccessExpression(element)) {
|
|
405
|
+
continue;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
const method = element.name.text;
|
|
409
|
+
|
|
410
|
+
if (method === 'ANY') {
|
|
411
|
+
return allRequestMethods();
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
methods.push(method);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
return methods;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
protected getImperativeRoutesContent(metas: readonly ImperativeRouteMeta[]): string {
|
|
421
|
+
if (metas.length === 0) {
|
|
422
|
+
return '{}';
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
const lines: string[] = [];
|
|
426
|
+
|
|
427
|
+
for (const meta of metas) {
|
|
428
|
+
// Imperative route expressions come parsed from a provider's `getRoutes()`
|
|
429
|
+
// body, so they are emitted verbatim via their original source text.
|
|
430
|
+
lines.push(` ['${meta.name}']: (): RouteContract => ${meta.expr.getText()},`);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
return ['{', ...lines, ' }'].join('\n ');
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
protected buildImperativePaths(
|
|
437
|
+
metas: readonly ImperativeRouteMeta[],
|
|
438
|
+
dynamic: boolean,
|
|
439
|
+
): Record<string, Record<string, string>> {
|
|
440
|
+
const paths: Record<string, Record<string, string>> = {};
|
|
441
|
+
|
|
442
|
+
for (const meta of metas) {
|
|
443
|
+
if (meta.isDynamic !== dynamic) {
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
for (const method of meta.methods) {
|
|
448
|
+
(paths[method] ??= {})[meta.path] = meta.name;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
return paths;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
protected buildImperativeRegexes(metas: readonly ImperativeRouteMeta[]): Record<string, Record<string, string>> {
|
|
456
|
+
const regexes: Record<string, Record<string, string>> = {};
|
|
457
|
+
|
|
458
|
+
for (const meta of metas) {
|
|
459
|
+
if (!meta.isDynamic || meta.regex === '') {
|
|
460
|
+
continue;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
for (const method of meta.methods) {
|
|
464
|
+
(regexes[method] ??= {})[meta.regex] = meta.name;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return regexes;
|
|
469
|
+
}
|
|
306
470
|
}
|
|
@@ -12,6 +12,9 @@ import type { ts } from 'ts-morph';
|
|
|
12
12
|
import type { GenerateStatus } from '../../Enum/GenerateStatus.ts';
|
|
13
13
|
|
|
14
14
|
export interface CliDataFileGeneratorContract {
|
|
15
|
+
/** Map of class name → module specifier for the provider imports the data cache references. */
|
|
16
|
+
classImportMap: Record<string, string>;
|
|
17
|
+
|
|
15
18
|
generateFile(
|
|
16
19
|
directory: string,
|
|
17
20
|
className: string,
|
|
@@ -19,5 +22,12 @@ export interface CliDataFileGeneratorContract {
|
|
|
19
22
|
routes: Record<string, ts.Expression>,
|
|
20
23
|
): GenerateStatus;
|
|
21
24
|
|
|
25
|
+
generateFileFromRoutes(
|
|
26
|
+
directory: string,
|
|
27
|
+
className: string,
|
|
28
|
+
namespace: string,
|
|
29
|
+
routeExprs: readonly ts.Expression[],
|
|
30
|
+
): GenerateStatus;
|
|
31
|
+
|
|
22
32
|
generateClassContents(routes: Record<string, ts.Expression>): string;
|
|
23
33
|
}
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
import type { GenerateStatus } from '../../Enum/GenerateStatus.ts';
|
|
11
11
|
|
|
12
12
|
export interface ContainerDataFileGeneratorContract {
|
|
13
|
+
/** Map of class name → module specifier for the provider imports the data cache references. */
|
|
14
|
+
classImportMap: Record<string, string>;
|
|
15
|
+
|
|
13
16
|
generateFile(
|
|
14
17
|
directory: string,
|
|
15
18
|
className: string,
|
|
@@ -13,6 +13,9 @@ import type { HttpRouteData } from '../../../Ast/Data/HttpRouteData.ts';
|
|
|
13
13
|
import type { GenerateStatus } from '../../Enum/GenerateStatus.ts';
|
|
14
14
|
|
|
15
15
|
export interface HttpDataFileGeneratorContract {
|
|
16
|
+
/** Map of class name → module specifier for the provider imports the data cache references. */
|
|
17
|
+
classImportMap: Record<string, string>;
|
|
18
|
+
|
|
16
19
|
generateFile(
|
|
17
20
|
directory: string,
|
|
18
21
|
className: string,
|
|
@@ -21,5 +24,12 @@ export interface HttpDataFileGeneratorContract {
|
|
|
21
24
|
routeData: Record<string, HttpRouteData>,
|
|
22
25
|
): GenerateStatus;
|
|
23
26
|
|
|
27
|
+
generateFileFromRoutes(
|
|
28
|
+
directory: string,
|
|
29
|
+
className: string,
|
|
30
|
+
namespace: string,
|
|
31
|
+
routeExprs: readonly ts.Expression[],
|
|
32
|
+
): GenerateStatus;
|
|
33
|
+
|
|
24
34
|
generateClassContents(routes: Record<string, ts.Expression>, routeData: Record<string, HttpRouteData>): string;
|
|
25
35
|
}
|