@valkyrjaio/sindri 26.0.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.
- package/LICENSE.md +21 -0
- package/README.md +111 -0
- package/package.json +63 -0
- package/src/Sindri/Ast/Abstract/AstReader.ts +710 -0
- package/src/Sindri/Ast/Abstract/RouteAttributeReader.ts +50 -0
- package/src/Sindri/Ast/CliRouteAttributeReader.ts +219 -0
- package/src/Sindri/Ast/CliRouteParameterReader.ts +204 -0
- package/src/Sindri/Ast/ComponentProviderReader.ts +41 -0
- package/src/Sindri/Ast/ConfigReader.ts +213 -0
- package/src/Sindri/Ast/Contract/CliRouteAttributeReaderContract.ts +14 -0
- package/src/Sindri/Ast/Contract/CliRouteParameterReaderContract.ts +34 -0
- package/src/Sindri/Ast/Contract/ComponentProviderReaderContract.ts +14 -0
- package/src/Sindri/Ast/Contract/ConfigReaderContract.ts +14 -0
- package/src/Sindri/Ast/Contract/HttpRouteAttributeReaderContract.ts +14 -0
- package/src/Sindri/Ast/Contract/HttpRouteMiddlewareReaderContract.ts +61 -0
- package/src/Sindri/Ast/Contract/HttpRouteParameterReaderContract.ts +26 -0
- package/src/Sindri/Ast/Contract/ListenerAttributeReaderContract.ts +14 -0
- package/src/Sindri/Ast/Contract/ListenerProviderReaderContract.ts +14 -0
- package/src/Sindri/Ast/Contract/RouteProviderReaderContract.ts +14 -0
- package/src/Sindri/Ast/Contract/ServiceProviderReaderContract.ts +14 -0
- package/src/Sindri/Ast/Data/CliArgumentParameterData.ts +20 -0
- package/src/Sindri/Ast/Data/CliOptionParameterData.ts +24 -0
- package/src/Sindri/Ast/Data/CliRouteData.ts +32 -0
- package/src/Sindri/Ast/Data/ConfigData.ts +20 -0
- package/src/Sindri/Ast/Data/Contract/CliArgumentParameterDataContract.ts +18 -0
- package/src/Sindri/Ast/Data/Contract/CliOptionParameterDataContract.ts +22 -0
- package/src/Sindri/Ast/Data/Contract/CliRouteDataContract.ts +25 -0
- package/src/Sindri/Ast/Data/Contract/ConfigDataContract.ts +16 -0
- package/src/Sindri/Ast/Data/Contract/HandlerDataContract.ts +13 -0
- package/src/Sindri/Ast/Data/Contract/HttpParameterDataContract.ts +17 -0
- package/src/Sindri/Ast/Data/Contract/HttpRouteDataContract.ts +28 -0
- package/src/Sindri/Ast/Data/Contract/ListenerDataContract.ts +16 -0
- package/src/Sindri/Ast/Data/HandlerData.ts +20 -0
- package/src/Sindri/Ast/Data/HttpParameterData.ts +20 -0
- package/src/Sindri/Ast/Data/HttpRouteData.ts +30 -0
- package/src/Sindri/Ast/Data/ListenerData.ts +19 -0
- package/src/Sindri/Ast/Data/Result/CliRouteAttributeResult.ts +14 -0
- package/src/Sindri/Ast/Data/Result/ComponentProviderResult.ts +28 -0
- package/src/Sindri/Ast/Data/Result/ConfigResult.ts +18 -0
- package/src/Sindri/Ast/Data/Result/HttpRouteAttributeResult.ts +19 -0
- package/src/Sindri/Ast/Data/Result/ListenerAttributeResult.ts +14 -0
- package/src/Sindri/Ast/Data/Result/ListenerProviderResult.ts +24 -0
- package/src/Sindri/Ast/Data/Result/RouteProviderResult.ts +24 -0
- package/src/Sindri/Ast/Data/Result/ServiceProviderResult.ts +22 -0
- package/src/Sindri/Ast/HttpRouteAttributeReader.ts +315 -0
- package/src/Sindri/Ast/HttpRouteMiddlewareReader.ts +214 -0
- package/src/Sindri/Ast/HttpRouteParameterReader.ts +193 -0
- package/src/Sindri/Ast/ListenerAttributeReader.ts +131 -0
- package/src/Sindri/Ast/ListenerProviderReader.ts +45 -0
- package/src/Sindri/Ast/RouteProviderReader.ts +45 -0
- package/src/Sindri/Ast/ServiceProviderReader.ts +124 -0
- package/src/Sindri/Ast/Throwable/Contract/AstThrowable.ts +12 -0
- package/src/Sindri/Ast/Throwable/Exception/Abstract/AstInvalidArgumentException.ts +14 -0
- package/src/Sindri/Ast/Throwable/Exception/Abstract/AstRuntimeException.ts +14 -0
- package/src/Sindri/Ast/Throwable/Exception/AstFileReadException.ts +12 -0
- package/src/Sindri/Cli/Command/GenerateDataFromConfigCommand.ts +83 -0
- package/src/Sindri/Constant/CommandName.ts +12 -0
- package/src/Sindri/Constant/SindriInfo.ts +20 -0
- package/src/Sindri/Constant/SindriServiceId.ts +32 -0
- package/src/Sindri/Generate/Abstract/GenerateDataFromAst.ts +391 -0
- package/src/Sindri/Generator/Abstract/AstFileGenerator.ts +54 -0
- package/src/Sindri/Generator/Abstract/FileGenerator.ts +59 -0
- package/src/Sindri/Generator/Ast/Cli/AstCliDataFileGenerator.ts +88 -0
- package/src/Sindri/Generator/Ast/Container/AstContainerDataFileGenerator.ts +86 -0
- package/src/Sindri/Generator/Ast/Event/AstEventDataFileGenerator.ts +79 -0
- package/src/Sindri/Generator/Ast/Http/AstHttpDataFileGenerator.ts +306 -0
- package/src/Sindri/Generator/Cli/Contract/CliDataFileGeneratorContract.ts +23 -0
- package/src/Sindri/Generator/Container/Contract/ContainerDataFileGeneratorContract.ts +21 -0
- package/src/Sindri/Generator/Contract/FileGeneratorContract.ts +15 -0
- package/src/Sindri/Generator/Enum/GenerateStatus.ts +14 -0
- package/src/Sindri/Generator/Event/Contract/EventDataFileGeneratorContract.ts +23 -0
- package/src/Sindri/Generator/Http/Contract/HttpDataFileGeneratorContract.ts +25 -0
- package/src/Sindri/Generator/Throwable/Contract/GeneratorThrowable.ts +12 -0
- package/src/Sindri/Generator/Throwable/Exception/Abstract/GeneratorInvalidArgumentException.ts +16 -0
- package/src/Sindri/Generator/Throwable/Exception/Abstract/GeneratorRuntimeException.ts +14 -0
- package/src/Sindri/Generator/Throwable/Exception/GeneratorUnreachableException.ts +12 -0
- package/src/Sindri/Provider/SindriAstServiceProvider.ts +182 -0
- package/src/Sindri/Provider/SindriCliRouteProvider.ts +32 -0
- package/src/Sindri/Provider/SindriCommandServiceProvider.ts +71 -0
- package/src/Sindri/Provider/SindriComponentProvider.ts +41 -0
- package/src/Sindri/Throwable/Contract/SindriThrowable.ts +12 -0
- package/src/Sindri/Throwable/Exception/Abstract/SindriInvalidArgumentException.ts +16 -0
- package/src/Sindri/Throwable/Exception/Abstract/SindriRuntimeException.ts +14 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Sindri package.
|
|
3
|
+
*
|
|
4
|
+
* (c) Melech Mizrachi <melechmizrachi@gmail.com>
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { ts } from 'ts-morph';
|
|
11
|
+
|
|
12
|
+
import { AstFileGenerator } from '../../Abstract/AstFileGenerator.ts';
|
|
13
|
+
import type { EventDataFileGeneratorContract } from '../../Event/Contract/EventDataFileGeneratorContract.ts';
|
|
14
|
+
import type { GenerateStatus } from '../../Enum/GenerateStatus.ts';
|
|
15
|
+
|
|
16
|
+
export class AstEventDataFileGenerator extends AstFileGenerator implements EventDataFileGeneratorContract {
|
|
17
|
+
public classImportMap: Record<string, string> = {};
|
|
18
|
+
|
|
19
|
+
private readonly printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
|
|
20
|
+
|
|
21
|
+
private readonly dummySourceFile = ts.createSourceFile(
|
|
22
|
+
'_dummy.ts',
|
|
23
|
+
'',
|
|
24
|
+
ts.ScriptTarget.ESNext,
|
|
25
|
+
false,
|
|
26
|
+
ts.ScriptKind.TS,
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
public generateFile(
|
|
30
|
+
directory: string,
|
|
31
|
+
className: string,
|
|
32
|
+
namespace: string,
|
|
33
|
+
listeners: Record<string, ts.Expression>,
|
|
34
|
+
): GenerateStatus {
|
|
35
|
+
const userImports = Object.entries(this.classImportMap)
|
|
36
|
+
.map(([name, specifier]) => `import { ${name} } from '${specifier}';`)
|
|
37
|
+
.join('\n');
|
|
38
|
+
|
|
39
|
+
const userImportsBlock = userImports ? `${userImports}\n` : '';
|
|
40
|
+
|
|
41
|
+
const contents = this.generateClassContents(listeners);
|
|
42
|
+
|
|
43
|
+
const data = [
|
|
44
|
+
'// This file was automatically generated by Sindri.',
|
|
45
|
+
'',
|
|
46
|
+
`import { EventData } from '@valkyrjaio/valkyrja/Event/Data/EventData.ts';`,
|
|
47
|
+
`import { Listener } from '@valkyrjaio/valkyrja/Event/Data/Listener.ts';`,
|
|
48
|
+
`import type { ListenerContract } from '@valkyrjaio/valkyrja/Event/Data/Contract/ListenerContract.ts';`,
|
|
49
|
+
userImportsBlock,
|
|
50
|
+
`export class ${className} extends EventData {`,
|
|
51
|
+
` constructor() {`,
|
|
52
|
+
` ${contents}`,
|
|
53
|
+
` }`,
|
|
54
|
+
`}`,
|
|
55
|
+
'',
|
|
56
|
+
].join('\n');
|
|
57
|
+
|
|
58
|
+
return this.writeFile(directory, className, data);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public generateClassContents(listeners: Record<string, ts.Expression>): string {
|
|
62
|
+
const entries = Object.entries(listeners);
|
|
63
|
+
|
|
64
|
+
if (entries.length === 0) {
|
|
65
|
+
return 'super();';
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const lines: string[] = [];
|
|
69
|
+
|
|
70
|
+
for (const [key, valueExpr] of entries) {
|
|
71
|
+
const printed = this.printer.printNode(ts.EmitHint.Unspecified, valueExpr, this.dummySourceFile);
|
|
72
|
+
lines.push(` ['${key}']: (): ListenerContract => ${printed},`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return ['super(', ' {},', ' {', ...lines, ' },', ' );'].join(
|
|
76
|
+
'\n ',
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Sindri package.
|
|
3
|
+
*
|
|
4
|
+
* (c) Melech Mizrachi <melechmizrachi@gmail.com>
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { ts } from 'ts-morph';
|
|
11
|
+
|
|
12
|
+
import { DynamicRoute } from '@valkyrjaio/valkyrja/Http/Routing/Data/DynamicRoute.ts';
|
|
13
|
+
import { Parameter } from '@valkyrjaio/valkyrja/Http/Routing/Data/Parameter.ts';
|
|
14
|
+
import { Regex } from '@valkyrjaio/valkyrja/Http/Routing/Constant/Regex.ts';
|
|
15
|
+
import { Processor } from '@valkyrjaio/valkyrja/Http/Routing/Processor/Processor.ts';
|
|
16
|
+
|
|
17
|
+
import { AstFileGenerator } from '../../Abstract/AstFileGenerator.ts';
|
|
18
|
+
import { GeneratorUnreachableException } from '../../Throwable/Exception/GeneratorUnreachableException.ts';
|
|
19
|
+
import type { HttpDataFileGeneratorContract } from '../../Http/Contract/HttpDataFileGeneratorContract.ts';
|
|
20
|
+
import type { GenerateStatus } from '../../Enum/GenerateStatus.ts';
|
|
21
|
+
import type { HttpParameterData } from '../../../Ast/Data/HttpParameterData.ts';
|
|
22
|
+
import type { HttpRouteData } from '../../../Ast/Data/HttpRouteData.ts';
|
|
23
|
+
import type { ProcessorContract } from '@valkyrjaio/valkyrja/Http/Routing/Processor/Contract/ProcessorContract.ts';
|
|
24
|
+
|
|
25
|
+
export class AstHttpDataFileGenerator extends AstFileGenerator implements HttpDataFileGeneratorContract {
|
|
26
|
+
public classImportMap: Record<string, string> = {};
|
|
27
|
+
|
|
28
|
+
protected readonly processor: ProcessorContract;
|
|
29
|
+
|
|
30
|
+
private readonly printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
|
|
31
|
+
|
|
32
|
+
private readonly dummySourceFile = ts.createSourceFile(
|
|
33
|
+
'_dummy.ts',
|
|
34
|
+
'',
|
|
35
|
+
ts.ScriptTarget.ESNext,
|
|
36
|
+
false,
|
|
37
|
+
ts.ScriptKind.TS,
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
public constructor(processor: ProcessorContract = new Processor()) {
|
|
41
|
+
super();
|
|
42
|
+
this.processor = processor;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public generateFile(
|
|
46
|
+
directory: string,
|
|
47
|
+
className: string,
|
|
48
|
+
namespace: string,
|
|
49
|
+
routes: Record<string, ts.Expression>,
|
|
50
|
+
routeData: Record<string, HttpRouteData>,
|
|
51
|
+
): GenerateStatus {
|
|
52
|
+
const userImports = Object.entries(this.classImportMap)
|
|
53
|
+
.map(([name, specifier]) => `import { ${name} } from '${specifier}';`)
|
|
54
|
+
.join('\n');
|
|
55
|
+
|
|
56
|
+
const userImportsBlock = userImports ? `${userImports}\n` : '';
|
|
57
|
+
|
|
58
|
+
const routesContent = this.getRoutesAsContent(routes, routeData);
|
|
59
|
+
const paths = this.printNestedObject(this.buildPaths(routeData));
|
|
60
|
+
const dynamicPaths = this.printNestedObject(this.buildDynamicPaths(routeData));
|
|
61
|
+
const regexes = this.printNestedObject(this.buildRegexes(routeData));
|
|
62
|
+
|
|
63
|
+
const data = [
|
|
64
|
+
'// This file was automatically generated by Sindri.',
|
|
65
|
+
'',
|
|
66
|
+
`import { HttpRoutingData } from '@valkyrjaio/valkyrja/Http/Routing/Data/HttpRoutingData.ts';`,
|
|
67
|
+
`import { DynamicRoute } from '@valkyrjaio/valkyrja/Http/Routing/Data/DynamicRoute.ts';`,
|
|
68
|
+
`import { Route } from '@valkyrjaio/valkyrja/Http/Routing/Data/Route.ts';`,
|
|
69
|
+
`import { Parameter } from '@valkyrjaio/valkyrja/Http/Routing/Data/Parameter.ts';`,
|
|
70
|
+
`import { RequestMethod } from '@valkyrjaio/valkyrja/Http/Message/Enum/RequestMethod.ts';`,
|
|
71
|
+
`import { Regex } from '@valkyrjaio/valkyrja/Http/Routing/Constant/Regex.ts';`,
|
|
72
|
+
`import type { RouteContract } from '@valkyrjaio/valkyrja/Http/Routing/Data/Contract/RouteContract.ts';`,
|
|
73
|
+
userImportsBlock,
|
|
74
|
+
`export class ${className} extends HttpRoutingData {`,
|
|
75
|
+
` constructor() {`,
|
|
76
|
+
` super(`,
|
|
77
|
+
` ${routesContent},`,
|
|
78
|
+
` ${paths},`,
|
|
79
|
+
` ${dynamicPaths},`,
|
|
80
|
+
` ${regexes},`,
|
|
81
|
+
` );`,
|
|
82
|
+
` }`,
|
|
83
|
+
`}`,
|
|
84
|
+
'',
|
|
85
|
+
].join('\n');
|
|
86
|
+
|
|
87
|
+
return this.writeFile(directory, className, data);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public generateClassContents(
|
|
91
|
+
routes: Record<string, ts.Expression>,
|
|
92
|
+
routeData: Record<string, HttpRouteData>,
|
|
93
|
+
): string {
|
|
94
|
+
const routesContent = this.getRoutesAsContent(routes, routeData);
|
|
95
|
+
const paths = this.printNestedObject(this.buildPaths(routeData));
|
|
96
|
+
const dynamicPaths = this.printNestedObject(this.buildDynamicPaths(routeData));
|
|
97
|
+
const regexes = this.printNestedObject(this.buildRegexes(routeData));
|
|
98
|
+
|
|
99
|
+
return [
|
|
100
|
+
'super(',
|
|
101
|
+
` ${routesContent},`,
|
|
102
|
+
` ${paths},`,
|
|
103
|
+
` ${dynamicPaths},`,
|
|
104
|
+
` ${regexes},`,
|
|
105
|
+
' );',
|
|
106
|
+
].join('\n ');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
protected buildPaths(routeData: Record<string, HttpRouteData>): Record<string, Record<string, string>> {
|
|
110
|
+
const paths: Record<string, Record<string, string>> = {};
|
|
111
|
+
|
|
112
|
+
for (const [name, data] of Object.entries(routeData)) {
|
|
113
|
+
if (data.isDynamic) {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const path = this.normalizePath(data.path);
|
|
118
|
+
|
|
119
|
+
for (const method of this.extractMethodNames(data.requestMethods)) {
|
|
120
|
+
if (paths[method] === undefined) {
|
|
121
|
+
paths[method] = {};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
paths[method][path] = name;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return paths;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
protected buildDynamicPaths(routeData: Record<string, HttpRouteData>): Record<string, Record<string, string>> {
|
|
132
|
+
const dynamicPaths: Record<string, Record<string, string>> = {};
|
|
133
|
+
|
|
134
|
+
for (const [name, data] of Object.entries(routeData)) {
|
|
135
|
+
if (!data.isDynamic) {
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const path = this.normalizePath(data.path);
|
|
140
|
+
|
|
141
|
+
for (const method of this.extractMethodNames(data.requestMethods)) {
|
|
142
|
+
if (dynamicPaths[method] === undefined) {
|
|
143
|
+
dynamicPaths[method] = {};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
dynamicPaths[method][path] = name;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return dynamicPaths;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
protected buildRegexes(routeData: Record<string, HttpRouteData>): Record<string, Record<string, string>> {
|
|
154
|
+
const regexes: Record<string, Record<string, string>> = {};
|
|
155
|
+
|
|
156
|
+
for (const [name, data] of Object.entries(routeData)) {
|
|
157
|
+
if (!data.isDynamic || data.parameters.length === 0) {
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const regex = this.computeRegex(data);
|
|
162
|
+
|
|
163
|
+
if (regex === '') {
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
for (const method of this.extractMethodNames(data.requestMethods)) {
|
|
168
|
+
if (regexes[method] === undefined) {
|
|
169
|
+
regexes[method] = {};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
regexes[method][regex] = name;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return regexes;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
protected buildNestedStringArrayExpr(data: Record<string, Record<string, string>>): ts.ObjectLiteralExpression {
|
|
180
|
+
const outerProps: ts.PropertyAssignment[] = [];
|
|
181
|
+
|
|
182
|
+
for (const [outerKey, innerMap] of Object.entries(data)) {
|
|
183
|
+
const innerProps: ts.PropertyAssignment[] = [];
|
|
184
|
+
|
|
185
|
+
for (const [innerKey, value] of Object.entries(innerMap)) {
|
|
186
|
+
innerProps.push(
|
|
187
|
+
ts.factory.createPropertyAssignment(
|
|
188
|
+
ts.factory.createStringLiteral(innerKey),
|
|
189
|
+
ts.factory.createStringLiteral(value),
|
|
190
|
+
),
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
outerProps.push(
|
|
195
|
+
ts.factory.createPropertyAssignment(
|
|
196
|
+
ts.factory.createStringLiteral(outerKey),
|
|
197
|
+
ts.factory.createObjectLiteralExpression(innerProps, true),
|
|
198
|
+
),
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return ts.factory.createObjectLiteralExpression(outerProps, true);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
protected printNestedObject(data: Record<string, Record<string, string>>): string {
|
|
206
|
+
return this.printer.printNode(
|
|
207
|
+
ts.EmitHint.Unspecified,
|
|
208
|
+
this.buildNestedStringArrayExpr(data),
|
|
209
|
+
this.dummySourceFile,
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
protected computeRegex(data: HttpRouteData): string {
|
|
214
|
+
const parameters = data.parameters.map((p) => this.buildParameter(p));
|
|
215
|
+
|
|
216
|
+
const route = new DynamicRoute(
|
|
217
|
+
data.path !== '' ? data.path : '/',
|
|
218
|
+
data.name !== '' ? data.name : 'temp',
|
|
219
|
+
'',
|
|
220
|
+
parameters,
|
|
221
|
+
(): never => {
|
|
222
|
+
throw new GeneratorUnreachableException('unreachable');
|
|
223
|
+
},
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
const processed = this.processor.route(route);
|
|
227
|
+
|
|
228
|
+
if ('getRegex' in processed && typeof (processed as DynamicRoute).getRegex === 'function') {
|
|
229
|
+
return (processed as DynamicRoute).getRegex();
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return '';
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
protected buildParameter(data: HttpParameterData): Parameter {
|
|
236
|
+
let regex = data.regex;
|
|
237
|
+
|
|
238
|
+
if (regex.includes('::')) {
|
|
239
|
+
const pos = regex.lastIndexOf('::');
|
|
240
|
+
const className = regex.substring(0, pos);
|
|
241
|
+
const propName = regex.substring(pos + 2);
|
|
242
|
+
|
|
243
|
+
if (className === 'Regex') {
|
|
244
|
+
const resolved = (Regex as unknown as Record<string, string>)[propName];
|
|
245
|
+
|
|
246
|
+
if (typeof resolved === 'string' && resolved !== '') {
|
|
247
|
+
regex = resolved;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return new Parameter(data.name, regex, null, data.isOptional, data.shouldCapture);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
protected normalizePath(path: string): string {
|
|
256
|
+
return '/' + path.replace(/^\/+|\/+$/g, '');
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
protected extractMethodNames(requestMethods: readonly string[]): string[] {
|
|
260
|
+
const methods: string[] = [];
|
|
261
|
+
|
|
262
|
+
for (const method of requestMethods) {
|
|
263
|
+
const pos = method.lastIndexOf('::');
|
|
264
|
+
|
|
265
|
+
if (pos !== -1) {
|
|
266
|
+
methods.push(method.substring(pos + 2));
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return methods;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
protected getRoutesAsContent(
|
|
274
|
+
routes: Record<string, ts.Expression>,
|
|
275
|
+
routeData: Record<string, HttpRouteData>,
|
|
276
|
+
): string {
|
|
277
|
+
const entries = Object.entries(routes);
|
|
278
|
+
|
|
279
|
+
if (entries.length === 0) {
|
|
280
|
+
return '{}';
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const lines: string[] = [];
|
|
284
|
+
|
|
285
|
+
for (const [key, routeExpr] of entries) {
|
|
286
|
+
const data = routeData[key] ?? null;
|
|
287
|
+
let expr = routeExpr;
|
|
288
|
+
|
|
289
|
+
if (data !== null && data.isDynamic && ts.isNewExpression(expr)) {
|
|
290
|
+
const computedRegex = data.parameters.length > 0 ? this.computeRegex(data) : '';
|
|
291
|
+
const args = [...(expr.arguments ?? []), ts.factory.createStringLiteral(computedRegex)];
|
|
292
|
+
expr = ts.factory.createNewExpression(expr.expression, expr.typeArguments, args);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const keyExpr = this.buildEnumCaseExpr(key);
|
|
296
|
+
const printedKey = this.printer.printNode(ts.EmitHint.Unspecified, keyExpr, this.dummySourceFile);
|
|
297
|
+
const printedRoute = this.printer.printNode(ts.EmitHint.Unspecified, expr, this.dummySourceFile);
|
|
298
|
+
|
|
299
|
+
const formattedKey = key.includes('::') ? `[${printedKey}]` : `['${printedKey}']`;
|
|
300
|
+
|
|
301
|
+
lines.push(` ${formattedKey}: (): RouteContract => ${printedRoute},`);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return ['{', ...lines, ' }'].join('\n ');
|
|
305
|
+
}
|
|
306
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Sindri package.
|
|
3
|
+
*
|
|
4
|
+
* (c) Melech Mizrachi <melechmizrachi@gmail.com>
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { ts } from 'ts-morph';
|
|
11
|
+
|
|
12
|
+
import type { GenerateStatus } from '../../Enum/GenerateStatus.ts';
|
|
13
|
+
|
|
14
|
+
export interface CliDataFileGeneratorContract {
|
|
15
|
+
generateFile(
|
|
16
|
+
directory: string,
|
|
17
|
+
className: string,
|
|
18
|
+
namespace: string,
|
|
19
|
+
routes: Record<string, ts.Expression>,
|
|
20
|
+
): GenerateStatus;
|
|
21
|
+
|
|
22
|
+
generateClassContents(routes: Record<string, ts.Expression>): string;
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Sindri package.
|
|
3
|
+
*
|
|
4
|
+
* (c) Melech Mizrachi <melechmizrachi@gmail.com>
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { GenerateStatus } from '../../Enum/GenerateStatus.ts';
|
|
11
|
+
|
|
12
|
+
export interface ContainerDataFileGeneratorContract {
|
|
13
|
+
generateFile(
|
|
14
|
+
directory: string,
|
|
15
|
+
className: string,
|
|
16
|
+
namespace: string,
|
|
17
|
+
publishers: Readonly<Record<string, readonly [string, string]>>,
|
|
18
|
+
): GenerateStatus;
|
|
19
|
+
|
|
20
|
+
generateClassContents(publishers: Readonly<Record<string, readonly [string, string]>>): string;
|
|
21
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Sindri package.
|
|
3
|
+
*
|
|
4
|
+
* (c) Melech Mizrachi <melechmizrachi@gmail.com>
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { GenerateStatus } from '../Enum/GenerateStatus.ts';
|
|
11
|
+
|
|
12
|
+
export interface FileGeneratorContract {
|
|
13
|
+
generateFile(): GenerateStatus;
|
|
14
|
+
generateFileContents(): string;
|
|
15
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Sindri package.
|
|
3
|
+
*
|
|
4
|
+
* (c) Melech Mizrachi <melechmizrachi@gmail.com>
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export enum GenerateStatus {
|
|
11
|
+
SUCCESS = 'SUCCESS',
|
|
12
|
+
FAILURE = 'FAILURE',
|
|
13
|
+
SKIPPED = 'SKIPPED',
|
|
14
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Sindri package.
|
|
3
|
+
*
|
|
4
|
+
* (c) Melech Mizrachi <melechmizrachi@gmail.com>
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { ts } from 'ts-morph';
|
|
11
|
+
|
|
12
|
+
import type { GenerateStatus } from '../../Enum/GenerateStatus.ts';
|
|
13
|
+
|
|
14
|
+
export interface EventDataFileGeneratorContract {
|
|
15
|
+
generateFile(
|
|
16
|
+
directory: string,
|
|
17
|
+
className: string,
|
|
18
|
+
namespace: string,
|
|
19
|
+
listeners: Record<string, ts.Expression>,
|
|
20
|
+
): GenerateStatus;
|
|
21
|
+
|
|
22
|
+
generateClassContents(listeners: Record<string, ts.Expression>): string;
|
|
23
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Sindri package.
|
|
3
|
+
*
|
|
4
|
+
* (c) Melech Mizrachi <melechmizrachi@gmail.com>
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { ts } from 'ts-morph';
|
|
11
|
+
|
|
12
|
+
import type { HttpRouteData } from '../../../Ast/Data/HttpRouteData.ts';
|
|
13
|
+
import type { GenerateStatus } from '../../Enum/GenerateStatus.ts';
|
|
14
|
+
|
|
15
|
+
export interface HttpDataFileGeneratorContract {
|
|
16
|
+
generateFile(
|
|
17
|
+
directory: string,
|
|
18
|
+
className: string,
|
|
19
|
+
namespace: string,
|
|
20
|
+
routes: Record<string, ts.Expression>,
|
|
21
|
+
routeData: Record<string, HttpRouteData>,
|
|
22
|
+
): GenerateStatus;
|
|
23
|
+
|
|
24
|
+
generateClassContents(routes: Record<string, ts.Expression>, routeData: Record<string, HttpRouteData>): string;
|
|
25
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Sindri package.
|
|
3
|
+
*
|
|
4
|
+
* (c) Melech Mizrachi <melechmizrachi@gmail.com>
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { SindriThrowable } from '../../../Throwable/Contract/SindriThrowable.ts';
|
|
11
|
+
|
|
12
|
+
export type GeneratorThrowable = SindriThrowable;
|
package/src/Sindri/Generator/Throwable/Exception/Abstract/GeneratorInvalidArgumentException.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Sindri package.
|
|
3
|
+
*
|
|
4
|
+
* (c) Melech Mizrachi <melechmizrachi@gmail.com>
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { SindriInvalidArgumentException } from '../../../../Throwable/Exception/Abstract/SindriInvalidArgumentException.ts';
|
|
11
|
+
|
|
12
|
+
import type { GeneratorThrowable } from '../../Contract/GeneratorThrowable.ts';
|
|
13
|
+
|
|
14
|
+
export abstract class GeneratorInvalidArgumentException
|
|
15
|
+
extends SindriInvalidArgumentException
|
|
16
|
+
implements GeneratorThrowable {}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Sindri package.
|
|
3
|
+
*
|
|
4
|
+
* (c) Melech Mizrachi <melechmizrachi@gmail.com>
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { SindriRuntimeException } from '../../../../Throwable/Exception/Abstract/SindriRuntimeException.ts';
|
|
11
|
+
|
|
12
|
+
import type { GeneratorThrowable } from '../../Contract/GeneratorThrowable.ts';
|
|
13
|
+
|
|
14
|
+
export abstract class GeneratorRuntimeException extends SindriRuntimeException implements GeneratorThrowable {}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Sindri package.
|
|
3
|
+
*
|
|
4
|
+
* (c) Melech Mizrachi <melechmizrachi@gmail.com>
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { GeneratorRuntimeException } from './Abstract/GeneratorRuntimeException.ts';
|
|
11
|
+
|
|
12
|
+
export class GeneratorUnreachableException extends GeneratorRuntimeException {}
|