@webpieces/nx-webpieces-rules 0.4.867 → 0.4.868
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/package.json +7 -7
- package/src/lib/runtime-wiring/prepared-targets.d.ts +4 -1
- package/src/lib/runtime-wiring/prepared-targets.js +6 -2
- package/src/lib/runtime-wiring/prepared-targets.js.map +1 -1
- package/src/lib/runtime-wiring/source-extractor.d.ts +12 -2
- package/src/lib/runtime-wiring/source-extractor.js +43 -26
- package/src/lib/runtime-wiring/source-extractor.js.map +1 -1
- package/src/lib/runtime-wiring/wiring-format.d.ts +28 -2
- package/src/lib/runtime-wiring/wiring-format.js +234 -37
- package/src/lib/runtime-wiring/wiring-format.js.map +1 -1
- package/src/lib/runtime-wiring/workspace-format.js +1 -1
- package/src/lib/runtime-wiring/workspace-format.js.map +1 -1
- package/src/rule-help.js +1 -1
- package/src/rule-help.js.map +1 -1
- package/src/rule-settings.js +1 -1
- package/src/rule-settings.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webpieces/nx-webpieces-rules",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.868",
|
|
4
4
|
"description": "Nx-specific webpieces validation rules, graph tooling, executors, and inference plugin.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -20,12 +20,12 @@
|
|
|
20
20
|
"README.md"
|
|
21
21
|
],
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@webpieces/api-doc-model": "0.4.
|
|
24
|
-
"@webpieces/core-util": "0.4.
|
|
25
|
-
"@webpieces/eslint-rules": "0.4.
|
|
26
|
-
"@webpieces/rules-config": "0.4.
|
|
23
|
+
"@webpieces/api-doc-model": "0.4.868",
|
|
24
|
+
"@webpieces/core-util": "0.4.868",
|
|
25
|
+
"@webpieces/eslint-rules": "0.4.868",
|
|
26
|
+
"@webpieces/rules-config": "0.4.868",
|
|
27
27
|
"madge": "8.0.0",
|
|
28
|
-
"@webpieces/rules-sdk": "0.4.
|
|
28
|
+
"@webpieces/rules-sdk": "0.4.868"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
31
|
"@nx/devkit": ">=18.0.0"
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"access": "public"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@webpieces/tooling-testkit": "0.4.
|
|
44
|
+
"@webpieces/tooling-testkit": "0.4.868"
|
|
45
45
|
},
|
|
46
46
|
"types": "./src/index.d.ts",
|
|
47
47
|
"bin": {
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import * as ts from 'typescript';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Infer graph-relevant constructor paths from destination uses and selected named modules. Only
|
|
4
|
+
* classes declared in a canonical src/wiring.ts are walked.
|
|
5
|
+
*/
|
|
3
6
|
export declare class PreparedTargets {
|
|
4
7
|
private readonly checker;
|
|
5
8
|
private readonly types;
|
|
@@ -4,7 +4,10 @@ exports.PreparedTargets = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const ts = tslib_1.__importStar(require("typescript"));
|
|
6
6
|
const source_types_1 = require("./source-types");
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* Infer graph-relevant constructor paths from destination uses and selected named modules. Only
|
|
9
|
+
* classes declared in a canonical src/wiring.ts are walked.
|
|
10
|
+
*/
|
|
8
11
|
class PreparedTargets {
|
|
9
12
|
checker;
|
|
10
13
|
types;
|
|
@@ -29,7 +32,8 @@ class PreparedTargets {
|
|
|
29
32
|
return parent === undefined ? undefined : `${parent}.${expression.name.text}`;
|
|
30
33
|
}
|
|
31
34
|
collect(declaration, active, channel) {
|
|
32
|
-
|
|
35
|
+
// Only canonical wiring declarations carry graph-relevant paths; another file's body is never read.
|
|
36
|
+
if (active.has(declaration) || !/(?:^|[\\/])src[\\/]wiring\.ts$/.test(declaration.getSourceFile().fileName))
|
|
33
37
|
return [];
|
|
34
38
|
const next = new Set([...active, declaration]);
|
|
35
39
|
const parameters = declaration.members.filter(ts.isConstructorDeclaration).flatMap((constructor) => constructor.parameters.map((parameter) => parameter.name.getText()));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepared-targets.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/prepared-targets.ts"],"names":[],"mappings":";;;;AAAA,uDAAiC;AACjC,iDAAmD;AAEnD
|
|
1
|
+
{"version":3,"file":"prepared-targets.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/prepared-targets.ts"],"names":[],"mappings":";;;;AAAA,uDAAiC;AACjC,iDAAmD;AAEnD;;;GAGG;AACH,MAAa,eAAe;IAGK;IAFZ,KAAK,CAAoB;IAE1C,YAA6B,OAAuB;QAAvB,YAAO,GAAP,OAAO,CAAgB;QAChD,IAAI,CAAC,KAAK,GAAG,IAAI,gCAAiB,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,UAAgD,EAAE,OAA4B;QAChF,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,UAAU,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC;QACvF,IAAI,WAAW,KAAK,SAAS,IAAI,CAAC,EAAE,CAAC,kBAAkB,CAAC,WAAW,CAAC;YAAE,OAAO,EAAE,CAAC;QAChF,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,GAAG,EAAuB,EAAE,OAAO,CAAC,CAAC;IAC9E,CAAC;IAED,IAAI,CAAC,UAAyB;QAC1B,IAAI,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC;YAAE,OAAO,UAAU,CAAC,IAAI,CAAC;QACxD,IAAI,CAAC,EAAE,CAAC,0BAA0B,CAAC,UAAU,CAAC;YAAE,OAAO,SAAS,CAAC;QACjE,IAAI,UAAU,CAAC,UAAU,CAAC,IAAI,KAAK,EAAE,CAAC,UAAU,CAAC,WAAW;YAAE,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;QAC1F,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAChD,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAClF,CAAC;IAEO,OAAO,CAAC,WAAgC,EAAE,MAAgC,EAAE,OAA4B;QAC5G,oGAAoG;QACpG,IAAI,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,gCAAgC,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,EAAE,CAAC,QAAQ,CAAC;YAAE,OAAO,EAAE,CAAC;QACvH,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;QAC/C,MAAM,UAAU,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,OAAO,CAC9E,CAAC,WAAsC,EAAE,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,CAClE,CAAC,SAAkC,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,CACnE,CACJ,CAAC;QACF,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;QAChC,MAAM,MAAM,GAAG,CAAC,IAAwB,EAAQ,EAAE;YAC9C,IAAI,IAAI,KAAK,SAAS,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACvF,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,CAAC,IAAa,EAAQ,EAAE;YAClC,IAAI,OAAO,KAAK,QAAQ,IAAI,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS;gBAC3F,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YACvC,IAAI,OAAO,KAAK,QAAQ,IAAI,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC7E,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;gBACjC,IAAI,MAAM,KAAK,SAAS;oBAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YACxD,CAAC;YACD,IAAI,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,SAAS,EAAE,CAAC;gBAC7E,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBACtD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;gBAC1D,IAAI,KAAK,KAAK,SAAS,IAAI,EAAE,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;oBACtD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;wBACpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;wBAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;wBACtB,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;wBAC9B,MAAM,KAAK,GAAG,SAAS,EAAE,aAAa,EAAE,CAAC,SAAS,CAAC,CAAC,SAAoB,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;wBAC5G,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC;wBACzC,IAAI,QAAQ,KAAK,SAAS;4BAAE,SAAS;wBACrC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;wBACnC,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;oBAC7E,CAAC;gBACL,CAAC;YACL,CAAC;YACD,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACjC,CAAC,CAAC;QACF,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;QACpC,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7B,CAAC;IAEO,UAAU,CAAC,IAAuB;QACtC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC;QACvE,IAAI,SAAS,KAAK,SAAS,IAAI,CAAC,CAAC,EAAE,CAAC,mBAAmB,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QAC1H,MAAM,IAAI,GAAG,SAAS,CAAC,aAAa,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACpE,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC;QACvC,OAAO,IAAI,KAAK,SAAS,IAAI,CAAC,SAAS,EAAE,YAAY,EAAE,kBAAkB,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;YACrF,2HAA2H,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/I,CAAC;CACJ;AAvED,0CAuEC","sourcesContent":["import * as ts from 'typescript';\nimport { WiringSourceTypes } from './source-types';\n\n/**\n * Infer graph-relevant constructor paths from destination uses and selected named modules. Only\n * classes declared in a canonical src/wiring.ts are walked.\n */\nexport class PreparedTargets {\n private readonly types: WiringSourceTypes;\n\n constructor(private readonly checker: ts.TypeChecker) {\n this.types = new WiringSourceTypes(checker);\n }\n\n paths(invocation: ts.NewExpression | ts.CallExpression, channel: 'target' | 'policy'): string[] {\n const declaration = this.checker.getResolvedSignature(invocation)?.declaration?.parent;\n if (declaration === undefined || !ts.isClassDeclaration(declaration)) return [];\n return this.collect(declaration, new Set<ts.ClassDeclaration>(), channel);\n }\n\n path(expression: ts.Expression): string | undefined {\n if (ts.isIdentifier(expression)) return expression.text;\n if (!ts.isPropertyAccessExpression(expression)) return undefined;\n if (expression.expression.kind === ts.SyntaxKind.ThisKeyword) return expression.name.text;\n const parent = this.path(expression.expression);\n return parent === undefined ? undefined : `${parent}.${expression.name.text}`;\n }\n\n private collect(declaration: ts.ClassDeclaration, active: Set<ts.ClassDeclaration>, channel: 'target' | 'policy'): string[] {\n // Only canonical wiring declarations carry graph-relevant paths; another file's body is never read.\n if (active.has(declaration) || !/(?:^|[\\\\/])src[\\\\/]wiring\\.ts$/.test(declaration.getSourceFile().fileName)) return [];\n const next = new Set([...active, declaration]);\n const parameters = declaration.members.filter(ts.isConstructorDeclaration).flatMap(\n (constructor: ts.ConstructorDeclaration) => constructor.parameters.map(\n (parameter: ts.ParameterDeclaration) => parameter.name.getText(),\n ),\n );\n const paths = new Set<string>();\n const retain = (path: string | undefined): void => {\n if (path !== undefined && parameters.includes(path.split('.')[0])) paths.add(path);\n };\n const visit = (node: ts.Node): void => {\n if (channel === 'policy' && ts.isPropertyAccessExpression(node) && node.name.text === 'enabled')\n retain(this.path(node.expression));\n if (channel === 'target' && ts.isCallExpression(node) && this.clientCall(node)) {\n const target = node.arguments[2];\n if (target !== undefined) retain(this.path(target));\n }\n if (ts.isNewExpression(node) && this.types.kind(node.expression) !== undefined) {\n const child = this.types.declaration(node.expression);\n const signature = this.checker.getResolvedSignature(node);\n if (child !== undefined && ts.isClassDeclaration(child)) {\n for (const path of this.collect(child, next, channel)) {\n const parts = path.split('.');\n const name = parts[0];\n const suffix = parts.slice(1);\n const index = signature?.getParameters().findIndex((parameter: ts.Symbol) => parameter.name === name) ?? -1;\n const argument = node.arguments?.[index];\n if (argument === undefined) continue;\n const parent = this.path(argument);\n retain(parent === undefined ? undefined : [parent, ...suffix].join('.'));\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n ts.forEachChild(declaration, visit);\n return [...paths].sort();\n }\n\n private clientCall(call: ts.CallExpression): boolean {\n const signature = this.checker.getResolvedSignature(call)?.declaration;\n if (signature === undefined || (!ts.isMethodDeclaration(signature) && !ts.isFunctionDeclaration(signature))) return false;\n const file = signature.getSourceFile().fileName.replace(/\\\\/g, '/');\n const name = signature.name?.getText();\n return name !== undefined && ['bindRpc', 'bindPubSub', 'provideRpcClient'].includes(name) &&\n /(?:\\/packages\\/(?:http|cloud)\\/|\\/node_modules\\/@webpieces\\/)(?:http-client-node|http-client-browser|cloudtasks-client)\\//.test(file);\n }\n}\n"]}
|
|
@@ -11,16 +11,26 @@ export declare class WiringSourceExtractor {
|
|
|
11
11
|
private entry;
|
|
12
12
|
private host;
|
|
13
13
|
constructor(workspaceRoot: string, info: ProjectInfo, infos: ReadonlyMap<string, ProjectInfo>, program: ts.Program);
|
|
14
|
+
/**
|
|
15
|
+
* Reads ONLY the owner's canonical src/wiring.ts. The program still type-checks every file so
|
|
16
|
+
* imports, aliases and re-exports resolve, but no other file's body is visited for wiring facts:
|
|
17
|
+
* a module declared elsewhere can neither add a relationship nor be discovered as a fallback.
|
|
18
|
+
*/
|
|
14
19
|
extract(): RuntimeDeclaration;
|
|
15
|
-
private visit;
|
|
16
20
|
private facts;
|
|
17
21
|
private recordExternal;
|
|
18
22
|
private recordRelationship;
|
|
19
23
|
private frameworkCall;
|
|
20
24
|
private recordWiring;
|
|
21
25
|
private moduleSelections;
|
|
26
|
+
/**
|
|
27
|
+
* A selected module must be declared in THIS wiring.ts, and a selected library Wiring in its own
|
|
28
|
+
* owner's src/wiring.ts. Proven by the resolved declaration, never by a name, and checked before
|
|
29
|
+
* any argument analysis, so an off-file module body is never read.
|
|
30
|
+
*/
|
|
31
|
+
private assertCanonicalDeclaration;
|
|
22
32
|
private exportOwner;
|
|
23
|
-
private
|
|
33
|
+
private get wiringPath();
|
|
24
34
|
private fail;
|
|
25
35
|
}
|
|
26
36
|
/** Factory kept separate so graph assembly cannot accidentally create a compiler. */
|
|
@@ -33,18 +33,18 @@ class WiringSourceExtractor {
|
|
|
33
33
|
this.program = program;
|
|
34
34
|
this.values = new source_values_1.WiringSourceValues(workspaceRoot, infos, program.getTypeChecker());
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Reads ONLY the owner's canonical src/wiring.ts. The program still type-checks every file so
|
|
38
|
+
* imports, aliases and re-exports resolve, but no other file's body is visited for wiring facts:
|
|
39
|
+
* a module declared elsewhere can neither add a relationship nor be discovered as a fallback.
|
|
40
|
+
*/
|
|
36
41
|
extract() {
|
|
37
|
-
const
|
|
38
|
-
const wiring = this.program.getSourceFile(wiringPath);
|
|
42
|
+
const wiring = this.program.getSourceFile(this.wiringPath);
|
|
39
43
|
if (wiring === undefined)
|
|
40
|
-
this.fail(`Missing canonical ${wiringPath}.`);
|
|
41
|
-
for (const
|
|
42
|
-
if (
|
|
43
|
-
|
|
44
|
-
/(?:\.spec\.|\.test\.|\/__tests__\/)/.test(file.fileName))
|
|
45
|
-
continue;
|
|
46
|
-
this.visit(file, file.fileName === wiringPath);
|
|
47
|
-
}
|
|
44
|
+
this.fail(`Missing canonical ${this.wiringPath}.`);
|
|
45
|
+
for (const statement of wiring.statements)
|
|
46
|
+
if (ts.isClassDeclaration(statement))
|
|
47
|
+
this.recordWiring(statement);
|
|
48
48
|
const framework = this.info.tags.includes('framework:angular')
|
|
49
49
|
? 'angular'
|
|
50
50
|
: this.info.tags.some((tag) => tag === 'framework:node' || tag === 'framework:express')
|
|
@@ -54,11 +54,6 @@ class WiringSourceExtractor {
|
|
|
54
54
|
this.fail(`${this.info.name} requires one unambiguous exported AppWiring in src/wiring.ts.`);
|
|
55
55
|
return new declaration_1.RuntimeDeclaration(this.info.name, framework, this.exported, this.entry, this.host);
|
|
56
56
|
}
|
|
57
|
-
visit(node, inWiring) {
|
|
58
|
-
if (ts.isClassDeclaration(node))
|
|
59
|
-
this.recordWiring(node, inWiring);
|
|
60
|
-
ts.forEachChild(node, (child) => this.visit(child, inWiring));
|
|
61
|
-
}
|
|
62
57
|
facts(node, owner) {
|
|
63
58
|
if (ts.isNewExpression(node) && new source_types_1.WiringSourceTypes(this.program.getTypeChecker()).isFramework(node.expression, 'ExternalContractUse'))
|
|
64
59
|
this.recordExternal(node, owner);
|
|
@@ -121,7 +116,7 @@ class WiringSourceExtractor {
|
|
|
121
116
|
const file = declaration.getSourceFile().fileName.replace(/\\/g, '/');
|
|
122
117
|
return /(?:\/packages\/(?:http|cloud)\/|\/node_modules\/@webpieces\/)(?:http-routing|http-client-node|http-client-browser|cloudtasks-client)\//.test(file);
|
|
123
118
|
}
|
|
124
|
-
recordWiring(declaration
|
|
119
|
+
recordWiring(declaration) {
|
|
125
120
|
const types = new source_types_1.WiringSourceTypes(this.program.getTypeChecker());
|
|
126
121
|
const kind = types.kind(declaration);
|
|
127
122
|
const owner = this.exportOwner(declaration);
|
|
@@ -132,14 +127,14 @@ class WiringSourceExtractor {
|
|
|
132
127
|
const configure = types.method(declaration, 'configure');
|
|
133
128
|
if (configure === undefined || configure.body === undefined)
|
|
134
129
|
this.fail(`${owner}: named module requires a statically resolvable configure implementation.`);
|
|
130
|
+
if (path.resolve(configure.getSourceFile().fileName) !== this.wiringPath)
|
|
131
|
+
this.fail(`${owner}: configure is inherited from ${configure.getSourceFile().fileName}; declare its registrations in ${owner}.configure in ${this.wiringPath}.`);
|
|
135
132
|
this.facts(configure.body, owner);
|
|
136
133
|
return;
|
|
137
134
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const
|
|
141
|
-
const routes = this.moduleSelections(types.method(declaration, 'getRoutingModules'), 'routing');
|
|
142
|
-
const libraries = kind === 'app' ? this.moduleSelections(types.method(declaration, 'getWirings'), 'wiring') : [];
|
|
135
|
+
const bindings = this.moduleSelections(owner, types.method(declaration, 'getBindingModules'), 'binding');
|
|
136
|
+
const routes = this.moduleSelections(owner, types.method(declaration, 'getRoutingModules'), 'routing');
|
|
137
|
+
const libraries = kind === 'app' ? this.moduleSelections(owner, types.method(declaration, 'getWirings'), 'wiring') : [];
|
|
143
138
|
if (kind === 'wiring' && types.method(declaration, 'getWirings') !== undefined)
|
|
144
139
|
this.fail(`${owner}: library Wiring cannot select other Wirings.`);
|
|
145
140
|
this.exported[owner] = new declaration_1.WiringExport(kind, [], bindings, routes, libraries);
|
|
@@ -156,7 +151,9 @@ class WiringSourceExtractor {
|
|
|
156
151
|
this.host = project.metadata?.webpieces?.serviceName;
|
|
157
152
|
}
|
|
158
153
|
}
|
|
159
|
-
moduleSelections(method, expected) {
|
|
154
|
+
moduleSelections(owner, method, expected) {
|
|
155
|
+
if (method !== undefined && path.resolve(method.getSourceFile().fileName) !== this.wiringPath)
|
|
156
|
+
this.fail(`${owner}: its selection getter is declared in ${method.getSourceFile().fileName}; declare getBindingModules/getRoutingModules/getWirings on ${owner} itself in ${this.wiringPath}.`);
|
|
160
157
|
const statements = method?.body?.statements;
|
|
161
158
|
const expression = statements?.length === 1 && ts.isReturnStatement(statements[0]) ? statements[0].expression : undefined;
|
|
162
159
|
if (expression === undefined || !ts.isArrayLiteralExpression(expression))
|
|
@@ -166,9 +163,30 @@ class WiringSourceExtractor {
|
|
|
166
163
|
if (!ts.isNewExpression(element) || types.kind(element.expression) !== expected)
|
|
167
164
|
this.fail(`Wrong ${expected} selection ${element.getText()}; AppWiring children, delegation and nested lists are forbidden.`);
|
|
168
165
|
const identity = this.values.identity(element.expression);
|
|
166
|
+
this.assertCanonicalDeclaration(owner, element.expression, identity, expected);
|
|
169
167
|
return new declaration_1.WiringSelection(identity.project, identity.exportedName, this.values.arguments(element), this.values.policies(element));
|
|
170
168
|
});
|
|
171
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* A selected module must be declared in THIS wiring.ts, and a selected library Wiring in its own
|
|
172
|
+
* owner's src/wiring.ts. Proven by the resolved declaration, never by a name, and checked before
|
|
173
|
+
* any argument analysis, so an off-file module body is never read.
|
|
174
|
+
*/
|
|
175
|
+
assertCanonicalDeclaration(owner, selected, identity, expected) {
|
|
176
|
+
const declaration = new source_types_1.WiringSourceTypes(this.program.getTypeChecker()).declaration(selected);
|
|
177
|
+
const declaredIn = declaration === undefined ? 'an unresolved file' : path.resolve(declaration.getSourceFile().fileName);
|
|
178
|
+
if (expected !== 'wiring') {
|
|
179
|
+
if (declaredIn === this.wiringPath)
|
|
180
|
+
return;
|
|
181
|
+
const role = expected === 'binding' ? 'BindingModule' : 'RouteModule';
|
|
182
|
+
this.fail(`${owner} selects ${identity.exportedName}, which is declared in ${declaredIn}. Declare the ${role} class ${identity.exportedName}, with its registrations, beside ${owner} in ${this.wiringPath}.`);
|
|
183
|
+
}
|
|
184
|
+
const library = this.infos.get(identity.project);
|
|
185
|
+
const canonical = library === undefined ? undefined : path.resolve(this.workspaceRoot, library.root, 'src/wiring.ts');
|
|
186
|
+
if (canonical !== undefined && declaredIn === canonical)
|
|
187
|
+
return;
|
|
188
|
+
this.fail(`${owner} selects library Wiring ${identity.project}#${identity.exportedName}, which is declared in ${declaredIn}. A library Wiring and its modules belong in that library's canonical ${canonical ?? 'src/wiring.ts'}.`);
|
|
189
|
+
}
|
|
172
190
|
exportOwner(node) {
|
|
173
191
|
let current = node;
|
|
174
192
|
while (current !== undefined) {
|
|
@@ -190,13 +208,12 @@ class WiringSourceExtractor {
|
|
|
190
208
|
}
|
|
191
209
|
return undefined;
|
|
192
210
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
return path.resolve(file).startsWith(root) && !file.includes('/node_modules/');
|
|
211
|
+
get wiringPath() {
|
|
212
|
+
return path.resolve(this.workspaceRoot, this.info.root, 'src/wiring.ts');
|
|
196
213
|
}
|
|
197
214
|
fail(message) {
|
|
198
215
|
throw new rules_config_1.RuleFailError('validate-runtime-architecture', message, undefined, undefined, [
|
|
199
|
-
new rules_config_1.Option('
|
|
216
|
+
new rules_config_1.Option('Declare each owner\'s Wiring/AppWiring class AND its BindingModule/RouteModule classes, with their registrations (RuntimeClients.bindRpc(token, Api, deployment), RuntimeTaskClients.bindPubSub, provideRpcClient, addRoutes, addFilter, DI binds), together in that owner\'s canonical src/wiring.ts, and use the documented getter grammar; extraction reads only wiring.ts and never executes configuration.', true),
|
|
200
217
|
]);
|
|
201
218
|
}
|
|
202
219
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-extractor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/source-extractor.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport * as ts from 'typescript';\nimport { Option, RuleFailError } from '@webpieces/rules-config';\nimport type { ProjectInfo } from '../project-info';\nimport { createProjectProgram } from '../di-graph/program';\nimport {\n ContractIdentity,\n ImplementsFacts,\n UsesFacts,\n RuntimeDeclaration,\n WiringExport,\n WiringRelationship,\n WiringSelection,\n} from './declaration';\nimport { WiringSourceValues } from './source-values';\nimport { WiringSourceTypes } from './source-types';\nimport * as fs from 'fs';\n\n/** Build-only extraction. It never imports application modules or invokes their constructors. */\nclass WiringProjectMetadata {\n declare metadata?: WiringProjectMetadataValues;\n}\nclass WiringProjectMetadataValues {\n declare webpieces?: WiringServiceMetadata;\n}\nclass WiringServiceMetadata {\n declare serviceName?: string;\n}\n\nexport class WiringSourceExtractor {\n private readonly values: WiringSourceValues;\n private readonly exported: Record<string, WiringExport> = {};\n private entry: string | undefined;\n private host: string | undefined;\n\n constructor(\n private readonly workspaceRoot: string,\n private readonly info: ProjectInfo,\n private readonly infos: ReadonlyMap<string, ProjectInfo>,\n private readonly program: ts.Program,\n ) {\n this.values = new WiringSourceValues(workspaceRoot, infos, program.getTypeChecker());\n }\n\n extract(): RuntimeDeclaration {\n const wiringPath = path.resolve(this.workspaceRoot, this.info.root, 'src/wiring.ts');\n const wiring = this.program.getSourceFile(wiringPath);\n if (wiring === undefined) this.fail(`Missing canonical ${wiringPath}.`);\n for (const file of this.program.getSourceFiles()) {\n if (\n file.isDeclarationFile ||\n !this.owns(file.fileName) ||\n /(?:\\.spec\\.|\\.test\\.|\\/__tests__\\/)/.test(file.fileName)\n )\n continue;\n this.visit(file, file.fileName === wiringPath);\n }\n const framework = this.info.tags.includes('framework:angular')\n ? 'angular'\n : this.info.tags.some((tag) => tag === 'framework:node' || tag === 'framework:express')\n ? 'node'\n : 'browser';\n if (this.info.tags.includes('webpieces') && this.entry === undefined)\n this.fail(`${this.info.name} requires one unambiguous exported AppWiring in src/wiring.ts.`);\n return new RuntimeDeclaration(\n this.info.name,\n framework,\n this.exported,\n this.entry,\n this.host,\n );\n }\n\n private visit(node: ts.Node, inWiring: boolean): void {\n if (ts.isClassDeclaration(node)) this.recordWiring(node, inWiring);\n ts.forEachChild(node, (child: ts.Node) => this.visit(child, inWiring));\n }\n\n private facts(node: ts.Node, owner: string): void {\n if (ts.isNewExpression(node) && new WiringSourceTypes(this.program.getTypeChecker()).isFramework(node.expression, 'ExternalContractUse'))\n this.recordExternal(node, owner);\n if (ts.isCallExpression(node) && this.frameworkCall(node)) {\n const name = this.values.symbolName(node.expression);\n if (['addRoutes', 'createRpcClient', 'createPubSubClient', 'bindRpc', 'bindPubSub', 'provideRpcClient'].includes(name))\n this.recordRelationship(node, name, owner);\n }\n ts.forEachChild(node, (child: ts.Node) => this.facts(child, owner));\n }\n\n private recordExternal(expression: ts.NewExpression, owner: string): void {\n const identity = expression.arguments?.[0];\n if (identity === undefined || !ts.isStringLiteralLike(identity))\n this.fail(\n 'ExternalContractUse belongs to a selected exported module and requires a literal project#contract identity.',\n );\n const qualified = (identity as ts.StringLiteralLike).text.split('#');\n const project = qualified[0];\n const exportedName = qualified[1];\n const extra = qualified[2];\n if (!project || !exportedName || extra !== undefined)\n this.fail('ExternalContractUse requires one qualified project#contract identity.');\n if (!this.values.hasExternalConsumer(this.info.name, project, exportedName, this.program))\n this.fail(\n `${project}#${exportedName} has no production business consumer in ${this.info.name}; adapters and test doubles do not establish uses.`,\n );\n const exported = this.exported[owner];\n exported.relationships.push(\n new WiringRelationship(\n new ContractIdentity(project, exportedName),\n new UsesFacts('external', {\n kind: 'unknown',\n reason: 'Vendor interface; destination classified by approved contract metadata',\n }),\n ),\n );\n this.exported[owner] = exported;\n }\n\n private recordRelationship(call: ts.CallExpression, method: string, owner: string): void {\n const apiIndex =\n method === 'bindRpc' || method === 'bindPubSub' || method === 'provideRpcClient'\n ? 1\n : 0;\n const api = call.arguments[apiIndex];\n if (api === undefined) this.fail(`${method} requires an explicit API contract.`);\n const contract = this.values.identity(api!);\n const direction = method === 'addRoutes' ? 'implements' : 'uses';\n const contractTransport = this.values.transport(api!);\n const transport =\n method === 'addRoutes'\n ? contractTransport\n : method === 'bindPubSub' || method === 'createPubSubClient'\n ? 'pubsub'\n : 'rpc';\n if (transport !== contractTransport)\n this.fail(\n `${method} transport disagrees with ${contract.project}#${contract.exportedName}.`,\n );\n const target =\n direction === 'implements'\n ? undefined\n : this.values.target(call.arguments[apiIndex + 1]);\n const exported = this.exported[owner];\n exported.relationships.push(\n new WiringRelationship(\n contract,\n direction === 'implements'\n ? new ImplementsFacts(transport, this.values.condition(call))\n : new UsesFacts(transport, target!, this.values.condition(call)),\n ),\n );\n this.exported[owner] = exported;\n }\n\n private frameworkCall(call: ts.CallExpression): boolean {\n const declaration = this.program.getTypeChecker().getResolvedSignature(call)?.declaration;\n if (declaration === undefined) return false;\n const file = declaration.getSourceFile().fileName.replace(/\\\\/g, '/');\n return /(?:\\/packages\\/(?:http|cloud)\\/|\\/node_modules\\/@webpieces\\/)(?:http-routing|http-client-node|http-client-browser|cloudtasks-client)\\//.test(file);\n }\n\n private recordWiring(declaration: ts.ClassDeclaration, inWiring: boolean): void {\n const types = new WiringSourceTypes(this.program.getTypeChecker());\n const kind = types.kind(declaration);\n const owner = this.exportOwner(declaration);\n if (kind === undefined || owner === undefined) return;\n if (kind === 'binding' || kind === 'routing') {\n this.exported[owner] = new WiringExport(kind, [], []);\n const configure = types.method(declaration, 'configure');\n if (configure === undefined || configure.body === undefined)\n this.fail(`${owner}: named module requires a statically resolvable configure implementation.`);\n this.facts(configure!.body!, owner);\n return;\n }\n if (!inWiring) this.fail(`${owner}: declare Wiring/AppWiring only in canonical src/wiring.ts.`);\n const bindings = this.moduleSelections(types.method(declaration, 'getBindingModules'), 'binding');\n const routes = this.moduleSelections(types.method(declaration, 'getRoutingModules'), 'routing');\n const libraries = kind === 'app' ? this.moduleSelections(types.method(declaration, 'getWirings'), 'wiring') : [];\n if (kind === 'wiring' && types.method(declaration, 'getWirings') !== undefined)\n this.fail(`${owner}: library Wiring cannot select other Wirings.`);\n this.exported[owner] = new WiringExport(kind, [], bindings, routes, libraries);\n if (kind !== 'app') return;\n if (!this.info.tags.includes('webpieces'))\n this.fail(`${owner}: library owners cannot declare an AppWiring entry.`);\n if (this.entry !== undefined) this.fail('Ambiguous AppWiring root; export exactly one application entry.');\n this.entry = owner;\n const projectFile = path.join(this.workspaceRoot, this.info.root, 'project.json');\n if (fs.existsSync(projectFile)) {\n const project = JSON.parse(fs.readFileSync(projectFile, 'utf8')) as WiringProjectMetadata;\n this.host = project.metadata?.webpieces?.serviceName;\n }\n }\n\n private moduleSelections(method: ts.MethodDeclaration | undefined, expected: 'binding' | 'routing' | 'wiring'): WiringSelection[] {\n const statements = method?.body?.statements;\n const expression = statements?.length === 1 && ts.isReturnStatement(statements[0]) ? statements[0].expression : undefined;\n if (expression === undefined || !ts.isArrayLiteralExpression(expression))\n this.fail(`Expected ${expected} getter to contain only return [new NamedModule(preparedInputs)].`);\n const types = new WiringSourceTypes(this.program.getTypeChecker());\n return expression.elements.map((element: ts.Expression) => {\n if (!ts.isNewExpression(element) || types.kind(element.expression) !== expected)\n this.fail(`Wrong ${expected} selection ${element.getText()}; AppWiring children, delegation and nested lists are forbidden.`);\n const identity = this.values.identity(element.expression);\n return new WiringSelection(identity.project, identity.exportedName, this.values.arguments(element), this.values.policies(element));\n });\n }\n\n private exportOwner(node: ts.Node): string | undefined {\n let current: ts.Node | undefined = node;\n while (current !== undefined) {\n if (\n ts.isClassDeclaration(current) &&\n current.name !== undefined &&\n (ts.getModifiers(current) ?? []).some(\n (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword,\n )\n )\n return current.name.text;\n if (\n ts.isFunctionDeclaration(current) &&\n current.name !== undefined &&\n (ts.getModifiers(current) ?? []).some(\n (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword,\n )\n )\n return current.name.text;\n if (ts.isVariableDeclaration(current) && ts.isIdentifier(current.name)) {\n const statement = current.parent.parent;\n if (\n ts.isVariableStatement(statement) &&\n (ts.getModifiers(statement) ?? []).some(\n (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword,\n )\n )\n return current.name.text;\n }\n current = current.parent;\n }\n return undefined;\n }\n\n private owns(file: string): boolean {\n const root = path.resolve(this.workspaceRoot, this.info.root) + path.sep;\n return path.resolve(file).startsWith(root) && !file.includes('/node_modules/');\n }\n\n private fail(message: string): never {\n throw new RuleFailError('validate-runtime-architecture', message, undefined, undefined, [\n new Option(\n 'Move topology into canonical src/wiring.ts using RuntimeClients.bindRpc(token, Api, deployment), RuntimeTaskClients.bindPubSub, or provideRpcClient for supported registrations, and use the documented Wiring/AppWiring getter grammar; do not execute configuration to extract it.',\n true,\n ),\n ]);\n }\n}\n\n/** Factory kept separate so graph assembly cannot accidentally create a compiler. */\nexport class WiringProjectProgram {\n create(workspaceRoot: string, info: ProjectInfo): ts.Program {\n const root = path.resolve(workspaceRoot, info.root);\n const configured = createProjectProgram(root);\n if (configured !== null) return configured;\n const config = ts.findConfigFile(root, ts.sys.fileExists, 'tsconfig.json');\n const parsed =\n config === undefined ? undefined : ts.readConfigFile(config, ts.sys.readFile);\n const options =\n parsed === undefined\n ? {}\n : ts.parseJsonConfigFileContent(parsed.config, ts.sys, root).options;\n const files = ts.sys.readDirectory(\n path.join(root, 'src'),\n ['.ts'],\n ['**/*.spec.ts', '**/*.test.ts'],\n );\n return ts.createProgram(files, options);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"source-extractor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/source-extractor.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport * as ts from 'typescript';\nimport { Option, RuleFailError } from '@webpieces/rules-config';\nimport type { ProjectInfo } from '../project-info';\nimport { createProjectProgram } from '../di-graph/program';\nimport {\n ContractIdentity,\n ImplementsFacts,\n UsesFacts,\n RuntimeDeclaration,\n WiringExport,\n WiringRelationship,\n WiringSelection,\n} from './declaration';\nimport { WiringSourceValues } from './source-values';\nimport { WiringSourceTypes } from './source-types';\nimport * as fs from 'fs';\n\n/** Build-only extraction. It never imports application modules or invokes their constructors. */\nclass WiringProjectMetadata {\n declare metadata?: WiringProjectMetadataValues;\n}\nclass WiringProjectMetadataValues {\n declare webpieces?: WiringServiceMetadata;\n}\nclass WiringServiceMetadata {\n declare serviceName?: string;\n}\n\nexport class WiringSourceExtractor {\n private readonly values: WiringSourceValues;\n private readonly exported: Record<string, WiringExport> = {};\n private entry: string | undefined;\n private host: string | undefined;\n\n constructor(\n private readonly workspaceRoot: string,\n private readonly info: ProjectInfo,\n private readonly infos: ReadonlyMap<string, ProjectInfo>,\n private readonly program: ts.Program,\n ) {\n this.values = new WiringSourceValues(workspaceRoot, infos, program.getTypeChecker());\n }\n\n /**\n * Reads ONLY the owner's canonical src/wiring.ts. The program still type-checks every file so\n * imports, aliases and re-exports resolve, but no other file's body is visited for wiring facts:\n * a module declared elsewhere can neither add a relationship nor be discovered as a fallback.\n */\n extract(): RuntimeDeclaration {\n const wiring = this.program.getSourceFile(this.wiringPath);\n if (wiring === undefined) this.fail(`Missing canonical ${this.wiringPath}.`);\n for (const statement of wiring!.statements)\n if (ts.isClassDeclaration(statement)) this.recordWiring(statement);\n const framework = this.info.tags.includes('framework:angular')\n ? 'angular'\n : this.info.tags.some((tag) => tag === 'framework:node' || tag === 'framework:express')\n ? 'node'\n : 'browser';\n if (this.info.tags.includes('webpieces') && this.entry === undefined)\n this.fail(`${this.info.name} requires one unambiguous exported AppWiring in src/wiring.ts.`);\n return new RuntimeDeclaration(\n this.info.name,\n framework,\n this.exported,\n this.entry,\n this.host,\n );\n }\n\n private facts(node: ts.Node, owner: string): void {\n if (ts.isNewExpression(node) && new WiringSourceTypes(this.program.getTypeChecker()).isFramework(node.expression, 'ExternalContractUse'))\n this.recordExternal(node, owner);\n if (ts.isCallExpression(node) && this.frameworkCall(node)) {\n const name = this.values.symbolName(node.expression);\n if (['addRoutes', 'createRpcClient', 'createPubSubClient', 'bindRpc', 'bindPubSub', 'provideRpcClient'].includes(name))\n this.recordRelationship(node, name, owner);\n }\n ts.forEachChild(node, (child: ts.Node) => this.facts(child, owner));\n }\n\n private recordExternal(expression: ts.NewExpression, owner: string): void {\n const identity = expression.arguments?.[0];\n if (identity === undefined || !ts.isStringLiteralLike(identity))\n this.fail(\n 'ExternalContractUse belongs to a selected exported module and requires a literal project#contract identity.',\n );\n const qualified = (identity as ts.StringLiteralLike).text.split('#');\n const project = qualified[0];\n const exportedName = qualified[1];\n const extra = qualified[2];\n if (!project || !exportedName || extra !== undefined)\n this.fail('ExternalContractUse requires one qualified project#contract identity.');\n if (!this.values.hasExternalConsumer(this.info.name, project, exportedName, this.program))\n this.fail(\n `${project}#${exportedName} has no production business consumer in ${this.info.name}; adapters and test doubles do not establish uses.`,\n );\n const exported = this.exported[owner];\n exported.relationships.push(\n new WiringRelationship(\n new ContractIdentity(project, exportedName),\n new UsesFacts('external', {\n kind: 'unknown',\n reason: 'Vendor interface; destination classified by approved contract metadata',\n }),\n ),\n );\n this.exported[owner] = exported;\n }\n\n private recordRelationship(call: ts.CallExpression, method: string, owner: string): void {\n const apiIndex =\n method === 'bindRpc' || method === 'bindPubSub' || method === 'provideRpcClient'\n ? 1\n : 0;\n const api = call.arguments[apiIndex];\n if (api === undefined) this.fail(`${method} requires an explicit API contract.`);\n const contract = this.values.identity(api!);\n const direction = method === 'addRoutes' ? 'implements' : 'uses';\n const contractTransport = this.values.transport(api!);\n const transport =\n method === 'addRoutes'\n ? contractTransport\n : method === 'bindPubSub' || method === 'createPubSubClient'\n ? 'pubsub'\n : 'rpc';\n if (transport !== contractTransport)\n this.fail(\n `${method} transport disagrees with ${contract.project}#${contract.exportedName}.`,\n );\n const target =\n direction === 'implements'\n ? undefined\n : this.values.target(call.arguments[apiIndex + 1]);\n const exported = this.exported[owner];\n exported.relationships.push(\n new WiringRelationship(\n contract,\n direction === 'implements'\n ? new ImplementsFacts(transport, this.values.condition(call))\n : new UsesFacts(transport, target!, this.values.condition(call)),\n ),\n );\n this.exported[owner] = exported;\n }\n\n private frameworkCall(call: ts.CallExpression): boolean {\n const declaration = this.program.getTypeChecker().getResolvedSignature(call)?.declaration;\n if (declaration === undefined) return false;\n const file = declaration.getSourceFile().fileName.replace(/\\\\/g, '/');\n return /(?:\\/packages\\/(?:http|cloud)\\/|\\/node_modules\\/@webpieces\\/)(?:http-routing|http-client-node|http-client-browser|cloudtasks-client)\\//.test(file);\n }\n\n private recordWiring(declaration: ts.ClassDeclaration): void {\n const types = new WiringSourceTypes(this.program.getTypeChecker());\n const kind = types.kind(declaration);\n const owner = this.exportOwner(declaration);\n if (kind === undefined || owner === undefined) return;\n if (kind === 'binding' || kind === 'routing') {\n this.exported[owner] = new WiringExport(kind, [], []);\n const configure = types.method(declaration, 'configure');\n if (configure === undefined || configure.body === undefined)\n this.fail(`${owner}: named module requires a statically resolvable configure implementation.`);\n if (path.resolve(configure!.getSourceFile().fileName) !== this.wiringPath)\n this.fail(`${owner}: configure is inherited from ${configure!.getSourceFile().fileName}; declare its registrations in ${owner}.configure in ${this.wiringPath}.`);\n this.facts(configure!.body!, owner);\n return;\n }\n const bindings = this.moduleSelections(owner, types.method(declaration, 'getBindingModules'), 'binding');\n const routes = this.moduleSelections(owner, types.method(declaration, 'getRoutingModules'), 'routing');\n const libraries = kind === 'app' ? this.moduleSelections(owner, types.method(declaration, 'getWirings'), 'wiring') : [];\n if (kind === 'wiring' && types.method(declaration, 'getWirings') !== undefined)\n this.fail(`${owner}: library Wiring cannot select other Wirings.`);\n this.exported[owner] = new WiringExport(kind, [], bindings, routes, libraries);\n if (kind !== 'app') return;\n if (!this.info.tags.includes('webpieces'))\n this.fail(`${owner}: library owners cannot declare an AppWiring entry.`);\n if (this.entry !== undefined) this.fail('Ambiguous AppWiring root; export exactly one application entry.');\n this.entry = owner;\n const projectFile = path.join(this.workspaceRoot, this.info.root, 'project.json');\n if (fs.existsSync(projectFile)) {\n const project = JSON.parse(fs.readFileSync(projectFile, 'utf8')) as WiringProjectMetadata;\n this.host = project.metadata?.webpieces?.serviceName;\n }\n }\n\n private moduleSelections(owner: string, method: ts.MethodDeclaration | undefined, expected: 'binding' | 'routing' | 'wiring'): WiringSelection[] {\n if (method !== undefined && path.resolve(method.getSourceFile().fileName) !== this.wiringPath)\n this.fail(`${owner}: its selection getter is declared in ${method.getSourceFile().fileName}; declare getBindingModules/getRoutingModules/getWirings on ${owner} itself in ${this.wiringPath}.`);\n const statements = method?.body?.statements;\n const expression = statements?.length === 1 && ts.isReturnStatement(statements[0]) ? statements[0].expression : undefined;\n if (expression === undefined || !ts.isArrayLiteralExpression(expression))\n this.fail(`Expected ${expected} getter to contain only return [new NamedModule(preparedInputs)].`);\n const types = new WiringSourceTypes(this.program.getTypeChecker());\n return expression.elements.map((element: ts.Expression) => {\n if (!ts.isNewExpression(element) || types.kind(element.expression) !== expected)\n this.fail(`Wrong ${expected} selection ${element.getText()}; AppWiring children, delegation and nested lists are forbidden.`);\n const identity = this.values.identity(element.expression);\n this.assertCanonicalDeclaration(owner, element.expression, identity, expected);\n return new WiringSelection(identity.project, identity.exportedName, this.values.arguments(element), this.values.policies(element));\n });\n }\n\n /**\n * A selected module must be declared in THIS wiring.ts, and a selected library Wiring in its own\n * owner's src/wiring.ts. Proven by the resolved declaration, never by a name, and checked before\n * any argument analysis, so an off-file module body is never read.\n */\n private assertCanonicalDeclaration(\n owner: string,\n selected: ts.Expression,\n identity: ContractIdentity,\n expected: 'binding' | 'routing' | 'wiring',\n ): void {\n const declaration = new WiringSourceTypes(this.program.getTypeChecker()).declaration(selected);\n const declaredIn = declaration === undefined ? 'an unresolved file' : path.resolve(declaration.getSourceFile().fileName);\n if (expected !== 'wiring') {\n if (declaredIn === this.wiringPath) return;\n const role = expected === 'binding' ? 'BindingModule' : 'RouteModule';\n this.fail(\n `${owner} selects ${identity.exportedName}, which is declared in ${declaredIn}. Declare the ${role} class ${identity.exportedName}, with its registrations, beside ${owner} in ${this.wiringPath}.`,\n );\n }\n const library = this.infos.get(identity.project);\n const canonical = library === undefined ? undefined : path.resolve(this.workspaceRoot, library.root, 'src/wiring.ts');\n if (canonical !== undefined && declaredIn === canonical) return;\n this.fail(\n `${owner} selects library Wiring ${identity.project}#${identity.exportedName}, which is declared in ${declaredIn}. A library Wiring and its modules belong in that library's canonical ${canonical ?? 'src/wiring.ts'}.`,\n );\n }\n\n private exportOwner(node: ts.Node): string | undefined {\n let current: ts.Node | undefined = node;\n while (current !== undefined) {\n if (\n ts.isClassDeclaration(current) &&\n current.name !== undefined &&\n (ts.getModifiers(current) ?? []).some(\n (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword,\n )\n )\n return current.name.text;\n if (\n ts.isFunctionDeclaration(current) &&\n current.name !== undefined &&\n (ts.getModifiers(current) ?? []).some(\n (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword,\n )\n )\n return current.name.text;\n if (ts.isVariableDeclaration(current) && ts.isIdentifier(current.name)) {\n const statement = current.parent.parent;\n if (\n ts.isVariableStatement(statement) &&\n (ts.getModifiers(statement) ?? []).some(\n (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword,\n )\n )\n return current.name.text;\n }\n current = current.parent;\n }\n return undefined;\n }\n\n private get wiringPath(): string {\n return path.resolve(this.workspaceRoot, this.info.root, 'src/wiring.ts');\n }\n\n private fail(message: string): never {\n throw new RuleFailError('validate-runtime-architecture', message, undefined, undefined, [\n new Option(\n 'Declare each owner\\'s Wiring/AppWiring class AND its BindingModule/RouteModule classes, with their registrations (RuntimeClients.bindRpc(token, Api, deployment), RuntimeTaskClients.bindPubSub, provideRpcClient, addRoutes, addFilter, DI binds), together in that owner\\'s canonical src/wiring.ts, and use the documented getter grammar; extraction reads only wiring.ts and never executes configuration.',\n true,\n ),\n ]);\n }\n}\n\n/** Factory kept separate so graph assembly cannot accidentally create a compiler. */\nexport class WiringProjectProgram {\n create(workspaceRoot: string, info: ProjectInfo): ts.Program {\n const root = path.resolve(workspaceRoot, info.root);\n const configured = createProjectProgram(root);\n if (configured !== null) return configured;\n const config = ts.findConfigFile(root, ts.sys.fileExists, 'tsconfig.json');\n const parsed =\n config === undefined ? undefined : ts.readConfigFile(config, ts.sys.readFile);\n const options =\n parsed === undefined\n ? {}\n : ts.parseJsonConfigFileContent(parsed.config, ts.sys, root).options;\n const files = ts.sys.readDirectory(\n path.join(root, 'src'),\n ['.ts'],\n ['**/*.spec.ts', '**/*.test.ts'],\n );\n return ts.createProgram(files, options);\n }\n}\n"]}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import * as ts from 'typescript';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* One canonical-file grammar. Each owner's src/wiring.ts holds its Wiring/AppWiring class AND the
|
|
4
|
+
* BindingModule/RouteModule classes it selects, with their actual registrations. Symbol resolution
|
|
5
|
+
* may read imports; format checking never does.
|
|
6
|
+
*/
|
|
3
7
|
export declare class WiringFormat {
|
|
4
8
|
private readonly checker;
|
|
5
9
|
private readonly maxLines;
|
|
@@ -9,7 +13,29 @@ export declare class WiringFormat {
|
|
|
9
13
|
assert(problems: readonly string[]): void;
|
|
10
14
|
private classProblems;
|
|
11
15
|
private arrayProblems;
|
|
16
|
+
/** Proven through the resolved declaration: a selected module lives in THIS file, a library Wiring in its own wiring.ts. */
|
|
17
|
+
private placementProblems;
|
|
12
18
|
private prepared;
|
|
13
19
|
private configureProblems;
|
|
14
|
-
private
|
|
20
|
+
private registration;
|
|
21
|
+
/** Every argument of every call in a registration chain, plus a loaded module's construction arguments. */
|
|
22
|
+
private registrationArguments;
|
|
23
|
+
/** `X.load`, `new X(prepared).load` or `createX(prepared).load`: an explicit, opaque module load. */
|
|
24
|
+
private moduleReceiver;
|
|
25
|
+
private clientBinder;
|
|
26
|
+
/** Returns the first non-declarative node inside a registration argument, or undefined. */
|
|
27
|
+
private offending;
|
|
28
|
+
private firstOffending;
|
|
29
|
+
/**
|
|
30
|
+
* A provider recipe or vendor factory (Angular, webpieces, another library) is a declaration; a
|
|
31
|
+
* call into this owner's own helpers would hide the registrations it returns.
|
|
32
|
+
*/
|
|
33
|
+
private outsideOwner;
|
|
34
|
+
/** A short DI factory: `(ctx) => ctx.get(Token)`, `(dep) => dep.build()` or `(dep) => new Named(dep)`. */
|
|
35
|
+
private factoryCallback;
|
|
36
|
+
/** An identifier, `this`, or a property path over them that does not read the environment. */
|
|
37
|
+
private path;
|
|
38
|
+
private literal;
|
|
39
|
+
private unwrap;
|
|
40
|
+
private signatureFile;
|
|
15
41
|
}
|
|
@@ -2,11 +2,35 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.WiringFormat = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
+
const path = tslib_1.__importStar(require("path"));
|
|
5
6
|
const ts = tslib_1.__importStar(require("typescript"));
|
|
6
7
|
const rules_config_1 = require("@webpieces/rules-config");
|
|
7
8
|
const source_types_1 = require("./source-types");
|
|
8
9
|
const canonical_clients_1 = require("./canonical-clients");
|
|
9
|
-
|
|
10
|
+
const WEBPIECES_SDK = /(?:\/packages\/(?:http|cloud)\/|\/node_modules\/@webpieces\/)(?:http-routing|http-client-node|http-client-browser|http-client-core|cloudtasks-client)\//;
|
|
11
|
+
const INVERSIFY = /\/node_modules\/(?:@inversifyjs\/|inversify\/)/;
|
|
12
|
+
/** Methods that START a registration: a DI bind, a client binding, a provider recipe, a route or a filter. */
|
|
13
|
+
const REGISTRATION_ROOTS = ['bind', 'bindRpc', 'bindPubSub', 'add', 'addRoutes', 'addFilter'];
|
|
14
|
+
/** Removed authoring shapes; their presence means an old wrapper or an anonymous module survived. */
|
|
15
|
+
const LEGACY_TOPOLOGY = /\b(?:rpcTarget|RpcTarget|ContainerModule|ServerWiring|ServerWiringOptions|BrowserWiring|getRuntimeWiring)\b/;
|
|
16
|
+
/** Environment discovery belongs in prepared configuration, never in a registration argument. */
|
|
17
|
+
const ENVIRONMENT = new Set(['process', 'window', 'document', 'localStorage', 'sessionStorage', 'navigator', 'location', 'globalThis']);
|
|
18
|
+
/** The one canonical file being checked, its owner directory and where problems go. */
|
|
19
|
+
class CanonicalFile {
|
|
20
|
+
file;
|
|
21
|
+
ownerRoot;
|
|
22
|
+
report;
|
|
23
|
+
constructor(file, ownerRoot, report) {
|
|
24
|
+
this.file = file;
|
|
25
|
+
this.ownerRoot = ownerRoot;
|
|
26
|
+
this.report = report;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* One canonical-file grammar. Each owner's src/wiring.ts holds its Wiring/AppWiring class AND the
|
|
31
|
+
* BindingModule/RouteModule classes it selects, with their actual registrations. Symbol resolution
|
|
32
|
+
* may read imports; format checking never does.
|
|
33
|
+
*/
|
|
10
34
|
class WiringFormat {
|
|
11
35
|
checker;
|
|
12
36
|
maxLines;
|
|
@@ -24,8 +48,10 @@ class WiringFormat {
|
|
|
24
48
|
const at = file.getLineAndCharacterOfPosition(node.getStart(file));
|
|
25
49
|
problems.push(`${file.fileName}:${at.line + 1}:${at.character + 1}: ${message}`);
|
|
26
50
|
};
|
|
27
|
-
|
|
28
|
-
|
|
51
|
+
const scope = new CanonicalFile(file, path.dirname(path.dirname(path.resolve(file.fileName))), report);
|
|
52
|
+
const lines = file.text.trimEnd().split('\n').length;
|
|
53
|
+
if (lines > this.maxLines)
|
|
54
|
+
report(file, `wiring.ts has ${lines} lines, above maxLines ${this.maxLines}. Keep every BindingModule/RouteModule and its registrations here beside the Wiring class; shorten the file by moving configuration building, translations, environment discovery and initializer or factory bodies into imported implementations, or give a cohesive group its own library owner with its own wiring.ts.`);
|
|
29
55
|
for (const statement of file.statements) {
|
|
30
56
|
if (ts.isImportDeclaration(statement) || ts.isExportDeclaration(statement))
|
|
31
57
|
continue;
|
|
@@ -38,7 +64,7 @@ class WiringFormat {
|
|
|
38
64
|
report(statement, 'Implement the framework Wiring, AppWiring, BindingModule or RouteModule contract.');
|
|
39
65
|
continue;
|
|
40
66
|
}
|
|
41
|
-
this.classProblems(statement, kind,
|
|
67
|
+
this.classProblems(statement, kind, scope);
|
|
42
68
|
}
|
|
43
69
|
return problems;
|
|
44
70
|
}
|
|
@@ -46,10 +72,11 @@ class WiringFormat {
|
|
|
46
72
|
if (problems.length === 0)
|
|
47
73
|
return;
|
|
48
74
|
throw new rules_config_1.RuleFailError('wiring-format', problems.join('\n'), undefined, undefined, [
|
|
49
|
-
new rules_config_1.Option('
|
|
75
|
+
new rules_config_1.Option("Declare each owner's Wiring/AppWiring class together with its named BindingModule/RouteModule classes and their registrations in its src/wiring.ts, selected by literal getters. Keep configuration building, environment discovery and initializer/factory bodies in imported implementations, and keep named WiringPolicy conditions explicit.", true),
|
|
50
76
|
]);
|
|
51
77
|
}
|
|
52
|
-
classProblems(declaration, kind,
|
|
78
|
+
classProblems(declaration, kind, scope) {
|
|
79
|
+
const report = scope.report;
|
|
53
80
|
for (const member of declaration.members) {
|
|
54
81
|
if (ts.isConstructorDeclaration(member)) {
|
|
55
82
|
if (member.body !== undefined && member.body.statements.length > 0)
|
|
@@ -65,27 +92,35 @@ class WiringFormat {
|
|
|
65
92
|
const expected = name === 'getWirings' ? 'wiring' : name === 'getBindingModules' ? 'binding' : 'routing';
|
|
66
93
|
if (name === 'getWirings' && kind !== 'app')
|
|
67
94
|
report(member, 'Only AppWiring can declare getWirings; libraries cannot compose libraries.');
|
|
68
|
-
this.arrayProblems(member, expected,
|
|
95
|
+
this.arrayProblems(member, expected, scope);
|
|
69
96
|
}
|
|
70
97
|
else if (name === 'configure' && ['binding', 'routing'].includes(kind)) {
|
|
71
98
|
for (const statement of member.body?.statements ?? [])
|
|
72
|
-
this.configureProblems(statement,
|
|
99
|
+
this.configureProblems(statement, scope);
|
|
73
100
|
}
|
|
74
101
|
else if (name !== 'getHeaders' || kind !== 'app')
|
|
75
102
|
report(member, 'Keep only canonical selection getters and short configure declarations; getRuntimeWiring and helper methods were removed.');
|
|
76
103
|
}
|
|
104
|
+
if (kind === 'binding' || kind === 'routing') {
|
|
105
|
+
const configure = this.types.method(declaration, 'configure');
|
|
106
|
+
if (configure !== undefined && configure.getSourceFile() !== scope.file)
|
|
107
|
+
report(declaration, `configure is inherited from ${configure.getSourceFile().fileName}; declare this module's registrations in its own configure here in wiring.ts.`);
|
|
108
|
+
}
|
|
77
109
|
if (kind === 'app' || kind === 'wiring') {
|
|
78
110
|
const names = ['getBindingModules', 'getRoutingModules', ...(kind === 'app' ? ['getWirings'] : [])];
|
|
79
111
|
for (const name of names) {
|
|
80
112
|
const method = this.types.method(declaration, name);
|
|
81
113
|
if (method === undefined)
|
|
82
114
|
report(declaration, `Missing ${name} literal array getter.`);
|
|
115
|
+
else if (method.getSourceFile() !== scope.file)
|
|
116
|
+
report(declaration, `${name} is inherited from ${method.getSourceFile().fileName}; declare the selection getter on this class in wiring.ts.`);
|
|
83
117
|
}
|
|
84
118
|
if (kind === 'wiring' && this.types.method(declaration, 'getWirings') !== undefined)
|
|
85
119
|
report(declaration, 'A library Wiring must not inherit getWirings.');
|
|
86
120
|
}
|
|
87
121
|
}
|
|
88
|
-
arrayProblems(method, expected,
|
|
122
|
+
arrayProblems(method, expected, scope) {
|
|
123
|
+
const report = scope.report;
|
|
89
124
|
const statements = method.body?.statements;
|
|
90
125
|
const returned = statements?.length === 1 && ts.isReturnStatement(statements[0]) ? statements[0].expression : undefined;
|
|
91
126
|
if (returned === undefined || !ts.isArrayLiteralExpression(returned)) {
|
|
@@ -93,14 +128,31 @@ class WiringFormat {
|
|
|
93
128
|
return;
|
|
94
129
|
}
|
|
95
130
|
for (const element of returned.elements) {
|
|
96
|
-
if (!ts.isNewExpression(element) || this.types.kind(element.expression) !== expected)
|
|
131
|
+
if (!ts.isNewExpression(element) || this.types.kind(element.expression) !== expected) {
|
|
97
132
|
report(element, `Select a named framework ${expected} instance; nested arrays and AppWiring children are forbidden.`);
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
this.placementProblems(element.expression, expected, scope);
|
|
136
|
+
for (const argument of element.arguments ?? []) {
|
|
137
|
+
if (!this.prepared(argument))
|
|
138
|
+
report(argument, 'Pass prepared inputs or a named WiringPolicy; no callbacks, topology wrappers or computed setup.');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/** Proven through the resolved declaration: a selected module lives in THIS file, a library Wiring in its own wiring.ts. */
|
|
143
|
+
placementProblems(selected, expected, scope) {
|
|
144
|
+
const declared = this.types.declaration(selected)?.getSourceFile();
|
|
145
|
+
const where = declared === undefined ? 'an unresolved file' : declared.fileName;
|
|
146
|
+
if (expected !== 'wiring') {
|
|
147
|
+
if (declared === scope.file)
|
|
148
|
+
return;
|
|
149
|
+
const role = expected === 'binding' ? 'BindingModule' : 'RouteModule';
|
|
150
|
+
scope.report(selected, `${selected.getText()} is declared in ${where}; declare this ${role} class, with its registrations, here in wiring.ts beside the Wiring class that selects it.`);
|
|
151
|
+
return;
|
|
103
152
|
}
|
|
153
|
+
if (declared !== undefined && /(?:^|[\\/])wiring\.(?:d\.)?ts$/.test(declared.fileName))
|
|
154
|
+
return;
|
|
155
|
+
scope.report(selected, `Library Wiring ${selected.getText()} is declared in ${where}; select a Wiring declared in its library's canonical src/wiring.ts.`);
|
|
104
156
|
}
|
|
105
157
|
prepared(expression) {
|
|
106
158
|
if (ts.isIdentifier(expression) || ts.isLiteralExpression(expression))
|
|
@@ -113,47 +165,192 @@ class WiringFormat {
|
|
|
113
165
|
return false;
|
|
114
166
|
return this.types.isFramework(expression.expression, 'WiringPolicy');
|
|
115
167
|
}
|
|
116
|
-
configureProblems(statement,
|
|
168
|
+
configureProblems(statement, scope) {
|
|
169
|
+
const report = scope.report;
|
|
117
170
|
if (ts.isVariableStatement(statement)) {
|
|
118
171
|
const declarations = statement.declarationList.declarations;
|
|
119
172
|
const initializer = declarations.length === 1 ? declarations[0].initializer : undefined;
|
|
120
|
-
if ((statement.declarationList.flags & ts.NodeFlags.Const) !== 0 && initializer !== undefined &&
|
|
121
|
-
['RuntimeClients', 'RuntimeTaskClients'].some((name) => this.types.isFramework(initializer.expression, name)) &&
|
|
122
|
-
(initializer.arguments ?? []).every((argument) => this.prepared(argument)))
|
|
173
|
+
if ((statement.declarationList.flags & ts.NodeFlags.Const) !== 0 && initializer !== undefined && this.clientBinder(initializer))
|
|
123
174
|
return;
|
|
124
175
|
}
|
|
125
176
|
if (ts.isIfStatement(statement) && ts.isPropertyAccessExpression(statement.expression) && statement.expression.name.text === 'enabled' && this.types.isPolicy(statement.expression.expression) && statement.elseStatement === undefined) {
|
|
126
177
|
const body = ts.isBlock(statement.thenStatement) ? statement.thenStatement.statements : [statement.thenStatement];
|
|
127
178
|
for (const child of body)
|
|
128
|
-
this.configureProblems(child,
|
|
179
|
+
this.configureProblems(child, scope);
|
|
129
180
|
return;
|
|
130
181
|
}
|
|
131
|
-
const
|
|
182
|
+
const written = ts.isExpressionStatement(statement) || ts.isReturnStatement(statement) ? statement.expression : undefined;
|
|
183
|
+
const expression = written !== undefined && ts.isAwaitExpression(written) ? written.expression : written;
|
|
132
184
|
if (expression === undefined || (!ts.isCallExpression(expression) && !ts.isNewExpression(expression))) {
|
|
133
|
-
report(statement, 'configure contains only
|
|
185
|
+
report(statement, 'configure contains only registration declarations (DI binds, client bindings, provider recipes, routes, filters, module loads, external-contract markers) and named policy conditions.');
|
|
134
186
|
return;
|
|
135
187
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return
|
|
188
|
+
if (LEGACY_TOPOLOGY.test(expression.getText())) {
|
|
189
|
+
report(expression, 'Removed topology shape (rpcTarget, an anonymous ContainerModule or a plan wrapper); declare a named module registration instead.');
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
if (!this.registration(expression, scope)) {
|
|
193
|
+
report(expression, 'Use a recognized registration declaration: options.bind(...) chains, RuntimeClients.bindRpc, RuntimeTaskClients.bindPubSub, bindings.add(provider recipes), router.addRoutes/addFilter, (await) NamedModule.load(options) or new ExternalContractUse(...). Move custom setup into imported implementations.');
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
for (const argument of this.registrationArguments(expression)) {
|
|
197
|
+
const offending = this.offending(argument, scope);
|
|
198
|
+
if (offending !== undefined)
|
|
199
|
+
report(offending, 'Pass declarative registration arguments: tokens, classes, prepared fields, literals, named factory or initializer references, provider recipe objects and calls, and short DI factory callbacks such as (ctx) => ctx.get(Token). Move computed setup, environment reads, helper calls of this owner and callback bodies into imported implementations or prepared constructor inputs.');
|
|
143
200
|
}
|
|
201
|
+
}
|
|
202
|
+
registration(expression, scope) {
|
|
203
|
+
if (ts.isNewExpression(expression))
|
|
204
|
+
return this.types.isFramework(expression.expression, 'ExternalContractUse') &&
|
|
205
|
+
(expression.arguments ?? []).every((argument) => ts.isStringLiteralLike(argument));
|
|
144
206
|
if (!ts.isPropertyAccessExpression(expression.expression))
|
|
145
207
|
return false;
|
|
146
|
-
const
|
|
208
|
+
const name = expression.expression.name.text;
|
|
209
|
+
const receiver = this.unwrap(expression.expression.expression);
|
|
210
|
+
const file = this.signatureFile(expression);
|
|
211
|
+
if (file === undefined)
|
|
212
|
+
return false;
|
|
213
|
+
if (name === 'load')
|
|
214
|
+
return INVERSIFY.test(file) && this.moduleReceiver(receiver);
|
|
215
|
+
if (!WEBPIECES_SDK.test(file) && !INVERSIFY.test(file))
|
|
216
|
+
return false;
|
|
147
217
|
if (ts.isCallExpression(receiver))
|
|
148
|
-
return this.
|
|
149
|
-
|
|
218
|
+
return this.registration(receiver, scope);
|
|
219
|
+
return REGISTRATION_ROOTS.includes(name) && (this.path(receiver) || this.clientBinder(receiver));
|
|
220
|
+
}
|
|
221
|
+
/** Every argument of every call in a registration chain, plus a loaded module's construction arguments. */
|
|
222
|
+
registrationArguments(expression) {
|
|
223
|
+
const own = [...(expression.arguments ?? [])];
|
|
224
|
+
if (!ts.isCallExpression(expression) || !ts.isPropertyAccessExpression(expression.expression))
|
|
225
|
+
return own;
|
|
226
|
+
const receiver = this.unwrap(expression.expression.expression);
|
|
227
|
+
if (ts.isCallExpression(receiver)) {
|
|
228
|
+
if (expression.expression.name.text === 'load')
|
|
229
|
+
return [...own, ...receiver.arguments];
|
|
230
|
+
return [...own, ...this.registrationArguments(receiver)];
|
|
231
|
+
}
|
|
232
|
+
if (ts.isNewExpression(receiver))
|
|
233
|
+
return [...own, ...(receiver.arguments ?? [])];
|
|
234
|
+
return own;
|
|
235
|
+
}
|
|
236
|
+
/** `X.load`, `new X(prepared).load` or `createX(prepared).load`: an explicit, opaque module load. */
|
|
237
|
+
moduleReceiver(receiver) {
|
|
238
|
+
if (this.path(receiver))
|
|
239
|
+
return true;
|
|
240
|
+
if (ts.isNewExpression(receiver) || ts.isCallExpression(receiver))
|
|
241
|
+
return this.path(receiver.expression) && !LEGACY_TOPOLOGY.test(receiver.expression.getText());
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
clientBinder(expression) {
|
|
245
|
+
return ts.isNewExpression(expression) &&
|
|
246
|
+
['RuntimeClients', 'RuntimeTaskClients'].some((name) => this.types.isFramework(expression.expression, name)) &&
|
|
247
|
+
(expression.arguments ?? []).every((argument) => this.prepared(argument));
|
|
248
|
+
}
|
|
249
|
+
/** Returns the first non-declarative node inside a registration argument, or undefined. */
|
|
250
|
+
offending(expression, scope) {
|
|
251
|
+
const value = this.unwrap(expression);
|
|
252
|
+
if (this.literal(value))
|
|
253
|
+
return undefined;
|
|
254
|
+
if (ts.isIdentifier(value) || value.kind === ts.SyntaxKind.ThisKeyword || ts.isPropertyAccessExpression(value))
|
|
255
|
+
return this.path(value) ? undefined : value;
|
|
256
|
+
if (ts.isArrayLiteralExpression(value)) {
|
|
257
|
+
for (const element of value.elements) {
|
|
258
|
+
const found = this.offending(ts.isSpreadElement(element) ? element.expression : element, scope);
|
|
259
|
+
if (found !== undefined)
|
|
260
|
+
return found;
|
|
261
|
+
}
|
|
262
|
+
return undefined;
|
|
263
|
+
}
|
|
264
|
+
if (ts.isObjectLiteralExpression(value)) {
|
|
265
|
+
for (const property of value.properties) {
|
|
266
|
+
if (ts.isShorthandPropertyAssignment(property)) {
|
|
267
|
+
if (ENVIRONMENT.has(property.name.text))
|
|
268
|
+
return property;
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
const initializer = ts.isPropertyAssignment(property) && !ts.isComputedPropertyName(property.name)
|
|
272
|
+
? property.initializer : ts.isSpreadAssignment(property) ? property.expression : undefined;
|
|
273
|
+
if (initializer === undefined)
|
|
274
|
+
return property;
|
|
275
|
+
const found = this.offending(initializer, scope);
|
|
276
|
+
if (found !== undefined)
|
|
277
|
+
return found;
|
|
278
|
+
}
|
|
279
|
+
return undefined;
|
|
280
|
+
}
|
|
281
|
+
if (ts.isNewExpression(value)) {
|
|
282
|
+
if (!this.path(value.expression) || LEGACY_TOPOLOGY.test(value.expression.getText()))
|
|
283
|
+
return value;
|
|
284
|
+
return this.firstOffending(value.arguments ?? [], scope);
|
|
285
|
+
}
|
|
286
|
+
if (ts.isCallExpression(value)) {
|
|
287
|
+
const callee = value.expression;
|
|
288
|
+
const receiverOk = this.path(callee) ||
|
|
289
|
+
(ts.isPropertyAccessExpression(callee) && ts.isNewExpression(callee.expression) && this.offending(callee.expression, scope) === undefined);
|
|
290
|
+
if (!receiverOk || !this.outsideOwner(value, scope))
|
|
291
|
+
return value;
|
|
292
|
+
return this.firstOffending(value.arguments, scope);
|
|
293
|
+
}
|
|
294
|
+
if (ts.isArrowFunction(value))
|
|
295
|
+
return this.factoryCallback(value) ? undefined : value;
|
|
296
|
+
return value;
|
|
297
|
+
}
|
|
298
|
+
firstOffending(values, scope) {
|
|
299
|
+
for (const value of values) {
|
|
300
|
+
const found = this.offending(value, scope);
|
|
301
|
+
if (found !== undefined)
|
|
302
|
+
return found;
|
|
303
|
+
}
|
|
304
|
+
return undefined;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* A provider recipe or vendor factory (Angular, webpieces, another library) is a declaration; a
|
|
308
|
+
* call into this owner's own helpers would hide the registrations it returns.
|
|
309
|
+
*/
|
|
310
|
+
outsideOwner(call, scope) {
|
|
311
|
+
const file = this.signatureFile(call);
|
|
312
|
+
if (file === undefined)
|
|
150
313
|
return false;
|
|
151
|
-
|
|
152
|
-
|
|
314
|
+
return file.includes('/node_modules/') || !file.startsWith(scope.ownerRoot.replace(/\\/g, '/') + '/');
|
|
315
|
+
}
|
|
316
|
+
/** A short DI factory: `(ctx) => ctx.get(Token)`, `(dep) => dep.build()` or `(dep) => new Named(dep)`. */
|
|
317
|
+
factoryCallback(arrow) {
|
|
318
|
+
if (ts.isBlock(arrow.body))
|
|
319
|
+
return false;
|
|
320
|
+
const parameters = new Set(arrow.parameters.map((parameter) => parameter.name.getText()));
|
|
321
|
+
const body = this.unwrap(arrow.body);
|
|
322
|
+
const simple = (argument) => this.literal(this.unwrap(argument)) || this.path(this.unwrap(argument));
|
|
323
|
+
if (ts.isNewExpression(body))
|
|
324
|
+
return this.path(body.expression) && (body.arguments ?? []).every(simple);
|
|
325
|
+
if (!ts.isCallExpression(body) || !ts.isPropertyAccessExpression(body.expression))
|
|
153
326
|
return false;
|
|
154
|
-
const
|
|
155
|
-
return
|
|
156
|
-
|
|
327
|
+
const receiver = body.expression.expression;
|
|
328
|
+
return ts.isIdentifier(receiver) && parameters.has(receiver.text) && body.arguments.every(simple);
|
|
329
|
+
}
|
|
330
|
+
/** An identifier, `this`, or a property path over them that does not read the environment. */
|
|
331
|
+
path(expression) {
|
|
332
|
+
if (ts.isIdentifier(expression))
|
|
333
|
+
return !ENVIRONMENT.has(expression.text);
|
|
334
|
+
if (expression.kind === ts.SyntaxKind.ThisKeyword)
|
|
335
|
+
return true;
|
|
336
|
+
return ts.isPropertyAccessExpression(expression) && this.path(expression.expression);
|
|
337
|
+
}
|
|
338
|
+
literal(expression) {
|
|
339
|
+
if (ts.isStringLiteralLike(expression) || ts.isNumericLiteral(expression))
|
|
340
|
+
return true;
|
|
341
|
+
if (ts.isPrefixUnaryExpression(expression))
|
|
342
|
+
return ts.isNumericLiteral(expression.operand);
|
|
343
|
+
return [ts.SyntaxKind.TrueKeyword, ts.SyntaxKind.FalseKeyword, ts.SyntaxKind.NullKeyword].includes(expression.kind) ||
|
|
344
|
+
(ts.isIdentifier(expression) && expression.text === 'undefined');
|
|
345
|
+
}
|
|
346
|
+
unwrap(expression) {
|
|
347
|
+
if (ts.isParenthesizedExpression(expression) || ts.isAsExpression(expression) || ts.isNonNullExpression(expression) || ts.isSatisfiesExpression(expression))
|
|
348
|
+
return this.unwrap(expression.expression);
|
|
349
|
+
return expression;
|
|
350
|
+
}
|
|
351
|
+
signatureFile(call) {
|
|
352
|
+
const declaration = this.checker.getResolvedSignature(call)?.declaration;
|
|
353
|
+
return declaration === undefined ? undefined : path.resolve(declaration.getSourceFile().fileName).replace(/\\/g, '/');
|
|
157
354
|
}
|
|
158
355
|
}
|
|
159
356
|
exports.WiringFormat = WiringFormat;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wiring-format.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/wiring-format.ts"],"names":[],"mappings":"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","sourcesContent":["import * as ts from 'typescript';\nimport { Option, RuleFailError } from '@webpieces/rules-config';\nimport { WiringSourceTypes, WiringKind } from './source-types';\nimport { CanonicalClientBindings } from './canonical-clients';\n\n/** One canonical-file grammar. Symbol resolution may read imports; format checking never does. */\nexport class WiringFormat {\n private readonly types: WiringSourceTypes;\n\n constructor(private readonly checker: ts.TypeChecker, private readonly maxLines: number) {\n this.types = new WiringSourceTypes(checker);\n }\n\n problems(file: ts.SourceFile): string[] {\n if (!/(?:^|\\/)wiring\\.ts$/.test(file.fileName)) return [];\n const problems: string[] = new CanonicalClientBindings(this.checker).problems(file);\n const report = (node: ts.Node, message: string): void => {\n const at = file.getLineAndCharacterOfPosition(node.getStart(file));\n problems.push(`${file.fileName}:${at.line + 1}:${at.character + 1}: ${message}`);\n };\n if (file.text.trimEnd().split('\\n').length > this.maxLines)\n report(file, `wiring.ts exceeds ${this.maxLines} lines; move implementations to imported named modules.`);\n for (const statement of file.statements) {\n if (ts.isImportDeclaration(statement) || ts.isExportDeclaration(statement)) continue;\n if (!ts.isClassDeclaration(statement)) {\n report(statement, 'Only imports, exports and named declarative classes belong in wiring.ts.');\n continue;\n }\n const kind = this.types.kind(statement);\n if (kind === undefined) {\n report(statement, 'Implement the framework Wiring, AppWiring, BindingModule or RouteModule contract.');\n continue;\n }\n this.classProblems(statement, kind, report);\n }\n return problems;\n }\n\n assert(problems: readonly string[]): void {\n if (problems.length === 0) return;\n throw new RuleFailError('wiring-format', problems.join('\\n'), undefined, undefined, [\n new Option('Use Wiring/AppWiring with literal named module selections. Move setup and business logic out of wiring.ts; keep named WiringPolicy conditions explicit.', true),\n ]);\n }\n\n private classProblems(\n declaration: ts.ClassDeclaration,\n kind: WiringKind,\n report: (node: ts.Node, message: string) => void,\n ): void {\n for (const member of declaration.members) {\n if (ts.isConstructorDeclaration(member)) {\n if (member.body !== undefined && member.body.statements.length > 0)\n report(member, 'Use constructor parameter properties to store prepared inputs; no setup logic.');\n continue;\n }\n if (!ts.isMethodDeclaration(member)) {\n report(member, 'Store prepared inputs in constructor parameter properties.');\n continue;\n }\n const name = member.name.getText();\n if (['getBindingModules', 'getRoutingModules', 'getWirings'].includes(name)) {\n const expected = name === 'getWirings' ? 'wiring' : name === 'getBindingModules' ? 'binding' : 'routing';\n if (name === 'getWirings' && kind !== 'app')\n report(member, 'Only AppWiring can declare getWirings; libraries cannot compose libraries.');\n this.arrayProblems(member, expected, report);\n } else if (name === 'configure' && ['binding', 'routing'].includes(kind)) {\n for (const statement of member.body?.statements ?? [])\n this.configureProblems(statement, report);\n } else if (name !== 'getHeaders' || kind !== 'app')\n report(member, 'Keep only canonical selection getters and short configure declarations; getRuntimeWiring and helper methods were removed.');\n }\n if (kind === 'app' || kind === 'wiring') {\n const names = ['getBindingModules', 'getRoutingModules', ...(kind === 'app' ? ['getWirings'] : [])];\n for (const name of names) {\n const method = this.types.method(declaration, name);\n if (method === undefined) report(declaration, `Missing ${name} literal array getter.`);\n }\n if (kind === 'wiring' && this.types.method(declaration, 'getWirings') !== undefined)\n report(declaration, 'A library Wiring must not inherit getWirings.');\n }\n }\n\n private arrayProblems(\n method: ts.MethodDeclaration,\n expected: WiringKind,\n report: (node: ts.Node, message: string) => void,\n ): void {\n const statements = method.body?.statements;\n const returned = statements?.length === 1 && ts.isReturnStatement(statements[0]) ? statements[0].expression : undefined;\n if (returned === undefined || !ts.isArrayLiteralExpression(returned)) {\n report(method, 'Getter body must be exactly return [new NamedModule(preparedInputs)]; no delegation, spreads, helpers or conditions.');\n return;\n }\n for (const element of returned.elements) {\n if (!ts.isNewExpression(element) || this.types.kind(element.expression) !== expected)\n report(element, `Select a named framework ${expected} instance; nested arrays and AppWiring children are forbidden.`);\n else for (const argument of element.arguments ?? []) {\n if (!this.prepared(argument)) report(argument, 'Pass prepared inputs or a named WiringPolicy; no callbacks, topology wrappers or computed setup.');\n }\n }\n }\n\n private prepared(expression: ts.Expression): boolean {\n if (ts.isIdentifier(expression) || ts.isLiteralExpression(expression)) return true;\n if (ts.isPropertyAccessExpression(expression)) return this.prepared(expression.expression);\n if ([ts.SyntaxKind.TrueKeyword, ts.SyntaxKind.FalseKeyword, ts.SyntaxKind.ThisKeyword].includes(expression.kind)) return true;\n if (!ts.isNewExpression(expression)) return false;\n return this.types.isFramework(expression.expression, 'WiringPolicy');\n }\n\n private configureProblems(statement: ts.Statement, report: (node: ts.Node, message: string) => void): void {\n if (ts.isVariableStatement(statement)) {\n const declarations = statement.declarationList.declarations;\n const initializer = declarations.length === 1 ? declarations[0].initializer : undefined;\n if ((statement.declarationList.flags & ts.NodeFlags.Const) !== 0 && initializer !== undefined && ts.isNewExpression(initializer) &&\n ['RuntimeClients', 'RuntimeTaskClients'].some((name: string) => this.types.isFramework(initializer.expression, name)) &&\n (initializer.arguments ?? []).every((argument: ts.Expression) => this.prepared(argument))) return;\n }\n if (ts.isIfStatement(statement) && ts.isPropertyAccessExpression(statement.expression) && statement.expression.name.text === 'enabled' && this.types.isPolicy(statement.expression.expression) && statement.elseStatement === undefined) {\n const body = ts.isBlock(statement.thenStatement) ? statement.thenStatement.statements : [statement.thenStatement];\n for (const child of body) this.configureProblems(child, report);\n return;\n }\n const expression = ts.isExpressionStatement(statement) || ts.isReturnStatement(statement) ? statement.expression : undefined;\n if (expression === undefined || (!ts.isCallExpression(expression) && !ts.isNewExpression(expression))) {\n report(statement, 'configure contains only short binding, route, external-contract or module-load declarations and named policy conditions.');\n return;\n }\n const text = expression.getText();\n if (!this.declarationCall(expression) || /(?:=>|\\bfunction\\b|\\brpcTarget\\b|\\bContainerModule\\b)/.test(text))\n report(expression, 'Use recognized declarative registration calls; move custom setup and factories into imported implementations.');\n }\n\n private declarationCall(expression: ts.CallExpression | ts.NewExpression): boolean {\n if (ts.isNewExpression(expression)) {\n return this.types.isFramework(expression.expression, 'ExternalContractUse');\n }\n if (!ts.isPropertyAccessExpression(expression.expression)) return false;\n const receiver = expression.expression.expression;\n if (ts.isCallExpression(receiver)) return this.declarationCall(receiver);\n if (!['bind', 'bindRpc', 'bindPubSub', 'add', 'addRoutes', 'addFilter', 'load'].includes(expression.expression.name.text)) return false;\n const declaration = this.checker.getResolvedSignature(expression)?.declaration;\n if (declaration === undefined) return false;\n const file = declaration.getSourceFile().fileName.replace(/\\\\/g, '/');\n return /(?:\\/packages\\/(?:http|cloud)\\/|\\/node_modules\\/@webpieces\\/)(?:http-routing|http-client-node|http-client-browser|cloudtasks-client)\\//.test(file) ||\n /\\/node_modules\\/(?:@inversifyjs\\/|inversify\\/)/.test(file);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"wiring-format.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/wiring-format.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport * as ts from 'typescript';\nimport { Option, RuleFailError } from '@webpieces/rules-config';\nimport { WiringSourceTypes, WiringKind } from './source-types';\nimport { CanonicalClientBindings } from './canonical-clients';\n\nconst WEBPIECES_SDK = /(?:\\/packages\\/(?:http|cloud)\\/|\\/node_modules\\/@webpieces\\/)(?:http-routing|http-client-node|http-client-browser|http-client-core|cloudtasks-client)\\//;\nconst INVERSIFY = /\\/node_modules\\/(?:@inversifyjs\\/|inversify\\/)/;\n/** Methods that START a registration: a DI bind, a client binding, a provider recipe, a route or a filter. */\nconst REGISTRATION_ROOTS = ['bind', 'bindRpc', 'bindPubSub', 'add', 'addRoutes', 'addFilter'];\n/** Removed authoring shapes; their presence means an old wrapper or an anonymous module survived. */\nconst LEGACY_TOPOLOGY = /\\b(?:rpcTarget|RpcTarget|ContainerModule|ServerWiring|ServerWiringOptions|BrowserWiring|getRuntimeWiring)\\b/;\n/** Environment discovery belongs in prepared configuration, never in a registration argument. */\nconst ENVIRONMENT = new Set(['process', 'window', 'document', 'localStorage', 'sessionStorage', 'navigator', 'location', 'globalThis']);\n\n/** The one canonical file being checked, its owner directory and where problems go. */\nclass CanonicalFile {\n constructor(\n readonly file: ts.SourceFile,\n readonly ownerRoot: string,\n readonly report: (node: ts.Node, message: string) => void,\n ) {}\n}\n\n/**\n * One canonical-file grammar. Each owner's src/wiring.ts holds its Wiring/AppWiring class AND the\n * BindingModule/RouteModule classes it selects, with their actual registrations. Symbol resolution\n * may read imports; format checking never does.\n */\nexport class WiringFormat {\n private readonly types: WiringSourceTypes;\n\n constructor(private readonly checker: ts.TypeChecker, private readonly maxLines: number) {\n this.types = new WiringSourceTypes(checker);\n }\n\n problems(file: ts.SourceFile): string[] {\n if (!/(?:^|\\/)wiring\\.ts$/.test(file.fileName)) return [];\n const problems: string[] = new CanonicalClientBindings(this.checker).problems(file);\n const report = (node: ts.Node, message: string): void => {\n const at = file.getLineAndCharacterOfPosition(node.getStart(file));\n problems.push(`${file.fileName}:${at.line + 1}:${at.character + 1}: ${message}`);\n };\n const scope = new CanonicalFile(file, path.dirname(path.dirname(path.resolve(file.fileName))), report);\n const lines = file.text.trimEnd().split('\\n').length;\n if (lines > this.maxLines)\n report(\n file,\n `wiring.ts has ${lines} lines, above maxLines ${this.maxLines}. Keep every BindingModule/RouteModule and its registrations here beside the Wiring class; shorten the file by moving configuration building, translations, environment discovery and initializer or factory bodies into imported implementations, or give a cohesive group its own library owner with its own wiring.ts.`,\n );\n for (const statement of file.statements) {\n if (ts.isImportDeclaration(statement) || ts.isExportDeclaration(statement)) continue;\n if (!ts.isClassDeclaration(statement)) {\n report(statement, 'Only imports, exports and named declarative classes belong in wiring.ts.');\n continue;\n }\n const kind = this.types.kind(statement);\n if (kind === undefined) {\n report(statement, 'Implement the framework Wiring, AppWiring, BindingModule or RouteModule contract.');\n continue;\n }\n this.classProblems(statement, kind, scope);\n }\n return problems;\n }\n\n assert(problems: readonly string[]): void {\n if (problems.length === 0) return;\n throw new RuleFailError('wiring-format', problems.join('\\n'), undefined, undefined, [\n new Option(\n \"Declare each owner's Wiring/AppWiring class together with its named BindingModule/RouteModule classes and their registrations in its src/wiring.ts, selected by literal getters. Keep configuration building, environment discovery and initializer/factory bodies in imported implementations, and keep named WiringPolicy conditions explicit.\",\n true,\n ),\n ]);\n }\n\n private classProblems(declaration: ts.ClassDeclaration, kind: WiringKind, scope: CanonicalFile): void {\n const report = scope.report;\n for (const member of declaration.members) {\n if (ts.isConstructorDeclaration(member)) {\n if (member.body !== undefined && member.body.statements.length > 0)\n report(member, 'Use constructor parameter properties to store prepared inputs; no setup logic.');\n continue;\n }\n if (!ts.isMethodDeclaration(member)) {\n report(member, 'Store prepared inputs in constructor parameter properties.');\n continue;\n }\n const name = member.name.getText();\n if (['getBindingModules', 'getRoutingModules', 'getWirings'].includes(name)) {\n const expected = name === 'getWirings' ? 'wiring' : name === 'getBindingModules' ? 'binding' : 'routing';\n if (name === 'getWirings' && kind !== 'app')\n report(member, 'Only AppWiring can declare getWirings; libraries cannot compose libraries.');\n this.arrayProblems(member, expected, scope);\n } else if (name === 'configure' && ['binding', 'routing'].includes(kind)) {\n for (const statement of member.body?.statements ?? []) this.configureProblems(statement, scope);\n } else if (name !== 'getHeaders' || kind !== 'app')\n report(member, 'Keep only canonical selection getters and short configure declarations; getRuntimeWiring and helper methods were removed.');\n }\n if (kind === 'binding' || kind === 'routing') {\n const configure = this.types.method(declaration, 'configure');\n if (configure !== undefined && configure.getSourceFile() !== scope.file)\n report(declaration, `configure is inherited from ${configure.getSourceFile().fileName}; declare this module's registrations in its own configure here in wiring.ts.`);\n }\n if (kind === 'app' || kind === 'wiring') {\n const names = ['getBindingModules', 'getRoutingModules', ...(kind === 'app' ? ['getWirings'] : [])];\n for (const name of names) {\n const method = this.types.method(declaration, name);\n if (method === undefined) report(declaration, `Missing ${name} literal array getter.`);\n else if (method.getSourceFile() !== scope.file)\n report(declaration, `${name} is inherited from ${method.getSourceFile().fileName}; declare the selection getter on this class in wiring.ts.`);\n }\n if (kind === 'wiring' && this.types.method(declaration, 'getWirings') !== undefined)\n report(declaration, 'A library Wiring must not inherit getWirings.');\n }\n }\n\n private arrayProblems(method: ts.MethodDeclaration, expected: WiringKind, scope: CanonicalFile): void {\n const report = scope.report;\n const statements = method.body?.statements;\n const returned = statements?.length === 1 && ts.isReturnStatement(statements[0]) ? statements[0].expression : undefined;\n if (returned === undefined || !ts.isArrayLiteralExpression(returned)) {\n report(method, 'Getter body must be exactly return [new NamedModule(preparedInputs)]; no delegation, spreads, helpers or conditions.');\n return;\n }\n for (const element of returned.elements) {\n if (!ts.isNewExpression(element) || this.types.kind(element.expression) !== expected) {\n report(element, `Select a named framework ${expected} instance; nested arrays and AppWiring children are forbidden.`);\n continue;\n }\n this.placementProblems(element.expression, expected, scope);\n for (const argument of element.arguments ?? []) {\n if (!this.prepared(argument)) report(argument, 'Pass prepared inputs or a named WiringPolicy; no callbacks, topology wrappers or computed setup.');\n }\n }\n }\n\n /** Proven through the resolved declaration: a selected module lives in THIS file, a library Wiring in its own wiring.ts. */\n private placementProblems(selected: ts.Expression, expected: WiringKind, scope: CanonicalFile): void {\n const declared = this.types.declaration(selected)?.getSourceFile();\n const where = declared === undefined ? 'an unresolved file' : declared.fileName;\n if (expected !== 'wiring') {\n if (declared === scope.file) return;\n const role = expected === 'binding' ? 'BindingModule' : 'RouteModule';\n scope.report(selected, `${selected.getText()} is declared in ${where}; declare this ${role} class, with its registrations, here in wiring.ts beside the Wiring class that selects it.`);\n return;\n }\n if (declared !== undefined && /(?:^|[\\\\/])wiring\\.(?:d\\.)?ts$/.test(declared.fileName)) return;\n scope.report(selected, `Library Wiring ${selected.getText()} is declared in ${where}; select a Wiring declared in its library's canonical src/wiring.ts.`);\n }\n\n private prepared(expression: ts.Expression): boolean {\n if (ts.isIdentifier(expression) || ts.isLiteralExpression(expression)) return true;\n if (ts.isPropertyAccessExpression(expression)) return this.prepared(expression.expression);\n if ([ts.SyntaxKind.TrueKeyword, ts.SyntaxKind.FalseKeyword, ts.SyntaxKind.ThisKeyword].includes(expression.kind)) return true;\n if (!ts.isNewExpression(expression)) return false;\n return this.types.isFramework(expression.expression, 'WiringPolicy');\n }\n\n private configureProblems(statement: ts.Statement, scope: CanonicalFile): void {\n const report = scope.report;\n if (ts.isVariableStatement(statement)) {\n const declarations = statement.declarationList.declarations;\n const initializer = declarations.length === 1 ? declarations[0].initializer : undefined;\n if ((statement.declarationList.flags & ts.NodeFlags.Const) !== 0 && initializer !== undefined && this.clientBinder(initializer)) return;\n }\n if (ts.isIfStatement(statement) && ts.isPropertyAccessExpression(statement.expression) && statement.expression.name.text === 'enabled' && this.types.isPolicy(statement.expression.expression) && statement.elseStatement === undefined) {\n const body = ts.isBlock(statement.thenStatement) ? statement.thenStatement.statements : [statement.thenStatement];\n for (const child of body) this.configureProblems(child, scope);\n return;\n }\n const written = ts.isExpressionStatement(statement) || ts.isReturnStatement(statement) ? statement.expression : undefined;\n const expression = written !== undefined && ts.isAwaitExpression(written) ? written.expression : written;\n if (expression === undefined || (!ts.isCallExpression(expression) && !ts.isNewExpression(expression))) {\n report(statement, 'configure contains only registration declarations (DI binds, client bindings, provider recipes, routes, filters, module loads, external-contract markers) and named policy conditions.');\n return;\n }\n if (LEGACY_TOPOLOGY.test(expression.getText())) {\n report(expression, 'Removed topology shape (rpcTarget, an anonymous ContainerModule or a plan wrapper); declare a named module registration instead.');\n return;\n }\n if (!this.registration(expression, scope)) {\n report(expression, 'Use a recognized registration declaration: options.bind(...) chains, RuntimeClients.bindRpc, RuntimeTaskClients.bindPubSub, bindings.add(provider recipes), router.addRoutes/addFilter, (await) NamedModule.load(options) or new ExternalContractUse(...). Move custom setup into imported implementations.');\n return;\n }\n for (const argument of this.registrationArguments(expression)) {\n const offending = this.offending(argument, scope);\n if (offending !== undefined)\n report(offending, 'Pass declarative registration arguments: tokens, classes, prepared fields, literals, named factory or initializer references, provider recipe objects and calls, and short DI factory callbacks such as (ctx) => ctx.get(Token). Move computed setup, environment reads, helper calls of this owner and callback bodies into imported implementations or prepared constructor inputs.');\n }\n }\n\n private registration(expression: ts.CallExpression | ts.NewExpression, scope: CanonicalFile): boolean {\n if (ts.isNewExpression(expression))\n return this.types.isFramework(expression.expression, 'ExternalContractUse') &&\n (expression.arguments ?? []).every((argument: ts.Expression) => ts.isStringLiteralLike(argument));\n if (!ts.isPropertyAccessExpression(expression.expression)) return false;\n const name = expression.expression.name.text;\n const receiver = this.unwrap(expression.expression.expression);\n const file = this.signatureFile(expression);\n if (file === undefined) return false;\n if (name === 'load') return INVERSIFY.test(file) && this.moduleReceiver(receiver);\n if (!WEBPIECES_SDK.test(file) && !INVERSIFY.test(file)) return false;\n if (ts.isCallExpression(receiver)) return this.registration(receiver, scope);\n return REGISTRATION_ROOTS.includes(name) && (this.path(receiver) || this.clientBinder(receiver));\n }\n\n /** Every argument of every call in a registration chain, plus a loaded module's construction arguments. */\n private registrationArguments(expression: ts.CallExpression | ts.NewExpression): ts.Expression[] {\n const own = [...(expression.arguments ?? [])];\n if (!ts.isCallExpression(expression) || !ts.isPropertyAccessExpression(expression.expression)) return own;\n const receiver = this.unwrap(expression.expression.expression);\n if (ts.isCallExpression(receiver)) {\n if (expression.expression.name.text === 'load') return [...own, ...receiver.arguments];\n return [...own, ...this.registrationArguments(receiver)];\n }\n if (ts.isNewExpression(receiver)) return [...own, ...(receiver.arguments ?? [])];\n return own;\n }\n\n /** `X.load`, `new X(prepared).load` or `createX(prepared).load`: an explicit, opaque module load. */\n private moduleReceiver(receiver: ts.Expression): boolean {\n if (this.path(receiver)) return true;\n if (ts.isNewExpression(receiver) || ts.isCallExpression(receiver))\n return this.path(receiver.expression) && !LEGACY_TOPOLOGY.test(receiver.expression.getText());\n return false;\n }\n\n private clientBinder(expression: ts.Expression): boolean {\n return ts.isNewExpression(expression) &&\n ['RuntimeClients', 'RuntimeTaskClients'].some((name: string) => this.types.isFramework(expression.expression, name)) &&\n (expression.arguments ?? []).every((argument: ts.Expression) => this.prepared(argument));\n }\n\n /** Returns the first non-declarative node inside a registration argument, or undefined. */\n private offending(expression: ts.Expression, scope: CanonicalFile): ts.Node | undefined {\n const value = this.unwrap(expression);\n if (this.literal(value)) return undefined;\n if (ts.isIdentifier(value) || value.kind === ts.SyntaxKind.ThisKeyword || ts.isPropertyAccessExpression(value))\n return this.path(value) ? undefined : value;\n if (ts.isArrayLiteralExpression(value)) {\n for (const element of value.elements) {\n const found = this.offending(ts.isSpreadElement(element) ? element.expression : element, scope);\n if (found !== undefined) return found;\n }\n return undefined;\n }\n if (ts.isObjectLiteralExpression(value)) {\n for (const property of value.properties) {\n if (ts.isShorthandPropertyAssignment(property)) {\n if (ENVIRONMENT.has(property.name.text)) return property;\n continue;\n }\n const initializer = ts.isPropertyAssignment(property) && !ts.isComputedPropertyName(property.name)\n ? property.initializer : ts.isSpreadAssignment(property) ? property.expression : undefined;\n if (initializer === undefined) return property;\n const found = this.offending(initializer, scope);\n if (found !== undefined) return found;\n }\n return undefined;\n }\n if (ts.isNewExpression(value)) {\n if (!this.path(value.expression) || LEGACY_TOPOLOGY.test(value.expression.getText())) return value;\n return this.firstOffending(value.arguments ?? [], scope);\n }\n if (ts.isCallExpression(value)) {\n const callee = value.expression;\n const receiverOk = this.path(callee) ||\n (ts.isPropertyAccessExpression(callee) && ts.isNewExpression(callee.expression) && this.offending(callee.expression, scope) === undefined);\n if (!receiverOk || !this.outsideOwner(value, scope)) return value;\n return this.firstOffending(value.arguments, scope);\n }\n if (ts.isArrowFunction(value)) return this.factoryCallback(value) ? undefined : value;\n return value;\n }\n\n private firstOffending(values: readonly ts.Expression[], scope: CanonicalFile): ts.Node | undefined {\n for (const value of values) {\n const found = this.offending(value, scope);\n if (found !== undefined) return found;\n }\n return undefined;\n }\n\n /**\n * A provider recipe or vendor factory (Angular, webpieces, another library) is a declaration; a\n * call into this owner's own helpers would hide the registrations it returns.\n */\n private outsideOwner(call: ts.CallExpression, scope: CanonicalFile): boolean {\n const file = this.signatureFile(call);\n if (file === undefined) return false;\n return file.includes('/node_modules/') || !file.startsWith(scope.ownerRoot.replace(/\\\\/g, '/') + '/');\n }\n\n /** A short DI factory: `(ctx) => ctx.get(Token)`, `(dep) => dep.build()` or `(dep) => new Named(dep)`. */\n private factoryCallback(arrow: ts.ArrowFunction): boolean {\n if (ts.isBlock(arrow.body)) return false;\n const parameters = new Set(arrow.parameters.map((parameter: ts.ParameterDeclaration) => parameter.name.getText()));\n const body = this.unwrap(arrow.body);\n const simple = (argument: ts.Expression): boolean => this.literal(this.unwrap(argument)) || this.path(this.unwrap(argument));\n if (ts.isNewExpression(body)) return this.path(body.expression) && (body.arguments ?? []).every(simple);\n if (!ts.isCallExpression(body) || !ts.isPropertyAccessExpression(body.expression)) return false;\n const receiver = body.expression.expression;\n return ts.isIdentifier(receiver) && parameters.has(receiver.text) && body.arguments.every(simple);\n }\n\n /** An identifier, `this`, or a property path over them that does not read the environment. */\n private path(expression: ts.Expression): boolean {\n if (ts.isIdentifier(expression)) return !ENVIRONMENT.has(expression.text);\n if (expression.kind === ts.SyntaxKind.ThisKeyword) return true;\n return ts.isPropertyAccessExpression(expression) && this.path(expression.expression);\n }\n\n private literal(expression: ts.Expression): boolean {\n if (ts.isStringLiteralLike(expression) || ts.isNumericLiteral(expression)) return true;\n if (ts.isPrefixUnaryExpression(expression)) return ts.isNumericLiteral(expression.operand);\n return [ts.SyntaxKind.TrueKeyword, ts.SyntaxKind.FalseKeyword, ts.SyntaxKind.NullKeyword].includes(expression.kind) ||\n (ts.isIdentifier(expression) && expression.text === 'undefined');\n }\n\n private unwrap(expression: ts.Expression): ts.Expression {\n if (ts.isParenthesizedExpression(expression) || ts.isAsExpression(expression) || ts.isNonNullExpression(expression) || ts.isSatisfiesExpression(expression))\n return this.unwrap(expression.expression);\n return expression;\n }\n\n private signatureFile(call: ts.CallExpression): string | undefined {\n const declaration = this.checker.getResolvedSignature(call)?.declaration;\n return declaration === undefined ? undefined : path.resolve(declaration.getSourceFile().fileName).replace(/\\\\/g, '/');\n }\n}\n"]}
|
|
@@ -31,7 +31,7 @@ class WorkspaceWiringFormat {
|
|
|
31
31
|
const rule = (0, rules_config_1.loadAndValidate)(root).resolved.rules.get('wiring-format');
|
|
32
32
|
const maxLines = rule?.options['maxLines'];
|
|
33
33
|
if (typeof maxLines !== 'number' || !Number.isInteger(maxLines) || maxLines < 1)
|
|
34
|
-
throw new rules_config_1.RuleFailError('wiring-format', 'Declare wiring-format.maxLines as a positive integer (agreed limit:
|
|
34
|
+
throw new rules_config_1.RuleFailError('wiring-format', 'Declare wiring-format.maxLines as a positive integer (agreed limit: 400).');
|
|
35
35
|
this.assert(root, infos, maxLines);
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-format.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/workspace-format.ts"],"names":[],"mappings":";;;;AAAA,mDAA6B;AAC7B,uDAAiC;AACjC,0DAAyE;AAEzE,4CAAwC;AACxC,yDAA0D;AAC1D,mDAA+C;AAE/C,uFAAuF;AACvF,MAAa,qBAAqB;IAC9B,MAAM,CAAC,IAAY,EAAE,KAAuC,EAAE,QAAgB;QAC1E,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YAChC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAAE,SAAS;YAC7F,MAAM,OAAO,GAAG,IAAI,uCAAoB,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAC9D,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC;YACnF,IAAI,IAAI,KAAK,SAAS;gBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,iEAAiE,CAAC,CAAC;;gBAChH,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,4BAAY,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/F,CAAC;QACD,oDAAoD;QACpD,IAAI,4BAAY,CAAC,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,cAAc,EAAE,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC3F,CAAC;IAED,GAAG,CAAC,IAAY,EAAE,KAAuC;QACrD,IAAI,IAAI,oBAAQ,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,eAAe,EAAE,IAAI,CAAC,KAAK,IAAI;YAAE,OAAO;QAC5E,MAAM,IAAI,GAAG,IAAA,8BAAe,EAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QACvE,MAAM,QAAQ,GAAG,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;QAC3C,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC;YAC3E,MAAM,IAAI,4BAAa,CAAC,eAAe,EAAE,2EAA2E,CAAC,CAAC;QAC1H,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IACvC,CAAC;CACJ;AAtBD,sDAsBC","sourcesContent":["import * as path from 'path';\nimport * as ts from 'typescript';\nimport { loadAndValidate, RuleFailError } from '@webpieces/rules-config';\nimport type { ProjectInfo } from '../project-info';\nimport { RuleGate } from '../rule-gate';\nimport { WiringProjectProgram } from './source-extractor';\nimport { WiringFormat } from './wiring-format';\n\n/** Every participating canonical file is checked, irrespective of the current diff. */\nexport class WorkspaceWiringFormat {\n assert(root: string, infos: ReadonlyMap<string, ProjectInfo>, maxLines: number): void {\n const problems: string[] = [];\n for (const info of infos.values()) {\n if (!info.tags.some((tag: string) => ['webpieces', 'webpieces-lib'].includes(tag))) continue;\n const program = new WiringProjectProgram().create(root, info);\n const file = program.getSourceFile(path.resolve(root, info.root, 'src/wiring.ts'));\n if (file === undefined) problems.push(`${info.root}/src/wiring.ts: missing canonical Wiring/AppWiring declaration.`);\n else problems.push(...new WiringFormat(program.getTypeChecker(), maxLines).problems(file));\n }\n // Rendering the aggregate needs no source compiler.\n new WiringFormat(ts.createProgram([], {}).getTypeChecker(), maxLines).assert(problems);\n }\n\n run(root: string, infos: ReadonlyMap<string, ProjectInfo>): void {\n if (new RuleGate().skipReason(root, 'wiring-format', true) !== null) return;\n const rule = loadAndValidate(root).resolved.rules.get('wiring-format');\n const maxLines = rule?.options['maxLines'];\n if (typeof maxLines !== 'number' || !Number.isInteger(maxLines) || maxLines < 1)\n throw new RuleFailError('wiring-format', 'Declare wiring-format.maxLines as a positive integer (agreed limit:
|
|
1
|
+
{"version":3,"file":"workspace-format.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/workspace-format.ts"],"names":[],"mappings":";;;;AAAA,mDAA6B;AAC7B,uDAAiC;AACjC,0DAAyE;AAEzE,4CAAwC;AACxC,yDAA0D;AAC1D,mDAA+C;AAE/C,uFAAuF;AACvF,MAAa,qBAAqB;IAC9B,MAAM,CAAC,IAAY,EAAE,KAAuC,EAAE,QAAgB;QAC1E,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YAChC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAAE,SAAS;YAC7F,MAAM,OAAO,GAAG,IAAI,uCAAoB,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAC9D,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC;YACnF,IAAI,IAAI,KAAK,SAAS;gBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,iEAAiE,CAAC,CAAC;;gBAChH,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,4BAAY,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/F,CAAC;QACD,oDAAoD;QACpD,IAAI,4BAAY,CAAC,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,cAAc,EAAE,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC3F,CAAC;IAED,GAAG,CAAC,IAAY,EAAE,KAAuC;QACrD,IAAI,IAAI,oBAAQ,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,eAAe,EAAE,IAAI,CAAC,KAAK,IAAI;YAAE,OAAO;QAC5E,MAAM,IAAI,GAAG,IAAA,8BAAe,EAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QACvE,MAAM,QAAQ,GAAG,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;QAC3C,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC;YAC3E,MAAM,IAAI,4BAAa,CAAC,eAAe,EAAE,2EAA2E,CAAC,CAAC;QAC1H,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IACvC,CAAC;CACJ;AAtBD,sDAsBC","sourcesContent":["import * as path from 'path';\nimport * as ts from 'typescript';\nimport { loadAndValidate, RuleFailError } from '@webpieces/rules-config';\nimport type { ProjectInfo } from '../project-info';\nimport { RuleGate } from '../rule-gate';\nimport { WiringProjectProgram } from './source-extractor';\nimport { WiringFormat } from './wiring-format';\n\n/** Every participating canonical file is checked, irrespective of the current diff. */\nexport class WorkspaceWiringFormat {\n assert(root: string, infos: ReadonlyMap<string, ProjectInfo>, maxLines: number): void {\n const problems: string[] = [];\n for (const info of infos.values()) {\n if (!info.tags.some((tag: string) => ['webpieces', 'webpieces-lib'].includes(tag))) continue;\n const program = new WiringProjectProgram().create(root, info);\n const file = program.getSourceFile(path.resolve(root, info.root, 'src/wiring.ts'));\n if (file === undefined) problems.push(`${info.root}/src/wiring.ts: missing canonical Wiring/AppWiring declaration.`);\n else problems.push(...new WiringFormat(program.getTypeChecker(), maxLines).problems(file));\n }\n // Rendering the aggregate needs no source compiler.\n new WiringFormat(ts.createProgram([], {}).getTypeChecker(), maxLines).assert(problems);\n }\n\n run(root: string, infos: ReadonlyMap<string, ProjectInfo>): void {\n if (new RuleGate().skipReason(root, 'wiring-format', true) !== null) return;\n const rule = loadAndValidate(root).resolved.rules.get('wiring-format');\n const maxLines = rule?.options['maxLines'];\n if (typeof maxLines !== 'number' || !Number.isInteger(maxLines) || maxLines < 1)\n throw new RuleFailError('wiring-format', 'Declare wiring-format.maxLines as a positive integer (agreed limit: 400).');\n this.assert(root, infos, maxLines);\n }\n}\n"]}
|
package/src/rule-help.js
CHANGED
|
@@ -4,7 +4,7 @@ exports.ruleHelp = void 0;
|
|
|
4
4
|
const rules_sdk_1 = require("@webpieces/rules-sdk");
|
|
5
5
|
/** Owner-authored guidance consumed by the registry catalog. */
|
|
6
6
|
exports.ruleHelp = {
|
|
7
|
-
'wiring-format': new rules_sdk_1.RuleHelp('Check every canonical wiring.ts
|
|
7
|
+
'wiring-format': new rules_sdk_1.RuleHelp('Check every canonical wiring.ts: its Wiring/AppWiring class plus the BindingModule/RouteModule classes it selects, with their actual registrations.', 'Declare each owner\'s Wiring/AppWiring class beside its named BindingModule/RouteModule classes and their registrations (bindRpc, provideRpcClient, bindPubSub, addRoutes, addFilter, DI binds, provider recipes) in its src/wiring.ts; select them with literal return arrays and select library Wirings only from AppWiring. Keep constructors as prepared-input storage, keep configuration building, environment discovery and initializer/factory bodies in imported implementations, use direct service strings and explicit WiringPolicy declarations. Set maxLines explicitly (agreed upstream limit: 400).'),
|
|
8
8
|
'no-file-import-cycles': new rules_sdk_1.RuleHelp('Keep each project free of circular file imports.', 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.'),
|
|
9
9
|
'runtime-architecture': new rules_sdk_1.RuleHelp('Validate runtime service and API dependency declarations.', 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.'),
|
|
10
10
|
'nx-wiring': new rules_sdk_1.RuleHelp('Wire the required validation targets into the Nx execution graph.', 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.'),
|
package/src/rule-help.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-help.js","sourceRoot":"","sources":["../../../../../packages/tooling/nx-webpieces-rules/src/rule-help.ts"],"names":[],"mappings":";;;AAAA,oDAAgD;AAEhD,gEAAgE;AACnD,QAAA,QAAQ,GAAuC;IACxD,eAAe,EAAE,IAAI,oBAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"rule-help.js","sourceRoot":"","sources":["../../../../../packages/tooling/nx-webpieces-rules/src/rule-help.ts"],"names":[],"mappings":";;;AAAA,oDAAgD;AAEhD,gEAAgE;AACnD,QAAA,QAAQ,GAAuC;IACxD,eAAe,EAAE,IAAI,oBAAQ,CAAC,qJAAqJ,EAAE,qlBAAqlB,CAAC;IAC3wB,uBAAuB,EAAE,IAAI,oBAAQ,CACjC,kDAAkD,EAClD,sIAAsI,CACzI;IACD,sBAAsB,EAAE,IAAI,oBAAQ,CAChC,2DAA2D,EAC3D,sIAAsI,CACzI;IACD,WAAW,EAAE,IAAI,oBAAQ,CACrB,mEAAmE,EACnE,sIAAsI,CACzI;IACD,UAAU,EAAE,IAAI,oBAAQ,CACpB,2DAA2D,EAC3D,sIAAsI,CACzI;IACD,2BAA2B,EAAE,IAAI,oBAAQ,CACrC,gEAAgE,EAChE,sIAAsI,CACzI;IACD,iCAAiC,EAAE,IAAI,oBAAQ,CAC3C,0EAA0E,EAC1E,2dAA2d,CAC9d;IACD,iCAAiC,EAAE,IAAI,oBAAQ,CAC3C,0DAA0D,EAC1D,sIAAsI,CACzI;IACD,sBAAsB,EAAE,IAAI,oBAAQ,CAChC,gEAAgE,EAChE,sIAAsI,CACzI;IACD,0BAA0B,EAAE,IAAI,oBAAQ,CACpC,gEAAgE,EAChE,sIAAsI,CACzI;IACD,sBAAsB,EAAE,IAAI,oBAAQ,CAChC,8EAA8E,EAC9E,sIAAsI,CACzI;IACD,wBAAwB,EAAE,IAAI,oBAAQ,CAClC,qEAAqE,EACrE,sIAAsI,CACzI;IACD,uBAAuB,EAAE,IAAI,oBAAQ,CACjC,uEAAuE,EACvE,sIAAsI,CACzI;IACD,mBAAmB,EAAE,IAAI,oBAAQ,CAC7B,mEAAmE,EACnE,sIAAsI,CACzI;IACD,sBAAsB,EAAE,IAAI,oBAAQ,CAChC,+DAA+D,EAC/D,sIAAsI,CACzI;IACD,cAAc,EAAE,IAAI,oBAAQ,CACxB,sDAAsD,EACtD,sIAAsI,CACzI;IACD,kBAAkB,EAAE,IAAI,oBAAQ,CAC5B,gEAAgE,EAChE,sIAAsI,CACzI;CACJ,CAAC","sourcesContent":["import { RuleHelp } from '@webpieces/rules-sdk';\n\n/** Owner-authored guidance consumed by the registry catalog. */\nexport const ruleHelp: Readonly<Record<string, RuleHelp>> = {\n 'wiring-format': new RuleHelp('Check every canonical wiring.ts: its Wiring/AppWiring class plus the BindingModule/RouteModule classes it selects, with their actual registrations.', 'Declare each owner\\'s Wiring/AppWiring class beside its named BindingModule/RouteModule classes and their registrations (bindRpc, provideRpcClient, bindPubSub, addRoutes, addFilter, DI binds, provider recipes) in its src/wiring.ts; select them with literal return arrays and select library Wirings only from AppWiring. Keep constructors as prepared-input storage, keep configuration building, environment discovery and initializer/factory bodies in imported implementations, use direct service strings and explicit WiringPolicy declarations. Set maxLines explicitly (agreed upstream limit: 400).'),\n 'no-file-import-cycles': new RuleHelp(\n 'Keep each project free of circular file imports.',\n 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.',\n ),\n 'runtime-architecture': new RuleHelp(\n 'Validate runtime service and API dependency declarations.',\n 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.',\n ),\n 'nx-wiring': new RuleHelp(\n 'Wire the required validation targets into the Nx execution graph.',\n 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.',\n ),\n 'di-graph': new RuleHelp(\n 'Generate and validate dependency-injection design graphs.',\n 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.',\n ),\n 'missing-design-annotation': new RuleHelp(\n 'Declare the application design roots required for DI analysis.',\n 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.',\n ),\n 'validate-architecture-unchanged': new RuleHelp(\n 'Keep the committed architecture graph aligned with current dependencies.',\n 'In src/wiring.ts use new RuntimeClients(options).bindRpc(token, Api, deployment, filters?) from @webpieces/http-client-node, new RuntimeTaskClients(options).bindPubSub(token, Api, deployment) from @webpieces/cloudtasks-client, and provideRpcClient(token, Api, deployment) from @webpieces/http-client-browser. wiring-format checks canonical wiring.ts in all participating owners; preserve tokens and filters. Review graph changes and runtime-deps.json candidates explicitly.',\n ),\n 'validate-no-architecture-cycles': new RuleHelp(\n 'Keep the project dependency architecture free of cycles.',\n 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.',\n ),\n 'validate-packagejson': new RuleHelp(\n 'Align package dependencies with declared project dependencies.',\n 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.',\n ),\n 'validate-versions-locked': new RuleHelp(\n 'Pin dependency versions consistently across governed projects.',\n 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.',\n ),\n 'validate-eslint-sync': new RuleHelp(\n 'Keep managed ESLint configuration synchronized with its installed templates.',\n 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.',\n ),\n 'no-root-union-api-type': new RuleHelp(\n 'Use a stable named root API contract rather than a root union type.',\n 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.',\n ),\n 'api-rules-for-openapi': new RuleHelp(\n 'Validate API contracts against their configured OpenAPI requirements.',\n 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.',\n ),\n 'api-rules-for-mcp': new RuleHelp(\n 'Validate API contracts against their configured MCP requirements.',\n 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.',\n ),\n 'api-lib-dependencies': new RuleHelp(\n 'Validate the configured API library dependency relationships.',\n 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.',\n ),\n 'api-lib-path': new RuleHelp(\n 'Use the configured paths for API contract libraries.',\n 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.',\n ),\n 'framework-folder': new RuleHelp(\n 'Align framework declarations with their project folder layout.',\n 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.',\n ),\n};\n"]}
|
package/src/rule-settings.js
CHANGED
package/src/rule-settings.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-settings.js","sourceRoot":"","sources":["../../../../../packages/tooling/nx-webpieces-rules/src/rule-settings.ts"],"names":[],"mappings":"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","sourcesContent":["import { ConfigObject } from '@webpieces/rules-sdk';\n\n/** Optional knobs only. Required behaviour is always supplied by the repository. */\nexport const optionalTuning: Readonly<Record<string, ConfigObject>> = {\n \"wiring-format\": {},\n \"no-file-import-cycles\": {},\n \"runtime-architecture\": {},\n \"nx-wiring\": {},\n \"di-graph\": {},\n \"missing-design-annotation\": {},\n \"validate-architecture-unchanged\": {},\n \"validate-no-architecture-cycles\": {},\n \"validate-packagejson\": {},\n \"validate-versions-locked\": {},\n \"validate-eslint-sync\": {},\n \"no-root-union-api-type\": {},\n \"api-rules-for-openapi\": {},\n \"api-rules-for-mcp\": {},\n \"api-lib-dependencies\": {},\n \"api-lib-path\": {},\n \"framework-folder\": {}\n};\n\n/** Written for review by setup/sync; never used as a loader fallback. */\nexport const recommendedSeeds: Readonly<Record<string, ConfigObject>> = {\n \"wiring-format\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"maxLines\": 200,\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"no-file-import-cycles\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"runtime-architecture\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"nx-wiring\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"di-graph\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"missing-design-annotation\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"validate-architecture-unchanged\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"validate-no-architecture-cycles\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"validate-packagejson\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"validate-versions-locked\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"validate-eslint-sync\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"no-root-union-api-type\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"api-rules-for-openapi\": {\n \"mode\": \"AFFECTED_PROJECT\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"api-rules-for-mcp\": {\n \"mode\": \"AFFECTED_PROJECT\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"api-lib-dependencies\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null,\n \"apiLibPackages\": [\n \"@webpieces/core-util\",\n \"tslib\"\n ],\n \"apiClients\": []\n },\n \"api-lib-path\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null,\n \"paths\": [\n \"libraries/apis/**\"\n ]\n },\n \"framework-folder\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null,\n \"entries\": [\n {\n \"paths\": [\n \"libraries/angular/**\"\n ],\n \"frameworkSets\": [\n \"angular\"\n ],\n \"roles\": [\n \"lib\",\n \"designed-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/node/**\"\n ],\n \"frameworkSets\": [\n \"node\",\n \"express\"\n ],\n \"roles\": [\n \"lib\",\n \"designed-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/universal/**\"\n ],\n \"frameworkSets\": [\n \"browser+node+react-native\"\n ],\n \"roles\": [\n \"lib\",\n \"designed-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/rn-browser/**\"\n ],\n \"frameworkSets\": [\n \"browser+react-native\"\n ],\n \"roles\": [\n \"lib\",\n \"designed-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/react-native/**\"\n ],\n \"frameworkSets\": [\n \"react-native\"\n ],\n \"roles\": [\n \"lib\",\n \"designed-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/apis/internal/**\"\n ],\n \"frameworkSets\": [\n \"browser+node+react-native\"\n ],\n \"roles\": [\n \"api-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/apis/external-node/**\"\n ],\n \"frameworkSets\": [\n \"node\"\n ],\n \"roles\": [\n \"api-client\"\n ]\n },\n {\n \"paths\": [\n \"libraries/apis/external-rn-browser/**\"\n ],\n \"frameworkSets\": [\n \"browser+react-native\"\n ],\n \"roles\": [\n \"api-lib\"\n ]\n }\n ]\n }\n};\n"]}
|
|
1
|
+
{"version":3,"file":"rule-settings.js","sourceRoot":"","sources":["../../../../../packages/tooling/nx-webpieces-rules/src/rule-settings.ts"],"names":[],"mappings":"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","sourcesContent":["import { ConfigObject } from '@webpieces/rules-sdk';\n\n/** Optional knobs only. Required behaviour is always supplied by the repository. */\nexport const optionalTuning: Readonly<Record<string, ConfigObject>> = {\n \"wiring-format\": {},\n \"no-file-import-cycles\": {},\n \"runtime-architecture\": {},\n \"nx-wiring\": {},\n \"di-graph\": {},\n \"missing-design-annotation\": {},\n \"validate-architecture-unchanged\": {},\n \"validate-no-architecture-cycles\": {},\n \"validate-packagejson\": {},\n \"validate-versions-locked\": {},\n \"validate-eslint-sync\": {},\n \"no-root-union-api-type\": {},\n \"api-rules-for-openapi\": {},\n \"api-rules-for-mcp\": {},\n \"api-lib-dependencies\": {},\n \"api-lib-path\": {},\n \"framework-folder\": {}\n};\n\n/** Written for review by setup/sync; never used as a loader fallback. */\nexport const recommendedSeeds: Readonly<Record<string, ConfigObject>> = {\n \"wiring-format\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"maxLines\": 400,\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"no-file-import-cycles\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"runtime-architecture\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"nx-wiring\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"di-graph\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"missing-design-annotation\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"validate-architecture-unchanged\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"validate-no-architecture-cycles\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"validate-packagejson\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"validate-versions-locked\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"validate-eslint-sync\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"no-root-union-api-type\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"api-rules-for-openapi\": {\n \"mode\": \"AFFECTED_PROJECT\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"api-rules-for-mcp\": {\n \"mode\": \"AFFECTED_PROJECT\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"api-lib-dependencies\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null,\n \"apiLibPackages\": [\n \"@webpieces/core-util\",\n \"tslib\"\n ],\n \"apiClients\": []\n },\n \"api-lib-path\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null,\n \"paths\": [\n \"libraries/apis/**\"\n ]\n },\n \"framework-folder\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null,\n \"entries\": [\n {\n \"paths\": [\n \"libraries/angular/**\"\n ],\n \"frameworkSets\": [\n \"angular\"\n ],\n \"roles\": [\n \"lib\",\n \"designed-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/node/**\"\n ],\n \"frameworkSets\": [\n \"node\",\n \"express\"\n ],\n \"roles\": [\n \"lib\",\n \"designed-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/universal/**\"\n ],\n \"frameworkSets\": [\n \"browser+node+react-native\"\n ],\n \"roles\": [\n \"lib\",\n \"designed-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/rn-browser/**\"\n ],\n \"frameworkSets\": [\n \"browser+react-native\"\n ],\n \"roles\": [\n \"lib\",\n \"designed-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/react-native/**\"\n ],\n \"frameworkSets\": [\n \"react-native\"\n ],\n \"roles\": [\n \"lib\",\n \"designed-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/apis/internal/**\"\n ],\n \"frameworkSets\": [\n \"browser+node+react-native\"\n ],\n \"roles\": [\n \"api-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/apis/external-node/**\"\n ],\n \"frameworkSets\": [\n \"node\"\n ],\n \"roles\": [\n \"api-client\"\n ]\n },\n {\n \"paths\": [\n \"libraries/apis/external-rn-browser/**\"\n ],\n \"frameworkSets\": [\n \"browser+react-native\"\n ],\n \"roles\": [\n \"api-lib\"\n ]\n }\n ]\n }\n};\n"]}
|