@webpieces/nx-webpieces-rules 0.4.865 → 0.4.866
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/configs/wiring-format-config.d.ts +7 -0
- package/src/configs/wiring-format-config.js +14 -0
- package/src/configs/wiring-format-config.js.map +1 -0
- package/src/executors/generate/executor.d.ts +11 -0
- package/src/executors/generate/executor.js +49 -42
- package/src/executors/generate/executor.js.map +1 -1
- package/src/executors/validate-architecture-unchanged/executor.js +0 -2
- package/src/executors/validate-architecture-unchanged/executor.js.map +1 -1
- package/src/index.d.ts +1 -0
- package/src/index.js +3 -1
- package/src/index.js.map +1 -1
- package/src/lib/di-graph/angular-providers.js +67 -39
- package/src/lib/di-graph/angular-providers.js.map +1 -1
- package/src/lib/di-graph/runtime-client-bindings.d.ts +1 -0
- package/src/lib/di-graph/runtime-client-bindings.js +10 -0
- package/src/lib/di-graph/runtime-client-bindings.js.map +1 -1
- package/src/lib/runtime-wiring/approved-graph.js +1 -2
- package/src/lib/runtime-wiring/approved-graph.js.map +1 -1
- package/src/lib/runtime-wiring/assembler.d.ts +2 -1
- package/src/lib/runtime-wiring/assembler.js +38 -18
- package/src/lib/runtime-wiring/assembler.js.map +1 -1
- package/src/lib/runtime-wiring/canonical-clients.d.ts +1 -8
- package/src/lib/runtime-wiring/canonical-clients.js +6 -45
- package/src/lib/runtime-wiring/canonical-clients.js.map +1 -1
- package/src/lib/runtime-wiring/codec.js +29 -9
- package/src/lib/runtime-wiring/codec.js.map +1 -1
- package/src/lib/runtime-wiring/declaration.d.ts +11 -6
- package/src/lib/runtime-wiring/declaration.js +8 -4
- package/src/lib/runtime-wiring/declaration.js.map +1 -1
- package/src/lib/runtime-wiring/prepared-targets.d.ts +11 -0
- package/src/lib/runtime-wiring/prepared-targets.js +82 -0
- package/src/lib/runtime-wiring/prepared-targets.js.map +1 -0
- package/src/lib/runtime-wiring/source-extractor.d.ts +4 -3
- package/src/lib/runtime-wiring/source-extractor.js +77 -118
- package/src/lib/runtime-wiring/source-extractor.js.map +1 -1
- package/src/lib/runtime-wiring/source-types.d.ts +13 -0
- package/src/lib/runtime-wiring/source-types.js +75 -0
- package/src/lib/runtime-wiring/source-types.js.map +1 -0
- package/src/lib/runtime-wiring/source-values.d.ts +4 -2
- package/src/lib/runtime-wiring/source-values.js +86 -35
- package/src/lib/runtime-wiring/source-values.js.map +1 -1
- package/src/lib/runtime-wiring/wiring-format.d.ts +15 -0
- package/src/lib/runtime-wiring/wiring-format.js +160 -0
- package/src/lib/runtime-wiring/wiring-format.js.map +1 -0
- package/src/lib/runtime-wiring/workspace-format.d.ts +6 -0
- package/src/lib/runtime-wiring/workspace-format.js +39 -0
- package/src/lib/runtime-wiring/workspace-format.js.map +1 -0
- package/src/native-actions.d.ts +1 -0
- package/src/native-actions.js +6 -0
- package/src/native-actions.js.map +1 -1
- package/src/nx-policy-registry.js +2 -0
- package/src/nx-policy-registry.js.map +1 -1
- package/src/rule-help.js +2 -1
- package/src/rule-help.js.map +1 -1
- package/src/rule-settings.js +7 -0
- package/src/rule-settings.js.map +1 -1
- package/src/runtime-wiring-targets.js +2 -0
- package/src/runtime-wiring-targets.js.map +1 -1
|
@@ -8,8 +8,15 @@ const rules_config_1 = require("@webpieces/rules-config");
|
|
|
8
8
|
const program_1 = require("../di-graph/program");
|
|
9
9
|
const declaration_1 = require("./declaration");
|
|
10
10
|
const source_values_1 = require("./source-values");
|
|
11
|
-
const
|
|
11
|
+
const source_types_1 = require("./source-types");
|
|
12
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
12
13
|
/** Build-only extraction. It never imports application modules or invokes their constructors. */
|
|
14
|
+
class WiringProjectMetadata {
|
|
15
|
+
}
|
|
16
|
+
class WiringProjectMetadataValues {
|
|
17
|
+
}
|
|
18
|
+
class WiringServiceMetadata {
|
|
19
|
+
}
|
|
13
20
|
class WiringSourceExtractor {
|
|
14
21
|
workspaceRoot;
|
|
15
22
|
info;
|
|
@@ -27,14 +34,6 @@ class WiringSourceExtractor {
|
|
|
27
34
|
this.values = new source_values_1.WiringSourceValues(workspaceRoot, infos, program.getTypeChecker());
|
|
28
35
|
}
|
|
29
36
|
extract() {
|
|
30
|
-
const clients = new canonical_clients_1.CanonicalClientBindings(this.program.getTypeChecker());
|
|
31
|
-
const problems = this.program
|
|
32
|
-
.getSourceFiles()
|
|
33
|
-
.filter((file) => !file.isDeclarationFile &&
|
|
34
|
-
this.owns(file.fileName) &&
|
|
35
|
-
!/(?:\.spec\.|\.test\.|\/__tests__\/)/.test(file.fileName))
|
|
36
|
-
.flatMap((file) => clients.problems(file));
|
|
37
|
-
clients.assert(problems);
|
|
38
37
|
const wiringPath = path.resolve(this.workspaceRoot, this.info.root, 'src/wiring.ts');
|
|
39
38
|
const wiring = this.program.getSourceFile(wiringPath);
|
|
40
39
|
if (wiring === undefined)
|
|
@@ -52,47 +51,27 @@ class WiringSourceExtractor {
|
|
|
52
51
|
? 'node'
|
|
53
52
|
: 'browser';
|
|
54
53
|
if (this.info.tags.includes('webpieces') && this.entry === undefined)
|
|
55
|
-
this.fail(`${this.info.name} requires
|
|
54
|
+
this.fail(`${this.info.name} requires one unambiguous exported AppWiring in src/wiring.ts.`);
|
|
56
55
|
return new declaration_1.RuntimeDeclaration(this.info.name, framework, this.exported, this.entry, this.host);
|
|
57
56
|
}
|
|
58
57
|
visit(node, inWiring) {
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
].includes(this.values.symbolName(node)))
|
|
68
|
-
this.fail(`${node.getSourceFile().fileName}: topology method references belong in src/wiring.ts, including aliases.`);
|
|
69
|
-
if (inWiring &&
|
|
70
|
-
ts.isNewExpression(node) &&
|
|
71
|
-
this.values.symbolName(node.expression) === 'ExternalContractUse')
|
|
72
|
-
this.recordExternal(node);
|
|
73
|
-
if (ts.isCallExpression(node)) {
|
|
58
|
+
if (ts.isClassDeclaration(node))
|
|
59
|
+
this.recordWiring(node, inWiring);
|
|
60
|
+
ts.forEachChild(node, (child) => this.visit(child, inWiring));
|
|
61
|
+
}
|
|
62
|
+
facts(node, owner) {
|
|
63
|
+
if (ts.isNewExpression(node) && new source_types_1.WiringSourceTypes(this.program.getTypeChecker()).isFramework(node.expression, 'ExternalContractUse'))
|
|
64
|
+
this.recordExternal(node, owner);
|
|
65
|
+
if (ts.isCallExpression(node) && this.frameworkCall(node)) {
|
|
74
66
|
const name = this.values.symbolName(node.expression);
|
|
75
|
-
if ([
|
|
76
|
-
|
|
77
|
-
'createRpcClient',
|
|
78
|
-
'createPubSubClient',
|
|
79
|
-
'bindRpc',
|
|
80
|
-
'bindPubSub',
|
|
81
|
-
'provideRpcClient',
|
|
82
|
-
].includes(name)) {
|
|
83
|
-
if (!inWiring)
|
|
84
|
-
this.fail(`${node.getSourceFile().fileName}: ${name} must be owned by src/wiring.ts.`);
|
|
85
|
-
this.recordRelationship(node, name);
|
|
86
|
-
}
|
|
67
|
+
if (['addRoutes', 'createRpcClient', 'createPubSubClient', 'bindRpc', 'bindPubSub', 'provideRpcClient'].includes(name))
|
|
68
|
+
this.recordRelationship(node, name, owner);
|
|
87
69
|
}
|
|
88
|
-
|
|
89
|
-
this.recordPlan(node);
|
|
90
|
-
ts.forEachChild(node, (child) => this.visit(child, inWiring));
|
|
70
|
+
ts.forEachChild(node, (child) => this.facts(child, owner));
|
|
91
71
|
}
|
|
92
|
-
recordExternal(expression) {
|
|
93
|
-
const owner = this.exportOwner(expression);
|
|
72
|
+
recordExternal(expression, owner) {
|
|
94
73
|
const identity = expression.arguments?.[0];
|
|
95
|
-
if (
|
|
74
|
+
if (identity === undefined || !ts.isStringLiteralLike(identity))
|
|
96
75
|
this.fail('ExternalContractUse belongs to a selected exported module and requires a literal project#contract identity.');
|
|
97
76
|
const qualified = identity.text.split('#');
|
|
98
77
|
const project = qualified[0];
|
|
@@ -102,20 +81,14 @@ class WiringSourceExtractor {
|
|
|
102
81
|
this.fail('ExternalContractUse requires one qualified project#contract identity.');
|
|
103
82
|
if (!this.values.hasExternalConsumer(this.info.name, project, exportedName, this.program))
|
|
104
83
|
this.fail(`${project}#${exportedName} has no production business consumer in ${this.info.name}; adapters and test doubles do not establish uses.`);
|
|
105
|
-
const exported = this.exported[owner]
|
|
84
|
+
const exported = this.exported[owner];
|
|
106
85
|
exported.relationships.push(new declaration_1.WiringRelationship(new declaration_1.ContractIdentity(project, exportedName), new declaration_1.UsesFacts('external', {
|
|
107
86
|
kind: 'unknown',
|
|
108
87
|
reason: 'Vendor interface; destination classified by approved contract metadata',
|
|
109
88
|
})));
|
|
110
89
|
this.exported[owner] = exported;
|
|
111
90
|
}
|
|
112
|
-
recordRelationship(call, method) {
|
|
113
|
-
const owner = this.exportOwner(call);
|
|
114
|
-
// The generic Angular integration adapter defines the primitive; its invocations own facts.
|
|
115
|
-
if (owner === 'provideRpcClient' && method === 'createRpcClient')
|
|
116
|
-
return;
|
|
117
|
-
if (owner === undefined)
|
|
118
|
-
this.fail(`Unowned ${method} at ${call.getSourceFile().fileName}:${call.getStart()}.`);
|
|
91
|
+
recordRelationship(call, method, owner) {
|
|
119
92
|
const apiIndex = method === 'bindRpc' || method === 'bindPubSub' || method === 'provideRpcClient'
|
|
120
93
|
? 1
|
|
121
94
|
: 0;
|
|
@@ -135,80 +108,66 @@ class WiringSourceExtractor {
|
|
|
135
108
|
const target = direction === 'implements'
|
|
136
109
|
? undefined
|
|
137
110
|
: this.values.target(call.arguments[apiIndex + 1]);
|
|
138
|
-
const
|
|
139
|
-
? 'routing'
|
|
140
|
-
: method === 'provideRpcClient'
|
|
141
|
-
? 'providers'
|
|
142
|
-
: 'binding';
|
|
143
|
-
const exported = this.exported[owner] ?? new declaration_1.WiringExport(kind, [], []);
|
|
111
|
+
const exported = this.exported[owner];
|
|
144
112
|
exported.relationships.push(new declaration_1.WiringRelationship(contract, direction === 'implements'
|
|
145
113
|
? new declaration_1.ImplementsFacts(transport, this.values.condition(call))
|
|
146
114
|
: new declaration_1.UsesFacts(transport, target, this.values.condition(call))));
|
|
147
115
|
this.exported[owner] = exported;
|
|
148
116
|
}
|
|
149
|
-
|
|
150
|
-
const
|
|
151
|
-
if (
|
|
152
|
-
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
this.fail(
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
else if (name === 'BrowserWiring')
|
|
170
|
-
arrays = args;
|
|
171
|
-
else
|
|
172
|
-
this.fail(`Unsupported plan ${name}; use ServerWiring or BrowserWiring.`);
|
|
173
|
-
const selections = [];
|
|
174
|
-
for (const array of arrays) {
|
|
175
|
-
if (!ts.isArrayLiteralExpression(array))
|
|
176
|
-
this.fail('Plan module/provider lists must be static arrays; dynamic composition needs an explicit supported policy.');
|
|
177
|
-
for (const element of array.elements) {
|
|
178
|
-
if (ts.isObjectLiteralExpression(element))
|
|
179
|
-
continue; // ordinary Angular providers; API factories are checked independently
|
|
180
|
-
if (ts.isCallExpression(element) &&
|
|
181
|
-
this.values.symbolName(element.expression) === 'provideRpcClient')
|
|
182
|
-
continue;
|
|
183
|
-
const invocation = ts.isNewExpression(element) || ts.isCallExpression(element)
|
|
184
|
-
? element
|
|
185
|
-
: undefined;
|
|
186
|
-
const identity = this.values.identity(invocation === undefined ? element : invocation.expression);
|
|
187
|
-
const targets = invocation === undefined ? {} : this.values.arguments(invocation);
|
|
188
|
-
selections.push(new declaration_1.WiringSelection(identity.project, identity.exportedName, targets, invocation === undefined ? {} : this.values.policies(invocation)));
|
|
189
|
-
if (identity.project === this.info.name &&
|
|
190
|
-
this.exported[identity.exportedName] === undefined)
|
|
191
|
-
this.exported[identity.exportedName] = new declaration_1.WiringExport('binding', [], []);
|
|
192
|
-
}
|
|
117
|
+
frameworkCall(call) {
|
|
118
|
+
const declaration = this.program.getTypeChecker().getResolvedSignature(call)?.declaration;
|
|
119
|
+
if (declaration === undefined)
|
|
120
|
+
return false;
|
|
121
|
+
const file = declaration.getSourceFile().fileName.replace(/\\/g, '/');
|
|
122
|
+
return /(?:\/packages\/(?:http|cloud)\/|\/node_modules\/@webpieces\/)(?:http-routing|http-client-node|http-client-browser|cloudtasks-client)\//.test(file);
|
|
123
|
+
}
|
|
124
|
+
recordWiring(declaration, inWiring) {
|
|
125
|
+
const types = new source_types_1.WiringSourceTypes(this.program.getTypeChecker());
|
|
126
|
+
const kind = types.kind(declaration);
|
|
127
|
+
const owner = this.exportOwner(declaration);
|
|
128
|
+
if (kind === undefined || owner === undefined)
|
|
129
|
+
return;
|
|
130
|
+
if (kind === 'binding' || kind === 'routing') {
|
|
131
|
+
this.exported[owner] = new declaration_1.WiringExport(kind, [], []);
|
|
132
|
+
const configure = types.method(declaration, 'configure');
|
|
133
|
+
if (configure === undefined || configure.body === undefined)
|
|
134
|
+
this.fail(`${owner}: named module requires a statically resolvable configure implementation.`);
|
|
135
|
+
this.facts(configure.body, owner);
|
|
136
|
+
return;
|
|
193
137
|
}
|
|
194
|
-
|
|
138
|
+
if (!inWiring)
|
|
139
|
+
this.fail(`${owner}: declare Wiring/AppWiring only in canonical src/wiring.ts.`);
|
|
140
|
+
const bindings = this.moduleSelections(types.method(declaration, 'getBindingModules'), 'binding');
|
|
141
|
+
const routes = this.moduleSelections(types.method(declaration, 'getRoutingModules'), 'routing');
|
|
142
|
+
const libraries = kind === 'app' ? this.moduleSelections(types.method(declaration, 'getWirings'), 'wiring') : [];
|
|
143
|
+
if (kind === 'wiring' && types.method(declaration, 'getWirings') !== undefined)
|
|
144
|
+
this.fail(`${owner}: library Wiring cannot select other Wirings.`);
|
|
145
|
+
this.exported[owner] = new declaration_1.WiringExport(kind, [], bindings, routes, libraries);
|
|
146
|
+
if (kind !== 'app')
|
|
147
|
+
return;
|
|
148
|
+
if (!this.info.tags.includes('webpieces'))
|
|
149
|
+
this.fail(`${owner}: library owners cannot declare an AppWiring entry.`);
|
|
150
|
+
if (this.entry !== undefined)
|
|
151
|
+
this.fail('Ambiguous AppWiring root; export exactly one application entry.');
|
|
195
152
|
this.entry = owner;
|
|
153
|
+
const projectFile = path.join(this.workspaceRoot, this.info.root, 'project.json');
|
|
154
|
+
if (fs.existsSync(projectFile)) {
|
|
155
|
+
const project = JSON.parse(fs.readFileSync(projectFile, 'utf8'));
|
|
156
|
+
this.host = project.metadata?.webpieces?.serviceName;
|
|
157
|
+
}
|
|
196
158
|
}
|
|
197
|
-
|
|
198
|
-
const
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
!ts.isNewExpression(returns[0].expression))
|
|
210
|
-
this.fail(`${owner}.getRuntimeWiring must return one statically composed plan.`);
|
|
211
|
-
return returns;
|
|
159
|
+
moduleSelections(method, expected) {
|
|
160
|
+
const statements = method?.body?.statements;
|
|
161
|
+
const expression = statements?.length === 1 && ts.isReturnStatement(statements[0]) ? statements[0].expression : undefined;
|
|
162
|
+
if (expression === undefined || !ts.isArrayLiteralExpression(expression))
|
|
163
|
+
this.fail(`Expected ${expected} getter to contain only return [new NamedModule(preparedInputs)].`);
|
|
164
|
+
const types = new source_types_1.WiringSourceTypes(this.program.getTypeChecker());
|
|
165
|
+
return expression.elements.map((element) => {
|
|
166
|
+
if (!ts.isNewExpression(element) || types.kind(element.expression) !== expected)
|
|
167
|
+
this.fail(`Wrong ${expected} selection ${element.getText()}; AppWiring children, delegation and nested lists are forbidden.`);
|
|
168
|
+
const identity = this.values.identity(element.expression);
|
|
169
|
+
return new declaration_1.WiringSelection(identity.project, identity.exportedName, this.values.arguments(element), this.values.policies(element));
|
|
170
|
+
});
|
|
212
171
|
}
|
|
213
172
|
exportOwner(node) {
|
|
214
173
|
let current = node;
|
|
@@ -237,7 +196,7 @@ class WiringSourceExtractor {
|
|
|
237
196
|
}
|
|
238
197
|
fail(message) {
|
|
239
198
|
throw new rules_config_1.RuleFailError('validate-runtime-architecture', message, undefined, undefined, [
|
|
240
|
-
new rules_config_1.Option('Move topology into canonical src/wiring.ts using RuntimeClients.bindRpc(token, Api,
|
|
199
|
+
new rules_config_1.Option('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.', true),
|
|
241
200
|
]);
|
|
242
201
|
}
|
|
243
202
|
}
|
|
@@ -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 { CanonicalClientBindings } from './canonical-clients';\n\n/** Build-only extraction. It never imports application modules or invokes their constructors. */\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 clients = new CanonicalClientBindings(this.program.getTypeChecker());\n const problems = this.program\n .getSourceFiles()\n .filter(\n (file) =>\n !file.isDeclarationFile &&\n this.owns(file.fileName) &&\n !/(?:\\.spec\\.|\\.test\\.|\\/__tests__\\/)/.test(file.fileName),\n )\n .flatMap((file) => clients.problems(file));\n clients.assert(problems);\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 getRuntimeWiring() returning a typed plan.`);\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 (\n !inWiring &&\n (ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node)) &&\n [\n 'addRoutes',\n 'createRpcClient',\n 'createPubSubClient',\n 'bindRpc',\n 'bindPubSub',\n ].includes(this.values.symbolName(node))\n )\n this.fail(\n `${node.getSourceFile().fileName}: topology method references belong in src/wiring.ts, including aliases.`,\n );\n if (\n inWiring &&\n ts.isNewExpression(node) &&\n this.values.symbolName(node.expression) === 'ExternalContractUse'\n )\n this.recordExternal(node);\n if (ts.isCallExpression(node)) {\n const name = this.values.symbolName(node.expression);\n if (\n [\n 'addRoutes',\n 'createRpcClient',\n 'createPubSubClient',\n 'bindRpc',\n 'bindPubSub',\n 'provideRpcClient',\n ].includes(name)\n ) {\n if (!inWiring)\n this.fail(\n `${node.getSourceFile().fileName}: ${name} must be owned by src/wiring.ts.`,\n );\n this.recordRelationship(node, name);\n }\n }\n if (inWiring && ts.isMethodDeclaration(node) && node.name.getText() === 'getRuntimeWiring')\n this.recordPlan(node);\n ts.forEachChild(node, (child) => this.visit(child, inWiring));\n }\n\n private recordExternal(expression: ts.NewExpression): void {\n const owner = this.exportOwner(expression);\n const identity = expression.arguments?.[0];\n if (owner === undefined || 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!] ?? new WiringExport('binding', [], []);\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): void {\n const owner = this.exportOwner(call);\n // The generic Angular integration adapter defines the primitive; its invocations own facts.\n if (owner === 'provideRpcClient' && method === 'createRpcClient') return;\n if (owner === undefined)\n this.fail(`Unowned ${method} at ${call.getSourceFile().fileName}:${call.getStart()}.`);\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 kind =\n direction === 'implements'\n ? 'routing'\n : method === 'provideRpcClient'\n ? 'providers'\n : 'binding';\n const exported = this.exported[owner!] ?? new WiringExport(kind, [], []);\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 recordPlan(method: ts.MethodDeclaration): void {\n const owner = this.exportOwner(method);\n if (owner === undefined) this.fail('The plan class must be exported from src/wiring.ts.');\n const returns = this.planReturns(method, owner!);\n const expression = returns[0].expression as ts.NewExpression;\n const name = this.values.symbolName(expression.expression);\n const args = expression.arguments ?? [];\n let arrays: readonly ts.Expression[];\n if (name === 'ServerWiring') {\n const host = this.values.target(args[0]);\n if (host.kind !== 'service')\n this.fail('ServerWiring requires a literal host identity.');\n this.host = host.service;\n if (\n args[1] === undefined ||\n !ts.isNewExpression(args[1]) ||\n this.values.symbolName(args[1].expression) !== 'ServerWiringOptions'\n )\n this.fail(\n 'Use ServerWiringOptions with separate bindingModules and routingModules arrays.',\n );\n arrays = (args[1] as ts.NewExpression).arguments ?? [];\n } else if (name === 'BrowserWiring') arrays = args;\n else this.fail(`Unsupported plan ${name}; use ServerWiring or BrowserWiring.`);\n const selections: WiringSelection[] = [];\n for (const array of arrays) {\n if (!ts.isArrayLiteralExpression(array))\n this.fail(\n 'Plan module/provider lists must be static arrays; dynamic composition needs an explicit supported policy.',\n );\n for (const element of (array as ts.ArrayLiteralExpression).elements) {\n if (ts.isObjectLiteralExpression(element)) continue; // ordinary Angular providers; API factories are checked independently\n if (\n ts.isCallExpression(element) &&\n this.values.symbolName(element.expression) === 'provideRpcClient'\n )\n continue;\n const invocation =\n ts.isNewExpression(element) || ts.isCallExpression(element)\n ? element\n : undefined;\n const identity = this.values.identity(\n invocation === undefined ? element : invocation.expression,\n );\n const targets = invocation === undefined ? {} : this.values.arguments(invocation);\n selections.push(\n new WiringSelection(\n identity.project,\n identity.exportedName,\n targets,\n invocation === undefined ? {} : this.values.policies(invocation),\n ),\n );\n if (\n identity.project === this.info.name &&\n this.exported[identity.exportedName] === undefined\n )\n this.exported[identity.exportedName] = new WiringExport('binding', [], []);\n }\n }\n this.exported[owner!] = new WiringExport('plan', [], selections);\n this.entry = owner;\n }\n\n private planReturns(method: ts.MethodDeclaration, owner: string): ts.ReturnStatement[] {\n const returns: ts.ReturnStatement[] = [];\n const visit = (node: ts.Node): void => {\n if (ts.isReturnStatement(node)) returns.push(node);\n else ts.forEachChild(node, visit);\n };\n if (method.body !== undefined) visit(method.body);\n if (\n returns.length !== 1 ||\n returns[0].expression === undefined ||\n !ts.isNewExpression(returns[0].expression)\n )\n this.fail(`${owner}.getRuntimeWiring must return one statically composed plan.`);\n return returns;\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, rpcTarget(Api, deployment)), RuntimeTaskClients.bindPubSub, or provideRpcClient for supported registrations, and use the documented static plan 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":";;;;AAAA,mDAA6B;AAC7B,uDAAiC;AACjC,0DAAgE;AAEhE,iDAA2D;AAC3D,+CAQuB;AACvB,mDAAqD;AACrD,iDAAmD;AACnD,+CAAyB;AAEzB,iGAAiG;AACjG,MAAM,qBAAqB;CAE1B;AACD,MAAM,2BAA2B;CAEhC;AACD,MAAM,qBAAqB;CAE1B;AAED,MAAa,qBAAqB;IAOT;IACA;IACA;IACA;IATJ,MAAM,CAAqB;IAC3B,QAAQ,GAAiC,EAAE,CAAC;IACrD,KAAK,CAAqB;IAC1B,IAAI,CAAqB;IAEjC,YACqB,aAAqB,EACrB,IAAiB,EACjB,KAAuC,EACvC,OAAmB;QAHnB,kBAAa,GAAb,aAAa,CAAQ;QACrB,SAAI,GAAJ,IAAI,CAAa;QACjB,UAAK,GAAL,KAAK,CAAkC;QACvC,YAAO,GAAP,OAAO,CAAY;QAEpC,IAAI,CAAC,MAAM,GAAG,IAAI,kCAAkB,CAAC,aAAa,EAAE,KAAK,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IACzF,CAAC;IAED,OAAO;QACH,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QACrF,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;QACtD,IAAI,MAAM,KAAK,SAAS;YAAE,IAAI,CAAC,IAAI,CAAC,qBAAqB,UAAU,GAAG,CAAC,CAAC;QACxE,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC;YAC/C,IACI,IAAI,CAAC,iBAAiB;gBACtB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;gBACzB,qCAAqC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;gBAEzD,SAAS;YACb,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC;QACnD,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC;YAC1D,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,gBAAgB,IAAI,GAAG,KAAK,mBAAmB,CAAC;gBACrF,CAAC,CAAC,MAAM;gBACR,CAAC,CAAC,SAAS,CAAC;QAClB,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAChE,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,gEAAgE,CAAC,CAAC;QACjG,OAAO,IAAI,gCAAkB,CACzB,IAAI,CAAC,IAAI,CAAC,IAAI,EACd,SAAS,EACT,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,IAAI,CACZ,CAAC;IACN,CAAC;IAEO,KAAK,CAAC,IAAa,EAAE,QAAiB;QAC1C,IAAI,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC;YAAE,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACnE,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,KAAc,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC3E,CAAC;IAEO,KAAK,CAAC,IAAa,EAAE,KAAa;QACtC,IAAI,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,IAAI,gCAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,qBAAqB,CAAC;YACpI,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACrC,IAAI,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YACxD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACrD,IAAI,CAAC,WAAW,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,SAAS,EAAE,YAAY,EAAE,kBAAkB,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAClH,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QACnD,CAAC;QACD,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,KAAc,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IACxE,CAAC;IAEO,cAAc,CAAC,UAA4B,EAAE,KAAa;QAC9D,MAAM,QAAQ,GAAG,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3C,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,EAAE,CAAC,mBAAmB,CAAC,QAAQ,CAAC;YAC3D,IAAI,CAAC,IAAI,CACL,6GAA6G,CAChH,CAAC;QACN,MAAM,SAAS,GAAI,QAAiC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrE,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAC7B,MAAM,YAAY,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAC3B,IAAI,CAAC,OAAO,IAAI,CAAC,YAAY,IAAI,KAAK,KAAK,SAAS;YAChD,IAAI,CAAC,IAAI,CAAC,uEAAuE,CAAC,CAAC;QACvF,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC;YACrF,IAAI,CAAC,IAAI,CACL,GAAG,OAAO,IAAI,YAAY,2CAA2C,IAAI,CAAC,IAAI,CAAC,IAAI,oDAAoD,CAC1I,CAAC;QACN,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACtC,QAAQ,CAAC,aAAa,CAAC,IAAI,CACvB,IAAI,gCAAkB,CAClB,IAAI,8BAAgB,CAAC,OAAO,EAAE,YAAY,CAAC,EAC3C,IAAI,uBAAS,CAAC,UAAU,EAAE;YACtB,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,wEAAwE;SACnF,CAAC,CACL,CACJ,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC;IACpC,CAAC;IAEO,kBAAkB,CAAC,IAAuB,EAAE,MAAc,EAAE,KAAa;QAC7E,MAAM,QAAQ,GACV,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,YAAY,IAAI,MAAM,KAAK,kBAAkB;YAC5E,CAAC,CAAC,CAAC;YACH,CAAC,CAAC,CAAC,CAAC;QACZ,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACrC,IAAI,GAAG,KAAK,SAAS;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,qCAAqC,CAAC,CAAC;QACjF,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAI,CAAC,CAAC;QAC5C,MAAM,SAAS,GAAG,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC;QACjE,MAAM,iBAAiB,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAI,CAAC,CAAC;QACtD,MAAM,SAAS,GACX,MAAM,KAAK,WAAW;YAClB,CAAC,CAAC,iBAAiB;YACnB,CAAC,CAAC,MAAM,KAAK,YAAY,IAAI,MAAM,KAAK,oBAAoB;gBAC1D,CAAC,CAAC,QAAQ;gBACV,CAAC,CAAC,KAAK,CAAC;QAClB,IAAI,SAAS,KAAK,iBAAiB;YAC/B,IAAI,CAAC,IAAI,CACL,GAAG,MAAM,6BAA6B,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,YAAY,GAAG,CACrF,CAAC;QACN,MAAM,MAAM,GACR,SAAS,KAAK,YAAY;YACtB,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC;QAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACtC,QAAQ,CAAC,aAAa,CAAC,IAAI,CACvB,IAAI,gCAAkB,CAClB,QAAQ,EACR,SAAS,KAAK,YAAY;YACtB,CAAC,CAAC,IAAI,6BAAe,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC7D,CAAC,CAAC,IAAI,uBAAS,CAAC,SAAS,EAAE,MAAO,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CACvE,CACJ,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC;IACpC,CAAC;IAEO,aAAa,CAAC,IAAuB;QACzC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC;QAC1F,IAAI,WAAW,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QAC5C,MAAM,IAAI,GAAG,WAAW,CAAC,aAAa,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACtE,OAAO,wIAAwI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/J,CAAC;IAEO,YAAY,CAAC,WAAgC,EAAE,QAAiB;QACpE,MAAM,KAAK,GAAG,IAAI,gCAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;QACnE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QAC5C,IAAI,IAAI,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO;QACtD,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YAC3C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAI,0BAAY,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;YACtD,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;YACzD,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,CAAC,IAAI,KAAK,SAAS;gBACvD,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,2EAA2E,CAAC,CAAC;YACnG,IAAI,CAAC,KAAK,CAAC,SAAU,CAAC,IAAK,EAAE,KAAK,CAAC,CAAC;YACpC,OAAO;QACX,CAAC;QACD,IAAI,CAAC,QAAQ;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,6DAA6D,CAAC,CAAC;QAChG,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,mBAAmB,CAAC,EAAE,SAAS,CAAC,CAAC;QAClG,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,mBAAmB,CAAC,EAAE,SAAS,CAAC,CAAC;QAChG,MAAM,SAAS,GAAG,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACjH,IAAI,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,KAAK,SAAS;YAC1E,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,+CAA+C,CAAC,CAAC;QACvE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAI,0BAAY,CAAC,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;QAC/E,IAAI,IAAI,KAAK,KAAK;YAAE,OAAO;QAC3B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;YACrC,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,qDAAqD,CAAC,CAAC;QAC7E,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC;QAC3G,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QAClF,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAA0B,CAAC;YAC1F,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,QAAQ,EAAE,SAAS,EAAE,WAAW,CAAC;QACzD,CAAC;IACL,CAAC;IAEO,gBAAgB,CAAC,MAAwC,EAAE,QAA0C;QACzG,MAAM,UAAU,GAAG,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC;QAC5C,MAAM,UAAU,GAAG,UAAU,EAAE,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1H,IAAI,UAAU,KAAK,SAAS,IAAI,CAAC,EAAE,CAAC,wBAAwB,CAAC,UAAU,CAAC;YACpE,IAAI,CAAC,IAAI,CAAC,YAAY,QAAQ,mEAAmE,CAAC,CAAC;QACvG,MAAM,KAAK,GAAG,IAAI,gCAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;QACnE,OAAO,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAsB,EAAE,EAAE;YACtD,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,QAAQ;gBAC3E,IAAI,CAAC,IAAI,CAAC,SAAS,QAAQ,cAAc,OAAO,CAAC,OAAO,EAAE,kEAAkE,CAAC,CAAC;YAClI,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAC1D,OAAO,IAAI,6BAAe,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;QACvI,CAAC,CAAC,CAAC;IACP,CAAC;IAEO,WAAW,CAAC,IAAa;QAC7B,IAAI,OAAO,GAAwB,IAAI,CAAC;QACxC,OAAO,OAAO,KAAK,SAAS,EAAE,CAAC;YAC3B,IACI,EAAE,CAAC,kBAAkB,CAAC,OAAO,CAAC;gBAC9B,OAAO,CAAC,IAAI,KAAK,SAAS;gBAC1B,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CACjC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,EAAE,CAAC,UAAU,CAAC,aAAa,CAC9D;gBAED,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAC7B,IACI,EAAE,CAAC,qBAAqB,CAAC,OAAO,CAAC;gBACjC,OAAO,CAAC,IAAI,KAAK,SAAS;gBAC1B,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CACjC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,EAAE,CAAC,UAAU,CAAC,aAAa,CAC9D;gBAED,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAC7B,IAAI,EAAE,CAAC,qBAAqB,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrE,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;gBACxC,IACI,EAAE,CAAC,mBAAmB,CAAC,SAAS,CAAC;oBACjC,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CACnC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,EAAE,CAAC,UAAU,CAAC,aAAa,CAC9D;oBAED,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YACjC,CAAC;YACD,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,CAAC;QACD,OAAO,SAAS,CAAC;IACrB,CAAC;IAEO,IAAI,CAAC,IAAY;QACrB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC;QACzE,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IACnF,CAAC;IAEO,IAAI,CAAC,OAAe;QACxB,MAAM,IAAI,4BAAa,CAAC,+BAA+B,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE;YACpF,IAAI,qBAAM,CACN,sRAAsR,EACtR,IAAI,CACP;SACJ,CAAC,CAAC;IACP,CAAC;CACJ;AAjOD,sDAiOC;AAED,qFAAqF;AACrF,MAAa,oBAAoB;IAC7B,MAAM,CAAC,aAAqB,EAAE,IAAiB;QAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACpD,MAAM,UAAU,GAAG,IAAA,8BAAoB,EAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,UAAU,KAAK,IAAI;YAAE,OAAO,UAAU,CAAC;QAC3C,MAAM,MAAM,GAAG,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;QAC3E,MAAM,MAAM,GACR,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClF,MAAM,OAAO,GACT,MAAM,KAAK,SAAS;YAChB,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,CAAC,0BAA0B,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC;QAC7E,MAAM,KAAK,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,CAC9B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,EACtB,CAAC,KAAK,CAAC,EACP,CAAC,cAAc,EAAE,cAAc,CAAC,CACnC,CAAC;QACF,OAAO,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;CACJ;AAnBD,oDAmBC","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"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as ts from 'typescript';
|
|
2
|
+
export type WiringKind = 'app' | 'wiring' | 'binding' | 'routing';
|
|
3
|
+
/** Identity comes from resolved framework declarations, including aliases and inherited roles. */
|
|
4
|
+
export declare class WiringSourceTypes {
|
|
5
|
+
private readonly checker;
|
|
6
|
+
constructor(checker: ts.TypeChecker);
|
|
7
|
+
declaration(node: ts.Node): ts.Declaration | undefined;
|
|
8
|
+
kind(node: ts.ClassDeclaration | ts.Expression): WiringKind | undefined;
|
|
9
|
+
isFramework(node: ts.Node, name: string): boolean;
|
|
10
|
+
method(declaration: ts.ClassDeclaration, name: string): ts.MethodDeclaration | undefined;
|
|
11
|
+
isPolicy(node: ts.Expression): boolean;
|
|
12
|
+
private role;
|
|
13
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WiringSourceTypes = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const ts = tslib_1.__importStar(require("typescript"));
|
|
6
|
+
/** Identity comes from resolved framework declarations, including aliases and inherited roles. */
|
|
7
|
+
class WiringSourceTypes {
|
|
8
|
+
checker;
|
|
9
|
+
constructor(checker) {
|
|
10
|
+
this.checker = checker;
|
|
11
|
+
}
|
|
12
|
+
declaration(node) {
|
|
13
|
+
let symbol = this.checker.getSymbolAtLocation(node);
|
|
14
|
+
if (symbol !== undefined && (symbol.flags & ts.SymbolFlags.Alias) !== 0)
|
|
15
|
+
symbol = this.checker.getAliasedSymbol(symbol);
|
|
16
|
+
return symbol?.valueDeclaration ?? symbol?.declarations?.[0];
|
|
17
|
+
}
|
|
18
|
+
kind(node) {
|
|
19
|
+
const declaration = ts.isClassDeclaration(node) ? node : this.declaration(node);
|
|
20
|
+
if (declaration === undefined)
|
|
21
|
+
return undefined;
|
|
22
|
+
return this.role(declaration, new Set());
|
|
23
|
+
}
|
|
24
|
+
isFramework(node, name) {
|
|
25
|
+
const declaration = this.declaration(node);
|
|
26
|
+
if (declaration === undefined || (!ts.isClassDeclaration(declaration) && !ts.isInterfaceDeclaration(declaration)))
|
|
27
|
+
return false;
|
|
28
|
+
return declaration.name?.text === name && /(?:\/packages\/(?:http|cloud)\/|\/node_modules\/@webpieces\/)(?:http-routing|http-client-node|http-client-browser|http-client-core|cloudtasks-client)\//.test(declaration.getSourceFile().fileName.replace(/\\/g, '/'));
|
|
29
|
+
}
|
|
30
|
+
method(declaration, name) {
|
|
31
|
+
const property = this.checker.getTypeAtLocation(declaration).getProperty(name);
|
|
32
|
+
const method = property?.valueDeclaration;
|
|
33
|
+
return method !== undefined && ts.isMethodDeclaration(method) ? method : undefined;
|
|
34
|
+
}
|
|
35
|
+
isPolicy(node) {
|
|
36
|
+
const symbol = this.checker.getTypeAtLocation(node).getSymbol();
|
|
37
|
+
const declaration = symbol?.valueDeclaration;
|
|
38
|
+
return declaration !== undefined && ts.isClassDeclaration(declaration) &&
|
|
39
|
+
declaration.name !== undefined && this.isFramework(declaration.name, 'WiringPolicy');
|
|
40
|
+
}
|
|
41
|
+
role(declaration, seen) {
|
|
42
|
+
if (seen.has(declaration))
|
|
43
|
+
return undefined;
|
|
44
|
+
seen.add(declaration);
|
|
45
|
+
if (!ts.isClassDeclaration(declaration) && !ts.isInterfaceDeclaration(declaration))
|
|
46
|
+
return undefined;
|
|
47
|
+
const name = declaration.name?.text;
|
|
48
|
+
const file = declaration.getSourceFile().fileName.replace(/\\/g, '/');
|
|
49
|
+
const framework = /(?:\/packages\/http\/|\/node_modules\/@webpieces\/)(?:http-routing|http-client-browser|http-client-core)\/.*Wiring\.(?:d\.)?ts$/.test(file);
|
|
50
|
+
if (framework) {
|
|
51
|
+
if (name === 'AppWiring')
|
|
52
|
+
return 'app';
|
|
53
|
+
if (name === 'Wiring')
|
|
54
|
+
return 'wiring';
|
|
55
|
+
if (name === 'BindingModule')
|
|
56
|
+
return 'binding';
|
|
57
|
+
if (name === 'RouteModule')
|
|
58
|
+
return 'routing';
|
|
59
|
+
}
|
|
60
|
+
const roles = [];
|
|
61
|
+
for (const clause of declaration.heritageClauses ?? []) {
|
|
62
|
+
for (const type of clause.types) {
|
|
63
|
+
const parent = this.declaration(type.expression);
|
|
64
|
+
if (parent === undefined)
|
|
65
|
+
continue;
|
|
66
|
+
const role = this.role(parent, seen);
|
|
67
|
+
if (role !== undefined)
|
|
68
|
+
roles.push(role);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return roles.includes('app') ? 'app' : roles[0];
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
exports.WiringSourceTypes = WiringSourceTypes;
|
|
75
|
+
//# sourceMappingURL=source-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-types.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/source-types.ts"],"names":[],"mappings":"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","sourcesContent":["import * as ts from 'typescript';\n\nexport type WiringKind = 'app' | 'wiring' | 'binding' | 'routing';\n\n/** Identity comes from resolved framework declarations, including aliases and inherited roles. */\nexport class WiringSourceTypes {\n constructor(private readonly checker: ts.TypeChecker) {}\n\n declaration(node: ts.Node): ts.Declaration | undefined {\n let symbol = this.checker.getSymbolAtLocation(node);\n if (symbol !== undefined && (symbol.flags & ts.SymbolFlags.Alias) !== 0)\n symbol = this.checker.getAliasedSymbol(symbol);\n return symbol?.valueDeclaration ?? symbol?.declarations?.[0];\n }\n\n kind(node: ts.ClassDeclaration | ts.Expression): WiringKind | undefined {\n const declaration = ts.isClassDeclaration(node) ? node : this.declaration(node);\n if (declaration === undefined) return undefined;\n return this.role(declaration, new Set<ts.Declaration>());\n }\n\n isFramework(node: ts.Node, name: string): boolean {\n const declaration = this.declaration(node);\n if (declaration === undefined || (!ts.isClassDeclaration(declaration) && !ts.isInterfaceDeclaration(declaration))) return false;\n return declaration.name?.text === name && /(?:\\/packages\\/(?:http|cloud)\\/|\\/node_modules\\/@webpieces\\/)(?:http-routing|http-client-node|http-client-browser|http-client-core|cloudtasks-client)\\//.test(declaration.getSourceFile().fileName.replace(/\\\\/g, '/'));\n }\n\n method(declaration: ts.ClassDeclaration, name: string): ts.MethodDeclaration | undefined {\n const property = this.checker.getTypeAtLocation(declaration).getProperty(name);\n const method = property?.valueDeclaration;\n return method !== undefined && ts.isMethodDeclaration(method) ? method : undefined;\n }\n\n isPolicy(node: ts.Expression): boolean {\n const symbol = this.checker.getTypeAtLocation(node).getSymbol();\n const declaration = symbol?.valueDeclaration;\n return declaration !== undefined && ts.isClassDeclaration(declaration) &&\n declaration.name !== undefined && this.isFramework(declaration.name, 'WiringPolicy');\n }\n\n private role(declaration: ts.Declaration, seen: Set<ts.Declaration>): WiringKind | undefined {\n if (seen.has(declaration)) return undefined;\n seen.add(declaration);\n if (!ts.isClassDeclaration(declaration) && !ts.isInterfaceDeclaration(declaration))\n return undefined;\n const name = declaration.name?.text;\n const file = declaration.getSourceFile().fileName.replace(/\\\\/g, '/');\n const framework = /(?:\\/packages\\/http\\/|\\/node_modules\\/@webpieces\\/)(?:http-routing|http-client-browser|http-client-core)\\/.*Wiring\\.(?:d\\.)?ts$/.test(file);\n if (framework) {\n if (name === 'AppWiring') return 'app';\n if (name === 'Wiring') return 'wiring';\n if (name === 'BindingModule') return 'binding';\n if (name === 'RouteModule') return 'routing';\n }\n const roles: WiringKind[] = [];\n for (const clause of declaration.heritageClauses ?? []) {\n for (const type of clause.types) {\n const parent = this.declaration(type.expression);\n if (parent === undefined) continue;\n const role = this.role(parent, seen);\n if (role !== undefined) roles.push(role);\n }\n }\n return roles.includes('app') ? 'app' : roles[0];\n }\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as ts from 'typescript';
|
|
2
2
|
import type { ProjectInfo } from '../project-info';
|
|
3
3
|
import { ContractIdentity } from './declaration';
|
|
4
|
-
import type { DeclaredTarget } from './declaration';
|
|
4
|
+
import type { DeclaredTarget, PolicyValue } from './declaration';
|
|
5
5
|
/** Resolves imported symbols and bounded literal expressions without invoking application code. */
|
|
6
6
|
export declare class WiringSourceValues {
|
|
7
7
|
private readonly workspaceRoot;
|
|
@@ -14,8 +14,10 @@ export declare class WiringSourceValues {
|
|
|
14
14
|
transport(expression: ts.Expression): 'rpc' | 'pubsub';
|
|
15
15
|
arguments(invocation: ts.NewExpression | ts.CallExpression): Record<string, DeclaredTarget>;
|
|
16
16
|
hasExternalConsumer(owner: string, project: string, exportedName: string, program: ts.Program): boolean;
|
|
17
|
-
policies(invocation: ts.NewExpression | ts.CallExpression): Record<string,
|
|
17
|
+
policies(invocation: ts.NewExpression | ts.CallExpression): Record<string, PolicyValue>;
|
|
18
18
|
condition(call: ts.Node): string | undefined;
|
|
19
|
+
private preparedValue;
|
|
20
|
+
private parameterPath;
|
|
19
21
|
private symbol;
|
|
20
22
|
private fail;
|
|
21
23
|
}
|