@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"angular-providers.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/di-graph/angular-providers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Angular Provider Table (pass 1, Angular flavor)\n *\n * The Angular analog of `bindings.ts` (Inversify): scans the program and maps\n * Angular's provider forms onto the SAME token-keyed {@link BindingTable} the\n * shared walker consumes, so `angular-analyzer.ts` reuses every downstream\n * mechanism (leaf labeling, factory-dep edges, unresolved handling).\n *\n * Provider sources (v1 flat global table — component-scoped shadowing is an\n * accepted approximation):\n * - Any `providers: [...]` array (ApplicationConfig, `@Component`, `@Directive`)\n * - `@Injectable({ providedIn: 'root' | 'platform' | 'any' })` self-registration\n *\n * Provider forms per array element:\n * - bare class `Foo` → to/self binding (implClass=Foo)\n * - `{ provide, useClass }` → to binding (implClass)\n * - `{ provide, useValue }` → toConstantValue leaf\n * - `{ provide, useFactory, deps: [A, B] }` → toDynamicValue leaf + factoryDeps\n * - `{ provide, useExisting }` → alias → target impl class\n * - `multi: true` → multiple bindings per token (fan-out)\n *\n * Framework-internal `provideXxx()` calls (`provideRouter`,\n * `provideZoneChangeDetection`, ...) have no DI leaves and are skipped.\n */\n\nimport * as ts from 'typescript';\nimport { RuntimeClientBindings } from './runtime-client-bindings';\nimport { Binding, DiScope, TokenRef } from './model';\nimport {\n BindingTable,\n classDecorators,\n decoratorCall,\n decoratorName,\n isApiClientBoundary,\n resolveClassDeclaration,\n} from './bindings';\nimport { classTokenKey, relativeFile, resolveTokenKey } from './token-resolver';\n\n// Angular injector-scoped providers are effectively singletons at their scope.\nconst ANGULAR_SCOPE: DiScope = 'singleton';\n\nfunction isAnalyzableFile(sourceFile: ts.SourceFile): boolean {\n if (sourceFile.isDeclarationFile) return false;\n if (sourceFile.fileName.includes('/node_modules/')) return false;\n return true;\n}\n\n/** First line of an expression's source text, truncated for leaf labels. */\nfunction firstLine(text: string): string {\n const line = text.split('\\n')[0].trim();\n return line.length > 60 ? line.slice(0, 57) + '...' : line;\n}\n\n/** Pull `{ name: value }` properties out of an object literal into a map. */\nfunction objectProps(obj: ts.ObjectLiteralExpression): Map<string, ts.Expression> {\n const props = new Map<string, ts.Expression>();\n for (const prop of obj.properties) {\n if (ts.isPropertyAssignment(prop) && (ts.isIdentifier(prop.name) || ts.isStringLiteralLike(prop.name))) {\n props.set(prop.name.text, prop.initializer);\n }\n }\n return props;\n}\n\n/** Resolve each `deps: [A, B]` element to a token reference for factory-dep edges. */\nfunction collectDeps(depsExpr: ts.Expression | undefined, checker: ts.TypeChecker, workspaceRoot: string): TokenRef[] {\n if (!depsExpr || !ts.isArrayLiteralExpression(depsExpr)) return [];\n const deps: TokenRef[] = [];\n for (const element of depsExpr.elements) {\n // Simple token form (`EnvironmentConfig`); the decorated array form\n // (`[new Optional(), Token]`) is out of scope for v1.\n if (ts.isIdentifier(element) || ts.isPropertyAccessExpression(element)) {\n const cls = resolveClassDeclaration(element, checker);\n deps.push(cls ? classTokenKey(cls, workspaceRoot) : resolveTokenKey(element, checker, workspaceRoot));\n }\n }\n return deps;\n}\n\n/** Record one provider-object literal (`{ provide, useX }`) as a binding. */\nfunction collectProviderObject(\n obj: ts.ObjectLiteralExpression,\n checker: ts.TypeChecker,\n workspaceRoot: string,\n file: string,\n table: BindingTable,\n): void {\n const props = objectProps(obj);\n const provideExpr = props.get('provide');\n if (!provideExpr) return;\n\n const provideClass = resolveClassDeclaration(provideExpr, checker);\n const token = provideClass\n ? classTokenKey(provideClass, workspaceRoot)\n : resolveTokenKey(provideExpr, checker, workspaceRoot);\n\n const useClass = props.get('useClass');\n const useValue = props.get('useValue');\n const useFactory = props.get('useFactory');\n const useExisting = props.get('useExisting');\n\n if (useClass) {\n const impl = resolveClassDeclaration(useClass, checker);\n table.add(new Binding(token.key, token.display, 'to', ANGULAR_SCOPE, impl, useClass.getText(), file));\n return;\n }\n if (useExisting) {\n // Alias: T resolves to whatever `useExisting` points at — resolve through\n // to the target impl class so the walk continues into its dependencies.\n const impl = resolveClassDeclaration(useExisting, checker);\n table.add(new Binding(token.key, token.display, 'to', ANGULAR_SCOPE, impl, useExisting.getText(), file));\n return;\n }\n if (useFactory) {\n const deps = collectDeps(props.get('deps'), checker, workspaceRoot);\n const isApiBoundary = isApiClientBoundary(useFactory, checker);\n table.add(\n new Binding(token.key, token.display, 'toDynamicValue', ANGULAR_SCOPE, null, firstLine(useFactory.getText()), file, deps, isApiBoundary),\n );\n return;\n }\n if (useValue) {\n table.add(\n new Binding(token.key, token.display, 'toConstantValue', ANGULAR_SCOPE, null, firstLine(useValue.getText()), file),\n );\n return;\n }\n // `{ provide: T }` with no recipe — treat the token itself as the impl class.\n if (provideClass) {\n table.add(new Binding(token.key, token.display, 'to', ANGULAR_SCOPE, provideClass, provideExpr.getText(), file));\n }\n}\n\n/** Record one element of a `providers: [...]` array. */\nfunction collectProviderElement(\n element: ts.Expression,\n checker: ts.TypeChecker,\n workspaceRoot: string,\n file: string,\n table: BindingTable,\n): void {\n // Framework-internal `provideRouter(...)` / `provideZoneChangeDetection(...)`.\n if (ts.isCallExpression(element)) return;\n\n // Bare class provider: `providers: [MyService]` → useClass: MyService.\n if (ts.isIdentifier(element) || ts.isPropertyAccessExpression(element)) {\n const cls = resolveClassDeclaration(element, checker);\n if (cls) {\n const token = classTokenKey(cls, workspaceRoot);\n table.add(new Binding(token.key, token.display, 'to', ANGULAR_SCOPE, cls, element.getText(), file));\n }\n return;\n }\n\n if (ts.isObjectLiteralExpression(element)) {\n collectProviderObject(element, checker, workspaceRoot, file, table);\n }\n}\n\n/** `@Injectable({ providedIn: 'root' | 'platform' | 'any' })` self-registration. */\nfunction collectInjectableSelfBinding(\n cls: ts.ClassDeclaration,\n checker: ts.TypeChecker,\n workspaceRoot: string,\n table: BindingTable,\n): void {\n for (const decorator of classDecorators(cls)) {\n if (decoratorName(decorator) !== 'Injectable') continue;\n const call = decoratorCall(decorator);\n const arg = call?.arguments[0];\n if (!arg || !ts.isObjectLiteralExpression(arg)) return;\n const providedIn = objectProps(arg).get('providedIn');\n if (providedIn && ts.isStringLiteralLike(providedIn)) {\n const token = classTokenKey(cls, workspaceRoot);\n const file = relativeFile(workspaceRoot, cls.getSourceFile());\n table.add(new Binding(token.key, token.display, 'decorator', ANGULAR_SCOPE, cls, '', file));\n }\n return;\n }\n}\n\n/**\n * Collect every Angular provider in the program into a token-keyed table.\n * `checker` is required so cross-package class tokens (`SaveApi`, `ClientConfig`)\n * resolve to the same declaration the injection sites reference.\n */\nexport function collectAngularProviders(\n program: ts.Program,\n checker: ts.TypeChecker,\n workspaceRoot: string,\n): BindingTable {\n const table = new BindingTable();\n const clients = new RuntimeClientBindings();\n\n for (const sourceFile of program.getSourceFiles()) {\n if (!isAnalyzableFile(sourceFile)) continue;\n const file = relativeFile(workspaceRoot, sourceFile);\n\n const visit = (node: ts.Node): void => {\n if (ts.isCallExpression(node)) {\n const client = clients.collectBrowser(node, checker, workspaceRoot);\n if (client !== undefined) table.add(client);\n }\n if (ts.isClassDeclaration(node)) {\n collectInjectableSelfBinding(node, checker, workspaceRoot, table);\n } else if (\n ts.isPropertyAssignment(node) &&\n (ts.isIdentifier(node.name) || ts.isStringLiteralLike(node.name)) &&\n node.name.text === 'providers' &&\n ts.isArrayLiteralExpression(node.initializer)\n ) {\n for (const element of node.initializer.elements) {\n collectProviderElement(element, checker, workspaceRoot, file, table);\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n }\n\n return table;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"angular-providers.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/di-graph/angular-providers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Angular Provider Table (pass 1, Angular flavor)\n *\n * The Angular analog of `bindings.ts` (Inversify): scans the program and maps\n * Angular's provider forms onto the SAME token-keyed {@link BindingTable} the\n * shared walker consumes, so `angular-analyzer.ts` reuses every downstream\n * mechanism (leaf labeling, factory-dep edges, unresolved handling).\n *\n * Provider sources (v1 flat global table — component-scoped shadowing is an\n * accepted approximation):\n * - Any `providers: [...]` array (ApplicationConfig, `@Component`, `@Directive`)\n * - `@Injectable({ providedIn: 'root' | 'platform' | 'any' })` self-registration\n *\n * Provider forms per array element:\n * - bare class `Foo` → to/self binding (implClass=Foo)\n * - `{ provide, useClass }` → to binding (implClass)\n * - `{ provide, useValue }` → toConstantValue leaf\n * - `{ provide, useFactory, deps: [A, B] }` → toDynamicValue leaf + factoryDeps\n * - `{ provide, useExisting }` → alias → target impl class\n * - `multi: true` → multiple bindings per token (fan-out)\n *\n * Framework-internal `provideXxx()` calls (`provideRouter`,\n * `provideZoneChangeDetection`, ...) have no DI leaves and are skipped.\n */\n\nimport * as ts from 'typescript';\nimport { RuntimeClientBindings } from './runtime-client-bindings';\nimport { Binding, DiScope, TokenRef } from './model';\nimport {\n BindingTable,\n classDecorators,\n decoratorCall,\n decoratorName,\n isApiClientBoundary,\n resolveClassDeclaration,\n} from './bindings';\nimport { classTokenKey, relativeFile, resolveTokenKey } from './token-resolver';\n\n// Angular injector-scoped providers are effectively singletons at their scope.\nconst ANGULAR_SCOPE: DiScope = 'singleton';\n\nfunction isAnalyzableFile(sourceFile: ts.SourceFile): boolean {\n if (sourceFile.isDeclarationFile) return false;\n if (sourceFile.fileName.includes('/node_modules/')) return false;\n return true;\n}\n\n/** First line of an expression's source text, truncated for leaf labels. */\nfunction firstLine(text: string): string {\n const line = text.split('\\n')[0].trim();\n return line.length > 60 ? line.slice(0, 57) + '...' : line;\n}\n\n/** Pull `{ name: value }` properties out of an object literal into a map. */\nfunction objectProps(obj: ts.ObjectLiteralExpression): Map<string, ts.Expression> {\n const props = new Map<string, ts.Expression>();\n for (const prop of obj.properties) {\n if (ts.isPropertyAssignment(prop) && (ts.isIdentifier(prop.name) || ts.isStringLiteralLike(prop.name))) {\n props.set(prop.name.text, prop.initializer);\n }\n }\n return props;\n}\n\n/** Resolve each `deps: [A, B]` element to a token reference for factory-dep edges. */\nfunction collectDeps(depsExpr: ts.Expression | undefined, checker: ts.TypeChecker, workspaceRoot: string): TokenRef[] {\n if (!depsExpr || !ts.isArrayLiteralExpression(depsExpr)) return [];\n const deps: TokenRef[] = [];\n for (const element of depsExpr.elements) {\n // Simple token form (`EnvironmentConfig`); the decorated array form\n // (`[new Optional(), Token]`) is out of scope for v1.\n if (ts.isIdentifier(element) || ts.isPropertyAccessExpression(element)) {\n const cls = resolveClassDeclaration(element, checker);\n deps.push(cls ? classTokenKey(cls, workspaceRoot) : resolveTokenKey(element, checker, workspaceRoot));\n }\n }\n return deps;\n}\n\n/** Record one provider-object literal (`{ provide, useX }`) as a binding. */\nclass ProviderRecipes {\n collect(\n props: Map<string, ts.Expression>,\n checker: ts.TypeChecker,\n workspaceRoot: string,\n file: string,\n table: BindingTable,\n ): void {\n const provideExpr = props.get('provide');\n if (!provideExpr) return;\n\n const provideClass = resolveClassDeclaration(provideExpr, checker);\n const token = provideClass\n ? classTokenKey(provideClass, workspaceRoot)\n : resolveTokenKey(provideExpr, checker, workspaceRoot);\n\n const useClass = props.get('useClass');\n const useValue = props.get('useValue');\n const useFactory = props.get('useFactory');\n const useExisting = props.get('useExisting');\n\n if (useClass) {\n const impl = resolveClassDeclaration(useClass, checker);\n table.add(new Binding(token.key, token.display, 'to', ANGULAR_SCOPE, impl, useClass.getText(), file));\n return;\n }\n if (useExisting) {\n // Alias: T resolves to whatever `useExisting` points at — resolve through\n // to the target impl class so the walk continues into its dependencies.\n const impl = resolveClassDeclaration(useExisting, checker);\n table.add(new Binding(token.key, token.display, 'to', ANGULAR_SCOPE, impl, useExisting.getText(), file));\n return;\n }\n if (useFactory) {\n const deps = collectDeps(props.get('deps'), checker, workspaceRoot);\n const isApiBoundary = isApiClientBoundary(useFactory, checker);\n table.add(\n new Binding(token.key, token.display, 'toDynamicValue', ANGULAR_SCOPE, null, firstLine(useFactory.getText()), file, deps, isApiBoundary),\n );\n return;\n }\n if (useValue) {\n table.add(\n new Binding(token.key, token.display, 'toConstantValue', ANGULAR_SCOPE, null, firstLine(useValue.getText()), file),\n );\n return;\n }\n // `{ provide: T }` with no recipe — treat the token itself as the impl class.\n if (provideClass) {\n table.add(new Binding(token.key, token.display, 'to', ANGULAR_SCOPE, provideClass, provideExpr.getText(), file));\n }\n }\n}\n\n/** Record one element of a `providers: [...]` array. */\nfunction collectProviderElement(\n element: ts.Expression,\n checker: ts.TypeChecker,\n workspaceRoot: string,\n file: string,\n table: BindingTable,\n): void {\n // Framework-internal `provideRouter(...)` / `provideZoneChangeDetection(...)`.\n if (ts.isCallExpression(element)) return;\n\n // Bare class provider: `providers: [MyService]` → useClass: MyService.\n if (ts.isIdentifier(element) || ts.isPropertyAccessExpression(element)) {\n const cls = resolveClassDeclaration(element, checker);\n if (cls) {\n const token = classTokenKey(cls, workspaceRoot);\n table.add(new Binding(token.key, token.display, 'to', ANGULAR_SCOPE, cls, element.getText(), file));\n }\n return;\n }\n\n if (ts.isObjectLiteralExpression(element)) {\n new ProviderRecipes().collect(objectProps(element), checker, workspaceRoot, file, table);\n }\n}\n\n/** Named browser recipes preserve the same aliases and factory dependency evidence. */\nclass NamedBrowserProviders {\n collect(node: ts.NewExpression, checker: ts.TypeChecker, root: string, file: string, table: BindingTable): void {\n let symbol = checker.getSymbolAtLocation(node.expression);\n if (symbol !== undefined && (symbol.flags & ts.SymbolFlags.Alias) !== 0)\n symbol = checker.getAliasedSymbol(symbol);\n const name = symbol?.getName();\n const recipe = name === 'BrowserValueProvider' ? 'useValue'\n : name === 'BrowserFactoryProvider' ? 'useFactory'\n : name === 'BrowserClassProvider' ? 'useClass'\n : name === 'BrowserExistingProvider' ? 'useExisting' : undefined;\n const declaration = symbol?.valueDeclaration;\n if (recipe === undefined || declaration === undefined ||\n !/(?:packages\\/http\\/|node_modules\\/@webpieces\\/)http-client-browser\\//.test(declaration.getSourceFile().fileName)) return;\n const args = node.arguments;\n if (args === undefined || args.length < 2) return;\n const props = new Map<string, ts.Expression>([['provide', args[0]], [recipe, args[1]]]);\n if (args[2] !== undefined) props.set('deps', args[2]);\n new ProviderRecipes().collect(props, checker, root, file, table);\n }\n}\n\n/** `@Injectable({ providedIn: 'root' | 'platform' | 'any' })` self-registration. */\nfunction collectInjectableSelfBinding(\n cls: ts.ClassDeclaration,\n checker: ts.TypeChecker,\n workspaceRoot: string,\n table: BindingTable,\n): void {\n for (const decorator of classDecorators(cls)) {\n if (decoratorName(decorator) !== 'Injectable') continue;\n const call = decoratorCall(decorator);\n const arg = call?.arguments[0];\n if (!arg || !ts.isObjectLiteralExpression(arg)) return;\n const providedIn = objectProps(arg).get('providedIn');\n if (providedIn && ts.isStringLiteralLike(providedIn)) {\n const token = classTokenKey(cls, workspaceRoot);\n const file = relativeFile(workspaceRoot, cls.getSourceFile());\n table.add(new Binding(token.key, token.display, 'decorator', ANGULAR_SCOPE, cls, '', file));\n }\n return;\n }\n}\n\n/**\n * Collect every Angular provider in the program into a token-keyed table.\n * `checker` is required so cross-package class tokens (`SaveApi`, `ClientConfig`)\n * resolve to the same declaration the injection sites reference.\n */\nexport function collectAngularProviders(\n program: ts.Program,\n checker: ts.TypeChecker,\n workspaceRoot: string,\n): BindingTable {\n const table = new BindingTable();\n const clients = new RuntimeClientBindings();\n const providers = new NamedBrowserProviders();\n\n for (const sourceFile of program.getSourceFiles()) {\n if (!isAnalyzableFile(sourceFile)) continue;\n const file = relativeFile(workspaceRoot, sourceFile);\n\n const visit = (node: ts.Node): void => {\n if (ts.isNewExpression(node)) providers.collect(node, checker, workspaceRoot, file, table);\n if (ts.isCallExpression(node)) {\n const client = clients.collectBrowser(node, checker, workspaceRoot);\n if (client !== undefined) table.add(client);\n }\n if (ts.isClassDeclaration(node)) {\n collectInjectableSelfBinding(node, checker, workspaceRoot, table);\n } else if (\n ts.isPropertyAssignment(node) &&\n (ts.isIdentifier(node.name) || ts.isStringLiteralLike(node.name)) &&\n node.name.text === 'providers' &&\n ts.isArrayLiteralExpression(node.initializer)\n ) {\n for (const element of node.initializer.elements) {\n collectProviderElement(element, checker, workspaceRoot, file, table);\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n }\n\n return table;\n}\n"]}
|
|
@@ -4,5 +4,6 @@ import { Binding } from './model';
|
|
|
4
4
|
export declare class RuntimeClientBindings {
|
|
5
5
|
collectNode(call: ts.CallExpression, checker: ts.TypeChecker, root: string): Binding | undefined;
|
|
6
6
|
collectBrowser(call: ts.CallExpression, checker: ts.TypeChecker, root: string): Binding | undefined;
|
|
7
|
+
private frameworkCall;
|
|
7
8
|
private binding;
|
|
8
9
|
}
|
|
@@ -8,6 +8,8 @@ const token_resolver_1 = require("./token-resolver");
|
|
|
8
8
|
/** Canonical lazy client helpers retain the same DI token and singleton boundary. */
|
|
9
9
|
class RuntimeClientBindings {
|
|
10
10
|
collectNode(call, checker, root) {
|
|
11
|
+
if (!this.frameworkCall(call, checker))
|
|
12
|
+
return;
|
|
11
13
|
const callee = call.expression;
|
|
12
14
|
if (!ts.isPropertyAccessExpression(callee))
|
|
13
15
|
return;
|
|
@@ -19,6 +21,8 @@ class RuntimeClientBindings {
|
|
|
19
21
|
return undefined;
|
|
20
22
|
}
|
|
21
23
|
collectBrowser(call, checker, root) {
|
|
24
|
+
if (!this.frameworkCall(call, checker))
|
|
25
|
+
return;
|
|
22
26
|
let symbol = checker.getSymbolAtLocation(call.expression);
|
|
23
27
|
if (symbol && (symbol.flags & ts.SymbolFlags.Alias) !== 0)
|
|
24
28
|
symbol = checker.getAliasedSymbol(symbol);
|
|
@@ -27,6 +31,12 @@ class RuntimeClientBindings {
|
|
|
27
31
|
return;
|
|
28
32
|
return this.binding(call, checker, root);
|
|
29
33
|
}
|
|
34
|
+
frameworkCall(call, checker) {
|
|
35
|
+
const declaration = checker.getResolvedSignature(call)?.declaration;
|
|
36
|
+
if (declaration === undefined)
|
|
37
|
+
return false;
|
|
38
|
+
return /(?:\/packages\/(?:http|cloud)\/|\/node_modules\/@webpieces\/)(?:http-client-node|http-client-browser|cloudtasks-client)\//.test(declaration.getSourceFile().fileName.replace(/\\/g, '/'));
|
|
39
|
+
}
|
|
30
40
|
binding(call, checker, root) {
|
|
31
41
|
if (call.arguments.length < 3)
|
|
32
42
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-client-bindings.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/di-graph/runtime-client-bindings.ts"],"names":[],"mappings":";;;;AAAA,uDAAiC;AACjC,mCAAkC;AAClC,qDAAiE;AAEjE,qFAAqF;AACrF,MAAa,qBAAqB;IAC9B,WAAW,CACP,IAAuB,EACvB,OAAuB,EACvB,IAAY;QAEZ,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC;QAC/B,IAAI,CAAC,EAAE,CAAC,0BAA0B,CAAC,MAAM,CAAC;YAAE,OAAO;QACnD,MAAM,KAAK,GAAG,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,CAAC;QAClF,IACI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,KAAK,gBAAgB,CAAC;YAC9D,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,YAAY,IAAI,KAAK,KAAK,oBAAoB,CAAC,EACvE,CAAC;YACC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,cAAc,CACV,IAAuB,EACvB,OAAuB,EACvB,IAAY;QAEZ,IAAI,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1D,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC;YACrD,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAC9C,IACI,MAAM,EAAE,OAAO,EAAE,KAAK,kBAAkB;YACxC,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,KAAK,mBAAmB;YAE9E,OAAO;QACX,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAC7C,CAAC;IAEO,OAAO,CACX,IAAuB,EACvB,OAAuB,EACvB,IAAY;QAEZ,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO;QACtC,MAAM,KAAK,GAAG,IAAA,gCAAe,EAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAChE,OAAO,IAAI,eAAO,CACd,KAAK,CAAC,GAAG,EACT,KAAK,CAAC,OAAO,EACb,gBAAgB,EAChB,WAAW,EACX,IAAI,EACJ,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,EACzB,IAAA,6BAAY,EAAC,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,EACxC,EAAE,EACF,IAAI,CACP,CAAC;IACN,CAAC;CACJ;
|
|
1
|
+
{"version":3,"file":"runtime-client-bindings.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/di-graph/runtime-client-bindings.ts"],"names":[],"mappings":";;;;AAAA,uDAAiC;AACjC,mCAAkC;AAClC,qDAAiE;AAEjE,qFAAqF;AACrF,MAAa,qBAAqB;IAC9B,WAAW,CACP,IAAuB,EACvB,OAAuB,EACvB,IAAY;QAEZ,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC;YAAE,OAAO;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC;QAC/B,IAAI,CAAC,EAAE,CAAC,0BAA0B,CAAC,MAAM,CAAC;YAAE,OAAO;QACnD,MAAM,KAAK,GAAG,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,CAAC;QAClF,IACI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,KAAK,gBAAgB,CAAC;YAC9D,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,YAAY,IAAI,KAAK,KAAK,oBAAoB,CAAC,EACvE,CAAC;YACC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,cAAc,CACV,IAAuB,EACvB,OAAuB,EACvB,IAAY;QAEZ,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC;YAAE,OAAO;QAC/C,IAAI,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1D,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC;YACrD,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAC9C,IACI,MAAM,EAAE,OAAO,EAAE,KAAK,kBAAkB;YACxC,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,KAAK,mBAAmB;YAE9E,OAAO;QACX,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAC7C,CAAC;IAEO,aAAa,CAAC,IAAuB,EAAE,OAAuB;QAClE,MAAM,WAAW,GAAG,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC;QACpE,IAAI,WAAW,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QAC5C,OAAO,2HAA2H,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;IACtM,CAAC;IAEO,OAAO,CACX,IAAuB,EACvB,OAAuB,EACvB,IAAY;QAEZ,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO;QACtC,MAAM,KAAK,GAAG,IAAA,gCAAe,EAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAChE,OAAO,IAAI,eAAO,CACd,KAAK,CAAC,GAAG,EACT,KAAK,CAAC,OAAO,EACb,gBAAgB,EAChB,WAAW,EACX,IAAI,EACJ,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,EACzB,IAAA,6BAAY,EAAC,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,EACxC,EAAE,EACF,IAAI,CACP,CAAC;IACN,CAAC;CACJ;AA7DD,sDA6DC","sourcesContent":["import * as ts from 'typescript';\nimport { Binding } from './model';\nimport { relativeFile, resolveTokenKey } from './token-resolver';\n\n/** Canonical lazy client helpers retain the same DI token and singleton boundary. */\nexport class RuntimeClientBindings {\n collectNode(\n call: ts.CallExpression,\n checker: ts.TypeChecker,\n root: string,\n ): Binding | undefined {\n if (!this.frameworkCall(call, checker)) return;\n const callee = call.expression;\n if (!ts.isPropertyAccessExpression(callee)) return;\n const owner = checker.getTypeAtLocation(callee.expression).getSymbol()?.getName();\n if (\n (callee.name.text === 'bindRpc' && owner === 'RuntimeClients') ||\n (callee.name.text === 'bindPubSub' && owner === 'RuntimeTaskClients')\n ) {\n return this.binding(call, checker, root);\n }\n return undefined;\n }\n\n collectBrowser(\n call: ts.CallExpression,\n checker: ts.TypeChecker,\n root: string,\n ): Binding | undefined {\n if (!this.frameworkCall(call, checker)) return;\n let symbol = checker.getSymbolAtLocation(call.expression);\n if (symbol && (symbol.flags & ts.SymbolFlags.Alias) !== 0)\n symbol = checker.getAliasedSymbol(symbol);\n if (\n symbol?.getName() !== 'provideRpcClient' ||\n checker.getTypeAtLocation(call).getSymbol()?.getName() !== 'RpcClientProvider'\n )\n return;\n return this.binding(call, checker, root);\n }\n\n private frameworkCall(call: ts.CallExpression, checker: ts.TypeChecker): boolean {\n const declaration = checker.getResolvedSignature(call)?.declaration;\n if (declaration === undefined) return false;\n return /(?:\\/packages\\/(?:http|cloud)\\/|\\/node_modules\\/@webpieces\\/)(?:http-client-node|http-client-browser|cloudtasks-client)\\//.test(declaration.getSourceFile().fileName.replace(/\\\\/g, '/'));\n }\n\n private binding(\n call: ts.CallExpression,\n checker: ts.TypeChecker,\n root: string,\n ): Binding | undefined {\n if (call.arguments.length < 3) return;\n const token = resolveTokenKey(call.arguments[0], checker, root);\n return new Binding(\n token.key,\n token.display,\n 'toDynamicValue',\n 'singleton',\n null,\n call.expression.getText(),\n relativeFile(root, call.getSourceFile()),\n [],\n true,\n );\n }\n}\n"]}
|
|
@@ -50,8 +50,7 @@ class ApprovedWiringGraph {
|
|
|
50
50
|
const ref = { api: resolved.api, type: resolved.transport };
|
|
51
51
|
if (resolved.conditional !== undefined)
|
|
52
52
|
ref.conditional = resolved.conditional;
|
|
53
|
-
|
|
54
|
-
ref.declaredVia = resolved.via;
|
|
53
|
+
ref.declaredVia = resolved.via;
|
|
55
54
|
if (resolved.target?.kind === 'service')
|
|
56
55
|
ref.targetService = resolved.target.service;
|
|
57
56
|
if (resolved.transport === 'pubsub' && resolved.direction === 'uses')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approved-graph.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/approved-graph.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport { Option, RuleFailError } from '@webpieces/rules-config';\nimport { RuntimeDeclarationCodec } from './codec';\nimport { RuntimeWiringAssembler } from './assembler';\nimport type { RuntimeDeclaration } from './declaration';\nimport type { EnhancedGraph } from '../graph-sorter';\nimport type { ProjectInfo } from '../project-info';\nimport type { ApiRef, ProjectApiRelations } from '../api-usage/api-relations';\nimport { loadBlessedGraph, DEFAULT_GRAPH_PATH } from '../graph-loader';\nimport { ApiContractFiles } from '../api-contract-files';\n\n/** Assembly consumes approvals only. Source verification is a separate per-project build target. */\nexport class ApprovedWiringGraph {\n attach(\n workspaceRoot: string,\n graph: EnhancedGraph,\n infos: ReadonlyMap<string, ProjectInfo>,\n graphPath: string = DEFAULT_GRAPH_PATH,\n ): void {\n const previous = loadBlessedGraph(workspaceRoot, graphPath);\n if (previous === null)\n this.fail(\n 'Missing saved graph. Complete the runtime declaration migration before generating architecture.',\n );\n const declarations = new Map<string, RuntimeDeclaration>();\n for (const project of infos) {\n const name = project[0];\n const info = project[1];\n const tagged = info.tags.includes('webpieces') || info.tags.includes('webpieces-lib');\n const existingRelations = previous.projects[name]?.apiRelations;\n if (!tagged && existingRelations !== undefined)\n this.fail(\n `${name} has saved runtime facts but is untagged. Migrate it before using declaration-only generation.`,\n );\n if (!tagged) continue;\n const file = path.join(workspaceRoot, info.root, 'runtime-deps.json');\n if (!fs.existsSync(file)) this.fail(`Missing approved declaration ${file}.`);\n declarations.set(\n name,\n new RuntimeDeclarationCodec().decode(fs.readFileSync(file, 'utf8'), name),\n );\n graph[name].runtimeDeclaration = `${info.root}/runtime-deps.json`;\n }\n const assembler = new RuntimeWiringAssembler(declarations);\n for (const project of declarations) {\n const name = project[0];\n const declaration = project[1];\n if (declaration.entry === undefined) continue;\n const entry = graph[name];\n if (declaration.host !== undefined && entry.serviceName !== declaration.host)\n this.fail(\n `${name}: plan host ${declaration.host} disagrees with project serviceName ${entry.serviceName}.`,\n );\n const relations: ProjectApiRelations = {};\n for (const resolved of assembler.assemble(name)) {\n const relation = relations[resolved.owner] ?? {\n kind: 'uses',\n implements: [],\n uses: [],\n };\n const ref: ApiRef = { api: resolved.api, type: resolved.transport };\n if (resolved.conditional !== undefined) ref.conditional = resolved.conditional;\n if (!resolved.via.startsWith(`${name}#`)) ref.declaredVia = resolved.via;\n if (resolved.target?.kind === 'service')\n ref.targetService = resolved.target.service;\n if (resolved.transport === 'pubsub' && resolved.direction === 'uses')\n ref.methodsInferred = true;\n relation[resolved.direction].push(ref);\n relation.kind =\n relation.implements.length === 0\n ? 'uses'\n : relation.uses.length === 0\n ? 'implements'\n : 'uses-implements';\n relations[resolved.owner] = relation;\n }\n entry.apiRelations = relations;\n entry.runtimeComposition = true;\n }\n this.validateTargets(workspaceRoot, graphPath, graph);\n }\n\n private validateTargets(workspaceRoot: string, graphPath: string, graph: EnhancedGraph): void {\n const hosts = new Map<string, string>();\n for (const [name, entry] of Object.entries(graph)) {\n if (entry.serviceName === undefined) continue;\n if (hosts.has(entry.serviceName))\n this.fail(\n `Duplicate service identity ${entry.serviceName}: ${hosts.get(entry.serviceName)} and ${name}.`,\n );\n hosts.set(entry.serviceName, name);\n }\n const saved = loadBlessedGraph(workspaceRoot, graphPath);\n if (saved === null)\n this.fail('Missing saved contract references for approved runtime wiring.');\n const contracts = new ApiContractFiles().load(\n workspaceRoot,\n graphPath,\n saved.apiContractFiles,\n );\n for (const [name, entry] of Object.entries(graph))\n for (const [owner, relation] of Object.entries(entry.apiRelations ?? {})) {\n for (const ref of [...relation.implements, ...relation.uses]) {\n if (\n ref.type !== 'external' &&\n (contracts[ref.api]?.owner !== owner ||\n contracts[ref.api]?.apiKind !== ref.type)\n )\n this.fail(`${name}: unknown qualified contract ${owner}#${ref.api}.`);\n }\n for (const ref of relation.uses) {\n if (ref.targetService === undefined) continue;\n if (\n Object.values(saved!.externalSystems).some((system) =>\n system.apis.includes(ref.api),\n )\n )\n continue;\n const provider = hosts.get(ref.targetService);\n const implemented =\n provider === undefined\n ? undefined\n : graph[provider].apiRelations?.[owner]?.implements;\n if (!implemented?.some((api) => api.api === ref.api && api.type === ref.type))\n this.fail(\n `${name}: target ${ref.targetService} does not implement ${owner}#${ref.api} (${ref.type}).`,\n );\n }\n }\n }\n\n private fail(message: string): never {\n throw new RuleFailError('validate-runtime-architecture', message, undefined, undefined, [\n new Option(\n 'Migrate canonical src/wiring.ts, tag owners webpieces/webpieces-lib, and review runtime-deps.json candidates before generation. Saved visualizations remain available.',\n true,\n ),\n ]);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"approved-graph.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/approved-graph.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport { Option, RuleFailError } from '@webpieces/rules-config';\nimport { RuntimeDeclarationCodec } from './codec';\nimport { RuntimeWiringAssembler } from './assembler';\nimport type { RuntimeDeclaration } from './declaration';\nimport type { EnhancedGraph } from '../graph-sorter';\nimport type { ProjectInfo } from '../project-info';\nimport type { ApiRef, ProjectApiRelations } from '../api-usage/api-relations';\nimport { loadBlessedGraph, DEFAULT_GRAPH_PATH } from '../graph-loader';\nimport { ApiContractFiles } from '../api-contract-files';\n\n/** Assembly consumes approvals only. Source verification is a separate per-project build target. */\nexport class ApprovedWiringGraph {\n attach(\n workspaceRoot: string,\n graph: EnhancedGraph,\n infos: ReadonlyMap<string, ProjectInfo>,\n graphPath: string = DEFAULT_GRAPH_PATH,\n ): void {\n const previous = loadBlessedGraph(workspaceRoot, graphPath);\n if (previous === null)\n this.fail(\n 'Missing saved graph. Complete the runtime declaration migration before generating architecture.',\n );\n const declarations = new Map<string, RuntimeDeclaration>();\n for (const project of infos) {\n const name = project[0];\n const info = project[1];\n const tagged = info.tags.includes('webpieces') || info.tags.includes('webpieces-lib');\n const existingRelations = previous.projects[name]?.apiRelations;\n if (!tagged && existingRelations !== undefined)\n this.fail(\n `${name} has saved runtime facts but is untagged. Migrate it before using declaration-only generation.`,\n );\n if (!tagged) continue;\n const file = path.join(workspaceRoot, info.root, 'runtime-deps.json');\n if (!fs.existsSync(file)) this.fail(`Missing approved declaration ${file}.`);\n declarations.set(\n name,\n new RuntimeDeclarationCodec().decode(fs.readFileSync(file, 'utf8'), name),\n );\n graph[name].runtimeDeclaration = `${info.root}/runtime-deps.json`;\n }\n const assembler = new RuntimeWiringAssembler(declarations);\n for (const project of declarations) {\n const name = project[0];\n const declaration = project[1];\n if (declaration.entry === undefined) continue;\n const entry = graph[name];\n if (declaration.host !== undefined && entry.serviceName !== declaration.host)\n this.fail(\n `${name}: plan host ${declaration.host} disagrees with project serviceName ${entry.serviceName}.`,\n );\n const relations: ProjectApiRelations = {};\n for (const resolved of assembler.assemble(name)) {\n const relation = relations[resolved.owner] ?? {\n kind: 'uses',\n implements: [],\n uses: [],\n };\n const ref: ApiRef = { api: resolved.api, type: resolved.transport };\n if (resolved.conditional !== undefined) ref.conditional = resolved.conditional;\n ref.declaredVia = resolved.via;\n if (resolved.target?.kind === 'service')\n ref.targetService = resolved.target.service;\n if (resolved.transport === 'pubsub' && resolved.direction === 'uses')\n ref.methodsInferred = true;\n relation[resolved.direction].push(ref);\n relation.kind =\n relation.implements.length === 0\n ? 'uses'\n : relation.uses.length === 0\n ? 'implements'\n : 'uses-implements';\n relations[resolved.owner] = relation;\n }\n entry.apiRelations = relations;\n entry.runtimeComposition = true;\n }\n this.validateTargets(workspaceRoot, graphPath, graph);\n }\n\n private validateTargets(workspaceRoot: string, graphPath: string, graph: EnhancedGraph): void {\n const hosts = new Map<string, string>();\n for (const [name, entry] of Object.entries(graph)) {\n if (entry.serviceName === undefined) continue;\n if (hosts.has(entry.serviceName))\n this.fail(\n `Duplicate service identity ${entry.serviceName}: ${hosts.get(entry.serviceName)} and ${name}.`,\n );\n hosts.set(entry.serviceName, name);\n }\n const saved = loadBlessedGraph(workspaceRoot, graphPath);\n if (saved === null)\n this.fail('Missing saved contract references for approved runtime wiring.');\n const contracts = new ApiContractFiles().load(\n workspaceRoot,\n graphPath,\n saved.apiContractFiles,\n );\n for (const [name, entry] of Object.entries(graph))\n for (const [owner, relation] of Object.entries(entry.apiRelations ?? {})) {\n for (const ref of [...relation.implements, ...relation.uses]) {\n if (\n ref.type !== 'external' &&\n (contracts[ref.api]?.owner !== owner ||\n contracts[ref.api]?.apiKind !== ref.type)\n )\n this.fail(`${name}: unknown qualified contract ${owner}#${ref.api}.`);\n }\n for (const ref of relation.uses) {\n if (ref.targetService === undefined) continue;\n if (\n Object.values(saved!.externalSystems).some((system) =>\n system.apis.includes(ref.api),\n )\n )\n continue;\n const provider = hosts.get(ref.targetService);\n const implemented =\n provider === undefined\n ? undefined\n : graph[provider].apiRelations?.[owner]?.implements;\n if (!implemented?.some((api) => api.api === ref.api && api.type === ref.type))\n this.fail(\n `${name}: target ${ref.targetService} does not implement ${owner}#${ref.api} (${ref.type}).`,\n );\n }\n }\n }\n\n private fail(message: string): never {\n throw new RuleFailError('validate-runtime-architecture', message, undefined, undefined, [\n new Option(\n 'Migrate canonical src/wiring.ts, tag owners webpieces/webpieces-lib, and review runtime-deps.json candidates before generation. Saved visualizations remain available.',\n true,\n ),\n ]);\n }\n}\n"]}
|
|
@@ -15,7 +15,8 @@ export declare class RuntimeWiringAssembler {
|
|
|
15
15
|
private readonly declarations;
|
|
16
16
|
constructor(declarations: ReadonlyMap<string, RuntimeDeclaration>);
|
|
17
17
|
assemble(project: string): ResolvedWiringRelationship[];
|
|
18
|
-
private
|
|
18
|
+
private exported;
|
|
19
|
+
private forward;
|
|
19
20
|
private resolveRelationships;
|
|
20
21
|
private isEnabled;
|
|
21
22
|
private resolveTarget;
|
|
@@ -32,33 +32,53 @@ class RuntimeWiringAssembler {
|
|
|
32
32
|
const declaration = this.getDeclaration(project);
|
|
33
33
|
if (declaration.entry === undefined)
|
|
34
34
|
this.fail(`${project} has no approved app entry.`);
|
|
35
|
-
|
|
35
|
+
const root = newSelection(project, declaration.entry);
|
|
36
|
+
const app = this.exported(root, 'app');
|
|
37
|
+
const selections = [root, ...app.wirings.map((child) => this.forward(child, root))];
|
|
38
|
+
const result = [];
|
|
39
|
+
for (const channel of ['bindingModules', 'routingModules']) {
|
|
40
|
+
for (const [index, selection] of selections.entries()) {
|
|
41
|
+
const owner = this.exported(selection, index === 0 ? 'app' : 'wiring');
|
|
42
|
+
if (index > 0 && owner.wirings.length > 0)
|
|
43
|
+
this.fail(`Only AppWiring selects libraries: ${selection.project}#${selection.exportedName}.`);
|
|
44
|
+
for (const [moduleIndex, module] of owner[channel].entries()) {
|
|
45
|
+
const selected = this.forward(module, selection);
|
|
46
|
+
const leaf = this.exported(selected, channel === 'bindingModules' ? 'binding' : 'routing');
|
|
47
|
+
if (leaf.bindingModules.length + leaf.routingModules.length + leaf.wirings.length > 0)
|
|
48
|
+
this.fail('Leaf modules cannot hide composition or composition cycles.');
|
|
49
|
+
const via = `${project}#${declaration.entry}/${index}:${selection.project}#${selection.exportedName}/${channel}[${moduleIndex}]:${selected.project}#${selected.exportedName}`;
|
|
50
|
+
result.push(...this.resolveRelationships(leaf, selected, via));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
36
55
|
}
|
|
37
|
-
|
|
56
|
+
exported(selection, kind) {
|
|
38
57
|
const key = `${selection.project}#${selection.exportedName}`;
|
|
39
|
-
if (stack.has(key))
|
|
40
|
-
this.fail(`Runtime composition cycle: ${[...stack, key].join(' -> ')}`);
|
|
41
58
|
const declaration = this.getDeclaration(selection.project);
|
|
42
59
|
const exported = Object.hasOwn(declaration.exports, selection.exportedName)
|
|
43
60
|
? declaration.exports[selection.exportedName]
|
|
44
61
|
: undefined;
|
|
45
62
|
if (exported === undefined)
|
|
46
63
|
this.fail(`Missing approved export ${key}.`);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
64
|
+
if (exported.kind !== kind)
|
|
65
|
+
this.fail(`${key}: expected ${kind}, found ${exported.kind}. Nested app/library composition is unsupported.`);
|
|
66
|
+
return exported;
|
|
67
|
+
}
|
|
68
|
+
forward(child, parent) {
|
|
69
|
+
const targets = {};
|
|
70
|
+
const policies = {};
|
|
71
|
+
for (const [name, target] of Object.entries(child.targets))
|
|
72
|
+
targets[name] = this.resolveTarget(target, parent);
|
|
73
|
+
for (const [name, value] of Object.entries(child.policies)) {
|
|
74
|
+
const resolved = typeof value === 'object' ? parent.policies[value.parameter] : value;
|
|
75
|
+
if (resolved === undefined || typeof resolved === 'object')
|
|
76
|
+
this.fail(`Unresolved policy parameter ${name} via ${parent.project}#${parent.exportedName}.`);
|
|
77
|
+
policies[name] = resolved;
|
|
58
78
|
}
|
|
59
|
-
return
|
|
79
|
+
return new declaration_1.WiringSelection(child.project, child.exportedName, targets, policies);
|
|
60
80
|
}
|
|
61
|
-
resolveRelationships(exported, selection) {
|
|
81
|
+
resolveRelationships(exported, selection, via) {
|
|
62
82
|
const result = [];
|
|
63
83
|
for (const relationship of exported.relationships) {
|
|
64
84
|
if (!this.isEnabled(relationship, selection))
|
|
@@ -73,7 +93,7 @@ class RuntimeWiringAssembler {
|
|
|
73
93
|
this.fail(`Target capability ${target.contract.project}#${target.contract.exportedName} disagrees with ${relationship.contract.project}#${relationship.contract.exportedName}.`);
|
|
74
94
|
if (relationship.direction === 'uses' && target === undefined)
|
|
75
95
|
this.fail(`Missing target for ${relationship.contract.exportedName}.`);
|
|
76
|
-
result.push(new ResolvedWiringRelationship(relationship.contract.project, relationship.contract.exportedName, relationship.direction, relationship.transport,
|
|
96
|
+
result.push(new ResolvedWiringRelationship(relationship.contract.project, relationship.contract.exportedName, relationship.direction, relationship.transport, via, target, relationship.policy !== undefined &&
|
|
77
97
|
selection.policies[relationship.policy] === 'runtime'
|
|
78
98
|
? `${selection.project}#${selection.exportedName}:${relationship.policy}`
|
|
79
99
|
: undefined));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assembler.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/assembler.ts"],"names":[],"mappings":"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","sourcesContent":["import { Option, RuleFailError } from '@webpieces/rules-config';\nimport type { ApiTransport } from '../api-usage/api-relations';\nimport type {\n DeclaredTarget,\n RuntimeDeclaration,\n WiringExport,\n WiringRelationship,\n} from './declaration';\nimport { WiringSelection } from './declaration';\n\nexport class ResolvedWiringRelationship {\n constructor(\n public readonly owner: string,\n public readonly api: string,\n public readonly direction: 'implements' | 'uses',\n public readonly transport: ApiTransport,\n public readonly via: string,\n public readonly target?: DeclaredTarget,\n public readonly conditional?: string,\n ) {}\n}\n\n/** Pure assembly of reviewed declarations; importing a library never activates its exports. */\nexport class RuntimeWiringAssembler {\n constructor(private readonly declarations: ReadonlyMap<string, RuntimeDeclaration>) {}\n\n assemble(project: string): ResolvedWiringRelationship[] {\n const declaration = this.getDeclaration(project);\n if (declaration.entry === undefined) this.fail(`${project} has no approved app entry.`);\n return this.visit(newSelection(project, declaration.entry!), new Set<string>());\n }\n\n private visit(selection: WiringSelection, stack: Set<string>): ResolvedWiringRelationship[] {\n const key = `${selection.project}#${selection.exportedName}`;\n if (stack.has(key)) this.fail(`Runtime composition cycle: ${[...stack, key].join(' -> ')}`);\n const declaration = this.getDeclaration(selection.project);\n const exported = Object.hasOwn(declaration.exports, selection.exportedName)\n ? declaration.exports[selection.exportedName]\n : undefined;\n if (exported === undefined) this.fail(`Missing approved export ${key}.`);\n const active = new Set([...stack, key]);\n const relationships = this.resolveRelationships(exported!, selection);\n for (const child of exported!.selections) {\n const targets: Record<string, DeclaredTarget> = {};\n for (const name of Object.keys(child.targets))\n targets[name] = this.resolveTarget(child.targets[name], selection);\n const next = newSelection(child.project, child.exportedName, targets, {\n ...selection.policies,\n ...child.policies,\n });\n relationships.push(...this.visit(next, active));\n }\n return relationships;\n }\n\n private resolveRelationships(\n exported: WiringExport,\n selection: WiringSelection,\n ): ResolvedWiringRelationship[] {\n const result: ResolvedWiringRelationship[] = [];\n for (const relationship of exported.relationships) {\n if (!this.isEnabled(relationship, selection)) continue;\n const target =\n relationship.target === undefined\n ? undefined\n : this.resolveTarget(relationship.target, selection);\n if (\n target?.kind === 'service' &&\n target.contract !== undefined &&\n (target.contract.project !== relationship.contract.project ||\n target.contract.exportedName !== relationship.contract.exportedName)\n )\n this.fail(\n `Target capability ${target.contract.project}#${target.contract.exportedName} disagrees with ${relationship.contract.project}#${relationship.contract.exportedName}.`,\n );\n if (relationship.direction === 'uses' && target === undefined)\n this.fail(`Missing target for ${relationship.contract.exportedName}.`);\n result.push(\n new ResolvedWiringRelationship(\n relationship.contract.project,\n relationship.contract.exportedName,\n relationship.direction,\n relationship.transport,\n `${selection.project}#${selection.exportedName}`,\n target,\n relationship.policy !== undefined &&\n selection.policies[relationship.policy] === 'runtime'\n ? `${selection.project}#${selection.exportedName}:${relationship.policy}`\n : undefined,\n ),\n );\n }\n return result;\n }\n\n private isEnabled(relationship: WiringRelationship, selection: WiringSelection): boolean {\n if (relationship.policy === undefined) return true;\n const decision = selection.policies[relationship.policy];\n if (decision === undefined)\n this.fail(\n `Missing explicit policy ${relationship.policy} in ${selection.project}#${selection.exportedName}.`,\n );\n return decision === 'runtime' || decision === true;\n }\n\n private resolveTarget(target: DeclaredTarget, selection: WiringSelection): DeclaredTarget {\n if (target.kind !== 'parameter') return target;\n const argument = selection.targets[target.parameter];\n if (argument === undefined || argument.kind === 'parameter')\n this.fail(\n `Unresolved target parameter ${target.parameter} in ${selection.project}#${selection.exportedName}.`,\n );\n return argument!;\n }\n\n private getDeclaration(project: string): RuntimeDeclaration {\n const declaration = this.declarations.get(project);\n if (declaration === undefined)\n this.fail(`Missing approved runtime-deps.json for ${project}.`);\n return declaration!;\n }\n\n private fail(message: string): never {\n throw new RuleFailError('validate-runtime-architecture', message, undefined, undefined, [\n new Option(\n 'Migrate src/wiring.ts and review its runtime-deps.json before generating the graph.',\n true,\n ),\n ]);\n }\n}\n\n// webpieces-disable no-function-outside-class -- construction helper for the pure assembly entry point\nfunction newSelection(\n project: string,\n exportedName: string,\n targets: Record<string, DeclaredTarget> = {},\n policies: Record<string, boolean | 'runtime'> = {},\n): WiringSelection {\n return new WiringSelection(project, exportedName, targets, policies);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"assembler.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/assembler.ts"],"names":[],"mappings":"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","sourcesContent":["import { Option, RuleFailError } from '@webpieces/rules-config';\nimport type { ApiTransport } from '../api-usage/api-relations';\nimport type {\n DeclaredTarget,\n RuntimeDeclaration,\n WiringExport,\n WiringRelationship,\n PolicyValue,\n} from './declaration';\nimport { WiringSelection } from './declaration';\n\nexport class ResolvedWiringRelationship {\n constructor(\n public readonly owner: string,\n public readonly api: string,\n public readonly direction: 'implements' | 'uses',\n public readonly transport: ApiTransport,\n public readonly via: string,\n public readonly target?: DeclaredTarget,\n public readonly conditional?: string,\n ) {}\n}\n\n/** Pure assembly of reviewed declarations; importing a library never activates its exports. */\nexport class RuntimeWiringAssembler {\n constructor(private readonly declarations: ReadonlyMap<string, RuntimeDeclaration>) {}\n\n assemble(project: string): ResolvedWiringRelationship[] {\n const declaration = this.getDeclaration(project);\n if (declaration.entry === undefined) this.fail(`${project} has no approved app entry.`);\n const root = newSelection(project, declaration.entry!);\n const app = this.exported(root, 'app');\n const selections = [root, ...app.wirings.map((child: WiringSelection) => this.forward(child, root))];\n const result: ResolvedWiringRelationship[] = [];\n for (const channel of ['bindingModules', 'routingModules'] as const) {\n for (const [index, selection] of selections.entries()) {\n const owner = this.exported(selection, index === 0 ? 'app' : 'wiring');\n if (index > 0 && owner.wirings.length > 0)\n this.fail(`Only AppWiring selects libraries: ${selection.project}#${selection.exportedName}.`);\n for (const [moduleIndex, module] of owner[channel].entries()) {\n const selected = this.forward(module, selection);\n const leaf = this.exported(selected, channel === 'bindingModules' ? 'binding' : 'routing');\n if (leaf.bindingModules.length + leaf.routingModules.length + leaf.wirings.length > 0)\n this.fail('Leaf modules cannot hide composition or composition cycles.');\n const via = `${project}#${declaration.entry}/${index}:${selection.project}#${selection.exportedName}/${channel}[${moduleIndex}]:${selected.project}#${selected.exportedName}`;\n result.push(...this.resolveRelationships(leaf, selected, via));\n }\n }\n }\n return result;\n }\n\n private exported(selection: WiringSelection, kind: WiringExport['kind']): WiringExport {\n const key = `${selection.project}#${selection.exportedName}`;\n const declaration = this.getDeclaration(selection.project);\n const exported = Object.hasOwn(declaration.exports, selection.exportedName)\n ? declaration.exports[selection.exportedName]\n : undefined;\n if (exported === undefined) this.fail(`Missing approved export ${key}.`);\n if (exported.kind !== kind)\n this.fail(`${key}: expected ${kind}, found ${exported.kind}. Nested app/library composition is unsupported.`);\n return exported;\n }\n\n private forward(child: WiringSelection, parent: WiringSelection): WiringSelection {\n const targets: Record<string, DeclaredTarget> = {};\n const policies: Record<string, PolicyValue> = {};\n for (const [name, target] of Object.entries(child.targets))\n targets[name] = this.resolveTarget(target, parent);\n for (const [name, value] of Object.entries(child.policies)) {\n const resolved = typeof value === 'object' ? parent.policies[value.parameter] : value;\n if (resolved === undefined || typeof resolved === 'object')\n this.fail(`Unresolved policy parameter ${name} via ${parent.project}#${parent.exportedName}.`);\n policies[name] = resolved;\n }\n return new WiringSelection(child.project, child.exportedName, targets, policies);\n }\n\n private resolveRelationships(\n exported: WiringExport,\n selection: WiringSelection,\n via: string,\n ): ResolvedWiringRelationship[] {\n const result: ResolvedWiringRelationship[] = [];\n for (const relationship of exported.relationships) {\n if (!this.isEnabled(relationship, selection)) continue;\n const target =\n relationship.target === undefined\n ? undefined\n : this.resolveTarget(relationship.target, selection);\n if (\n target?.kind === 'service' &&\n target.contract !== undefined &&\n (target.contract.project !== relationship.contract.project ||\n target.contract.exportedName !== relationship.contract.exportedName)\n )\n this.fail(\n `Target capability ${target.contract.project}#${target.contract.exportedName} disagrees with ${relationship.contract.project}#${relationship.contract.exportedName}.`,\n );\n if (relationship.direction === 'uses' && target === undefined)\n this.fail(`Missing target for ${relationship.contract.exportedName}.`);\n result.push(\n new ResolvedWiringRelationship(\n relationship.contract.project,\n relationship.contract.exportedName,\n relationship.direction,\n relationship.transport,\n via,\n target,\n relationship.policy !== undefined &&\n selection.policies[relationship.policy] === 'runtime'\n ? `${selection.project}#${selection.exportedName}:${relationship.policy}`\n : undefined,\n ),\n );\n }\n return result;\n }\n\n private isEnabled(relationship: WiringRelationship, selection: WiringSelection): boolean {\n if (relationship.policy === undefined) return true;\n const decision = selection.policies[relationship.policy];\n if (decision === undefined)\n this.fail(\n `Missing explicit policy ${relationship.policy} in ${selection.project}#${selection.exportedName}.`,\n );\n return decision === 'runtime' || decision === true;\n }\n\n private resolveTarget(target: DeclaredTarget, selection: WiringSelection): DeclaredTarget {\n if (target.kind !== 'parameter') return target;\n const argument = selection.targets[target.parameter];\n if (argument === undefined || argument.kind === 'parameter')\n this.fail(\n `Unresolved target parameter ${target.parameter} in ${selection.project}#${selection.exportedName}.`,\n );\n return argument!;\n }\n\n private getDeclaration(project: string): RuntimeDeclaration {\n const declaration = this.declarations.get(project);\n if (declaration === undefined)\n this.fail(`Missing approved runtime-deps.json for ${project}.`);\n return declaration!;\n }\n\n private fail(message: string): never {\n throw new RuleFailError('validate-runtime-architecture', message, undefined, undefined, [\n new Option(\n 'Migrate src/wiring.ts and review its runtime-deps.json before generating the graph.',\n true,\n ),\n ]);\n }\n}\n\n// webpieces-disable no-function-outside-class -- construction helper for the pure assembly entry point\nfunction newSelection(\n project: string,\n exportedName: string,\n targets: Record<string, DeclaredTarget> = {},\n policies: Record<string, PolicyValue> = {},\n): WiringSelection {\n return new WiringSelection(project, exportedName, targets, policies);\n}\n"]}
|
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
import * as ts from 'typescript';
|
|
2
|
-
|
|
3
|
-
/** ALL-CODE grammar check: no git diff, line exemptions, or wiring.ts carve-out. */
|
|
2
|
+
/** Replacement diagnostics used only by the canonical wiring-format analyzer. */
|
|
4
3
|
export declare class CanonicalClientBindings {
|
|
5
4
|
private readonly checker;
|
|
6
5
|
constructor(checker: ts.TypeChecker);
|
|
7
6
|
problems(file: ts.SourceFile): string[];
|
|
8
|
-
assert(problems: readonly string[]): void;
|
|
9
7
|
private checkFactory;
|
|
10
8
|
private singleton;
|
|
11
9
|
private property;
|
|
12
10
|
private method;
|
|
13
11
|
private expand;
|
|
14
12
|
}
|
|
15
|
-
/** Architecture validation scans every participating owner, even when its build isn't affected. */
|
|
16
|
-
export declare class WorkspaceClientBindings {
|
|
17
|
-
private program;
|
|
18
|
-
assert(workspaceRoot: string, infos: ReadonlyMap<string, ProjectInfo>): void;
|
|
19
|
-
}
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.CanonicalClientBindings = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const path = tslib_1.__importStar(require("path"));
|
|
6
5
|
const ts = tslib_1.__importStar(require("typescript"));
|
|
7
|
-
|
|
8
|
-
const program_1 = require("../di-graph/program");
|
|
9
|
-
/** ALL-CODE grammar check: no git diff, line exemptions, or wiring.ts carve-out. */
|
|
6
|
+
/** Replacement diagnostics used only by the canonical wiring-format analyzer. */
|
|
10
7
|
class CanonicalClientBindings {
|
|
11
8
|
checker;
|
|
12
9
|
constructor(checker) {
|
|
13
10
|
this.checker = checker;
|
|
14
11
|
}
|
|
15
12
|
problems(file) {
|
|
13
|
+
if (!/(?:^|\/)wiring\.ts$/.test(file.fileName))
|
|
14
|
+
return [];
|
|
16
15
|
const problems = [];
|
|
17
16
|
const visit = (node) => {
|
|
18
17
|
if (ts.isCallExpression(node) && this.method(node.expression) === 'toDynamicValue') {
|
|
@@ -38,13 +37,6 @@ class CanonicalClientBindings {
|
|
|
38
37
|
visit(file);
|
|
39
38
|
return problems;
|
|
40
39
|
}
|
|
41
|
-
assert(problems) {
|
|
42
|
-
if (problems.length === 0)
|
|
43
|
-
return;
|
|
44
|
-
throw new rules_config_1.RuleFailError('validate-runtime-architecture', problems.join('\n'), undefined, undefined, [
|
|
45
|
-
new rules_config_1.Option('Replace every supported hand-written registration, including unchanged code in src/wiring.ts. Use RuntimeClients.bindRpc with rpcTarget; RuntimeTaskClients.bindPubSub for task clients; provideRpcClient for browser providers. Preserve tokens, filters and lazy singleton resolution.', true),
|
|
46
|
-
]);
|
|
47
|
-
}
|
|
48
40
|
checkFactory(factory, token, browser, file, problems) {
|
|
49
41
|
if (factory === undefined || token === undefined)
|
|
50
42
|
return;
|
|
@@ -87,8 +79,8 @@ class CanonicalClientBindings {
|
|
|
87
79
|
const replacement = task
|
|
88
80
|
? `new RuntimeTaskClients(options).bindPubSub(${token.getText()}, ${api}, ${target});`
|
|
89
81
|
: provider
|
|
90
|
-
? `provideRpcClient(${token.getText()}, ${api},
|
|
91
|
-
: `new RuntimeClients(options).bindRpc(${token.getText()}, ${api},
|
|
82
|
+
? `provideRpcClient(${token.getText()}, ${api}, ${target})`
|
|
83
|
+
: `new RuntimeClients(options).bindRpc(${token.getText()}, ${api}, ${target}${filters});`;
|
|
92
84
|
const location = file.getLineAndCharacterOfPosition(factory.getStart(file));
|
|
93
85
|
problems.push(`${file.fileName}:${location.line + 1}:${location.character + 1}: canonical client registration required: ${replacement}`);
|
|
94
86
|
}
|
|
@@ -144,35 +136,4 @@ class CanonicalClientBindings {
|
|
|
144
136
|
}
|
|
145
137
|
}
|
|
146
138
|
exports.CanonicalClientBindings = CanonicalClientBindings;
|
|
147
|
-
/** Architecture validation scans every participating owner, even when its build isn't affected. */
|
|
148
|
-
class WorkspaceClientBindings {
|
|
149
|
-
program(root) {
|
|
150
|
-
const configured = (0, program_1.createProjectProgram)(root);
|
|
151
|
-
const files = ts.sys.readDirectory(path.join(root, 'src'), ['.ts', '.tsx'], ['**/*.spec.ts', '**/*.test.ts', '**/__tests__/**', '**/node_modules/**']);
|
|
152
|
-
return ts.createProgram(files, configured?.getCompilerOptions() ?? {});
|
|
153
|
-
}
|
|
154
|
-
assert(workspaceRoot, infos) {
|
|
155
|
-
const problems = [];
|
|
156
|
-
for (const info of infos.values()) {
|
|
157
|
-
if (!info.tags.some((tag) => tag === 'webpieces' || tag === 'webpieces-lib'))
|
|
158
|
-
continue;
|
|
159
|
-
const program = this.program(path.resolve(workspaceRoot, info.root));
|
|
160
|
-
const check = new CanonicalClientBindings(program.getTypeChecker());
|
|
161
|
-
const root = path.resolve(workspaceRoot, info.root) + path.sep;
|
|
162
|
-
for (const file of program.getSourceFiles()) {
|
|
163
|
-
if (file.isDeclarationFile ||
|
|
164
|
-
!file.fileName.startsWith(root) ||
|
|
165
|
-
/(?:\.spec\.|\.test\.|\/__tests__\/|\/node_modules\/)/.test(file.fileName))
|
|
166
|
-
continue;
|
|
167
|
-
problems.push(...check.problems(file));
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
// No source program is needed to render a structured aggregate failure.
|
|
171
|
-
if (problems.length > 0)
|
|
172
|
-
throw new rules_config_1.RuleFailError('validate-runtime-architecture', problems.join('\n'), undefined, undefined, [
|
|
173
|
-
new rules_config_1.Option('Migrate all reported registrations using the canonical helpers and rpcTarget, preserving tokens and filters. This checks ALL CODE in every participating runtime owner, irrespective of the current diff.', true),
|
|
174
|
-
]);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
exports.WorkspaceClientBindings = WorkspaceClientBindings;
|
|
178
139
|
//# sourceMappingURL=canonical-clients.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canonical-clients.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/canonical-clients.ts"],"names":[],"mappings":";;;;AAAA,mDAA6B;AAC7B,uDAAiC;AACjC,0DAAgE;AAEhE,iDAA2D;AAE3D,oFAAoF;AACpF,MAAa,uBAAuB;IACH;IAA7B,YAA6B,OAAuB;QAAvB,YAAO,GAAP,OAAO,CAAgB;IAAG,CAAC;IAExD,QAAQ,CAAC,IAAmB;QACxB,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,CAAC,IAAa,EAAQ,EAAE;YAClC,IAAI,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,gBAAgB,EAAE,CAAC;gBACjF,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAC1C,MAAM,QAAQ,GACV,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC;oBACrE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;oBAC9B,CAAC,CAAC,SAAS,CAAC;gBACpB,IACI,QAAQ,KAAK,SAAS;oBACtB,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC;oBAC7B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,MAAM;oBAC3C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EACtB,CAAC;oBACC,IAAI,CAAC,YAAY,CACb,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EACjB,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EACrB,KAAK,EACL,IAAI,EACJ,QAAQ,CACX,CAAC;gBACN,CAAC;YACL,CAAC;YACD,IAAI,EAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;gBAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;gBAClD,IAAI,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,SAAS;oBAC5C,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;YAChE,CAAC;YACD,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACjC,CAAC,CAAC;QACF,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,OAAO,QAAQ,CAAC;IACpB,CAAC;IAED,MAAM,CAAC,QAA2B;QAC9B,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAClC,MAAM,IAAI,4BAAa,CACnB,+BAA+B,EAC/B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EACnB,SAAS,EACT,SAAS,EACT;YACI,IAAI,qBAAM,CACN,0RAA0R,EAC1R,IAAI,CACP;SACJ,CACJ,CAAC;IACN,CAAC;IAEO,YAAY,CAChB,OAAkC,EAClC,KAAgC,EAChC,OAAgB,EAChB,IAAmB,EACnB,QAAkB;QAElB,IAAI,OAAO,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO;QACzD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACnC,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,oBAAoB,CAAC,KAAK,CAAC;YAAE,OAAO;QAC1E,MAAM,MAAM,GACR,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC;YACtB,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC;YAClC,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAC1C,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU;YACrC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC;gBACtB,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;QACvB,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,CAAC,0DAA0D;QAC5F,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACjC,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC;YAAE,OAAO;QACvC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC;QACzE,MAAM,KAAK,GAAG,WAAW,EAAE,MAAM,CAAC;QAClC,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,EAAE,CAAC,kBAAkB,CAAC,KAAK,CAAC;YAAE,OAAO;QACjE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC5C,MAAM,GAAG,GAAG,IAAI,KAAK,mBAAmB,IAAI,MAAM,KAAK,iBAAiB,IAAI,CAAC,OAAO,CAAC;QACrF,MAAM,IAAI,GACN,IAAI,KAAK,yBAAyB,IAAI,MAAM,KAAK,oBAAoB,IAAI,CAAC,OAAO,CAAC;QACtF,MAAM,QAAQ,GACV,IAAI,KAAK,0BAA0B,IAAI,MAAM,KAAK,iBAAiB,IAAI,OAAO,CAAC;QACnF,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QACvC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAAE,OAAO;QAC/E,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,IACI,CAAC,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC;YAC3B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,cAAc,CAAC;YAC/E,MAAM,CAAC,SAAS,EAAE,MAAM,KAAK,CAAC;YAE9B,OAAO,CAAC,qDAAqD;QACjE,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;QAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;QAC1F,MAAM,WAAW,GAAG,IAAI;YACpB,CAAC,CAAC,8CAA8C,KAAK,CAAC,OAAO,EAAE,KAAK,GAAG,KAAK,MAAM,IAAI;YACtF,CAAC,CAAC,QAAQ;gBACR,CAAC,CAAC,oBAAoB,KAAK,CAAC,OAAO,EAAE,KAAK,GAAG,eAAe,GAAG,KAAK,MAAM,IAAI;gBAC9E,CAAC,CAAC,uCAAuC,KAAK,CAAC,OAAO,EAAE,KAAK,GAAG,eAAe,GAAG,KAAK,MAAM,IAAI,OAAO,IAAI,CAAC;QACnH,MAAM,QAAQ,GAAG,IAAI,CAAC,6BAA6B,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5E,QAAQ,CAAC,IAAI,CACT,GAAG,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC,IAAI,QAAQ,CAAC,SAAS,GAAG,CAAC,6CAA6C,WAAW,EAAE,CAC5H,CAAC;IACN,CAAC;IAEO,SAAS,CAAC,IAAuB;QACrC,IAAI,IAAI,GAAY,IAAI,CAAC;QACzB,OACI,IAAI,CAAC,MAAM,KAAK,SAAS;YACzB,CAAC,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,MAAM,CAAC;gBACvC,EAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC,MAAM,CAAC;gBACzC,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EACvC,CAAC;YACC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC;YACnB,IAAI,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,kBAAkB;gBAChF,OAAO,IAAI,CAAC;QACpB,CAAC;QACD,OAAO,KAAK,CAAC;IACjB,CAAC;IAEO,QAAQ,CAAC,IAAgC,EAAE,IAAY;QAC3D,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACrC,IACI,EAAE,CAAC,oBAAoB,CAAC,QAAQ,CAAC;gBACjC,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,mBAAmB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACzE,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI;gBAE3B,OAAO,QAAQ,CAAC,WAAW,CAAC;YAChC,IAAI,EAAE,CAAC,6BAA6B,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI;gBACzE,OAAO,QAAQ,CAAC,IAAI,CAAC;QAC7B,CAAC;QACD,OAAO,SAAS,CAAC;IACrB,CAAC;IAEO,MAAM,CAAC,UAAyB;QACpC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACtC,IAAI,EAAE,CAAC,0BAA0B,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QACjE,IAAI,EAAE,CAAC,yBAAyB,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,mBAAmB,CAAC,KAAK,CAAC,kBAAkB,CAAC;YACvF,OAAO,KAAK,CAAC,kBAAkB,CAAC,IAAI,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;QACvD,OAAO,MAAM,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC;YACtE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE;YACjD,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACjD,CAAC;IAEO,MAAM,CAAC,UAAyB,EAAE,OAAqB,IAAI,GAAG,EAAE;QACpE,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;YAAE,OAAO,UAAU,CAAC;QAC5C,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACrB,IACI,EAAE,CAAC,yBAAyB,CAAC,UAAU,CAAC;YACxC,EAAE,CAAC,cAAc,CAAC,UAAU,CAAC;YAC7B,EAAE,CAAC,mBAAmB,CAAC,UAAU,CAAC;YAClC,EAAE,CAAC,qBAAqB,CAAC,UAAU,CAAC;YAEpC,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACpD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAC;QACnF,IACI,WAAW,KAAK,SAAS;YACzB,EAAE,CAAC,qBAAqB,CAAC,WAAW,CAAC;YACrC,WAAW,CAAC,WAAW,KAAK,SAAS;YAErC,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACtD,OAAO,UAAU,CAAC;IACtB,CAAC;CACJ;AAxKD,0DAwKC;AAED,mGAAmG;AACnG,MAAa,uBAAuB;IACxB,OAAO,CAAC,IAAY;QACxB,MAAM,UAAU,GAAG,IAAA,8BAAoB,EAAC,IAAI,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,CAC9B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,EACtB,CAAC,KAAK,EAAE,MAAM,CAAC,EACf,CAAC,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,oBAAoB,CAAC,CAC5E,CAAC;QACF,OAAO,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,MAAM,CAAC,aAAqB,EAAE,KAAuC;QACjE,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,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,eAAe,CAAC;gBAAE,SAAS;YACvF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YACrE,MAAM,KAAK,GAAG,IAAI,uBAAuB,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;YACpE,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC;YAC/D,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC;gBAC1C,IACI,IAAI,CAAC,iBAAiB;oBACtB,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC;oBAC/B,sDAAsD,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;oBAE1E,SAAS;gBACb,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;YAC3C,CAAC;QACL,CAAC;QACD,wEAAwE;QACxE,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;YACnB,MAAM,IAAI,4BAAa,CACnB,+BAA+B,EAC/B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EACnB,SAAS,EACT,SAAS,EACT;gBACI,IAAI,qBAAM,CACN,2MAA2M,EAC3M,IAAI,CACP;aACJ,CACJ,CAAC;IACV,CAAC;CACJ;AA3CD,0DA2CC","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';\n\n/** ALL-CODE grammar check: no git diff, line exemptions, or wiring.ts carve-out. */\nexport class CanonicalClientBindings {\n constructor(private readonly checker: ts.TypeChecker) {}\n\n problems(file: ts.SourceFile): string[] {\n const problems: string[] = [];\n const visit = (node: ts.Node): void => {\n if (ts.isCallExpression(node) && this.method(node.expression) === 'toDynamicValue') {\n const bind = this.expand(node.expression);\n const receiver =\n ts.isPropertyAccessExpression(bind) || ts.isElementAccessExpression(bind)\n ? this.expand(bind.expression)\n : undefined;\n if (\n receiver !== undefined &&\n ts.isCallExpression(receiver) &&\n this.method(receiver.expression) === 'bind' &&\n this.singleton(node)\n ) {\n this.checkFactory(\n node.arguments[0],\n receiver.arguments[0],\n false,\n file,\n problems,\n );\n }\n }\n if (ts.isObjectLiteralExpression(node)) {\n const token = this.property(node, 'provide');\n const factory = this.property(node, 'useFactory');\n if (token !== undefined && factory !== undefined)\n this.checkFactory(factory, token, true, file, problems);\n }\n ts.forEachChild(node, visit);\n };\n visit(file);\n return problems;\n }\n\n assert(problems: readonly string[]): void {\n if (problems.length === 0) return;\n throw new RuleFailError(\n 'validate-runtime-architecture',\n problems.join('\\n'),\n undefined,\n undefined,\n [\n new Option(\n 'Replace every supported hand-written registration, including unchanged code in src/wiring.ts. Use RuntimeClients.bindRpc with rpcTarget; RuntimeTaskClients.bindPubSub for task clients; provideRpcClient for browser providers. Preserve tokens, filters and lazy singleton resolution.',\n true,\n ),\n ],\n );\n }\n\n private checkFactory(\n factory: ts.Expression | undefined,\n token: ts.Expression | undefined,\n browser: boolean,\n file: ts.SourceFile,\n problems: string[],\n ): void {\n if (factory === undefined || token === undefined) return;\n const value = this.expand(factory);\n if (!ts.isArrowFunction(value) && !ts.isFunctionExpression(value)) return;\n const result =\n ts.isBlock(value.body) &&\n value.body.statements.length === 1 &&\n ts.isReturnStatement(value.body.statements[0])\n ? value.body.statements[0].expression\n : ts.isBlock(value.body)\n ? undefined\n : value.body;\n if (result === undefined) return; // Side effects/custom adapters have no helper equivalent.\n const call = this.expand(result);\n if (!ts.isCallExpression(call)) return;\n const declaration = this.checker.getResolvedSignature(call)?.declaration;\n const owner = declaration?.parent;\n if (owner === undefined || !ts.isClassDeclaration(owner)) return;\n const name = owner.name?.text;\n const method = this.method(call.expression);\n const rpc = name === 'ClientHttpFactory' && method === 'createRpcClient' && !browser;\n const task =\n name === 'ClientCloudTasksFactory' && method === 'createPubSubClient' && !browser;\n const provider =\n name === 'ClientHttpBrowserFactory' && method === 'createRpcClient' && browser;\n if (!rpc && !task && !provider) return;\n if (call.arguments.length < 2 || call.arguments.length > (rpc ? 3 : 2)) return;\n const config = this.expand(call.arguments[1]);\n if (\n !ts.isNewExpression(config) ||\n this.method(config.expression) !== (task ? 'TaskClientConfig' : 'ClientConfig') ||\n config.arguments?.length !== 1\n )\n return; // Custom config options aren't supported by helpers.\n const api = call.arguments[0].getText();\n const target = config.arguments[0].getText();\n const filters = call.arguments[2] === undefined ? '' : `, ${call.arguments[2].getText()}`;\n const replacement = task\n ? `new RuntimeTaskClients(options).bindPubSub(${token.getText()}, ${api}, ${target});`\n : provider\n ? `provideRpcClient(${token.getText()}, ${api}, rpcTarget(${api}, ${target}))`\n : `new RuntimeClients(options).bindRpc(${token.getText()}, ${api}, rpcTarget(${api}, ${target})${filters});`;\n const location = file.getLineAndCharacterOfPosition(factory.getStart(file));\n problems.push(\n `${file.fileName}:${location.line + 1}:${location.character + 1}: canonical client registration required: ${replacement}`,\n );\n }\n\n private singleton(call: ts.CallExpression): boolean {\n let node: ts.Node = call;\n while (\n node.parent !== undefined &&\n (ts.isPropertyAccessExpression(node.parent) ||\n ts.isElementAccessExpression(node.parent) ||\n ts.isCallExpression(node.parent))\n ) {\n node = node.parent;\n if (ts.isCallExpression(node) && this.method(node.expression) === 'inSingletonScope')\n return true;\n }\n return false;\n }\n\n private property(node: ts.ObjectLiteralExpression, name: string): ts.Expression | undefined {\n for (const property of node.properties) {\n if (\n ts.isPropertyAssignment(property) &&\n (ts.isIdentifier(property.name) || ts.isStringLiteralLike(property.name)) &&\n property.name.text === name\n )\n return property.initializer;\n if (ts.isShorthandPropertyAssignment(property) && property.name.text === name)\n return property.name;\n }\n return undefined;\n }\n\n private method(expression: ts.Expression): string {\n const value = this.expand(expression);\n if (ts.isPropertyAccessExpression(value)) return value.name.text;\n if (ts.isElementAccessExpression(value) && ts.isStringLiteralLike(value.argumentExpression))\n return value.argumentExpression.text;\n const symbol = this.checker.getSymbolAtLocation(value);\n return symbol !== undefined && (symbol.flags & ts.SymbolFlags.Alias) !== 0\n ? this.checker.getAliasedSymbol(symbol).getName()\n : (symbol?.getName() ?? value.getText());\n }\n\n private expand(expression: ts.Expression, seen: Set<ts.Node> = new Set()): ts.Expression {\n if (seen.has(expression)) return expression;\n seen.add(expression);\n if (\n ts.isParenthesizedExpression(expression) ||\n ts.isAsExpression(expression) ||\n ts.isNonNullExpression(expression) ||\n ts.isSatisfiesExpression(expression)\n )\n return this.expand(expression.expression, seen);\n const declaration = this.checker.getSymbolAtLocation(expression)?.valueDeclaration;\n if (\n declaration !== undefined &&\n ts.isVariableDeclaration(declaration) &&\n declaration.initializer !== undefined\n )\n return this.expand(declaration.initializer, seen);\n return expression;\n }\n}\n\n/** Architecture validation scans every participating owner, even when its build isn't affected. */\nexport class WorkspaceClientBindings {\n private program(root: string): ts.Program {\n const configured = createProjectProgram(root);\n const files = ts.sys.readDirectory(\n path.join(root, 'src'),\n ['.ts', '.tsx'],\n ['**/*.spec.ts', '**/*.test.ts', '**/__tests__/**', '**/node_modules/**'],\n );\n return ts.createProgram(files, configured?.getCompilerOptions() ?? {});\n }\n\n assert(workspaceRoot: string, infos: ReadonlyMap<string, ProjectInfo>): void {\n const problems: string[] = [];\n for (const info of infos.values()) {\n if (!info.tags.some((tag) => tag === 'webpieces' || tag === 'webpieces-lib')) continue;\n const program = this.program(path.resolve(workspaceRoot, info.root));\n const check = new CanonicalClientBindings(program.getTypeChecker());\n const root = path.resolve(workspaceRoot, info.root) + path.sep;\n for (const file of program.getSourceFiles()) {\n if (\n file.isDeclarationFile ||\n !file.fileName.startsWith(root) ||\n /(?:\\.spec\\.|\\.test\\.|\\/__tests__\\/|\\/node_modules\\/)/.test(file.fileName)\n )\n continue;\n problems.push(...check.problems(file));\n }\n }\n // No source program is needed to render a structured aggregate failure.\n if (problems.length > 0)\n throw new RuleFailError(\n 'validate-runtime-architecture',\n problems.join('\\n'),\n undefined,\n undefined,\n [\n new Option(\n 'Migrate all reported registrations using the canonical helpers and rpcTarget, preserving tokens and filters. This checks ALL CODE in every participating runtime owner, irrespective of the current diff.',\n true,\n ),\n ],\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"canonical-clients.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/canonical-clients.ts"],"names":[],"mappings":"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","sourcesContent":["import * as ts from 'typescript';\n\n/** Replacement diagnostics used only by the canonical wiring-format analyzer. */\nexport class CanonicalClientBindings {\n constructor(private readonly checker: ts.TypeChecker) {}\n\n problems(file: ts.SourceFile): string[] {\n if (!/(?:^|\\/)wiring\\.ts$/.test(file.fileName)) return [];\n const problems: string[] = [];\n const visit = (node: ts.Node): void => {\n if (ts.isCallExpression(node) && this.method(node.expression) === 'toDynamicValue') {\n const bind = this.expand(node.expression);\n const receiver =\n ts.isPropertyAccessExpression(bind) || ts.isElementAccessExpression(bind)\n ? this.expand(bind.expression)\n : undefined;\n if (\n receiver !== undefined &&\n ts.isCallExpression(receiver) &&\n this.method(receiver.expression) === 'bind' &&\n this.singleton(node)\n ) {\n this.checkFactory(\n node.arguments[0],\n receiver.arguments[0],\n false,\n file,\n problems,\n );\n }\n }\n if (ts.isObjectLiteralExpression(node)) {\n const token = this.property(node, 'provide');\n const factory = this.property(node, 'useFactory');\n if (token !== undefined && factory !== undefined)\n this.checkFactory(factory, token, true, file, problems);\n }\n ts.forEachChild(node, visit);\n };\n visit(file);\n return problems;\n }\n\n private checkFactory(\n factory: ts.Expression | undefined,\n token: ts.Expression | undefined,\n browser: boolean,\n file: ts.SourceFile,\n problems: string[],\n ): void {\n if (factory === undefined || token === undefined) return;\n const value = this.expand(factory);\n if (!ts.isArrowFunction(value) && !ts.isFunctionExpression(value)) return;\n const result =\n ts.isBlock(value.body) &&\n value.body.statements.length === 1 &&\n ts.isReturnStatement(value.body.statements[0])\n ? value.body.statements[0].expression\n : ts.isBlock(value.body)\n ? undefined\n : value.body;\n if (result === undefined) return; // Side effects/custom adapters have no helper equivalent.\n const call = this.expand(result);\n if (!ts.isCallExpression(call)) return;\n const declaration = this.checker.getResolvedSignature(call)?.declaration;\n const owner = declaration?.parent;\n if (owner === undefined || !ts.isClassDeclaration(owner)) return;\n const name = owner.name?.text;\n const method = this.method(call.expression);\n const rpc = name === 'ClientHttpFactory' && method === 'createRpcClient' && !browser;\n const task =\n name === 'ClientCloudTasksFactory' && method === 'createPubSubClient' && !browser;\n const provider =\n name === 'ClientHttpBrowserFactory' && method === 'createRpcClient' && browser;\n if (!rpc && !task && !provider) return;\n if (call.arguments.length < 2 || call.arguments.length > (rpc ? 3 : 2)) return;\n const config = this.expand(call.arguments[1]);\n if (\n !ts.isNewExpression(config) ||\n this.method(config.expression) !== (task ? 'TaskClientConfig' : 'ClientConfig') ||\n config.arguments?.length !== 1\n )\n return; // Custom config options aren't supported by helpers.\n const api = call.arguments[0].getText();\n const target = config.arguments[0].getText();\n const filters = call.arguments[2] === undefined ? '' : `, ${call.arguments[2].getText()}`;\n const replacement = task\n ? `new RuntimeTaskClients(options).bindPubSub(${token.getText()}, ${api}, ${target});`\n : provider\n ? `provideRpcClient(${token.getText()}, ${api}, ${target})`\n : `new RuntimeClients(options).bindRpc(${token.getText()}, ${api}, ${target}${filters});`;\n const location = file.getLineAndCharacterOfPosition(factory.getStart(file));\n problems.push(\n `${file.fileName}:${location.line + 1}:${location.character + 1}: canonical client registration required: ${replacement}`,\n );\n }\n\n private singleton(call: ts.CallExpression): boolean {\n let node: ts.Node = call;\n while (\n node.parent !== undefined &&\n (ts.isPropertyAccessExpression(node.parent) ||\n ts.isElementAccessExpression(node.parent) ||\n ts.isCallExpression(node.parent))\n ) {\n node = node.parent;\n if (ts.isCallExpression(node) && this.method(node.expression) === 'inSingletonScope')\n return true;\n }\n return false;\n }\n\n private property(node: ts.ObjectLiteralExpression, name: string): ts.Expression | undefined {\n for (const property of node.properties) {\n if (\n ts.isPropertyAssignment(property) &&\n (ts.isIdentifier(property.name) || ts.isStringLiteralLike(property.name)) &&\n property.name.text === name\n )\n return property.initializer;\n if (ts.isShorthandPropertyAssignment(property) && property.name.text === name)\n return property.name;\n }\n return undefined;\n }\n\n private method(expression: ts.Expression): string {\n const value = this.expand(expression);\n if (ts.isPropertyAccessExpression(value)) return value.name.text;\n if (ts.isElementAccessExpression(value) && ts.isStringLiteralLike(value.argumentExpression))\n return value.argumentExpression.text;\n const symbol = this.checker.getSymbolAtLocation(value);\n return symbol !== undefined && (symbol.flags & ts.SymbolFlags.Alias) !== 0\n ? this.checker.getAliasedSymbol(symbol).getName()\n : (symbol?.getName() ?? value.getText());\n }\n\n private expand(expression: ts.Expression, seen: Set<ts.Node> = new Set()): ts.Expression {\n if (seen.has(expression)) return expression;\n seen.add(expression);\n if (\n ts.isParenthesizedExpression(expression) ||\n ts.isAsExpression(expression) ||\n ts.isNonNullExpression(expression) ||\n ts.isSatisfiesExpression(expression)\n )\n return this.expand(expression.expression, seen);\n const declaration = this.checker.getSymbolAtLocation(expression)?.valueDeclaration;\n if (\n declaration !== undefined &&\n ts.isVariableDeclaration(declaration) &&\n declaration.initializer !== undefined\n )\n return this.expand(declaration.initializer, seen);\n return expression;\n }\n}\n"]}
|