@valkyrjaio/sindri 26.5.1 → 26.6.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 +1 -1
- package/dist/bin/sindri.cjs +574 -268
- package/package.json +2 -2
- package/src/Sindri/Ast/Abstract/AstReader.ts +187 -5
- package/src/Sindri/Ast/Abstract/RouteAttributeReader.ts +2 -3
- package/src/Sindri/Ast/CliRouteAttributeReader.ts +102 -17
- package/src/Sindri/Ast/CliRouteParameterReader.ts +44 -26
- package/src/Sindri/Ast/ComponentProviderReader.ts +2 -3
- package/src/Sindri/Ast/ConfigReader.ts +2 -3
- package/src/Sindri/Ast/ConfigSourceReader.ts +2 -3
- package/src/Sindri/Ast/Contract/CliRouteAttributeReaderContract.ts +2 -3
- package/src/Sindri/Ast/Contract/CliRouteParameterReaderContract.ts +2 -3
- package/src/Sindri/Ast/Contract/ComponentProviderReaderContract.ts +2 -3
- package/src/Sindri/Ast/Contract/ConfigReaderContract.ts +2 -3
- package/src/Sindri/Ast/Contract/ConfigSourceReaderContract.ts +2 -3
- package/src/Sindri/Ast/Contract/HttpRouteAttributeReaderContract.ts +2 -3
- package/src/Sindri/Ast/Contract/HttpRouteMiddlewareReaderContract.ts +5 -10
- package/src/Sindri/Ast/Contract/HttpRouteParameterReaderContract.ts +3 -7
- package/src/Sindri/Ast/Contract/ListenerAttributeReaderContract.ts +2 -3
- package/src/Sindri/Ast/Contract/ListenerProviderReaderContract.ts +2 -3
- package/src/Sindri/Ast/Contract/RouteProviderReaderContract.ts +2 -3
- package/src/Sindri/Ast/Contract/ServiceProviderReaderContract.ts +2 -3
- package/src/Sindri/Ast/Data/CliArgumentParameterData.ts +2 -3
- package/src/Sindri/Ast/Data/CliOptionParameterData.ts +2 -3
- package/src/Sindri/Ast/Data/CliRouteData.ts +2 -3
- package/src/Sindri/Ast/Data/ConfigData.ts +2 -3
- package/src/Sindri/Ast/Data/ConfigImport.ts +2 -3
- package/src/Sindri/Ast/Data/Contract/CliArgumentParameterDataContract.ts +2 -3
- package/src/Sindri/Ast/Data/Contract/CliOptionParameterDataContract.ts +2 -3
- package/src/Sindri/Ast/Data/Contract/CliRouteDataContract.ts +2 -3
- package/src/Sindri/Ast/Data/Contract/ConfigDataContract.ts +2 -3
- package/src/Sindri/Ast/Data/Contract/HandlerDataContract.ts +2 -3
- package/src/Sindri/Ast/Data/Contract/HttpParameterDataContract.ts +4 -3
- package/src/Sindri/Ast/Data/Contract/HttpRouteDataContract.ts +2 -3
- package/src/Sindri/Ast/Data/Contract/ListenerDataContract.ts +2 -3
- package/src/Sindri/Ast/Data/HandlerData.ts +2 -3
- package/src/Sindri/Ast/Data/HttpParameterData.ts +3 -3
- package/src/Sindri/Ast/Data/HttpRouteData.ts +2 -3
- package/src/Sindri/Ast/Data/ListenerData.ts +2 -3
- package/src/Sindri/Ast/Data/Result/CliRouteAttributeResult.ts +7 -4
- package/src/Sindri/Ast/Data/Result/ComponentProviderResult.ts +2 -3
- package/src/Sindri/Ast/Data/Result/ConfigResult.ts +2 -3
- package/src/Sindri/Ast/Data/Result/ConfigSourceResult.ts +2 -3
- package/src/Sindri/Ast/Data/Result/HttpRouteAttributeResult.ts +4 -3
- package/src/Sindri/Ast/Data/Result/ListenerAttributeResult.ts +2 -3
- package/src/Sindri/Ast/Data/Result/ListenerProviderResult.ts +2 -3
- package/src/Sindri/Ast/Data/Result/RouteProviderResult.ts +2 -3
- package/src/Sindri/Ast/Data/Result/ServiceProviderResult.ts +2 -3
- package/src/Sindri/Ast/HttpRouteAttributeReader.ts +180 -51
- package/src/Sindri/Ast/HttpRouteMiddlewareReader.ts +38 -18
- package/src/Sindri/Ast/HttpRouteParameterReader.ts +50 -109
- package/src/Sindri/Ast/ListenerAttributeReader.ts +2 -3
- package/src/Sindri/Ast/ListenerProviderReader.ts +2 -3
- package/src/Sindri/Ast/RouteProviderReader.ts +2 -3
- package/src/Sindri/Ast/ServiceProviderReader.ts +2 -3
- package/src/Sindri/Ast/Throwable/Contract/AstThrowable.ts +2 -3
- package/src/Sindri/Ast/Throwable/Exception/Abstract/AstInvalidArgumentException.ts +2 -3
- package/src/Sindri/Ast/Throwable/Exception/Abstract/AstRuntimeException.ts +2 -3
- package/src/Sindri/Ast/Throwable/Exception/AstFileReadException.ts +2 -3
- package/src/Sindri/Cli/Command/GenerateCachedConfigCommand.ts +2 -3
- package/src/Sindri/Cli/Command/GenerateDataFromConfigCommand.ts +2 -3
- package/src/Sindri/Constant/CommandName.ts +2 -3
- package/src/Sindri/Constant/SindriInfo.ts +4 -5
- package/src/Sindri/Constant/SindriServiceId.ts +2 -3
- package/src/Sindri/Generate/Abstract/GenerateCachedConfigFromAst.ts +2 -3
- package/src/Sindri/Generate/Abstract/GenerateDataFromAst.ts +39 -27
- package/src/Sindri/Generate/Abstract/GenerateFromAst.ts +2 -3
- package/src/Sindri/Generator/Abstract/AstFileGenerator.ts +2 -3
- package/src/Sindri/Generator/Abstract/FileGenerator.ts +2 -3
- package/src/Sindri/Generator/Ast/Cli/AstCliDataFileGenerator.ts +21 -6
- package/src/Sindri/Generator/Ast/Config/AstCachedConfigFileGenerator.ts +2 -3
- package/src/Sindri/Generator/Ast/Container/AstContainerDataFileGenerator.ts +2 -3
- package/src/Sindri/Generator/Ast/Event/AstEventDataFileGenerator.ts +2 -3
- package/src/Sindri/Generator/Ast/Http/AstHttpDataFileGenerator.ts +83 -45
- package/src/Sindri/Generator/Cli/Contract/CliDataFileGeneratorContract.ts +10 -3
- package/src/Sindri/Generator/Config/Contract/CachedConfigFileGeneratorContract.ts +2 -3
- package/src/Sindri/Generator/Container/Contract/ContainerDataFileGeneratorContract.ts +2 -3
- package/src/Sindri/Generator/Contract/FileGeneratorContract.ts +2 -3
- package/src/Sindri/Generator/Enum/GenerateStatus.ts +2 -3
- package/src/Sindri/Generator/Event/Contract/EventDataFileGeneratorContract.ts +2 -3
- package/src/Sindri/Generator/Http/Contract/HttpDataFileGeneratorContract.ts +11 -3
- package/src/Sindri/Generator/Throwable/Contract/GeneratorThrowable.ts +2 -3
- package/src/Sindri/Generator/Throwable/Exception/Abstract/GeneratorInvalidArgumentException.ts +2 -3
- package/src/Sindri/Generator/Throwable/Exception/Abstract/GeneratorRuntimeException.ts +2 -3
- package/src/Sindri/Generator/Throwable/Exception/GeneratorUnreachableException.ts +2 -3
- package/src/Sindri/Provider/SindriAstServiceProvider.ts +2 -3
- package/src/Sindri/Provider/SindriCliRouteProvider.ts +2 -3
- package/src/Sindri/Provider/SindriCommandServiceProvider.ts +2 -3
- package/src/Sindri/Provider/SindriComponentProvider.ts +2 -3
- package/src/Sindri/Throwable/Contract/SindriThrowable.ts +2 -3
- package/src/Sindri/Throwable/Exception/Abstract/SindriInvalidArgumentException.ts +2 -3
- package/src/Sindri/Throwable/Exception/Abstract/SindriRuntimeException.ts +2 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@valkyrjaio/sindri",
|
|
3
|
-
"version": "26.
|
|
3
|
+
"version": "26.6.1",
|
|
4
4
|
"description": "The Valkyrja Sindri build tool.",
|
|
5
5
|
"homepage": "https://www.valkyrja.io/sindri",
|
|
6
6
|
"keywords": [
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"node": ">=22"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@valkyrjaio/valkyrja": "^26.
|
|
41
|
+
"@valkyrjaio/valkyrja": "^26.6.1",
|
|
42
42
|
"ts-morph": "^28.0.0"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* This file is part of the Sindri package.
|
|
3
3
|
*
|
|
4
|
-
* (c) Melech Mizrachi
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* file that was distributed with this source code.
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
8
7
|
*/
|
|
9
8
|
|
|
10
9
|
import * as fs from 'fs';
|
|
@@ -612,6 +611,153 @@ export abstract class AstReader {
|
|
|
612
611
|
return decorator.getArguments()[position];
|
|
613
612
|
}
|
|
614
613
|
|
|
614
|
+
// -------------------------------------------------------------------------
|
|
615
|
+
// Object-literal decorator helpers — the shipped decorators accept a single
|
|
616
|
+
// options object (`@Route({ path, name, ... })`) rather than positional args.
|
|
617
|
+
// -------------------------------------------------------------------------
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Return the decorator's first argument when it is an object literal, else undefined.
|
|
621
|
+
*/
|
|
622
|
+
protected getDecoratorObjectArg(decorator: Decorator): ts.ObjectLiteralExpression | undefined {
|
|
623
|
+
const arg = this.getDecoratorArg(decorator, 0);
|
|
624
|
+
|
|
625
|
+
if (arg === undefined) {
|
|
626
|
+
return undefined;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
const tsNode = arg.compilerNode;
|
|
630
|
+
|
|
631
|
+
return ts.isObjectLiteralExpression(tsNode) ? tsNode : undefined;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Return the value expression of the named property on an object literal, or
|
|
636
|
+
* undefined when the property is absent (or is not a plain property assignment).
|
|
637
|
+
*/
|
|
638
|
+
protected getObjectProp(obj: ts.ObjectLiteralExpression, key: string): ts.Expression | undefined {
|
|
639
|
+
for (const prop of obj.properties) {
|
|
640
|
+
if (ts.isPropertyAssignment(prop) && this.propertyNameToString(prop.name) === key) {
|
|
641
|
+
return prop.initializer;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
return undefined;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* Resolve a property name node (identifier or string literal) to its text.
|
|
650
|
+
*/
|
|
651
|
+
protected propertyNameToString(name: ts.PropertyName): string | undefined {
|
|
652
|
+
if (ts.isIdentifier(name) || ts.isStringLiteral(name)) {
|
|
653
|
+
return name.text;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
return undefined;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* Extract a string-valued object property, falling back to defaultValue.
|
|
661
|
+
*/
|
|
662
|
+
protected getObjectStringProp(
|
|
663
|
+
obj: ts.ObjectLiteralExpression,
|
|
664
|
+
key: string,
|
|
665
|
+
useMap: Record<string, string>,
|
|
666
|
+
currentFilePath: string,
|
|
667
|
+
currentClass: string,
|
|
668
|
+
defaultValue: string = '',
|
|
669
|
+
): string {
|
|
670
|
+
const value = this.extractExprValue(this.getObjectProp(obj, key), useMap, currentFilePath, currentClass);
|
|
671
|
+
|
|
672
|
+
return typeof value === 'string' ? value : defaultValue;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/**
|
|
676
|
+
* Extract a boolean-valued object property, falling back to defaultValue.
|
|
677
|
+
*/
|
|
678
|
+
protected getObjectBoolProp(
|
|
679
|
+
obj: ts.ObjectLiteralExpression,
|
|
680
|
+
key: string,
|
|
681
|
+
useMap: Record<string, string>,
|
|
682
|
+
currentFilePath: string,
|
|
683
|
+
currentClass: string,
|
|
684
|
+
defaultValue: boolean = false,
|
|
685
|
+
): boolean {
|
|
686
|
+
const value = this.extractExprValue(this.getObjectProp(obj, key), useMap, currentFilePath, currentClass);
|
|
687
|
+
|
|
688
|
+
return typeof value === 'boolean' ? value : defaultValue;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* Extract a class-list object property (an array literal of class references),
|
|
693
|
+
* returning an empty array when the property is absent or not an array.
|
|
694
|
+
*/
|
|
695
|
+
protected getObjectClassListProp(
|
|
696
|
+
obj: ts.ObjectLiteralExpression,
|
|
697
|
+
key: string,
|
|
698
|
+
useMap: Record<string, string>,
|
|
699
|
+
currentFilePath: string,
|
|
700
|
+
currentClass: string,
|
|
701
|
+
): string[] {
|
|
702
|
+
const node = this.getObjectProp(obj, key);
|
|
703
|
+
|
|
704
|
+
if (node === undefined || !ts.isArrayLiteralExpression(node)) {
|
|
705
|
+
return [];
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
return this.extractClassListFromArrayExpr(node, useMap, currentFilePath, currentClass);
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
* Extract a string-list object property (an array literal of string values),
|
|
713
|
+
* returning an empty array when the property is absent or not an array.
|
|
714
|
+
*/
|
|
715
|
+
protected getObjectStringListProp(
|
|
716
|
+
obj: ts.ObjectLiteralExpression,
|
|
717
|
+
key: string,
|
|
718
|
+
useMap: Record<string, string>,
|
|
719
|
+
currentFilePath: string,
|
|
720
|
+
currentClass: string,
|
|
721
|
+
): string[] {
|
|
722
|
+
const node = this.getObjectProp(obj, key);
|
|
723
|
+
|
|
724
|
+
if (node === undefined || !ts.isArrayLiteralExpression(node)) {
|
|
725
|
+
return [];
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
const values: string[] = [];
|
|
729
|
+
|
|
730
|
+
for (const element of node.elements) {
|
|
731
|
+
const value = this.extractExprValue(element, useMap, currentFilePath, currentClass);
|
|
732
|
+
|
|
733
|
+
if (typeof value === 'string') {
|
|
734
|
+
values.push(value);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
return values;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
/**
|
|
742
|
+
* Extract a handler-reference object property (`[Class, 'method']`), returning
|
|
743
|
+
* undefined when the property is absent or not a two-element handler array.
|
|
744
|
+
*/
|
|
745
|
+
protected getObjectHandlerProp(
|
|
746
|
+
obj: ts.ObjectLiteralExpression,
|
|
747
|
+
key: string,
|
|
748
|
+
useMap: Record<string, string>,
|
|
749
|
+
currentFilePath: string,
|
|
750
|
+
currentClass: string,
|
|
751
|
+
): HandlerData | undefined {
|
|
752
|
+
const node = this.getObjectProp(obj, key);
|
|
753
|
+
|
|
754
|
+
if (node === undefined || !ts.isArrayLiteralExpression(node)) {
|
|
755
|
+
return undefined;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
return this.extractHandlerFromTsArray(node, useMap, currentFilePath, currentClass);
|
|
759
|
+
}
|
|
760
|
+
|
|
615
761
|
/**
|
|
616
762
|
* Convert a simple expression node to a scalar value or HandlerData.
|
|
617
763
|
*/
|
|
@@ -692,7 +838,12 @@ export abstract class AstReader {
|
|
|
692
838
|
return undefined;
|
|
693
839
|
}
|
|
694
840
|
|
|
695
|
-
const classValue = this.extractExprValue(
|
|
841
|
+
const classValue = this.extractExprValue(
|
|
842
|
+
this.unwrapClassThunk(array.elements[0]),
|
|
843
|
+
useMap,
|
|
844
|
+
currentFilePath,
|
|
845
|
+
currentClass,
|
|
846
|
+
);
|
|
696
847
|
const methodValue = this.extractExprValue(array.elements[1], useMap, currentFilePath, currentClass);
|
|
697
848
|
|
|
698
849
|
if (typeof classValue !== 'string' || classValue === '') {
|
|
@@ -706,6 +857,35 @@ export abstract class AstReader {
|
|
|
706
857
|
return new HandlerData(classValue, methodValue);
|
|
707
858
|
}
|
|
708
859
|
|
|
860
|
+
/**
|
|
861
|
+
* Unwrap a class **thunk** to the class expression it returns —
|
|
862
|
+
* `() => HomeController` becomes `HomeController`.
|
|
863
|
+
*
|
|
864
|
+
* Every class reference in a decorator argument is authored as a thunk —
|
|
865
|
+
* `[() => SomeClass, 'method']` for a handler, `@Middleware(() => SomeClass)`
|
|
866
|
+
* for middleware — rather than as a bare class name. A TC39 Stage-3
|
|
867
|
+
* decorator runs while the class binding is still in its temporal dead zone,
|
|
868
|
+
* so naming the class directly throws at class-definition time on a circular
|
|
869
|
+
* or self-referential import. The thunk is purely a runtime deferral: the
|
|
870
|
+
* emitted cache is unchanged (`HttpRouteProvider.versionHandler`), so the
|
|
871
|
+
* reader simply looks through it. A bare class expression is returned
|
|
872
|
+
* untouched, and a block-bodied arrow (`() => { … }`) is left alone so it
|
|
873
|
+
* falls through to the usual "not a class reference" handling.
|
|
874
|
+
*/
|
|
875
|
+
protected unwrapClassThunk(node: Node | ts.Node | undefined): Node | ts.Node | undefined {
|
|
876
|
+
if (node === undefined) {
|
|
877
|
+
return node;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
const tsNode = Node.isNode(node) ? node.compilerNode : node;
|
|
881
|
+
|
|
882
|
+
if (!ts.isArrowFunction(tsNode) || tsNode.parameters.length !== 0) {
|
|
883
|
+
return node;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
return ts.isBlock(tsNode.body) ? node : tsNode.body;
|
|
887
|
+
}
|
|
888
|
+
|
|
709
889
|
protected extractClassListFromArrayExpr(
|
|
710
890
|
array: ts.ArrayLiteralExpression,
|
|
711
891
|
useMap: Record<string, string>,
|
|
@@ -715,7 +895,9 @@ export abstract class AstReader {
|
|
|
715
895
|
const classes: string[] = [];
|
|
716
896
|
|
|
717
897
|
for (const element of array.elements) {
|
|
718
|
-
|
|
898
|
+
// A class list inside a decorator argument holds thunked references
|
|
899
|
+
// (`middleware: [() => AuthMiddleware]`), so look through the thunk.
|
|
900
|
+
const value = this.extractExprValue(this.unwrapClassThunk(element), useMap, currentFilePath, currentClass);
|
|
719
901
|
|
|
720
902
|
if (typeof value === 'string' && value !== '') {
|
|
721
903
|
classes.push(value);
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* This file is part of the Sindri package.
|
|
3
3
|
*
|
|
4
|
-
* (c) Melech Mizrachi
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* file that was distributed with this source code.
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
8
7
|
*/
|
|
9
8
|
|
|
10
9
|
import type { MethodDeclaration } from 'ts-morph';
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* This file is part of the Sindri package.
|
|
3
3
|
*
|
|
4
|
-
* (c) Melech Mizrachi
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* file that was distributed with this source code.
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
8
7
|
*/
|
|
9
8
|
|
|
10
9
|
import { ts } from 'ts-morph';
|
|
@@ -18,6 +17,7 @@ import type { Decorator, MethodDeclaration } from 'ts-morph';
|
|
|
18
17
|
|
|
19
18
|
import type { CliRouteAttributeReaderContract } from './Contract/CliRouteAttributeReaderContract.ts';
|
|
20
19
|
import type { CliRouteParameterReaderContract } from './Contract/CliRouteParameterReaderContract.ts';
|
|
20
|
+
import type { HandlerData } from './Data/HandlerData.ts';
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Scans a CLI controller class file for @Route and related sub-decorators and
|
|
@@ -40,6 +40,7 @@ export class CliRouteAttributeReader extends RouteAttributeReader implements Cli
|
|
|
40
40
|
|
|
41
41
|
const { classDecl, useMap, currentClass } = context;
|
|
42
42
|
const routes: Record<string, ts.Expression> = {};
|
|
43
|
+
const routeData: Record<string, CliRouteData> = {};
|
|
43
44
|
|
|
44
45
|
for (const method of classDecl.getMethods()) {
|
|
45
46
|
for (const decorator of this.findDecoratorsOnNode(method, 'Route', useMap, filePath)) {
|
|
@@ -47,11 +48,14 @@ export class CliRouteAttributeReader extends RouteAttributeReader implements Cli
|
|
|
47
48
|
|
|
48
49
|
if (data !== null) {
|
|
49
50
|
routes[data.name] = this.buildRouteExpr(data);
|
|
51
|
+
routeData[data.name] = data;
|
|
50
52
|
}
|
|
51
53
|
}
|
|
52
54
|
}
|
|
53
55
|
|
|
54
|
-
|
|
56
|
+
const importMap = this.buildImportMap(routeData, useMap, filePath, currentClass);
|
|
57
|
+
|
|
58
|
+
return new CliRouteAttributeResult(routes, importMap);
|
|
55
59
|
}
|
|
56
60
|
|
|
57
61
|
protected getRouteHandlerDecoratorName(): string {
|
|
@@ -65,8 +69,14 @@ export class CliRouteAttributeReader extends RouteAttributeReader implements Cli
|
|
|
65
69
|
currentFilePath: string,
|
|
66
70
|
currentClass: string,
|
|
67
71
|
): CliRouteData | null {
|
|
68
|
-
const
|
|
69
|
-
|
|
72
|
+
const obj = this.getDecoratorObjectArg(decorator);
|
|
73
|
+
|
|
74
|
+
if (obj === undefined) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const name = this.getObjectStringProp(obj, 'name', useMap, currentFilePath, currentClass);
|
|
79
|
+
const description = this.getObjectStringProp(obj, 'description', useMap, currentFilePath, currentClass);
|
|
70
80
|
|
|
71
81
|
if (name === '' || description === '') {
|
|
72
82
|
return null;
|
|
@@ -79,17 +89,14 @@ export class CliRouteAttributeReader extends RouteAttributeReader implements Cli
|
|
|
79
89
|
useMap,
|
|
80
90
|
currentFilePath,
|
|
81
91
|
currentClass,
|
|
82
|
-
this.
|
|
83
|
-
this.extractClassListArgFromDecorator(decorator, 5, useMap, currentFilePath, currentClass),
|
|
84
|
-
this.extractClassListArgFromDecorator(decorator, 6, useMap, currentFilePath, currentClass),
|
|
85
|
-
this.extractClassListArgFromDecorator(decorator, 7, useMap, currentFilePath, currentClass),
|
|
92
|
+
this.getObjectClassListProp(obj, 'middleware', useMap, currentFilePath, currentClass),
|
|
86
93
|
);
|
|
87
94
|
|
|
88
95
|
return new CliRouteData(
|
|
89
96
|
updatedName,
|
|
90
97
|
description,
|
|
91
|
-
this.
|
|
92
|
-
null,
|
|
98
|
+
this.resolveHandler(obj, method, useMap, currentFilePath, currentClass),
|
|
99
|
+
this.getObjectHandlerProp(obj, 'helpText', useMap, currentFilePath, currentClass) ?? null,
|
|
93
100
|
routeMatchedMiddleware,
|
|
94
101
|
routeDispatchedMiddleware,
|
|
95
102
|
throwableCaughtMiddleware,
|
|
@@ -99,6 +106,22 @@ export class CliRouteAttributeReader extends RouteAttributeReader implements Cli
|
|
|
99
106
|
);
|
|
100
107
|
}
|
|
101
108
|
|
|
109
|
+
protected resolveHandler(
|
|
110
|
+
obj: ts.ObjectLiteralExpression,
|
|
111
|
+
method: MethodDeclaration,
|
|
112
|
+
useMap: Record<string, string>,
|
|
113
|
+
currentFilePath: string,
|
|
114
|
+
currentClass: string,
|
|
115
|
+
): HandlerData {
|
|
116
|
+
const fromObj = this.getObjectHandlerProp(obj, 'handler', useMap, currentFilePath, currentClass);
|
|
117
|
+
|
|
118
|
+
if (fromObj !== undefined) {
|
|
119
|
+
return fromObj;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return this.updateHandler(method, useMap, currentFilePath, currentClass);
|
|
123
|
+
}
|
|
124
|
+
|
|
102
125
|
protected updateName(
|
|
103
126
|
name: string,
|
|
104
127
|
method: MethodDeclaration,
|
|
@@ -127,14 +150,30 @@ export class CliRouteAttributeReader extends RouteAttributeReader implements Cli
|
|
|
127
150
|
useMap: Record<string, string>,
|
|
128
151
|
currentFilePath: string,
|
|
129
152
|
currentClass: string,
|
|
130
|
-
|
|
131
|
-
routeDispatchedMiddleware: string[],
|
|
132
|
-
throwableCaughtMiddleware: string[],
|
|
133
|
-
processExitingMiddleware: string[],
|
|
153
|
+
middleware: string[],
|
|
134
154
|
): [string[], string[], string[], string[]] {
|
|
155
|
+
let routeMatchedMiddleware: string[] = [];
|
|
156
|
+
let routeDispatchedMiddleware: string[] = [];
|
|
157
|
+
let throwableCaughtMiddleware: string[] = [];
|
|
158
|
+
let processExitingMiddleware: string[] = [];
|
|
159
|
+
|
|
160
|
+
for (const mwName of middleware) {
|
|
161
|
+
[routeMatchedMiddleware, routeDispatchedMiddleware, throwableCaughtMiddleware, processExitingMiddleware] =
|
|
162
|
+
this.classifyMiddleware(
|
|
163
|
+
mwName,
|
|
164
|
+
useMap,
|
|
165
|
+
currentFilePath,
|
|
166
|
+
routeMatchedMiddleware,
|
|
167
|
+
routeDispatchedMiddleware,
|
|
168
|
+
throwableCaughtMiddleware,
|
|
169
|
+
processExitingMiddleware,
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
135
173
|
for (const decorator of this.findDecoratorsOnNode(method, 'Middleware', useMap, currentFilePath)) {
|
|
174
|
+
// `@Middleware` takes a thunked class reference (`() => AuthMiddleware`).
|
|
136
175
|
const mwName = this.extractExprValue(
|
|
137
|
-
this.getDecoratorArg(decorator, 0),
|
|
176
|
+
this.unwrapClassThunk(this.getDecoratorArg(decorator, 0)),
|
|
138
177
|
useMap,
|
|
139
178
|
currentFilePath,
|
|
140
179
|
currentClass,
|
|
@@ -216,4 +255,50 @@ export class CliRouteAttributeReader extends RouteAttributeReader implements Cli
|
|
|
216
255
|
this.buildClassArrayExpr(data.processExitingMiddleware),
|
|
217
256
|
];
|
|
218
257
|
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Build the class-name → absolute-file-path map for every handler and
|
|
261
|
+
* help-text class the generated data cache references, so the generator can
|
|
262
|
+
* emit the matching import statements. (Middleware are emitted as string
|
|
263
|
+
* literals and therefore need no import.)
|
|
264
|
+
*/
|
|
265
|
+
protected buildImportMap(
|
|
266
|
+
routeData: Record<string, CliRouteData>,
|
|
267
|
+
useMap: Record<string, string>,
|
|
268
|
+
currentFilePath: string,
|
|
269
|
+
currentClass: string,
|
|
270
|
+
): Record<string, string> {
|
|
271
|
+
const importMap: Record<string, string> = {};
|
|
272
|
+
|
|
273
|
+
for (const data of Object.values(routeData)) {
|
|
274
|
+
if (data.handler !== null) {
|
|
275
|
+
this.addClassImport(importMap, data.handler.class, useMap, currentFilePath, currentClass);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (data.helpText !== null) {
|
|
279
|
+
this.addClassImport(importMap, data.helpText.class, useMap, currentFilePath, currentClass);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return importMap;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
protected addClassImport(
|
|
287
|
+
importMap: Record<string, string>,
|
|
288
|
+
className: string,
|
|
289
|
+
useMap: Record<string, string>,
|
|
290
|
+
currentFilePath: string,
|
|
291
|
+
currentClass: string,
|
|
292
|
+
): void {
|
|
293
|
+
const shortName = className.slice(className.lastIndexOf('\\') + 1);
|
|
294
|
+
|
|
295
|
+
const filePath =
|
|
296
|
+
shortName === currentClass
|
|
297
|
+
? currentFilePath
|
|
298
|
+
: this.resolveImportToFilePath(shortName, useMap, currentFilePath);
|
|
299
|
+
|
|
300
|
+
if (filePath !== '') {
|
|
301
|
+
importMap[shortName] = filePath;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
219
304
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* This file is part of the Sindri package.
|
|
3
3
|
*
|
|
4
|
-
* (c) Melech Mizrachi
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* file that was distributed with this source code.
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
8
7
|
*/
|
|
9
8
|
|
|
10
9
|
import { ts } from 'ts-morph';
|
|
@@ -28,7 +27,10 @@ export class CliRouteParameterReader extends AstReader implements CliRouteParame
|
|
|
28
27
|
buildParameterArgs(data: CliRouteData): ts.Expression[] {
|
|
29
28
|
const args: ts.Expression[] = [];
|
|
30
29
|
|
|
31
|
-
|
|
30
|
+
// The `arguments_` constructor parameter precedes `options`, so an empty
|
|
31
|
+
// arguments array must still be emitted whenever options are present, to
|
|
32
|
+
// keep `options` in its correct positional slot.
|
|
33
|
+
if (data.arguments.length > 0 || data.options.length > 0) {
|
|
32
34
|
args.push(this.buildArgumentListExpr(data.arguments));
|
|
33
35
|
}
|
|
34
36
|
|
|
@@ -83,8 +85,14 @@ export class CliRouteParameterReader extends AstReader implements CliRouteParame
|
|
|
83
85
|
currentFilePath: string,
|
|
84
86
|
currentClass: string,
|
|
85
87
|
): CliArgumentParameterData | null {
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
+
const obj = this.getDecoratorObjectArg(decorator);
|
|
89
|
+
|
|
90
|
+
if (obj === undefined) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const name = this.getObjectStringProp(obj, 'name', useMap, currentFilePath, currentClass);
|
|
95
|
+
const description = this.getObjectStringProp(obj, 'description', useMap, currentFilePath, currentClass);
|
|
88
96
|
|
|
89
97
|
if (name === '' || description === '') {
|
|
90
98
|
return null;
|
|
@@ -93,18 +101,18 @@ export class CliRouteParameterReader extends AstReader implements CliRouteParame
|
|
|
93
101
|
return new CliArgumentParameterData(
|
|
94
102
|
name,
|
|
95
103
|
description,
|
|
96
|
-
this.
|
|
97
|
-
this.
|
|
98
|
-
|
|
99
|
-
|
|
104
|
+
this.getObjectStringProp(obj, 'cast', useMap, currentFilePath, currentClass) || null,
|
|
105
|
+
this.getObjectStringProp(
|
|
106
|
+
obj,
|
|
107
|
+
'mode',
|
|
100
108
|
useMap,
|
|
101
109
|
currentFilePath,
|
|
102
110
|
currentClass,
|
|
103
111
|
'Valkyrja\\Cli\\Routing\\Enum\\ArgumentMode::OPTIONAL',
|
|
104
112
|
),
|
|
105
|
-
this.
|
|
106
|
-
|
|
107
|
-
|
|
113
|
+
this.getObjectStringProp(
|
|
114
|
+
obj,
|
|
115
|
+
'valueMode',
|
|
108
116
|
useMap,
|
|
109
117
|
currentFilePath,
|
|
110
118
|
currentClass,
|
|
@@ -119,8 +127,14 @@ export class CliRouteParameterReader extends AstReader implements CliRouteParame
|
|
|
119
127
|
currentFilePath: string,
|
|
120
128
|
currentClass: string,
|
|
121
129
|
): CliOptionParameterData | null {
|
|
122
|
-
const
|
|
123
|
-
|
|
130
|
+
const obj = this.getDecoratorObjectArg(decorator);
|
|
131
|
+
|
|
132
|
+
if (obj === undefined) {
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const name = this.getObjectStringProp(obj, 'name', useMap, currentFilePath, currentClass);
|
|
137
|
+
const description = this.getObjectStringProp(obj, 'description', useMap, currentFilePath, currentClass);
|
|
124
138
|
|
|
125
139
|
if (name === '' || description === '') {
|
|
126
140
|
return null;
|
|
@@ -129,22 +143,22 @@ export class CliRouteParameterReader extends AstReader implements CliRouteParame
|
|
|
129
143
|
return new CliOptionParameterData(
|
|
130
144
|
name,
|
|
131
145
|
description,
|
|
132
|
-
this.
|
|
133
|
-
this.
|
|
134
|
-
this.
|
|
135
|
-
this.
|
|
136
|
-
this.
|
|
137
|
-
this.
|
|
138
|
-
|
|
139
|
-
|
|
146
|
+
this.getObjectStringProp(obj, 'valueDisplayName', useMap, currentFilePath, currentClass),
|
|
147
|
+
this.getObjectStringProp(obj, 'cast', useMap, currentFilePath, currentClass) || null,
|
|
148
|
+
this.getObjectStringProp(obj, 'defaultValue', useMap, currentFilePath, currentClass),
|
|
149
|
+
this.getObjectStringListProp(obj, 'shortNames', useMap, currentFilePath, currentClass),
|
|
150
|
+
this.getObjectStringListProp(obj, 'validValues', useMap, currentFilePath, currentClass),
|
|
151
|
+
this.getObjectStringProp(
|
|
152
|
+
obj,
|
|
153
|
+
'mode',
|
|
140
154
|
useMap,
|
|
141
155
|
currentFilePath,
|
|
142
156
|
currentClass,
|
|
143
157
|
'Valkyrja\\Cli\\Routing\\Enum\\OptionMode::OPTIONAL',
|
|
144
158
|
),
|
|
145
|
-
this.
|
|
146
|
-
|
|
147
|
-
|
|
159
|
+
this.getObjectStringProp(
|
|
160
|
+
obj,
|
|
161
|
+
'valueMode',
|
|
148
162
|
useMap,
|
|
149
163
|
currentFilePath,
|
|
150
164
|
currentClass,
|
|
@@ -196,6 +210,10 @@ export class CliRouteParameterReader extends AstReader implements CliRouteParame
|
|
|
196
210
|
args.push(ts.factory.createArrayLiteralExpression([]));
|
|
197
211
|
}
|
|
198
212
|
|
|
213
|
+
// The framework `OptionParameter` constructor carries a runtime-populated
|
|
214
|
+
// `options` array between `validValues` and `mode`; emit an empty array so
|
|
215
|
+
// `mode`/`valueMode` land in their correct positional slots.
|
|
216
|
+
args.push(ts.factory.createArrayLiteralExpression([]));
|
|
199
217
|
args.push(this.buildEnumCaseExpr(data.mode));
|
|
200
218
|
args.push(this.buildEnumCaseExpr(data.valueMode));
|
|
201
219
|
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* This file is part of the Sindri package.
|
|
3
3
|
*
|
|
4
|
-
* (c) Melech Mizrachi
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* file that was distributed with this source code.
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
8
7
|
*/
|
|
9
8
|
|
|
10
9
|
import { AstReader } from './Abstract/AstReader.ts';
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* This file is part of the Sindri package.
|
|
3
3
|
*
|
|
4
|
-
* (c) Melech Mizrachi
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* file that was distributed with this source code.
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
8
7
|
*/
|
|
9
8
|
|
|
10
9
|
import * as path from 'path';
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* This file is part of the Sindri package.
|
|
3
3
|
*
|
|
4
|
-
* (c) Melech Mizrachi
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* file that was distributed with this source code.
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
8
7
|
*/
|
|
9
8
|
|
|
10
9
|
import { Node } from 'ts-morph';
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* This file is part of the Sindri package.
|
|
3
3
|
*
|
|
4
|
-
* (c) Melech Mizrachi
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* file that was distributed with this source code.
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
8
7
|
*/
|
|
9
8
|
|
|
10
9
|
import type { CliRouteAttributeResult } from '../Data/Result/CliRouteAttributeResult.ts';
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* This file is part of the Sindri package.
|
|
3
3
|
*
|
|
4
|
-
* (c) Melech Mizrachi
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* file that was distributed with this source code.
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
8
7
|
*/
|
|
9
8
|
|
|
10
9
|
import type { ts } from 'ts-morph';
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* This file is part of the Sindri package.
|
|
3
3
|
*
|
|
4
|
-
* (c) Melech Mizrachi
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* file that was distributed with this source code.
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
8
7
|
*/
|
|
9
8
|
|
|
10
9
|
import type { ComponentProviderResult } from '../Data/Result/ComponentProviderResult.ts';
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* This file is part of the Sindri package.
|
|
3
3
|
*
|
|
4
|
-
* (c) Melech Mizrachi
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* file that was distributed with this source code.
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
8
7
|
*/
|
|
9
8
|
|
|
10
9
|
import type { ConfigResult } from '../Data/Result/ConfigResult.ts';
|