@valkyrjaio/sindri 26.3.0 → 26.4.1

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.
@@ -14,6 +14,23 @@ import type { CliDataFileGeneratorContract } from '../../Cli/Contract/CliDataFil
14
14
  import type { GenerateStatus } from '../../Enum/GenerateStatus.ts';
15
15
 
16
16
  export class AstCliDataFileGenerator extends AstFileGenerator implements CliDataFileGeneratorContract {
17
+ /** The framework classes every generated CLI data file imports as values. */
18
+ protected static readonly FRAMEWORK_IMPORTS: Readonly<Record<string, string>> = {
19
+ CliRoutingData: '@valkyrjaio/valkyrja/Cli/Routing/Data/CliRoutingData.ts',
20
+ Route: '@valkyrjaio/valkyrja/Cli/Routing/Data/Route.ts',
21
+ ArgumentParameter: '@valkyrjaio/valkyrja/Cli/Routing/Data/ArgumentParameter.ts',
22
+ OptionParameter: '@valkyrjaio/valkyrja/Cli/Routing/Data/OptionParameter.ts',
23
+ ArgumentMode: '@valkyrjaio/valkyrja/Cli/Routing/Enum/ArgumentMode.ts',
24
+ ArgumentValueMode: '@valkyrjaio/valkyrja/Cli/Routing/Enum/ArgumentValueMode.ts',
25
+ OptionMode: '@valkyrjaio/valkyrja/Cli/Routing/Enum/OptionMode.ts',
26
+ OptionValueMode: '@valkyrjaio/valkyrja/Cli/Routing/Enum/OptionValueMode.ts',
27
+ };
28
+
29
+ /** The framework types every generated CLI data file imports. */
30
+ protected static readonly FRAMEWORK_TYPE_IMPORTS: Readonly<Record<string, string>> = {
31
+ RouteContract: '@valkyrjaio/valkyrja/Cli/Routing/Data/Contract/RouteContract.ts',
32
+ };
33
+
17
34
  public classImportMap: Record<string, string> = {};
18
35
 
19
36
  private readonly printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
@@ -32,22 +49,18 @@ export class AstCliDataFileGenerator extends AstFileGenerator implements CliData
32
49
  namespace: string,
33
50
  routes: Record<string, ts.Expression>,
34
51
  ): GenerateStatus {
35
- const userImportsBlock = this.buildUserImportsBlock(this.classImportMap);
52
+ const userImportsBlock = this.buildUserImportsBlock(this.classImportMap, [
53
+ ...Object.keys(AstCliDataFileGenerator.FRAMEWORK_IMPORTS),
54
+ ...Object.keys(AstCliDataFileGenerator.FRAMEWORK_TYPE_IMPORTS),
55
+ ]);
36
56
 
37
57
  const contents = this.generateClassContents(routes);
38
58
 
39
59
  const data = [
40
60
  '// This file was automatically generated by Sindri.',
41
61
  '',
42
- `import { CliRoutingData } from '@valkyrjaio/valkyrja/Cli/Routing/Data/CliRoutingData.ts';`,
43
- `import { Route } from '@valkyrjaio/valkyrja/Cli/Routing/Data/Route.ts';`,
44
- `import { ArgumentParameter } from '@valkyrjaio/valkyrja/Cli/Routing/Data/ArgumentParameter.ts';`,
45
- `import { OptionParameter } from '@valkyrjaio/valkyrja/Cli/Routing/Data/OptionParameter.ts';`,
46
- `import { ArgumentMode } from '@valkyrjaio/valkyrja/Cli/Routing/Enum/ArgumentMode.ts';`,
47
- `import { ArgumentValueMode } from '@valkyrjaio/valkyrja/Cli/Routing/Enum/ArgumentValueMode.ts';`,
48
- `import { OptionMode } from '@valkyrjaio/valkyrja/Cli/Routing/Enum/OptionMode.ts';`,
49
- `import { OptionValueMode } from '@valkyrjaio/valkyrja/Cli/Routing/Enum/OptionValueMode.ts';`,
50
- `import type { RouteContract } from '@valkyrjaio/valkyrja/Cli/Routing/Data/Contract/RouteContract.ts';`,
62
+ ...this.buildFrameworkImportLines(AstCliDataFileGenerator.FRAMEWORK_IMPORTS),
63
+ ...this.buildFrameworkImportLines(AstCliDataFileGenerator.FRAMEWORK_TYPE_IMPORTS, true),
51
64
  userImportsBlock,
52
65
  `export class ${className} extends CliRoutingData {`,
53
66
  ` constructor() {`,
@@ -78,18 +91,43 @@ export class AstCliDataFileGenerator extends AstFileGenerator implements CliData
78
91
  continue;
79
92
  }
80
93
 
81
- const nameArg = (expr.arguments ?? [])[0];
94
+ const key = this.routeKey((expr.arguments ?? [])[0]);
82
95
 
83
- if (nameArg === undefined || !ts.isStringLiteral(nameArg)) {
96
+ if (key === undefined) {
84
97
  continue;
85
98
  }
86
99
 
87
- routes[nameArg.text] = expr;
100
+ routes[key] = expr;
88
101
  }
89
102
 
90
103
  return this.generateFile(directory, className, namespace, routes);
91
104
  }
92
105
 
106
+ /**
107
+ * Derive the map key for a route from its name argument.
108
+ *
109
+ * A literal name keys the map by its own text. A constant reference
110
+ * (`CliCommandName.LIST` — how the framework's own commands name
111
+ * themselves) is kept as a `Class::CASE` marker, so the generated file
112
+ * emits the constant reference as a computed key rather than baking in the
113
+ * value it happens to hold today.
114
+ */
115
+ protected routeKey(nameArg: ts.Expression | undefined): string | undefined {
116
+ if (nameArg === undefined) {
117
+ return undefined;
118
+ }
119
+
120
+ if (ts.isStringLiteral(nameArg)) {
121
+ return nameArg.text;
122
+ }
123
+
124
+ if (ts.isPropertyAccessExpression(nameArg) && ts.isIdentifier(nameArg.expression)) {
125
+ return `${nameArg.expression.text}::${nameArg.name.text}`;
126
+ }
127
+
128
+ return undefined;
129
+ }
130
+
93
131
  public generateClassContents(routes: Record<string, ts.Expression>): string {
94
132
  const entries = Object.entries(routes);
95
133
 
@@ -14,6 +14,16 @@ import type { ContainerDataFileGeneratorContract } from '../../Container/Contrac
14
14
  import type { GenerateStatus } from '../../Enum/GenerateStatus.ts';
15
15
 
16
16
  export class AstContainerDataFileGenerator extends AstFileGenerator implements ContainerDataFileGeneratorContract {
17
+ /** The framework class every generated container data file imports as a value. */
18
+ protected static readonly FRAMEWORK_IMPORTS: Readonly<Record<string, string>> = {
19
+ ContainerData: '@valkyrjaio/valkyrja/Container/Data/ContainerData.ts',
20
+ };
21
+
22
+ /** The framework type every generated container data file imports. */
23
+ protected static readonly FRAMEWORK_TYPE_IMPORTS: Readonly<Record<string, string>> = {
24
+ ContainerContract: '@valkyrjaio/valkyrja/Container/Manager/Contract/ContainerContract.ts',
25
+ };
26
+
17
27
  public classImportMap: Record<string, string> = {};
18
28
 
19
29
  private readonly printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
@@ -32,15 +42,18 @@ export class AstContainerDataFileGenerator extends AstFileGenerator implements C
32
42
  namespace: string,
33
43
  publishers: Readonly<Record<string, readonly [string, string]>>,
34
44
  ): GenerateStatus {
35
- const userImportsBlock = this.buildUserImportsBlock(this.classImportMap);
45
+ const userImportsBlock = this.buildUserImportsBlock(this.classImportMap, [
46
+ ...Object.keys(AstContainerDataFileGenerator.FRAMEWORK_IMPORTS),
47
+ ...Object.keys(AstContainerDataFileGenerator.FRAMEWORK_TYPE_IMPORTS),
48
+ ]);
36
49
 
37
50
  const contents = this.generateClassContents(publishers);
38
51
 
39
52
  const data = [
40
53
  '// This file was automatically generated by Sindri.',
41
54
  '',
42
- `import { ContainerData } from '@valkyrjaio/valkyrja/Container/Data/ContainerData.ts';`,
43
- `import type { ContainerContract } from '@valkyrjaio/valkyrja/Container/Manager/Contract/ContainerContract.ts';`,
55
+ ...this.buildFrameworkImportLines(AstContainerDataFileGenerator.FRAMEWORK_IMPORTS),
56
+ ...this.buildFrameworkImportLines(AstContainerDataFileGenerator.FRAMEWORK_TYPE_IMPORTS, true),
44
57
  userImportsBlock,
45
58
  `export class ${className} extends ContainerData {`,
46
59
  ` constructor() {`,
@@ -14,6 +14,21 @@ import type { EventDataFileGeneratorContract } from '../../Event/Contract/EventD
14
14
  import type { GenerateStatus } from '../../Enum/GenerateStatus.ts';
15
15
 
16
16
  export class AstEventDataFileGenerator extends AstFileGenerator implements EventDataFileGeneratorContract {
17
+ /** The framework class every generated event data file imports as a value. */
18
+ protected static readonly FRAMEWORK_IMPORTS: Readonly<Record<string, string>> = {
19
+ EventData: '@valkyrjaio/valkyrja/Event/Data/EventData.ts',
20
+ };
21
+
22
+ /** The framework classes a generated event data file imports only when it holds listeners. */
23
+ protected static readonly LISTENER_IMPORTS: Readonly<Record<string, string>> = {
24
+ Listener: '@valkyrjaio/valkyrja/Event/Data/Listener.ts',
25
+ };
26
+
27
+ /** The framework types a generated event data file imports only when it holds listeners. */
28
+ protected static readonly LISTENER_TYPE_IMPORTS: Readonly<Record<string, string>> = {
29
+ ListenerContract: '@valkyrjaio/valkyrja/Event/Data/Contract/ListenerContract.ts',
30
+ };
31
+
17
32
  public classImportMap: Record<string, string> = {};
18
33
 
19
34
  private readonly printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
@@ -32,7 +47,11 @@ export class AstEventDataFileGenerator extends AstFileGenerator implements Event
32
47
  namespace: string,
33
48
  listeners: Record<string, ts.Expression>,
34
49
  ): GenerateStatus {
35
- const userImportsBlock = this.buildUserImportsBlock(this.classImportMap);
50
+ const userImportsBlock = this.buildUserImportsBlock(this.classImportMap, [
51
+ ...Object.keys(AstEventDataFileGenerator.FRAMEWORK_IMPORTS),
52
+ ...Object.keys(AstEventDataFileGenerator.LISTENER_IMPORTS),
53
+ ...Object.keys(AstEventDataFileGenerator.LISTENER_TYPE_IMPORTS),
54
+ ]);
36
55
 
37
56
  const contents = this.generateClassContents(listeners);
38
57
 
@@ -42,15 +61,15 @@ export class AstEventDataFileGenerator extends AstFileGenerator implements Event
42
61
  const listenerImports =
43
62
  Object.keys(listeners).length > 0
44
63
  ? [
45
- `import { Listener } from '@valkyrjaio/valkyrja/Event/Data/Listener.ts';`,
46
- `import type { ListenerContract } from '@valkyrjaio/valkyrja/Event/Data/Contract/ListenerContract.ts';`,
64
+ ...this.buildFrameworkImportLines(AstEventDataFileGenerator.LISTENER_IMPORTS),
65
+ ...this.buildFrameworkImportLines(AstEventDataFileGenerator.LISTENER_TYPE_IMPORTS, true),
47
66
  ]
48
67
  : [];
49
68
 
50
69
  const data = [
51
70
  '// This file was automatically generated by Sindri.',
52
71
  '',
53
- `import { EventData } from '@valkyrjaio/valkyrja/Event/Data/EventData.ts';`,
72
+ ...this.buildFrameworkImportLines(AstEventDataFileGenerator.FRAMEWORK_IMPORTS),
54
73
  ...listenerImports,
55
74
  userImportsBlock,
56
75
  `export class ${className} extends EventData {`,
@@ -34,6 +34,21 @@ interface ImperativeRouteMeta {
34
34
  }
35
35
 
36
36
  export class AstHttpDataFileGenerator extends AstFileGenerator implements HttpDataFileGeneratorContract {
37
+ /** The framework classes every generated HTTP data file imports as values. */
38
+ protected static readonly FRAMEWORK_IMPORTS: Readonly<Record<string, string>> = {
39
+ HttpRoutingData: '@valkyrjaio/valkyrja/Http/Routing/Data/HttpRoutingData.ts',
40
+ DynamicRoute: '@valkyrjaio/valkyrja/Http/Routing/Data/DynamicRoute.ts',
41
+ Route: '@valkyrjaio/valkyrja/Http/Routing/Data/Route.ts',
42
+ Parameter: '@valkyrjaio/valkyrja/Http/Routing/Data/Parameter.ts',
43
+ RequestMethod: '@valkyrjaio/valkyrja/Http/Message/Enum/RequestMethod.ts',
44
+ Regex: '@valkyrjaio/valkyrja/Http/Routing/Constant/Regex.ts',
45
+ };
46
+
47
+ /** The framework types every generated HTTP data file imports. */
48
+ protected static readonly FRAMEWORK_TYPE_IMPORTS: Readonly<Record<string, string>> = {
49
+ RouteContract: '@valkyrjaio/valkyrja/Http/Routing/Data/Contract/RouteContract.ts',
50
+ };
51
+
37
52
  public classImportMap: Record<string, string> = {};
38
53
 
39
54
  protected readonly processor: ProcessorContract;
@@ -60,7 +75,10 @@ export class AstHttpDataFileGenerator extends AstFileGenerator implements HttpDa
60
75
  routes: Record<string, ts.Expression>,
61
76
  routeData: Record<string, HttpRouteData>,
62
77
  ): GenerateStatus {
63
- const userImportsBlock = this.buildUserImportsBlock(this.classImportMap);
78
+ const userImportsBlock = this.buildUserImportsBlock(this.classImportMap, [
79
+ ...Object.keys(AstHttpDataFileGenerator.FRAMEWORK_IMPORTS),
80
+ ...Object.keys(AstHttpDataFileGenerator.FRAMEWORK_TYPE_IMPORTS),
81
+ ]);
64
82
 
65
83
  const routesContent = this.getRoutesAsContent(routes, routeData);
66
84
  const paths = this.printNestedObject(this.buildPaths(routeData));
@@ -87,7 +105,10 @@ export class AstHttpDataFileGenerator extends AstFileGenerator implements HttpDa
87
105
  _namespace: string,
88
106
  routeExprs: readonly ts.Expression[],
89
107
  ): GenerateStatus {
90
- const userImportsBlock = this.buildUserImportsBlock(this.classImportMap);
108
+ const userImportsBlock = this.buildUserImportsBlock(this.classImportMap, [
109
+ ...Object.keys(AstHttpDataFileGenerator.FRAMEWORK_IMPORTS),
110
+ ...Object.keys(AstHttpDataFileGenerator.FRAMEWORK_TYPE_IMPORTS),
111
+ ]);
91
112
 
92
113
  const metas = routeExprs
93
114
  .map((expr) => this.extractRouteMeta(expr))
@@ -114,13 +135,8 @@ export class AstHttpDataFileGenerator extends AstFileGenerator implements HttpDa
114
135
  return [
115
136
  '// This file was automatically generated by Sindri.',
116
137
  '',
117
- `import { HttpRoutingData } from '@valkyrjaio/valkyrja/Http/Routing/Data/HttpRoutingData.ts';`,
118
- `import { DynamicRoute } from '@valkyrjaio/valkyrja/Http/Routing/Data/DynamicRoute.ts';`,
119
- `import { Route } from '@valkyrjaio/valkyrja/Http/Routing/Data/Route.ts';`,
120
- `import { Parameter } from '@valkyrjaio/valkyrja/Http/Routing/Data/Parameter.ts';`,
121
- `import { RequestMethod } from '@valkyrjaio/valkyrja/Http/Message/Enum/RequestMethod.ts';`,
122
- `import { Regex } from '@valkyrjaio/valkyrja/Http/Routing/Constant/Regex.ts';`,
123
- `import type { RouteContract } from '@valkyrjaio/valkyrja/Http/Routing/Data/Contract/RouteContract.ts';`,
138
+ ...this.buildFrameworkImportLines(AstHttpDataFileGenerator.FRAMEWORK_IMPORTS),
139
+ ...this.buildFrameworkImportLines(AstHttpDataFileGenerator.FRAMEWORK_TYPE_IMPORTS, true),
124
140
  userImportsBlock,
125
141
  `export class ${className} extends HttpRoutingData {`,
126
142
  ` constructor() {`,