@webpieces/nx-webpieces-rules 0.4.854 → 0.4.855

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.
Files changed (88) hide show
  1. package/executors.json +5 -0
  2. package/package.json +7 -7
  3. package/src/executors/generate/executor.js +31 -55
  4. package/src/executors/generate/executor.js.map +1 -1
  5. package/src/executors/runtime-wiring-check/executor.d.ts +10 -0
  6. package/src/executors/runtime-wiring-check/executor.js +42 -0
  7. package/src/executors/runtime-wiring-check/executor.js.map +1 -0
  8. package/src/executors/runtime-wiring-check/schema.json +14 -0
  9. package/src/executors/validate-api-lib-tag/executor.js +5 -3
  10. package/src/executors/validate-api-lib-tag/executor.js.map +1 -1
  11. package/src/executors/validate-api-relations/executor.js +11 -8
  12. package/src/executors/validate-api-relations/executor.js.map +1 -1
  13. package/src/executors/validate-architecture-unchanged/executor.d.ts +1 -1
  14. package/src/executors/validate-architecture-unchanged/executor.js +22 -24
  15. package/src/executors/validate-architecture-unchanged/executor.js.map +1 -1
  16. package/src/lib/api-usage/api-contract-approval.d.ts +7 -0
  17. package/src/lib/api-usage/api-contract-approval.js +50 -0
  18. package/src/lib/api-usage/api-contract-approval.js.map +1 -0
  19. package/src/lib/api-usage/api-contract-evidence.d.ts +6 -0
  20. package/src/lib/api-usage/api-contract-evidence.js +41 -0
  21. package/src/lib/api-usage/api-contract-evidence.js.map +1 -0
  22. package/src/lib/api-usage/api-relations-validator.d.ts +13 -2
  23. package/src/lib/api-usage/api-relations-validator.js +23 -0
  24. package/src/lib/api-usage/api-relations-validator.js.map +1 -1
  25. package/src/lib/api-usage/api-relations.d.ts +3 -0
  26. package/src/lib/api-usage/api-relations.js.map +1 -1
  27. package/src/lib/api-usage/api-scanner.d.ts +40 -0
  28. package/src/lib/api-usage/api-scanner.js +7 -1
  29. package/src/lib/api-usage/api-scanner.js.map +1 -1
  30. package/src/lib/graph-comparator.js +11 -1
  31. package/src/lib/graph-comparator.js.map +1 -1
  32. package/src/lib/graph-loader.js +12 -6
  33. package/src/lib/graph-loader.js.map +1 -1
  34. package/src/lib/graph-navigation.d.ts +5 -0
  35. package/src/lib/graph-navigation.js +102 -0
  36. package/src/lib/graph-navigation.js.map +1 -0
  37. package/src/lib/graph-sorter.d.ts +2 -0
  38. package/src/lib/graph-sorter.js.map +1 -1
  39. package/src/lib/graph-visualizer.d.ts +0 -11
  40. package/src/lib/graph-visualizer.js +13 -9
  41. package/src/lib/graph-visualizer.js.map +1 -1
  42. package/src/lib/runtime-details.d.ts +13 -0
  43. package/src/lib/runtime-details.js +191 -0
  44. package/src/lib/runtime-details.js.map +1 -0
  45. package/src/lib/runtime-graph-model.d.ts +4 -1
  46. package/src/lib/runtime-graph-model.js.map +1 -1
  47. package/src/lib/runtime-graph.js +10 -4
  48. package/src/lib/runtime-graph.js.map +1 -1
  49. package/src/lib/runtime-html-page.d.ts +2 -1
  50. package/src/lib/runtime-html-page.js +6 -1
  51. package/src/lib/runtime-html-page.js.map +1 -1
  52. package/src/lib/runtime-visualizer.d.ts +0 -46
  53. package/src/lib/runtime-visualizer.js +29 -43
  54. package/src/lib/runtime-visualizer.js.map +1 -1
  55. package/src/lib/runtime-viz-theme.js +4 -3
  56. package/src/lib/runtime-viz-theme.js.map +1 -1
  57. package/src/lib/runtime-wiring/DeclarationCompileAssertions.d.ts +4 -0
  58. package/src/lib/runtime-wiring/DeclarationCompileAssertions.js +27 -0
  59. package/src/lib/runtime-wiring/DeclarationCompileAssertions.js.map +1 -0
  60. package/src/lib/runtime-wiring/approved-graph.d.ts +8 -0
  61. package/src/lib/runtime-wiring/approved-graph.js +115 -0
  62. package/src/lib/runtime-wiring/approved-graph.js.map +1 -0
  63. package/src/lib/runtime-wiring/assembler.d.ts +24 -0
  64. package/src/lib/runtime-wiring/assembler.js +116 -0
  65. package/src/lib/runtime-wiring/assembler.js.map +1 -0
  66. package/src/lib/runtime-wiring/codec.d.ts +14 -0
  67. package/src/lib/runtime-wiring/codec.js +162 -0
  68. package/src/lib/runtime-wiring/codec.js.map +1 -0
  69. package/src/lib/runtime-wiring/declaration.d.ts +68 -0
  70. package/src/lib/runtime-wiring/declaration.js +88 -0
  71. package/src/lib/runtime-wiring/declaration.js.map +1 -0
  72. package/src/lib/runtime-wiring/source-extractor.d.ts +28 -0
  73. package/src/lib/runtime-wiring/source-extractor.js +253 -0
  74. package/src/lib/runtime-wiring/source-extractor.js.map +1 -0
  75. package/src/lib/runtime-wiring/source-values.d.ts +21 -0
  76. package/src/lib/runtime-wiring/source-values.js +204 -0
  77. package/src/lib/runtime-wiring/source-values.js.map +1 -0
  78. package/src/lib/runtime-wiring/verification.d.ts +9 -0
  79. package/src/lib/runtime-wiring/verification.js +56 -0
  80. package/src/lib/runtime-wiring/verification.js.map +1 -0
  81. package/src/plugin.d.ts +0 -21
  82. package/src/plugin.js +12 -7
  83. package/src/plugin.js.map +1 -1
  84. package/src/runtime-wiring-targets.d.ts +7 -0
  85. package/src/runtime-wiring-targets.js +58 -0
  86. package/src/runtime-wiring-targets.js.map +1 -0
  87. package/src/validation-targets.js +10 -2
  88. package/src/validation-targets.js.map +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/codec.ts"],"names":[],"mappings":"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","sourcesContent":["import { toError } from '../../toError';\nimport { Option, RuleFailError } from '@webpieces/rules-config';\nimport {\n ContractIdentity,\n ImplementsFacts,\n UsesFacts,\n RuntimeDeclaration,\n WiringExport,\n WiringRelationship,\n WiringSelection,\n} from './declaration';\nimport type { DeclaredTarget } from './declaration';\nimport { isExternalSystemKind } from '../api-usage/api-relations';\n\n/** JSON is validated before it is allowed to influence graph assembly. */\nexport class RuntimeDeclarationCodec {\n decode(text: string, expectedProject: string): RuntimeDeclaration {\n const root = this.record(this.parse(text, expectedProject), [\n 'schemaVersion',\n 'project',\n 'framework',\n 'exports',\n 'entry',\n 'host',\n ]);\n if (root['schemaVersion'] !== 1)\n this.fail('Unsupported runtime-deps schemaVersion; migrate to version 1.');\n if (root['project'] !== expectedProject)\n this.fail(`Expected project ${expectedProject}, found ${String(root['project'])}.`);\n const framework = this.string(root['framework']);\n if (framework !== 'node' && framework !== 'angular' && framework !== 'browser')\n this.fail(`Unsupported framework ${framework}.`);\n const exports: Record<string, WiringExport> = {};\n for (const [name, value] of Object.entries(this.record(root['exports'])))\n exports[name] = this.exported(value);\n return new RuntimeDeclaration(\n expectedProject,\n framework,\n exports,\n root['entry'] === undefined ? undefined : this.string(root['entry']),\n root['host'] === undefined ? undefined : this.string(root['host']),\n );\n }\n\n // webpieces-disable no-any-unknown -- JSON syntax boundary; fields are narrowed by decode\n private parse(text: string, project: string): unknown {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n return JSON.parse(text);\n } catch (err: unknown) {\n const error = toError(err);\n this.fail(`${project}/runtime-deps.json contains invalid JSON.`, error);\n }\n }\n\n // webpieces-disable no-any-unknown -- untrusted JSON is narrowed and validated at the input boundary\n private exported(value: unknown): WiringExport {\n const exported = this.record(value, ['kind', 'relationships', 'selections']);\n const kind = this.string(exported['kind']);\n if (\n kind !== 'binding' &&\n kind !== 'routing' &&\n kind !== 'providers' &&\n kind !== 'plan' &&\n kind !== 'external'\n )\n this.fail(`Invalid export kind ${kind}.`);\n return new WiringExport(\n kind,\n this.array(exported['relationships']).map((value) => this.relationship(value)),\n this.array(exported['selections']).map((value) => this.selection(value)),\n );\n }\n\n // webpieces-disable no-any-unknown -- untrusted relationship JSON is narrowed before construction\n private relationship(value: unknown): WiringRelationship {\n const relation = this.record(value, [\n 'contract',\n 'direction',\n 'transport',\n 'target',\n 'policy',\n ]);\n const contract = this.record(relation['contract'], ['project', 'exportedName']);\n const direction = this.string(relation['direction']);\n const transport = this.string(relation['transport']);\n if (direction !== 'implements' && direction !== 'uses')\n this.fail(`Invalid direction ${direction}.`);\n if (transport !== 'rpc' && transport !== 'pubsub' && transport !== 'external')\n this.fail(`Invalid transport ${transport}.`);\n const target =\n relation['target'] === undefined ? undefined : this.target(relation['target']);\n const policy =\n relation['policy'] === undefined ? undefined : this.string(relation['policy']);\n if (direction === 'uses' && target === undefined)\n this.fail('Uses requires an explicit target.');\n if (direction === 'implements' && target !== undefined)\n this.fail('Implements cannot declare a client target.');\n return new WiringRelationship(\n new ContractIdentity(\n this.string(contract['project']),\n this.string(contract['exportedName']),\n ),\n direction === 'uses'\n ? new UsesFacts(transport, target!, policy)\n : new ImplementsFacts(transport, policy),\n );\n }\n\n // webpieces-disable no-any-unknown -- untrusted selection arguments are validated before substitution\n private selection(value: unknown): WiringSelection {\n const selection = this.record(value, ['project', 'exportedName', 'targets', 'policies']);\n const targets: Record<string, DeclaredTarget> = {};\n const policies: Record<string, boolean | 'runtime'> = {};\n for (const [name, target] of Object.entries(this.record(selection['targets'])))\n targets[name] = this.target(target);\n for (const [name, policy] of Object.entries(this.record(selection['policies']))) {\n if (typeof policy !== 'boolean' && policy !== 'runtime')\n this.fail(`Policy ${name} must be explicitly true, false, or runtime.`);\n policies[name] = policy;\n }\n return new WiringSelection(\n this.string(selection['project']),\n this.string(selection['exportedName']),\n targets,\n policies,\n );\n }\n\n // webpieces-disable no-any-unknown -- target discriminant controls the exact accepted JSON shape\n private target(value: unknown): DeclaredTarget {\n const target = this.record(value);\n switch (target['kind']) {\n case 'service': {\n this.record(value, ['kind', 'service', 'contract']);\n const contract =\n target['contract'] === undefined\n ? undefined\n : this.record(target['contract'], ['project', 'exportedName']);\n return {\n kind: 'service',\n service: this.string(target['service']),\n contract:\n contract === undefined\n ? undefined\n : new ContractIdentity(\n this.string(contract['project']),\n this.string(contract['exportedName']),\n ),\n };\n }\n case 'parameter':\n this.record(value, ['kind', 'parameter']);\n return { kind: 'parameter', parameter: this.string(target['parameter']) };\n case 'unknown':\n this.record(value, ['kind', 'reason']);\n return { kind: 'unknown', reason: this.string(target['reason']) };\n case 'external': {\n this.record(value, ['kind', 'system']);\n const system = this.record(target['system'], ['kind', 'label']);\n const kind = this.string(system['kind']);\n if (!isExternalSystemKind(kind)) this.fail(`Invalid external system kind ${kind}.`);\n return { kind: 'external', system: { kind, label: this.string(system['label']) } };\n }\n default:\n return this.fail(\n 'Targets require an explicit service, parameter, external, or unknown kind.',\n );\n }\n }\n\n // webpieces-disable no-any-unknown -- JSON record boundary; never a runtime topology type\n private record(value: unknown, allowed?: readonly string[]): Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value))\n this.fail('Expected a JSON object.');\n const record = value as Record<string, unknown>;\n for (const key of Object.keys(record))\n if (['__proto__', 'constructor', 'prototype'].includes(key))\n this.fail(`Reserved runtime-deps field ${key}.`);\n if (allowed !== undefined)\n for (const key of Object.keys(record))\n if (!allowed.includes(key)) this.fail(`Unknown runtime-deps field ${key}.`);\n return record;\n }\n\n // webpieces-disable no-any-unknown -- JSON array boundary\n private array(value: unknown): unknown[] {\n if (!Array.isArray(value)) this.fail('Expected a JSON array.');\n return value;\n }\n\n // webpieces-disable no-any-unknown -- JSON scalar boundary\n private string(value: unknown): string {\n if (typeof value !== 'string' || value.trim() === '')\n this.fail('Expected a non-empty string.');\n return value;\n }\n\n private fail(message: string, cause?: Error): never {\n throw new RuleFailError(\n 'validate-runtime-architecture',\n message,\n undefined,\n undefined,\n [\n new Option(\n 'Review and correct runtime-deps.json using the versioned runtime wiring schema.',\n true,\n ),\n ],\n undefined,\n cause,\n );\n }\n}\n"]}
@@ -0,0 +1,68 @@
1
+ import type { ApiTransport, ExternalSystemDeclaration } from '../api-usage/api-relations';
2
+ /** Stable source identity. Equal class shapes or short names never establish API identity. */
3
+ export declare class ContractIdentity {
4
+ readonly project: string;
5
+ readonly exportedName: string;
6
+ constructor(project: string, exportedName: string);
7
+ }
8
+ export type DeclaredTarget = {
9
+ kind: 'service';
10
+ service: string;
11
+ contract?: ContractIdentity;
12
+ } | {
13
+ kind: 'parameter';
14
+ parameter: string;
15
+ } | {
16
+ kind: 'external';
17
+ system: ExternalSystemDeclaration;
18
+ } | {
19
+ kind: 'unknown';
20
+ reason: string;
21
+ };
22
+ export declare class ImplementsFacts {
23
+ readonly transport: ApiTransport;
24
+ readonly policy?: string | undefined;
25
+ readonly direction = "implements";
26
+ readonly target?: never;
27
+ constructor(transport: ApiTransport, policy?: string | undefined);
28
+ }
29
+ export declare class UsesFacts {
30
+ readonly transport: ApiTransport;
31
+ readonly target: DeclaredTarget;
32
+ readonly policy?: string | undefined;
33
+ readonly direction = "uses";
34
+ constructor(transport: ApiTransport, target: DeclaredTarget, policy?: string | undefined);
35
+ }
36
+ export type WiringFacts = ImplementsFacts | UsesFacts;
37
+ export declare class WiringRelationship {
38
+ readonly contract: ContractIdentity;
39
+ readonly direction: 'implements' | 'uses';
40
+ readonly transport: ApiTransport;
41
+ readonly target?: DeclaredTarget;
42
+ readonly policy?: string;
43
+ constructor(contract: ContractIdentity, facts: WiringFacts);
44
+ }
45
+ /** Only these exports execute, in this order, with these graph-relevant arguments. */
46
+ export declare class WiringSelection {
47
+ readonly project: string;
48
+ readonly exportedName: string;
49
+ readonly targets: Record<string, DeclaredTarget>;
50
+ readonly policies: Record<string, boolean | 'runtime'>;
51
+ constructor(project: string, exportedName: string, targets: Record<string, DeclaredTarget>, policies: Record<string, boolean | 'runtime'>);
52
+ }
53
+ export declare class WiringExport {
54
+ readonly kind: 'binding' | 'routing' | 'providers' | 'plan' | 'external';
55
+ readonly relationships: WiringRelationship[];
56
+ readonly selections: WiringSelection[];
57
+ constructor(kind: 'binding' | 'routing' | 'providers' | 'plan' | 'external', relationships: WiringRelationship[], selections: WiringSelection[]);
58
+ }
59
+ /** No timestamps, machine paths, credentials, deployment URLs, or cache keys belong here. */
60
+ export declare class RuntimeDeclaration {
61
+ readonly schemaVersion: 1;
62
+ readonly project: string;
63
+ readonly framework: 'node' | 'angular' | 'browser';
64
+ readonly exports: Record<string, WiringExport>;
65
+ readonly entry?: string;
66
+ readonly host?: string;
67
+ constructor(project: string, framework: 'node' | 'angular' | 'browser', exports: Record<string, WiringExport>, entry?: string, host?: string);
68
+ }
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RuntimeDeclaration = exports.WiringExport = exports.WiringSelection = exports.WiringRelationship = exports.UsesFacts = exports.ImplementsFacts = exports.ContractIdentity = void 0;
4
+ /** Stable source identity. Equal class shapes or short names never establish API identity. */
5
+ class ContractIdentity {
6
+ project;
7
+ exportedName;
8
+ constructor(project, exportedName) {
9
+ this.project = project;
10
+ this.exportedName = exportedName;
11
+ }
12
+ }
13
+ exports.ContractIdentity = ContractIdentity;
14
+ class ImplementsFacts {
15
+ transport;
16
+ policy;
17
+ direction = 'implements';
18
+ constructor(transport, policy) {
19
+ this.transport = transport;
20
+ this.policy = policy;
21
+ }
22
+ }
23
+ exports.ImplementsFacts = ImplementsFacts;
24
+ class UsesFacts {
25
+ transport;
26
+ target;
27
+ policy;
28
+ direction = 'uses';
29
+ constructor(transport, target, policy) {
30
+ this.transport = transport;
31
+ this.target = target;
32
+ this.policy = policy;
33
+ }
34
+ }
35
+ exports.UsesFacts = UsesFacts;
36
+ class WiringRelationship {
37
+ contract;
38
+ direction;
39
+ transport;
40
+ target;
41
+ policy;
42
+ constructor(contract, facts) {
43
+ this.contract = contract;
44
+ this.direction = facts.direction;
45
+ this.transport = facts.transport;
46
+ this.target = facts.direction === 'uses' ? facts.target : undefined;
47
+ this.policy = facts.policy;
48
+ }
49
+ }
50
+ exports.WiringRelationship = WiringRelationship;
51
+ /** Only these exports execute, in this order, with these graph-relevant arguments. */
52
+ class WiringSelection {
53
+ project;
54
+ exportedName;
55
+ targets;
56
+ policies;
57
+ constructor(project, exportedName, targets, policies) {
58
+ this.project = project;
59
+ this.exportedName = exportedName;
60
+ this.targets = targets;
61
+ this.policies = policies;
62
+ }
63
+ }
64
+ exports.WiringSelection = WiringSelection;
65
+ class WiringExport {
66
+ kind;
67
+ relationships;
68
+ selections;
69
+ constructor(kind, relationships, selections) {
70
+ this.kind = kind;
71
+ this.relationships = relationships;
72
+ this.selections = selections;
73
+ }
74
+ }
75
+ exports.WiringExport = WiringExport;
76
+ /** No timestamps, machine paths, credentials, deployment URLs, or cache keys belong here. */
77
+ class RuntimeDeclaration {
78
+ constructor(project, framework, exports, entry, host) {
79
+ this.schemaVersion = 1;
80
+ this.project = project;
81
+ this.framework = framework;
82
+ this.exports = exports;
83
+ this.entry = entry;
84
+ this.host = host;
85
+ }
86
+ }
87
+ exports.RuntimeDeclaration = RuntimeDeclaration;
88
+ //# sourceMappingURL=declaration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"declaration.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/declaration.ts"],"names":[],"mappings":";;;AAEA,8FAA8F;AAC9F,MAAa,gBAAgB;IAEL;IACA;IAFpB,YACoB,OAAe,EACf,YAAoB;QADpB,YAAO,GAAP,OAAO,CAAQ;QACf,iBAAY,GAAZ,YAAY,CAAQ;IACrC,CAAC;CACP;AALD,4CAKC;AAQD,MAAa,eAAe;IAIJ;IACA;IAJX,SAAS,GAAG,YAAY,CAAC;IAElC,YACoB,SAAuB,EACvB,MAAe;QADf,cAAS,GAAT,SAAS,CAAc;QACvB,WAAM,GAAN,MAAM,CAAS;IAChC,CAAC;CACP;AAPD,0CAOC;AAED,MAAa,SAAS;IAGE;IACA;IACA;IAJX,SAAS,GAAG,MAAM,CAAC;IAC5B,YACoB,SAAuB,EACvB,MAAsB,EACtB,MAAe;QAFf,cAAS,GAAT,SAAS,CAAc;QACvB,WAAM,GAAN,MAAM,CAAgB;QACtB,WAAM,GAAN,MAAM,CAAS;IAChC,CAAC;CACP;AAPD,8BAOC;AAID,MAAa,kBAAkB;IAOP;IANX,SAAS,CAAwB;IACjC,SAAS,CAAe;IACxB,MAAM,CAAkB;IACxB,MAAM,CAAU;IAEzB,YACoB,QAA0B,EAC1C,KAAkB;QADF,aAAQ,GAAR,QAAQ,CAAkB;QAG1C,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;QACjC,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;QACjC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;QACpE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC/B,CAAC;CACJ;AAfD,gDAeC;AAED,sFAAsF;AACtF,MAAa,eAAe;IAEJ;IACA;IACA;IACA;IAJpB,YACoB,OAAe,EACf,YAAoB,EACpB,OAAuC,EACvC,QAA6C;QAH7C,YAAO,GAAP,OAAO,CAAQ;QACf,iBAAY,GAAZ,YAAY,CAAQ;QACpB,YAAO,GAAP,OAAO,CAAgC;QACvC,aAAQ,GAAR,QAAQ,CAAqC;IAC9D,CAAC;CACP;AAPD,0CAOC;AAED,MAAa,YAAY;IAED;IACA;IACA;IAHpB,YACoB,IAA+D,EAC/D,aAAmC,EACnC,UAA6B;QAF7B,SAAI,GAAJ,IAAI,CAA2D;QAC/D,kBAAa,GAAb,aAAa,CAAsB;QACnC,eAAU,GAAV,UAAU,CAAmB;IAC9C,CAAC;CACP;AAND,oCAMC;AAED,6FAA6F;AAC7F,MAAa,kBAAkB;IAQ3B,YACI,OAAe,EACf,SAAyC,EACzC,OAAqC,EACrC,KAAc,EACd,IAAa;QAEb,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACrB,CAAC;CACJ;AAtBD,gDAsBC","sourcesContent":["import type { ApiTransport, ExternalSystemDeclaration } from '../api-usage/api-relations';\n\n/** Stable source identity. Equal class shapes or short names never establish API identity. */\nexport class ContractIdentity {\n constructor(\n public readonly project: string,\n public readonly exportedName: string,\n ) {}\n}\n\nexport type DeclaredTarget =\n | { kind: 'service'; service: string; contract?: ContractIdentity }\n | { kind: 'parameter'; parameter: string }\n | { kind: 'external'; system: ExternalSystemDeclaration }\n | { kind: 'unknown'; reason: string };\n\nexport class ImplementsFacts {\n readonly direction = 'implements';\n declare readonly target?: never;\n constructor(\n public readonly transport: ApiTransport,\n public readonly policy?: string,\n ) {}\n}\n\nexport class UsesFacts {\n readonly direction = 'uses';\n constructor(\n public readonly transport: ApiTransport,\n public readonly target: DeclaredTarget,\n public readonly policy?: string,\n ) {}\n}\n\nexport type WiringFacts = ImplementsFacts | UsesFacts;\n\nexport class WiringRelationship {\n readonly direction: 'implements' | 'uses';\n readonly transport: ApiTransport;\n readonly target?: DeclaredTarget;\n readonly policy?: string;\n\n constructor(\n public readonly contract: ContractIdentity,\n facts: WiringFacts,\n ) {\n this.direction = facts.direction;\n this.transport = facts.transport;\n this.target = facts.direction === 'uses' ? facts.target : undefined;\n this.policy = facts.policy;\n }\n}\n\n/** Only these exports execute, in this order, with these graph-relevant arguments. */\nexport class WiringSelection {\n constructor(\n public readonly project: string,\n public readonly exportedName: string,\n public readonly targets: Record<string, DeclaredTarget>,\n public readonly policies: Record<string, boolean | 'runtime'>,\n ) {}\n}\n\nexport class WiringExport {\n constructor(\n public readonly kind: 'binding' | 'routing' | 'providers' | 'plan' | 'external',\n public readonly relationships: WiringRelationship[],\n public readonly selections: WiringSelection[],\n ) {}\n}\n\n/** No timestamps, machine paths, credentials, deployment URLs, or cache keys belong here. */\nexport class RuntimeDeclaration {\n declare readonly schemaVersion: 1;\n declare readonly project: string;\n declare readonly framework: 'node' | 'angular' | 'browser';\n declare readonly exports: Record<string, WiringExport>;\n declare readonly entry?: string;\n declare readonly host?: string;\n\n constructor(\n project: string,\n framework: 'node' | 'angular' | 'browser',\n exports: Record<string, WiringExport>,\n entry?: string,\n host?: string,\n ) {\n this.schemaVersion = 1;\n this.project = project;\n this.framework = framework;\n this.exports = exports;\n this.entry = entry;\n this.host = host;\n }\n}\n"]}
@@ -0,0 +1,28 @@
1
+ import * as ts from 'typescript';
2
+ import type { ProjectInfo } from '../project-info';
3
+ import { RuntimeDeclaration } from './declaration';
4
+ /** Build-only extraction. It never imports application modules or invokes their constructors. */
5
+ export declare class WiringSourceExtractor {
6
+ private readonly workspaceRoot;
7
+ private readonly info;
8
+ private readonly infos;
9
+ private readonly program;
10
+ private readonly values;
11
+ private readonly exported;
12
+ private entry;
13
+ private host;
14
+ constructor(workspaceRoot: string, info: ProjectInfo, infos: ReadonlyMap<string, ProjectInfo>, program: ts.Program);
15
+ extract(): RuntimeDeclaration;
16
+ private visit;
17
+ private recordExternal;
18
+ private recordRelationship;
19
+ private recordPlan;
20
+ private planReturns;
21
+ private exportOwner;
22
+ private owns;
23
+ private fail;
24
+ }
25
+ /** Factory kept separate so graph assembly cannot accidentally create a compiler. */
26
+ export declare class WiringProjectProgram {
27
+ create(workspaceRoot: string, info: ProjectInfo): ts.Program;
28
+ }
@@ -0,0 +1,253 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WiringProjectProgram = exports.WiringSourceExtractor = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const path = tslib_1.__importStar(require("path"));
6
+ const ts = tslib_1.__importStar(require("typescript"));
7
+ const rules_config_1 = require("@webpieces/rules-config");
8
+ const program_1 = require("../di-graph/program");
9
+ const declaration_1 = require("./declaration");
10
+ const source_values_1 = require("./source-values");
11
+ /** Build-only extraction. It never imports application modules or invokes their constructors. */
12
+ class WiringSourceExtractor {
13
+ workspaceRoot;
14
+ info;
15
+ infos;
16
+ program;
17
+ values;
18
+ exported = {};
19
+ entry;
20
+ host;
21
+ constructor(workspaceRoot, info, infos, program) {
22
+ this.workspaceRoot = workspaceRoot;
23
+ this.info = info;
24
+ this.infos = infos;
25
+ this.program = program;
26
+ this.values = new source_values_1.WiringSourceValues(workspaceRoot, infos, program.getTypeChecker());
27
+ }
28
+ extract() {
29
+ const wiringPath = path.resolve(this.workspaceRoot, this.info.root, 'src/wiring.ts');
30
+ const wiring = this.program.getSourceFile(wiringPath);
31
+ if (wiring === undefined)
32
+ this.fail(`Missing canonical ${wiringPath}.`);
33
+ for (const file of this.program.getSourceFiles()) {
34
+ if (file.isDeclarationFile ||
35
+ !this.owns(file.fileName) ||
36
+ /(?:\.spec\.|\.test\.|\/__tests__\/)/.test(file.fileName))
37
+ continue;
38
+ this.visit(file, file.fileName === wiringPath);
39
+ }
40
+ const framework = this.info.tags.includes('framework:angular')
41
+ ? 'angular'
42
+ : this.info.tags.some((tag) => tag === 'framework:node' || tag === 'framework:express')
43
+ ? 'node'
44
+ : 'browser';
45
+ if (this.info.tags.includes('webpieces') && this.entry === undefined)
46
+ this.fail(`${this.info.name} requires getRuntimeWiring() returning a typed plan.`);
47
+ return new declaration_1.RuntimeDeclaration(this.info.name, framework, this.exported, this.entry, this.host);
48
+ }
49
+ visit(node, inWiring) {
50
+ if (!inWiring &&
51
+ (ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node)) &&
52
+ [
53
+ 'addRoutes',
54
+ 'createRpcClient',
55
+ 'createPubSubClient',
56
+ 'bindRpc',
57
+ 'bindPubSub',
58
+ ].includes(this.values.symbolName(node)))
59
+ this.fail(`${node.getSourceFile().fileName}: topology method references belong in src/wiring.ts, including aliases.`);
60
+ if (inWiring &&
61
+ ts.isNewExpression(node) &&
62
+ this.values.symbolName(node.expression) === 'ExternalContractUse')
63
+ this.recordExternal(node);
64
+ if (ts.isCallExpression(node)) {
65
+ const name = this.values.symbolName(node.expression);
66
+ if ([
67
+ 'addRoutes',
68
+ 'createRpcClient',
69
+ 'createPubSubClient',
70
+ 'bindRpc',
71
+ 'bindPubSub',
72
+ 'provideRpcClient',
73
+ ].includes(name)) {
74
+ if (!inWiring)
75
+ this.fail(`${node.getSourceFile().fileName}: ${name} must be owned by src/wiring.ts.`);
76
+ this.recordRelationship(node, name);
77
+ }
78
+ }
79
+ if (inWiring && ts.isMethodDeclaration(node) && node.name.getText() === 'getRuntimeWiring')
80
+ this.recordPlan(node);
81
+ ts.forEachChild(node, (child) => this.visit(child, inWiring));
82
+ }
83
+ recordExternal(expression) {
84
+ const owner = this.exportOwner(expression);
85
+ const identity = expression.arguments?.[0];
86
+ if (owner === undefined || identity === undefined || !ts.isStringLiteralLike(identity))
87
+ this.fail('ExternalContractUse belongs to a selected exported module and requires a literal project#contract identity.');
88
+ const qualified = identity.text.split('#');
89
+ const project = qualified[0];
90
+ const exportedName = qualified[1];
91
+ const extra = qualified[2];
92
+ if (!project || !exportedName || extra !== undefined)
93
+ this.fail('ExternalContractUse requires one qualified project#contract identity.');
94
+ if (!this.values.hasExternalConsumer(this.info.name, project, exportedName, this.program))
95
+ this.fail(`${project}#${exportedName} has no production business consumer in ${this.info.name}; adapters and test doubles do not establish uses.`);
96
+ const exported = this.exported[owner] ?? new declaration_1.WiringExport('binding', [], []);
97
+ exported.relationships.push(new declaration_1.WiringRelationship(new declaration_1.ContractIdentity(project, exportedName), new declaration_1.UsesFacts('external', {
98
+ kind: 'unknown',
99
+ reason: 'Vendor interface; destination classified by approved contract metadata',
100
+ })));
101
+ this.exported[owner] = exported;
102
+ }
103
+ recordRelationship(call, method) {
104
+ const owner = this.exportOwner(call);
105
+ // The generic Angular integration adapter defines the primitive; its invocations own facts.
106
+ if (owner === 'provideRpcClient' && method === 'createRpcClient')
107
+ return;
108
+ if (owner === undefined)
109
+ this.fail(`Unowned ${method} at ${call.getSourceFile().fileName}:${call.getStart()}.`);
110
+ const apiIndex = method === 'bindRpc' || method === 'bindPubSub' || method === 'provideRpcClient'
111
+ ? 1
112
+ : 0;
113
+ const api = call.arguments[apiIndex];
114
+ if (api === undefined)
115
+ this.fail(`${method} requires an explicit API contract.`);
116
+ const contract = this.values.identity(api);
117
+ const direction = method === 'addRoutes' ? 'implements' : 'uses';
118
+ const contractTransport = this.values.transport(api);
119
+ const transport = method === 'addRoutes'
120
+ ? contractTransport
121
+ : method === 'bindPubSub' || method === 'createPubSubClient'
122
+ ? 'pubsub'
123
+ : 'rpc';
124
+ if (transport !== contractTransport)
125
+ this.fail(`${method} transport disagrees with ${contract.project}#${contract.exportedName}.`);
126
+ const target = direction === 'implements'
127
+ ? undefined
128
+ : this.values.target(call.arguments[apiIndex + 1]);
129
+ const kind = direction === 'implements'
130
+ ? 'routing'
131
+ : method === 'provideRpcClient'
132
+ ? 'providers'
133
+ : 'binding';
134
+ const exported = this.exported[owner] ?? new declaration_1.WiringExport(kind, [], []);
135
+ exported.relationships.push(new declaration_1.WiringRelationship(contract, direction === 'implements'
136
+ ? new declaration_1.ImplementsFacts(transport, this.values.condition(call))
137
+ : new declaration_1.UsesFacts(transport, target, this.values.condition(call))));
138
+ this.exported[owner] = exported;
139
+ }
140
+ recordPlan(method) {
141
+ const owner = this.exportOwner(method);
142
+ if (owner === undefined)
143
+ this.fail('The plan class must be exported from src/wiring.ts.');
144
+ const returns = this.planReturns(method, owner);
145
+ const expression = returns[0].expression;
146
+ const name = this.values.symbolName(expression.expression);
147
+ const args = expression.arguments ?? [];
148
+ let arrays;
149
+ if (name === 'ServerWiring') {
150
+ const host = this.values.target(args[0]);
151
+ if (host.kind !== 'service')
152
+ this.fail('ServerWiring requires a literal host identity.');
153
+ this.host = host.service;
154
+ if (args[1] === undefined ||
155
+ !ts.isNewExpression(args[1]) ||
156
+ this.values.symbolName(args[1].expression) !== 'ServerWiringOptions')
157
+ this.fail('Use ServerWiringOptions with separate bindingModules and routingModules arrays.');
158
+ arrays = args[1].arguments ?? [];
159
+ }
160
+ else if (name === 'BrowserWiring')
161
+ arrays = args;
162
+ else
163
+ this.fail(`Unsupported plan ${name}; use ServerWiring or BrowserWiring.`);
164
+ const selections = [];
165
+ for (const array of arrays) {
166
+ if (!ts.isArrayLiteralExpression(array))
167
+ this.fail('Plan module/provider lists must be static arrays; dynamic composition needs an explicit supported policy.');
168
+ for (const element of array.elements) {
169
+ if (ts.isObjectLiteralExpression(element))
170
+ continue; // ordinary Angular providers; API factories are checked independently
171
+ if (ts.isCallExpression(element) &&
172
+ this.values.symbolName(element.expression) === 'provideRpcClient')
173
+ continue;
174
+ const invocation = ts.isNewExpression(element) || ts.isCallExpression(element)
175
+ ? element
176
+ : undefined;
177
+ const identity = this.values.identity(invocation === undefined ? element : invocation.expression);
178
+ const targets = invocation === undefined ? {} : this.values.arguments(invocation);
179
+ selections.push(new declaration_1.WiringSelection(identity.project, identity.exportedName, targets, invocation === undefined ? {} : this.values.policies(invocation)));
180
+ if (identity.project === this.info.name &&
181
+ this.exported[identity.exportedName] === undefined)
182
+ this.exported[identity.exportedName] = new declaration_1.WiringExport('binding', [], []);
183
+ }
184
+ }
185
+ this.exported[owner] = new declaration_1.WiringExport('plan', [], selections);
186
+ this.entry = owner;
187
+ }
188
+ planReturns(method, owner) {
189
+ const returns = [];
190
+ const visit = (node) => {
191
+ if (ts.isReturnStatement(node))
192
+ returns.push(node);
193
+ else
194
+ ts.forEachChild(node, visit);
195
+ };
196
+ if (method.body !== undefined)
197
+ visit(method.body);
198
+ if (returns.length !== 1 ||
199
+ returns[0].expression === undefined ||
200
+ !ts.isNewExpression(returns[0].expression))
201
+ this.fail(`${owner}.getRuntimeWiring must return one statically composed plan.`);
202
+ return returns;
203
+ }
204
+ exportOwner(node) {
205
+ let current = node;
206
+ while (current !== undefined) {
207
+ if (ts.isClassDeclaration(current) &&
208
+ current.name !== undefined &&
209
+ (ts.getModifiers(current) ?? []).some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword))
210
+ return current.name.text;
211
+ if (ts.isFunctionDeclaration(current) &&
212
+ current.name !== undefined &&
213
+ (ts.getModifiers(current) ?? []).some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword))
214
+ return current.name.text;
215
+ if (ts.isVariableDeclaration(current) && ts.isIdentifier(current.name)) {
216
+ const statement = current.parent.parent;
217
+ if (ts.isVariableStatement(statement) &&
218
+ (ts.getModifiers(statement) ?? []).some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword))
219
+ return current.name.text;
220
+ }
221
+ current = current.parent;
222
+ }
223
+ return undefined;
224
+ }
225
+ owns(file) {
226
+ const root = path.resolve(this.workspaceRoot, this.info.root) + path.sep;
227
+ return path.resolve(file).startsWith(root) && !file.includes('/node_modules/');
228
+ }
229
+ fail(message) {
230
+ throw new rules_config_1.RuleFailError('validate-runtime-architecture', message, undefined, undefined, [
231
+ new rules_config_1.Option('Move topology into canonical src/wiring.ts and use the documented static plan grammar; do not execute configuration to extract it.', true),
232
+ ]);
233
+ }
234
+ }
235
+ exports.WiringSourceExtractor = WiringSourceExtractor;
236
+ /** Factory kept separate so graph assembly cannot accidentally create a compiler. */
237
+ class WiringProjectProgram {
238
+ create(workspaceRoot, info) {
239
+ const root = path.resolve(workspaceRoot, info.root);
240
+ const configured = (0, program_1.createProjectProgram)(root);
241
+ if (configured !== null)
242
+ return configured;
243
+ const config = ts.findConfigFile(root, ts.sys.fileExists, 'tsconfig.json');
244
+ const parsed = config === undefined ? undefined : ts.readConfigFile(config, ts.sys.readFile);
245
+ const options = parsed === undefined
246
+ ? {}
247
+ : ts.parseJsonConfigFileContent(parsed.config, ts.sys, root).options;
248
+ const files = ts.sys.readDirectory(path.join(root, 'src'), ['.ts'], ['**/*.spec.ts', '**/*.test.ts']);
249
+ return ts.createProgram(files, options);
250
+ }
251
+ }
252
+ exports.WiringProjectProgram = WiringProjectProgram;
253
+ //# sourceMappingURL=source-extractor.js.map
@@ -0,0 +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';\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 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 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"]}
@@ -0,0 +1,21 @@
1
+ import * as ts from 'typescript';
2
+ import type { ProjectInfo } from '../project-info';
3
+ import { ContractIdentity } from './declaration';
4
+ import type { DeclaredTarget } from './declaration';
5
+ /** Resolves imported symbols and bounded literal expressions without invoking application code. */
6
+ export declare class WiringSourceValues {
7
+ private readonly workspaceRoot;
8
+ private readonly infos;
9
+ private readonly checker;
10
+ constructor(workspaceRoot: string, infos: ReadonlyMap<string, ProjectInfo>, checker: ts.TypeChecker);
11
+ symbolName(node: ts.Node): string;
12
+ identity(node: ts.Node): ContractIdentity;
13
+ target(expression: ts.Expression | undefined, depth?: number): DeclaredTarget;
14
+ transport(expression: ts.Expression): 'rpc' | 'pubsub';
15
+ arguments(invocation: ts.NewExpression | ts.CallExpression): Record<string, DeclaredTarget>;
16
+ hasExternalConsumer(owner: string, project: string, exportedName: string, program: ts.Program): boolean;
17
+ policies(invocation: ts.NewExpression | ts.CallExpression): Record<string, boolean | 'runtime'>;
18
+ condition(call: ts.Node): string | undefined;
19
+ private symbol;
20
+ private fail;
21
+ }