@webpieces/nx-webpieces-rules 0.4.956 → 0.4.958
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +7 -7
- package/src/lib/api-usage/api-ast.d.ts +11 -3
- package/src/lib/api-usage/api-ast.js +109 -14
- package/src/lib/api-usage/api-ast.js.map +1 -1
- package/src/lib/api-usage/api-contract-errors.d.ts +6 -1
- package/src/lib/api-usage/api-contract-errors.js +24 -6
- package/src/lib/api-usage/api-contract-errors.js.map +1 -1
- package/src/lib/api-usage/api-contract-evidence.js +1 -0
- package/src/lib/api-usage/api-contract-evidence.js.map +1 -1
- package/src/lib/api-usage/api-doc-rules-scan.d.ts +8 -8
- package/src/lib/api-usage/api-doc-rules-scan.js +8 -8
- package/src/lib/api-usage/api-doc-rules-scan.js.map +1 -1
- package/src/lib/api-usage/api-doc-rules-verdicts.d.ts +9 -7
- package/src/lib/api-usage/api-doc-rules-verdicts.js +15 -14
- package/src/lib/api-usage/api-doc-rules-verdicts.js.map +1 -1
- package/src/lib/api-usage/api-relations.d.ts +33 -8
- package/src/lib/api-usage/api-relations.js +32 -1
- package/src/lib/api-usage/api-relations.js.map +1 -1
- package/src/lib/api-usage/api-scanner.d.ts +3 -1
- package/src/lib/api-usage/api-scanner.js +7 -2
- package/src/lib/api-usage/api-scanner.js.map +1 -1
- package/src/lib/runtime-graph-model.d.ts +2 -2
- package/src/lib/runtime-graph-model.js.map +1 -1
- package/src/lib/runtime-graph.js +6 -4
- package/src/lib/runtime-graph.js.map +1 -1
- package/src/lib/runtime-wiring/service-targets.js +6 -0
- package/src/lib/runtime-wiring/service-targets.js.map +1 -1
- package/src/lib/runtime-wiring/source-extractor.d.ts +5 -0
- package/src/lib/runtime-wiring/source-extractor.js +20 -0
- package/src/lib/runtime-wiring/source-extractor.js.map +1 -1
- package/src/lib/runtime-wiring/source-values.d.ts +6 -1
- package/src/lib/runtime-wiring/source-values.js +21 -0
- package/src/lib/runtime-wiring/source-values.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-graph.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-graph.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Runtime Graph\n *\n * Derives the runtime microservice graph SOLELY from architecture/dependencies.json\n * (the single source of truth): each project's `apiRelations` carry which api\n * classes it implements/uses and their transport (rpc | pubsub). Both\n * `architecture:generate` and `architecture:validate-runtime-architecture` call\n * the SAME `deriveRuntimeGraph`, so the committed graph and the validated graph\n * can never diverge.\n *\n * The runtime edge Z -> X (Z depends on X at runtime) is INFERRED: Z `uses` api\n * Y and X `implements` api Y. This edge does not exist in the compile-time\n * dependencies.json (both Z and X only compile-depend on the api library Y).\n *\n * WHICH X is decided by the call site, not by \"everyone who implements Y\", in\n * priority order: (1) a literal at the call site —\n * `createRpcClient(Y, new ClientConfig('helper-fsdb'))` — kept as\n * `ApiRef.targetService`; else (2) the calling project's declared `callsService`\n * (project.json metadata.webpieces.callsService), the symmetric half of\n * `serviceName` for the shared-library case where the client is built once from a\n * config field so no literal can sit at the call site; else (3) fan-out. A named\n * target from (1) or (2) is matched against each node's DECLARED `serviceName`.\n * Fanning an edge out to every implementer is catastrophic for a company-wide\n * contract registered in a shared library — it manufactures calls that cannot\n * happen, and cycles that do not exist. When a target cannot be resolved the old\n * fan-out still happens, but a warning names the call site (see\n * RuntimeGraphReport.warnings): a wrong-but-green graph is worse than a failing\n * one, so it must never degrade silently.\n */\n\nimport { sortGraphTopologically } from './graph-sorter';\nimport type { EnhancedGraph, GraphEntry } from './graph-sorter';\nimport type {\n ApiContracts,\n ApiMethodMeta,\n ApiRef,\n ApiTransport,\n ExternalSystemDecls,\n} from './api-usage/api-relations';\nimport { sortApiRefs } from './api-usage/api-relations';\nimport { RelationSink } from './runtime-graph-decls';\nimport type { ScanDecl } from './runtime-graph-decls';\nimport { dedupApiRefs, sortedRecord, sortUnresolved } from './runtime-graph-sorters';\nimport { attachExternalSystems, resolveExternalSystems } from './api-usage/external-systems';\nimport { RuntimeProductMembership } from './graph-products';\nimport { RemoteCallCollector } from './runtime-remote-calls';\nimport type { RemoteServices } from './remote-services';\nimport type {\n RuntimeApi,\n RuntimeEdge,\n RuntimeExternalSystem,\n RuntimeGraph,\n RuntimeQueue,\n RuntimeService,\n RuntimeTrigger,\n RuntimeUnresolved,\n} from './runtime-graph-model';\nimport { toError } from '../toError';\n\n// The committed data shape lives in runtime-graph-model.ts; re-exported here so every existing\n// `from './runtime-graph'` import keeps working and there is still one obvious place to import from.\nexport type {\n RuntimeApi,\n RuntimeEdge,\n RuntimeExternalSystem,\n RuntimeGraph,\n RuntimeQueue,\n RuntimeRemoteCall,\n RuntimeRemoteService,\n RuntimeService,\n RuntimeTrigger,\n RuntimeUnresolved,\n} from './runtime-graph-model';\nimport { applyCycleCuts } from './runtime-graph-levels';\nimport { RuntimeNodeLevels } from './runtime-node-levels';\n\n// Persistence lives in runtime-graph-io.ts; re-exported for the same reason as the model types.\nexport {\n DEFAULT_RUNTIME_GRAPH_PATH,\n saveRuntimeGraph,\n runtimeGraphFileExists,\n loadRuntimeGraph,\n serializeRuntimeGraph,\n} from './runtime-graph-io';\n\ninterface EdgeResult {\n edges: RuntimeEdge[];\n unresolved: RuntimeUnresolved[];\n queues: Record<string, RuntimeQueue>;\n}\n\n/**\n * The derived graph PLUS everything the derivation had to guess at. `warnings` is deliberately not\n * part of RuntimeGraph: it is not committed data, it is the report that stops a guessed edge from\n * passing for a derived one. Executors print it.\n */\nexport class RuntimeGraphReport {\n constructor(\n public readonly graph: RuntimeGraph,\n /** Human-readable lines naming every call site whose target the graph could not pin down. */\n public readonly warnings: string[],\n /**\n * Call sites that name a target the repo does not contain. Unlike a warning these FAIL the\n * build: the contract IS served in-repo, so the name is a typo or a stale rename, and the\n * only reason it stayed invisible is that the graph quietly fanned the edge out instead.\n * (A call to a service outside the repo never reaches here — nothing in-repo implements its\n * contract, so it is `unresolvedUses`.)\n */\n public readonly problems: string[] = [],\n /**\n * role:server nodes omitted from the DRAWING because they declare no webpieces runtime\n * package anywhere in their library closure and serve/call nothing in-repo. Neither a\n * warning nor a problem — this is intended behavior, and shouting on every clean run is how\n * warnings stop being read. Deliberately NOT persisted: a graph file that records its own\n * omissions gets committed and stops being read. Executors print it instead, so the\n * omission is always visible and never silent.\n */\n public readonly autoHidden: string[] = [],\n ) {}\n}\n\n/**\n * Derives the runtime microservice graph from architecture/dependencies.json `apiRelations`:\n * implementers × users per API, split by transport. An rpc edge is a direct call; a pubsub edge flows\n * through a queue (drawn producer → queue → consumer by the visualizer).\n *\n * Nodes are the runnable apps only — role:server / role:client. A library is NEVER a node; its\n * implements/uses (a shared client-factory or route-registration lib) are attributed to the\n * servers/clients that embed it, walked transitively over dependsOn (see collectDecls).\n */\nclass RuntimeGraphDeriver {\n /** apiClassName -> the api-lib project that owns the contract (from the apiRelations key). */\n private readonly apiOwners = new Map<string, string>();\n /** Addressable name -> the runtime node answering to it; how a targeted call resolves. */\n private readonly nodeByServiceName = new Map<string, string>();\n private readonly warnings: string[] = [];\n private readonly problems: string[] = [];\n /** role:server nodes hidden by isNonParticipantServer, in the order buildServices met them. */\n private readonly autoHidden: string[] = [];\n /** Uses aimed at a reviewed out-of-workspace service (#1203); built once the names are claimed. */\n private readonly remoteCalls: RemoteCallCollector;\n\n /**\n * False when NO project in the graph carries `webpiecesRuntime`, i.e. the file was written\n * before the field existed. Auto-hiding is then off ENTIRELY, so an old dependencies.json\n * renders exactly as it did — absence of the field must never be read as \"declares none\".\n * Any repo regenerated after this change has at least one webpieces project, so the guard\n * cannot wrongly suppress the feature.\n */\n private readonly markersKnown: boolean;\n\n constructor(\n private readonly projects: EnhancedGraph,\n /** Project names tagged drawOnGraph:false — kept in the JSON but flagged so the viz omits them. */\n private readonly hiddenProjects: Set<string>,\n /**\n * The per-contract method tables, read from the generated `architecture/apis/<Api>.json`\n * files (ApiContractFiles). Pubsub edges remain at the contract level, independently\n * of method metadata: an endpoint table does not declare which methods a client uses.\n */\n private readonly apiContracts: ApiContracts = {},\n /**\n * Declared external systems from dependencies.json, keyed by identity. Empty means nothing\n * was declared, which renders exactly as it did before declarations existed.\n */\n private readonly externalSystemDecls: ExternalSystemDecls = {},\n /** Reviewed out-of-workspace services from dependencies.json `remoteServices` (#1203). */\n remoteServices: RemoteServices = {},\n ) {\n this.markersKnown = Object.values(projects).some(\n (entry: GraphEntry) => entry.webpiecesRuntime !== undefined,\n );\n // A node ALWAYS answers to its own module name, so a repo whose deployed names match its\n // project names needs no declaration at all — and no alias can ever redirect 'ai-chat' away\n // from the ai-chat module. Module names are therefore claimed FIRST and are unshadowable.\n for (const name of Object.keys(projects).sort()) {\n if (this.isNode(name)) this.nodeByServiceName.set(name, name);\n }\n // `serviceName` then adds the alias a repo needs when its deployed name is NOT its module\n // name (helper-svr serving 'helper-portal'). Colliding with a module is a misconfiguration,\n // not a precedence question: the alias is silently unreachable, so say so.\n for (const name of Object.keys(projects).sort()) {\n const declared = projects[name].serviceName;\n if (!this.isNode(name) || declared === undefined) continue;\n const claimant = this.nodeByServiceName.get(declared);\n if (claimant === undefined) {\n this.nodeByServiceName.set(declared, name);\n } else if (claimant !== name) {\n this.problems.push(\n `${name} declares serviceName '${declared}', but that is already the module name of ` +\n `${claimant} — the alias can never be reached. Rename one of them.`,\n );\n }\n }\n this.remoteCalls = new RemoteCallCollector(\n remoteServices,\n (name: string): boolean => this.nodeByServiceName.has(name),\n this.problems,\n );\n }\n\n assemble(): RuntimeGraphReport {\n const decls = this.collectDecls();\n const apis = this.buildApis(decls);\n const edgeResult = this.buildEdges(decls, apis);\n // Cuts are stamped BEFORE buildServices, which is where leveling reads the edges.\n this.problems.push(\n ...applyCycleCuts(edgeResult.edges, this.projects, this.nodeByServiceName),\n );\n const services = this.buildServices(decls, edgeResult.edges);\n const apisObj: Record<string, RuntimeApi> = {};\n for (const api of Array.from(apis.keys()).sort()) apisObj[api] = apis.get(api)!;\n const graph: RuntimeGraph = {\n maxLevel: 0,\n contractQueues: {},\n services,\n apis: apisObj,\n runtimeEdges: edgeResult.edges,\n unresolvedUses: edgeResult.unresolved,\n queues: edgeResult.queues,\n triggers: this.buildTriggers(decls),\n };\n // #1179/#1216: each service's products are exactly its project's declared product tags.\n new RuntimeProductMembership().apply(graph, this.projects);\n // A destination whose address arrives at RUNTIME is declared on its CONTRACT\n // (`@externalSystem runtime partner-webhooks`), so it needs no branch of its own here: it is\n // resolved by the same call every other declared system is, converges on one node when two\n // services deliver over the same contract, and is watched by the same drift check.\n const systems = resolveExternalSystems(this.externalSystemDecls, services);\n attachExternalSystems(graph, systems);\n this.remoteCalls.attach(graph);\n new RuntimeNodeLevels().apply(graph);\n return new RuntimeGraphReport(\n graph,\n this.warnings,\n this.problems,\n [...this.autoHidden].sort(),\n );\n }\n\n /**\n * The clock- and outside-driven entry points: for every contract a node IMPLEMENTS, each method\n * declared `cron` or `external` becomes a trigger pointing AT that node.\n *\n * Driven off `implements` rather than `uses` on purpose — these have no in-repo caller at all,\n * which is why they never produced an edge and stayed invisible.\n */\n private buildTriggers(decls: ScanDecl[]): RuntimeTrigger[] {\n const triggers: RuntimeTrigger[] = [];\n for (const decl of decls) {\n for (const ref of decl.implementsApis) {\n for (const method of this.methodsOf(ref.api)) {\n if (method.kind !== 'cron' && method.kind !== 'external') continue;\n const trigger: RuntimeTrigger = {\n level: 0,\n levelBecause: '',\n kind: method.kind,\n api: ref.api,\n method: method.name,\n service: decl.name,\n };\n if (method.kind === 'cron') trigger.queueName = method.queueName;\n // ONLY for 'external' (a clock needs no vendor name), and only when declared —\n // a graph committed before callers were required has none and must still render.\n if (method.kind === 'external' && method.caller !== undefined)\n trigger.caller = method.caller;\n triggers.push(trigger);\n }\n }\n }\n return triggers.sort(\n (a: RuntimeTrigger, b: RuntimeTrigger) =>\n a.kind.localeCompare(b.kind) ||\n a.api.localeCompare(b.api) ||\n a.method.localeCompare(b.method) ||\n a.service.localeCompare(b.service),\n );\n }\n\n /** The committed method table for a contract, or [] when it declares none (e.g. a vendor seam). */\n private methodsOf(api: string): ApiMethodMeta[] {\n return this.apiContracts[api]?.methods ?? [];\n }\n\n /**\n * One ScanDecl per RUNTIME NODE (role:server / role:client). A node's effective\n * relations are its OWN apiRelations PLUS those of every library in its transitive\n * dependsOn closure: a lib that calls createRpcClient/addRoutes runs inside the\n * server/client that embeds it, so the relation is attributed to that node — the\n * lib is never a runtime node. Recursion stops at other nodes (each server/client\n * owns its own relations). dependsOn is transitively reduced, but reduction\n * preserves reachability, so the recursive walk still reaches every lib a node\n * embeds through libraries.\n */\n private collectDecls(): ScanDecl[] {\n const decls: ScanDecl[] = [];\n for (const name of Object.keys(this.projects).sort()) {\n if (!this.isNode(name)) continue;\n const sink = new RelationSink(name);\n this.collectEffectiveRelations(name, sink, new Set<string>([name]));\n // EVERY node gets a decl, including one with zero relations. Gating this on \"has at\n // least one implements/uses\" silently DELETED any deployed server whose work arrives\n // from outside the repo (a pull subscription): the diagram looked complete while missing\n // a running service — confidently wrong, not visibly incomplete. isNode() is the whole\n // test; drawOnGraph:false is the ONE opt-out, and such a node renders as an isolated box.\n decls.push({\n name,\n implementsApis: dedupApiRefs(sortApiRefs(sink.implementsApis)),\n usesApis: dedupApiRefs(sortApiRefs(sink.usesApis)),\n implementsVia: sink.implementsVia,\n markerVia: sink.markerVia,\n });\n }\n return decls;\n }\n\n /** True when a project is a runtime node — a server or client app (never a library). */\n private isNode(name: string): boolean {\n const role = this.projects[name]?.role;\n return role === 'server' || role === 'client';\n }\n\n /**\n * True for a role:server that speaks NO webpieces runtime package anywhere in its library\n * closure AND serves/calls no in-repo contract — a legacy Express/NestJS service sitting in the\n * same monorepo. This graph is built entirely out of webpieces contracts, so such a service can\n * only ever draw as a disconnected box: it has no edges by construction and never will.\n *\n * It stays a NODE and stays in runtime-dependencies.json (drawOnGraph:false), which is the whole\n * difference between hiding it and the silent deletion #542 removed — the data view still shows\n * a deployed role:server, only the picture drops it. Removing it from isNode() instead would\n * also drop it from nodeByServiceName, so a targeted ClientConfig('orders-manager') from a drawn\n * service would stop resolving and decay into an unresolved use: a graph that got quietly WORSE\n * while looking cleaner. The COMPILE-TIME graph (dependencies.html) still draws these projects;\n * they genuinely exist, and only the runtime drawing claims to show webpieces services.\n *\n * role:client is deliberately never auto-hidden: a browser app can legitimately declare no\n * marker at all, and nothing checks clients for presence the way checkServersPresent checks\n * servers, so there is no equivalent failure to prevent.\n */\n private isNonParticipantServer(decl: ScanDecl): boolean {\n if (!this.markersKnown) return false;\n if (this.projects[decl.name]?.role !== 'server') return false;\n if (decl.markerVia.size > 0) return false;\n // Belt-and-braces: serving or calling an in-repo contract IS participation, whatever the\n // package list says. This is what keeps a mechanism we did not anticipate from being blanked.\n return decl.implementsApis.length === 0 && decl.usesApis.length === 0;\n }\n\n /**\n * Accumulate `name`'s own api relations, then recurse through its LIBRARY deps\n * (skipping other nodes, which own their own relations). `visited` guards against\n * re-walking a lib reachable by more than one path (and any cycle).\n */\n private collectEffectiveRelations(\n name: string,\n sink: RelationSink,\n visited: Set<string>,\n includeRelations: boolean = true,\n ): void {\n const entry = this.projects[name];\n if (entry === undefined) return;\n sink.addMarkers(entry.webpiecesRuntime, name);\n const relations = entry.apiRelations;\n if (includeRelations && relations !== undefined) {\n for (const owner of Object.keys(relations).sort()) {\n for (const ref of relations[owner].implements) {\n this.apiOwners.set(ref.api, owner);\n sink.addImplements(ref, ref.declaredVia ?? name);\n }\n for (const ref of relations[owner].uses) {\n this.apiOwners.set(ref.api, owner);\n sink.addUses(ref);\n }\n }\n }\n for (const dep of entry.dependsOn) {\n if (visited.has(dep)) continue;\n visited.add(dep);\n if (this.isNode(dep)) continue; // another server/client owns its own relations\n this.collectEffectiveRelations(\n dep,\n sink,\n visited,\n includeRelations && entry.runtimeComposition !== true,\n );\n }\n }\n\n /** apiClassName -> { implementedBy, usedBy, type }. */\n private buildApis(decls: ScanDecl[]): Map<string, RuntimeApi> {\n const apis = new Map<string, RuntimeApi>();\n const ensure = (api: string, type: ApiTransport): RuntimeApi => {\n let entry = apis.get(api);\n if (!entry) {\n entry = { implementedBy: [], usedBy: [], type };\n apis.set(api, entry);\n }\n return entry;\n };\n for (const decl of decls) {\n for (const ref of decl.implementsApis)\n ensure(ref.api, ref.type).implementedBy.push(decl.name);\n for (const ref of decl.usesApis) ensure(ref.api, ref.type).usedBy.push(decl.name);\n }\n for (const api of apis.keys()) {\n const entry = apis.get(api)!;\n entry.implementedBy.sort();\n entry.usedBy = Array.from(new Set(entry.usedBy)).sort();\n const owner = this.apiOwners.get(api);\n if (owner !== undefined) entry.owner = owner;\n }\n return apis;\n }\n\n /** Inferred edges U -> I via api A, split by transport; plus uses with no implementer. */\n private buildEdges(decls: ScanDecl[], apis: Map<string, RuntimeApi>): EdgeResult {\n const viaByKey = new Map<string, Set<string>>();\n const unresolved: RuntimeUnresolved[] = [];\n for (const decl of decls) {\n for (const ref of decl.usesApis) {\n // A named target outside this workspace (#1203) is a remote service, not an implementer\n // to resolve among the nodes and not an unresolved vendor call.\n const wanted = ref.targetService ?? this.callsServiceFor(decl.name, ref.api);\n if (this.remoteCalls.claim(decl.name, ref, wanted)) continue;\n const implementers = apis.get(ref.api)?.implementedBy ?? [];\n if (implementers.length === 0) {\n // Nobody in-repo serves it. For a vendor contract that is the ANSWER, not a gap:\n // the call leaves the repo, and the viz terminates it at a dashed vendor node.\n unresolved.push({\n level: 0,\n levelBecause: 'outbound sink',\n service: decl.name,\n api: ref.api,\n });\n continue;\n }\n for (const target of this.targetsFor(decl.name, ref, implementers)) {\n // A service calling ITSELF synchronously is noise; a service ENQUEUEING to\n // itself is a real, common topology (deferring its own work), and dropping it\n // was hiding the single most interesting thing about a queue.\n if (target === decl.name && ref.type !== 'pubsub') continue;\n const key = `${decl.name} ${target} ${ref.type}`;\n if (!viaByKey.has(key)) viaByKey.set(key, new Set());\n viaByKey.get(key)!.add(ref.api);\n }\n }\n }\n return {\n edges: this.edgesFromKeys(viaByKey),\n unresolved: sortUnresolved(unresolved),\n // Client wiring declares contracts, never the methods a producer enqueues.\n queues: {},\n };\n }\n\n /**\n * WHICH implementers this one `uses` reaches. Resolution order (most specific wins):\n * 1. a literal `ClientConfig` at the call site (`ref.targetService`) — names ONE node;\n * 2. else the calling project's declared `callsService` (project.json) — for the shared-library\n * case where the literal cannot sit at the call site, it lives one indirection away in the app;\n * 3. else the historical fan-out — the only safe superset — recording WHY, so a fanned-out (i.e.\n * possibly fictional) edge can never pass for a derived one.\n * A named target (1 or 2) that resolves to no module, or to a module that does not serve the\n * contract, is a PROBLEM (fails the build), never a silent drop.\n */\n private targetsFor(user: string, ref: ApiRef, implementers: string[]): string[] {\n const literal = ref.targetService;\n if (literal !== undefined)\n return this.resolveNamedTarget(user, ref, implementers, literal, 'literal');\n\n const declared = this.callsServiceFor(user, ref.api);\n if (declared !== undefined)\n return this.resolveNamedTarget(user, ref, implementers, declared, 'callsService');\n\n return this.untargetedFanOut(user, ref, implementers);\n }\n\n /**\n * The declared `callsService` target for this node's use of `api`, or undefined when none applies.\n * A string declaration aims every untargeted use at one service; a map aims per api-class.\n */\n private callsServiceFor(user: string, api: string): string | undefined {\n const declared = this.projects[user]?.callsService;\n if (declared === undefined) return undefined;\n if (typeof declared === 'string') return declared;\n return declared[api];\n }\n\n /**\n * Resolve a NAMED target (from a call-site literal or a project-level `callsService`) to the one\n * module that serves it. A name no module answers to, or a module that does not serve the\n * contract, fails the build — the wording names which declaration to fix, `source` deciding it.\n */\n private resolveNamedTarget(\n user: string,\n ref: ApiRef,\n implementers: string[],\n wanted: string,\n source: 'literal' | 'callsService',\n ): string[] {\n const node = this.nodeByServiceName.get(wanted);\n const served = `${implementers.length} module(s) serve this contract (${implementers.join(', ')})`;\n if (node === undefined) {\n this.problems.push(\n source === 'callsService'\n ? `${user} declares metadata.webpieces.callsService '${wanted}' in its project.json, but NO ` +\n `module answers to that name. ${served}. Point callsService at a module name, or declare ` +\n `metadata.webpieces.serviceName: '${wanted}' on the module that serves \"${ref.api}\".`\n : `${user} calls \"${ref.api}\" at service '${wanted}', but NO module answers to that name. ` +\n `${served}. Either use the module name, or declare metadata.webpieces.serviceName: ` +\n `'${wanted}' on the module that serves it (and translate any environment prefix in ` +\n `ClientRegistry.setDeriver, not here).`,\n );\n return implementers;\n }\n if (!implementers.includes(node)) {\n const via =\n source === 'callsService'\n ? `${user} declares callsService '${wanted}' (module ${node})`\n : `${user} calls \"${ref.api}\" at service '${wanted}' (module ${node})`;\n this.problems.push(\n `${via}, but ${node} does NOT serve \"${ref.api}\" — ${implementers.join(', ')} do. At runtime that ` +\n `call has nothing to answer it.`,\n );\n return implementers;\n }\n return [node];\n }\n\n /**\n * A use with no literal client config. One implementer is unambiguous, so it stays silent; more\n * than one means every edge but one is fiction — exactly the failure this mechanism exists to\n * stop — so it is reported even though the graph still (conservatively) draws them all.\n */\n private untargetedFanOut(user: string, ref: ApiRef, implementers: string[]): string[] {\n if (implementers.length > 1) {\n this.warnings.push(\n `${user} uses \"${ref.api}\" with no literal client config, and ${implementers.length} services ` +\n `implement it (${implementers.join(', ')}) — an edge is drawn to EVERY one, so all but one ` +\n `are fiction. Name the target: createRpcClient(${ref.api}, new ClientConfig('<serviceName>', ClientRole.SERVER)); ` +\n `or, when the client is built in a shared library (no literal can sit at the call site), ` +\n `declare metadata.webpieces.callsService: '<serviceName>' on ${user}'s project.json.`,\n );\n }\n return implementers;\n }\n\n /**\n * Rebuild edges from their `\"from to type queue\"` keys. The 4th part is the queue (\"Api.method\")\n * and is empty for every non-queued edge; it is part of the KEY so two queued methods between\n * the same pair stay two edges instead of collapsing into one.\n */\n private edgesFromKeys(viaByKey: Map<string, Set<string>>): RuntimeEdge[] {\n const edges: RuntimeEdge[] = [];\n for (const key of viaByKey.keys()) {\n const parts = key.split(' ');\n const edge: RuntimeEdge = {\n from: parts[0],\n to: parts[1],\n via: Array.from(viaByKey.get(key)!).sort(),\n type: parts[2] as ApiTransport,\n };\n if (parts[3] !== undefined && parts[3] !== '') edge.queue = parts[3];\n edges.push(edge);\n }\n edges.sort(\n (a: RuntimeEdge, b: RuntimeEdge) =>\n a.from.localeCompare(b.from) ||\n a.to.localeCompare(b.to) ||\n (a.type ?? '').localeCompare(b.type ?? '') ||\n (a.queue ?? '').localeCompare(b.queue ?? ''),\n );\n return edges;\n }\n\n private buildServices(decls: ScanDecl[], edges: RuntimeEdge[]): Record<string, RuntimeService> {\n const services: Record<string, RuntimeService> = {};\n for (const decl of decls) {\n // A queued hop depends on the QUEUE, not on the peer: the producer hands off and returns,\n // so naming the consumer here would assert a coupling that does not exist (and would make\n // a service that defers work to itself look self-dependent).\n const dependsOn = Array.from(\n new Set(\n edges\n .filter((e: RuntimeEdge) => e.from === decl.name)\n .flatMap((e: RuntimeEdge) =>\n e.type === 'pubsub'\n ? e.via.map((api) => `queue:${e.queue ?? api}`)\n : [e.to],\n ),\n ),\n ).sort();\n // Keys are written in this order; an undefined value is omitted by JSON.stringify, so\n // the committed JSON stays clean AND deterministic without conditional assembly.\n const service: RuntimeService = {\n level: 0,\n levelBecause: '',\n role: this.projects[decl.name]?.role, // labels a relation-less node for what it IS\n serviceName: this.projects[decl.name]?.serviceName,\n callsService: this.projects[decl.name]?.callsService,\n implements: decl.implementsApis.map((r: ApiRef) => r.api),\n implementsVia:\n decl.implementsVia.size > 0 ? sortedRecord(decl.implementsVia) : undefined,\n // One api used against two services is two refs but ONE api in this list.\n uses: Array.from(new Set(decl.usesApis.map((r: ApiRef) => r.api))),\n dependsOn,\n wiringUses: decl.usesApis.some((ref) => ref.declaredVia !== undefined)\n ? decl.usesApis\n : undefined,\n wiringImplements: decl.implementsApis.some((ref) => ref.declaredVia !== undefined)\n ? decl.implementsApis\n : undefined,\n };\n services[decl.name] = service;\n // The explicit tag wins and is NOT reported as auto-hidden — somebody asked for it.\n if (this.hiddenProjects.has(decl.name)) {\n service.drawOnGraph = false;\n } else if (this.isNonParticipantServer(decl)) {\n service.drawOnGraph = false;\n this.autoHidden.push(decl.name);\n }\n }\n return services;\n }\n}\n\n/**\n * Derive the runtime graph from dependencies.json's project `apiRelations` — the\n * single source of truth shared by generate + validate. `hiddenProjects`\n * (drawOnGraph:false, defaults to none) are kept in the graph but flagged so the\n * runtime visualizer omits their nodes + edges.\n */\n// webpieces-disable no-function-outside-class -- module entry point for the runtime graph derivation\nexport function deriveRuntimeGraph(\n projects: EnhancedGraph,\n hiddenProjects: Set<string> = new Set<string>(),\n apiContracts: ApiContracts = {},\n): RuntimeGraph {\n return deriveRuntimeGraphReport(projects, hiddenProjects, apiContracts).graph;\n}\n\n/**\n * The same derivation, plus the warnings it produced (every edge it had to GUESS at). Executors use\n * this form and print the warnings; `deriveRuntimeGraph` is the convenience form for callers that\n * only want the data. The warnings are deliberately kept OUT of runtime-dependencies.json — a graph\n * file that records its own doubts would just get committed and stop being read.\n */\n// webpieces-disable no-function-outside-class -- module entry point for the runtime graph derivation\nexport function deriveRuntimeGraphReport(\n projects: EnhancedGraph,\n hiddenProjects: Set<string> = new Set<string>(),\n apiContracts: ApiContracts = {},\n externalSystems: ExternalSystemDecls = {},\n remoteServices: RemoteServices = {},\n): RuntimeGraphReport {\n return new RuntimeGraphDeriver(\n projects,\n hiddenProjects,\n apiContracts,\n externalSystems,\n remoteServices,\n ).assemble();\n}\n\n// Levels + adjacency live in runtime-graph-levels.ts; re-exported for the same reason the model types\n// and the io helpers above are — one obvious place to import the runtime graph from.\nexport { runtimeAdjacency } from './runtime-node-levels';\n"]}
|
|
1
|
+
{"version":3,"file":"runtime-graph.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-graph.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Runtime Graph\n *\n * Derives the runtime microservice graph SOLELY from architecture/dependencies.json\n * (the single source of truth): each project's `apiRelations` carry which api\n * classes it implements/uses and their transport (rpc | pubsub). Both\n * `architecture:generate` and `architecture:validate-runtime-architecture` call\n * the SAME `deriveRuntimeGraph`, so the committed graph and the validated graph\n * can never diverge.\n *\n * The runtime edge Z -> X (Z depends on X at runtime) is INFERRED: Z `uses` api\n * Y and X `implements` api Y. This edge does not exist in the compile-time\n * dependencies.json (both Z and X only compile-depend on the api library Y).\n *\n * WHICH X is decided by the call site, not by \"everyone who implements Y\", in\n * priority order: (1) a literal at the call site —\n * `createRpcClient(Y, new ClientConfig('helper-fsdb'))` — kept as\n * `ApiRef.targetService`; else (2) the calling project's declared `callsService`\n * (project.json metadata.webpieces.callsService), the symmetric half of\n * `serviceName` for the shared-library case where the client is built once from a\n * config field so no literal can sit at the call site; else (3) fan-out. A named\n * target from (1) or (2) is matched against each node's DECLARED `serviceName`.\n * Fanning an edge out to every implementer is catastrophic for a company-wide\n * contract registered in a shared library — it manufactures calls that cannot\n * happen, and cycles that do not exist. When a target cannot be resolved the old\n * fan-out still happens, but a warning names the call site (see\n * RuntimeGraphReport.warnings): a wrong-but-green graph is worse than a failing\n * one, so it must never degrade silently.\n */\n\nimport { sortGraphTopologically } from './graph-sorter';\nimport type { EnhancedGraph, GraphEntry } from './graph-sorter';\nimport type {\n ApiContracts,\n ApiMethodMeta,\n ApiRef,\n ApiTransport,\n ExternalSystemDecls,\n} from './api-usage/api-relations';\nimport { sortApiRefs } from './api-usage/api-relations';\nimport { RelationSink } from './runtime-graph-decls';\nimport type { ScanDecl } from './runtime-graph-decls';\nimport { dedupApiRefs, sortedRecord, sortUnresolved } from './runtime-graph-sorters';\nimport { attachExternalSystems, resolveExternalSystems } from './api-usage/external-systems';\nimport { RuntimeProductMembership } from './graph-products';\nimport { RemoteCallCollector } from './runtime-remote-calls';\nimport type { RemoteServices } from './remote-services';\nimport type {\n RuntimeApi,\n RuntimeEdge,\n RuntimeExternalSystem,\n RuntimeGraph,\n RuntimeQueue,\n RuntimeService,\n RuntimeTrigger,\n RuntimeUnresolved,\n} from './runtime-graph-model';\nimport { toError } from '../toError';\n\n// The committed data shape lives in runtime-graph-model.ts; re-exported here so every existing\n// `from './runtime-graph'` import keeps working and there is still one obvious place to import from.\nexport type {\n RuntimeApi,\n RuntimeEdge,\n RuntimeExternalSystem,\n RuntimeGraph,\n RuntimeQueue,\n RuntimeRemoteCall,\n RuntimeRemoteService,\n RuntimeService,\n RuntimeTrigger,\n RuntimeUnresolved,\n} from './runtime-graph-model';\nimport { applyCycleCuts } from './runtime-graph-levels';\nimport { RuntimeNodeLevels } from './runtime-node-levels';\n\n// Persistence lives in runtime-graph-io.ts; re-exported for the same reason as the model types.\nexport {\n DEFAULT_RUNTIME_GRAPH_PATH,\n saveRuntimeGraph,\n runtimeGraphFileExists,\n loadRuntimeGraph,\n serializeRuntimeGraph,\n} from './runtime-graph-io';\n\ninterface EdgeResult {\n edges: RuntimeEdge[];\n unresolved: RuntimeUnresolved[];\n queues: Record<string, RuntimeQueue>;\n}\n\n/**\n * The derived graph PLUS everything the derivation had to guess at. `warnings` is deliberately not\n * part of RuntimeGraph: it is not committed data, it is the report that stops a guessed edge from\n * passing for a derived one. Executors print it.\n */\nexport class RuntimeGraphReport {\n constructor(\n public readonly graph: RuntimeGraph,\n /** Human-readable lines naming every call site whose target the graph could not pin down. */\n public readonly warnings: string[],\n /**\n * Call sites that name a target the repo does not contain. Unlike a warning these FAIL the\n * build: the contract IS served in-repo, so the name is a typo or a stale rename, and the\n * only reason it stayed invisible is that the graph quietly fanned the edge out instead.\n * (A call to a service outside the repo never reaches here — nothing in-repo implements its\n * contract, so it is `unresolvedUses`.)\n */\n public readonly problems: string[] = [],\n /**\n * role:server nodes omitted from the DRAWING because they declare no webpieces runtime\n * package anywhere in their library closure and serve/call nothing in-repo. Neither a\n * warning nor a problem — this is intended behavior, and shouting on every clean run is how\n * warnings stop being read. Deliberately NOT persisted: a graph file that records its own\n * omissions gets committed and stops being read. Executors print it instead, so the\n * omission is always visible and never silent.\n */\n public readonly autoHidden: string[] = [],\n ) {}\n}\n\n/**\n * Derives the runtime microservice graph from architecture/dependencies.json `apiRelations`:\n * implementers × users per API, split by transport. An rpc edge is a direct call; a pubsub edge flows\n * through a queue (drawn producer → queue → consumer by the visualizer).\n *\n * Nodes are the runnable apps only — role:server / role:client. A library is NEVER a node; its\n * implements/uses (a shared client-factory or route-registration lib) are attributed to the\n * servers/clients that embed it, walked transitively over dependsOn (see collectDecls).\n */\nclass RuntimeGraphDeriver {\n /** apiClassName -> the api-lib project that owns the contract (from the apiRelations key). */\n private readonly apiOwners = new Map<string, string>();\n /** Addressable name -> the runtime node answering to it; how a targeted call resolves. */\n private readonly nodeByServiceName = new Map<string, string>();\n private readonly warnings: string[] = [];\n private readonly problems: string[] = [];\n /** role:server nodes hidden by isNonParticipantServer, in the order buildServices met them. */\n private readonly autoHidden: string[] = [];\n /** Uses aimed at a reviewed out-of-workspace service (#1203); built once the names are claimed. */\n private readonly remoteCalls: RemoteCallCollector;\n\n /**\n * False when NO project in the graph carries `webpiecesRuntime`, i.e. the file was written\n * before the field existed. Auto-hiding is then off ENTIRELY, so an old dependencies.json\n * renders exactly as it did — absence of the field must never be read as \"declares none\".\n * Any repo regenerated after this change has at least one webpieces project, so the guard\n * cannot wrongly suppress the feature.\n */\n private readonly markersKnown: boolean;\n\n constructor(\n private readonly projects: EnhancedGraph,\n /** Project names tagged drawOnGraph:false — kept in the JSON but flagged so the viz omits them. */\n private readonly hiddenProjects: Set<string>,\n /**\n * The per-contract method tables, read from the generated `architecture/apis/<Api>.json`\n * files (ApiContractFiles). Pubsub edges remain at the contract level, independently\n * of method metadata: an endpoint table does not declare which methods a client uses.\n */\n private readonly apiContracts: ApiContracts = {},\n /**\n * Declared external systems from dependencies.json, keyed by identity. Empty means nothing\n * was declared, which renders exactly as it did before declarations existed.\n */\n private readonly externalSystemDecls: ExternalSystemDecls = {},\n /** Reviewed out-of-workspace services from dependencies.json `remoteServices` (#1203). */\n remoteServices: RemoteServices = {},\n ) {\n this.markersKnown = Object.values(projects).some(\n (entry: GraphEntry) => entry.webpiecesRuntime !== undefined,\n );\n // A node ALWAYS answers to its own module name, so a repo whose deployed names match its\n // project names needs no declaration at all — and no alias can ever redirect 'ai-chat' away\n // from the ai-chat module. Module names are therefore claimed FIRST and are unshadowable.\n for (const name of Object.keys(projects).sort()) {\n if (this.isNode(name)) this.nodeByServiceName.set(name, name);\n }\n // `serviceName` then adds the alias a repo needs when its deployed name is NOT its module\n // name (helper-svr serving 'helper-portal'). Colliding with a module is a misconfiguration,\n // not a precedence question: the alias is silently unreachable, so say so.\n for (const name of Object.keys(projects).sort()) {\n const declared = projects[name].serviceName;\n if (!this.isNode(name) || declared === undefined) continue;\n const claimant = this.nodeByServiceName.get(declared);\n if (claimant === undefined) {\n this.nodeByServiceName.set(declared, name);\n } else if (claimant !== name) {\n this.problems.push(\n `${name} declares serviceName '${declared}', but that is already the module name of ` +\n `${claimant} — the alias can never be reached. Rename one of them.`,\n );\n }\n }\n this.remoteCalls = new RemoteCallCollector(\n remoteServices,\n (name: string): boolean => this.nodeByServiceName.has(name),\n this.problems,\n );\n }\n\n assemble(): RuntimeGraphReport {\n const decls = this.collectDecls();\n const apis = this.buildApis(decls);\n const edgeResult = this.buildEdges(decls, apis);\n // Cuts are stamped BEFORE buildServices, which is where leveling reads the edges.\n this.problems.push(\n ...applyCycleCuts(edgeResult.edges, this.projects, this.nodeByServiceName),\n );\n const services = this.buildServices(decls, edgeResult.edges);\n const apisObj: Record<string, RuntimeApi> = {};\n for (const api of Array.from(apis.keys()).sort()) apisObj[api] = apis.get(api)!;\n const graph: RuntimeGraph = {\n maxLevel: 0,\n contractQueues: {},\n services,\n apis: apisObj,\n runtimeEdges: edgeResult.edges,\n unresolvedUses: edgeResult.unresolved,\n queues: edgeResult.queues,\n triggers: this.buildTriggers(decls),\n };\n // #1179/#1216: each service's products are exactly its project's declared product tags.\n new RuntimeProductMembership().apply(graph, this.projects);\n // A destination whose address arrives at RUNTIME is declared on its CONTRACT\n // (`@externalSystem runtime partner-webhooks`), so it needs no branch of its own here: it is\n // resolved by the same call every other declared system is, converges on one node when two\n // services deliver over the same contract, and is watched by the same drift check.\n const systems = resolveExternalSystems(this.externalSystemDecls, services);\n attachExternalSystems(graph, systems);\n this.remoteCalls.attach(graph);\n new RuntimeNodeLevels().apply(graph);\n return new RuntimeGraphReport(\n graph,\n this.warnings,\n this.problems,\n [...this.autoHidden].sort(),\n );\n }\n\n /**\n * The clock- and outside-driven entry points: for every contract a node IMPLEMENTS, each method\n * declared `cron` or `external-inbound` becomes a trigger pointing AT that node.\n *\n * Driven off `implements` rather than `uses` on purpose — these have no in-repo caller at all,\n * which is why they never produced an edge and stayed invisible.\n */\n private buildTriggers(decls: ScanDecl[]): RuntimeTrigger[] {\n const triggers: RuntimeTrigger[] = [];\n for (const decl of decls) {\n for (const ref of decl.implementsApis) {\n for (const method of this.methodsOf(ref.api)) {\n if (method.kind !== 'cron' && method.kind !== 'external-inbound') continue;\n const trigger: RuntimeTrigger = {\n level: 0,\n levelBecause: '',\n // A trigger's 'external' IS inbound: an outbound method has no in-repo\n // implementer, so it never reaches this loop.\n kind: method.kind === 'cron' ? 'cron' : 'external',\n api: ref.api,\n method: method.name,\n service: decl.name,\n };\n if (method.kind === 'cron') trigger.queueName = method.queueName;\n // ONLY for 'external' (a clock needs no vendor name), and only when declared —\n // a graph committed before callers were required has none and must still render.\n if (method.kind === 'external-inbound' && method.caller !== undefined)\n trigger.caller = method.caller;\n triggers.push(trigger);\n }\n }\n }\n return triggers.sort(\n (a: RuntimeTrigger, b: RuntimeTrigger) =>\n a.kind.localeCompare(b.kind) ||\n a.api.localeCompare(b.api) ||\n a.method.localeCompare(b.method) ||\n a.service.localeCompare(b.service),\n );\n }\n\n /** The committed method table for a contract, or [] when it declares none (e.g. a vendor seam). */\n private methodsOf(api: string): ApiMethodMeta[] {\n return this.apiContracts[api]?.methods ?? [];\n }\n\n /**\n * One ScanDecl per RUNTIME NODE (role:server / role:client). A node's effective\n * relations are its OWN apiRelations PLUS those of every library in its transitive\n * dependsOn closure: a lib that calls createRpcClient/addRoutes runs inside the\n * server/client that embeds it, so the relation is attributed to that node — the\n * lib is never a runtime node. Recursion stops at other nodes (each server/client\n * owns its own relations). dependsOn is transitively reduced, but reduction\n * preserves reachability, so the recursive walk still reaches every lib a node\n * embeds through libraries.\n */\n private collectDecls(): ScanDecl[] {\n const decls: ScanDecl[] = [];\n for (const name of Object.keys(this.projects).sort()) {\n if (!this.isNode(name)) continue;\n const sink = new RelationSink(name);\n this.collectEffectiveRelations(name, sink, new Set<string>([name]));\n // EVERY node gets a decl, including one with zero relations. Gating this on \"has at\n // least one implements/uses\" silently DELETED any deployed server whose work arrives\n // from outside the repo (a pull subscription): the diagram looked complete while missing\n // a running service — confidently wrong, not visibly incomplete. isNode() is the whole\n // test; drawOnGraph:false is the ONE opt-out, and such a node renders as an isolated box.\n decls.push({\n name,\n implementsApis: dedupApiRefs(sortApiRefs(sink.implementsApis)),\n usesApis: dedupApiRefs(sortApiRefs(sink.usesApis)),\n implementsVia: sink.implementsVia,\n markerVia: sink.markerVia,\n });\n }\n return decls;\n }\n\n /** True when a project is a runtime node — a server or client app (never a library). */\n private isNode(name: string): boolean {\n const role = this.projects[name]?.role;\n return role === 'server' || role === 'client';\n }\n\n /**\n * True for a role:server that speaks NO webpieces runtime package anywhere in its library\n * closure AND serves/calls no in-repo contract — a legacy Express/NestJS service sitting in the\n * same monorepo. This graph is built entirely out of webpieces contracts, so such a service can\n * only ever draw as a disconnected box: it has no edges by construction and never will.\n *\n * It stays a NODE and stays in runtime-dependencies.json (drawOnGraph:false), which is the whole\n * difference between hiding it and the silent deletion #542 removed — the data view still shows\n * a deployed role:server, only the picture drops it. Removing it from isNode() instead would\n * also drop it from nodeByServiceName, so a targeted ClientConfig('orders-manager') from a drawn\n * service would stop resolving and decay into an unresolved use: a graph that got quietly WORSE\n * while looking cleaner. The COMPILE-TIME graph (dependencies.html) still draws these projects;\n * they genuinely exist, and only the runtime drawing claims to show webpieces services.\n *\n * role:client is deliberately never auto-hidden: a browser app can legitimately declare no\n * marker at all, and nothing checks clients for presence the way checkServersPresent checks\n * servers, so there is no equivalent failure to prevent.\n */\n private isNonParticipantServer(decl: ScanDecl): boolean {\n if (!this.markersKnown) return false;\n if (this.projects[decl.name]?.role !== 'server') return false;\n if (decl.markerVia.size > 0) return false;\n // Belt-and-braces: serving or calling an in-repo contract IS participation, whatever the\n // package list says. This is what keeps a mechanism we did not anticipate from being blanked.\n return decl.implementsApis.length === 0 && decl.usesApis.length === 0;\n }\n\n /**\n * Accumulate `name`'s own api relations, then recurse through its LIBRARY deps\n * (skipping other nodes, which own their own relations). `visited` guards against\n * re-walking a lib reachable by more than one path (and any cycle).\n */\n private collectEffectiveRelations(\n name: string,\n sink: RelationSink,\n visited: Set<string>,\n includeRelations: boolean = true,\n ): void {\n const entry = this.projects[name];\n if (entry === undefined) return;\n sink.addMarkers(entry.webpiecesRuntime, name);\n const relations = entry.apiRelations;\n if (includeRelations && relations !== undefined) {\n for (const owner of Object.keys(relations).sort()) {\n for (const ref of relations[owner].implements) {\n this.apiOwners.set(ref.api, owner);\n sink.addImplements(ref, ref.declaredVia ?? name);\n }\n for (const ref of relations[owner].uses) {\n this.apiOwners.set(ref.api, owner);\n sink.addUses(ref);\n }\n }\n }\n for (const dep of entry.dependsOn) {\n if (visited.has(dep)) continue;\n visited.add(dep);\n if (this.isNode(dep)) continue; // another server/client owns its own relations\n this.collectEffectiveRelations(\n dep,\n sink,\n visited,\n includeRelations && entry.runtimeComposition !== true,\n );\n }\n }\n\n /** apiClassName -> { implementedBy, usedBy, type }. */\n private buildApis(decls: ScanDecl[]): Map<string, RuntimeApi> {\n const apis = new Map<string, RuntimeApi>();\n const ensure = (api: string, type: ApiTransport): RuntimeApi => {\n let entry = apis.get(api);\n if (!entry) {\n entry = { implementedBy: [], usedBy: [], type };\n apis.set(api, entry);\n }\n return entry;\n };\n for (const decl of decls) {\n for (const ref of decl.implementsApis)\n ensure(ref.api, ref.type).implementedBy.push(decl.name);\n for (const ref of decl.usesApis) ensure(ref.api, ref.type).usedBy.push(decl.name);\n }\n for (const api of apis.keys()) {\n const entry = apis.get(api)!;\n entry.implementedBy.sort();\n entry.usedBy = Array.from(new Set(entry.usedBy)).sort();\n const owner = this.apiOwners.get(api);\n if (owner !== undefined) entry.owner = owner;\n }\n return apis;\n }\n\n /** Inferred edges U -> I via api A, split by transport; plus uses with no implementer. */\n private buildEdges(decls: ScanDecl[], apis: Map<string, RuntimeApi>): EdgeResult {\n const viaByKey = new Map<string, Set<string>>();\n const unresolved: RuntimeUnresolved[] = [];\n for (const decl of decls) {\n for (const ref of decl.usesApis) {\n // A named target outside this workspace (#1203) is a remote service, not an implementer\n // to resolve among the nodes and not an unresolved vendor call.\n const wanted = ref.targetService ?? this.callsServiceFor(decl.name, ref.api);\n if (this.remoteCalls.claim(decl.name, ref, wanted)) continue;\n const implementers = apis.get(ref.api)?.implementedBy ?? [];\n if (implementers.length === 0) {\n // Nobody in-repo serves it. For a vendor contract that is the ANSWER, not a gap:\n // the call leaves the repo, and the viz terminates it at a dashed vendor node.\n unresolved.push({\n level: 0,\n levelBecause: 'outbound sink',\n service: decl.name,\n api: ref.api,\n });\n continue;\n }\n for (const target of this.targetsFor(decl.name, ref, implementers)) {\n // A service calling ITSELF synchronously is noise; a service ENQUEUEING to\n // itself is a real, common topology (deferring its own work), and dropping it\n // was hiding the single most interesting thing about a queue.\n if (target === decl.name && ref.type !== 'pubsub') continue;\n const key = `${decl.name} ${target} ${ref.type}`;\n if (!viaByKey.has(key)) viaByKey.set(key, new Set());\n viaByKey.get(key)!.add(ref.api);\n }\n }\n }\n return {\n edges: this.edgesFromKeys(viaByKey),\n unresolved: sortUnresolved(unresolved),\n // Client wiring declares contracts, never the methods a producer enqueues.\n queues: {},\n };\n }\n\n /**\n * WHICH implementers this one `uses` reaches. Resolution order (most specific wins):\n * 1. a literal `ClientConfig` at the call site (`ref.targetService`) — names ONE node;\n * 2. else the calling project's declared `callsService` (project.json) — for the shared-library\n * case where the literal cannot sit at the call site, it lives one indirection away in the app;\n * 3. else the historical fan-out — the only safe superset — recording WHY, so a fanned-out (i.e.\n * possibly fictional) edge can never pass for a derived one.\n * A named target (1 or 2) that resolves to no module, or to a module that does not serve the\n * contract, is a PROBLEM (fails the build), never a silent drop.\n */\n private targetsFor(user: string, ref: ApiRef, implementers: string[]): string[] {\n const literal = ref.targetService;\n if (literal !== undefined)\n return this.resolveNamedTarget(user, ref, implementers, literal, 'literal');\n\n const declared = this.callsServiceFor(user, ref.api);\n if (declared !== undefined)\n return this.resolveNamedTarget(user, ref, implementers, declared, 'callsService');\n\n return this.untargetedFanOut(user, ref, implementers);\n }\n\n /**\n * The declared `callsService` target for this node's use of `api`, or undefined when none applies.\n * A string declaration aims every untargeted use at one service; a map aims per api-class.\n */\n private callsServiceFor(user: string, api: string): string | undefined {\n const declared = this.projects[user]?.callsService;\n if (declared === undefined) return undefined;\n if (typeof declared === 'string') return declared;\n return declared[api];\n }\n\n /**\n * Resolve a NAMED target (from a call-site literal or a project-level `callsService`) to the one\n * module that serves it. A name no module answers to, or a module that does not serve the\n * contract, fails the build — the wording names which declaration to fix, `source` deciding it.\n */\n private resolveNamedTarget(\n user: string,\n ref: ApiRef,\n implementers: string[],\n wanted: string,\n source: 'literal' | 'callsService',\n ): string[] {\n const node = this.nodeByServiceName.get(wanted);\n const served = `${implementers.length} module(s) serve this contract (${implementers.join(', ')})`;\n if (node === undefined) {\n this.problems.push(\n source === 'callsService'\n ? `${user} declares metadata.webpieces.callsService '${wanted}' in its project.json, but NO ` +\n `module answers to that name. ${served}. Point callsService at a module name, or declare ` +\n `metadata.webpieces.serviceName: '${wanted}' on the module that serves \"${ref.api}\".`\n : `${user} calls \"${ref.api}\" at service '${wanted}', but NO module answers to that name. ` +\n `${served}. Either use the module name, or declare metadata.webpieces.serviceName: ` +\n `'${wanted}' on the module that serves it (and translate any environment prefix in ` +\n `ClientRegistry.setDeriver, not here).`,\n );\n return implementers;\n }\n if (!implementers.includes(node)) {\n const via =\n source === 'callsService'\n ? `${user} declares callsService '${wanted}' (module ${node})`\n : `${user} calls \"${ref.api}\" at service '${wanted}' (module ${node})`;\n this.problems.push(\n `${via}, but ${node} does NOT serve \"${ref.api}\" — ${implementers.join(', ')} do. At runtime that ` +\n `call has nothing to answer it.`,\n );\n return implementers;\n }\n return [node];\n }\n\n /**\n * A use with no literal client config. One implementer is unambiguous, so it stays silent; more\n * than one means every edge but one is fiction — exactly the failure this mechanism exists to\n * stop — so it is reported even though the graph still (conservatively) draws them all.\n */\n private untargetedFanOut(user: string, ref: ApiRef, implementers: string[]): string[] {\n if (implementers.length > 1) {\n this.warnings.push(\n `${user} uses \"${ref.api}\" with no literal client config, and ${implementers.length} services ` +\n `implement it (${implementers.join(', ')}) — an edge is drawn to EVERY one, so all but one ` +\n `are fiction. Name the target: createRpcClient(${ref.api}, new ClientConfig('<serviceName>', ClientRole.SERVER)); ` +\n `or, when the client is built in a shared library (no literal can sit at the call site), ` +\n `declare metadata.webpieces.callsService: '<serviceName>' on ${user}'s project.json.`,\n );\n }\n return implementers;\n }\n\n /**\n * Rebuild edges from their `\"from to type queue\"` keys. The 4th part is the queue (\"Api.method\")\n * and is empty for every non-queued edge; it is part of the KEY so two queued methods between\n * the same pair stay two edges instead of collapsing into one.\n */\n private edgesFromKeys(viaByKey: Map<string, Set<string>>): RuntimeEdge[] {\n const edges: RuntimeEdge[] = [];\n for (const key of viaByKey.keys()) {\n const parts = key.split(' ');\n const edge: RuntimeEdge = {\n from: parts[0],\n to: parts[1],\n via: Array.from(viaByKey.get(key)!).sort(),\n type: parts[2] as ApiTransport,\n };\n if (parts[3] !== undefined && parts[3] !== '') edge.queue = parts[3];\n edges.push(edge);\n }\n edges.sort(\n (a: RuntimeEdge, b: RuntimeEdge) =>\n a.from.localeCompare(b.from) ||\n a.to.localeCompare(b.to) ||\n (a.type ?? '').localeCompare(b.type ?? '') ||\n (a.queue ?? '').localeCompare(b.queue ?? ''),\n );\n return edges;\n }\n\n private buildServices(decls: ScanDecl[], edges: RuntimeEdge[]): Record<string, RuntimeService> {\n const services: Record<string, RuntimeService> = {};\n for (const decl of decls) {\n // A queued hop depends on the QUEUE, not on the peer: the producer hands off and returns,\n // so naming the consumer here would assert a coupling that does not exist (and would make\n // a service that defers work to itself look self-dependent).\n const dependsOn = Array.from(\n new Set(\n edges\n .filter((e: RuntimeEdge) => e.from === decl.name)\n .flatMap((e: RuntimeEdge) =>\n e.type === 'pubsub'\n ? e.via.map((api) => `queue:${e.queue ?? api}`)\n : [e.to],\n ),\n ),\n ).sort();\n // Keys are written in this order; an undefined value is omitted by JSON.stringify, so\n // the committed JSON stays clean AND deterministic without conditional assembly.\n const service: RuntimeService = {\n level: 0,\n levelBecause: '',\n role: this.projects[decl.name]?.role, // labels a relation-less node for what it IS\n serviceName: this.projects[decl.name]?.serviceName,\n callsService: this.projects[decl.name]?.callsService,\n implements: decl.implementsApis.map((r: ApiRef) => r.api),\n implementsVia:\n decl.implementsVia.size > 0 ? sortedRecord(decl.implementsVia) : undefined,\n // One api used against two services is two refs but ONE api in this list.\n uses: Array.from(new Set(decl.usesApis.map((r: ApiRef) => r.api))),\n dependsOn,\n wiringUses: decl.usesApis.some((ref) => ref.declaredVia !== undefined)\n ? decl.usesApis\n : undefined,\n wiringImplements: decl.implementsApis.some((ref) => ref.declaredVia !== undefined)\n ? decl.implementsApis\n : undefined,\n };\n services[decl.name] = service;\n // The explicit tag wins and is NOT reported as auto-hidden — somebody asked for it.\n if (this.hiddenProjects.has(decl.name)) {\n service.drawOnGraph = false;\n } else if (this.isNonParticipantServer(decl)) {\n service.drawOnGraph = false;\n this.autoHidden.push(decl.name);\n }\n }\n return services;\n }\n}\n\n/**\n * Derive the runtime graph from dependencies.json's project `apiRelations` — the\n * single source of truth shared by generate + validate. `hiddenProjects`\n * (drawOnGraph:false, defaults to none) are kept in the graph but flagged so the\n * runtime visualizer omits their nodes + edges.\n */\n// webpieces-disable no-function-outside-class -- module entry point for the runtime graph derivation\nexport function deriveRuntimeGraph(\n projects: EnhancedGraph,\n hiddenProjects: Set<string> = new Set<string>(),\n apiContracts: ApiContracts = {},\n): RuntimeGraph {\n return deriveRuntimeGraphReport(projects, hiddenProjects, apiContracts).graph;\n}\n\n/**\n * The same derivation, plus the warnings it produced (every edge it had to GUESS at). Executors use\n * this form and print the warnings; `deriveRuntimeGraph` is the convenience form for callers that\n * only want the data. The warnings are deliberately kept OUT of runtime-dependencies.json — a graph\n * file that records its own doubts would just get committed and stop being read.\n */\n// webpieces-disable no-function-outside-class -- module entry point for the runtime graph derivation\nexport function deriveRuntimeGraphReport(\n projects: EnhancedGraph,\n hiddenProjects: Set<string> = new Set<string>(),\n apiContracts: ApiContracts = {},\n externalSystems: ExternalSystemDecls = {},\n remoteServices: RemoteServices = {},\n): RuntimeGraphReport {\n return new RuntimeGraphDeriver(\n projects,\n hiddenProjects,\n apiContracts,\n externalSystems,\n remoteServices,\n ).assemble();\n}\n\n// Levels + adjacency live in runtime-graph-levels.ts; re-exported for the same reason the model types\n// and the io helpers above are — one obvious place to import the runtime graph from.\nexport { runtimeAdjacency } from './runtime-node-levels';\n"]}
|
|
@@ -18,6 +18,12 @@ class ServiceTargetValidator {
|
|
|
18
18
|
this.validateRemoteServices(graph, hosts, contracts, remoteServices);
|
|
19
19
|
for (const [name, entry] of Object.entries(graph))
|
|
20
20
|
for (const [owner, relation] of Object.entries(entry.apiRelations ?? {})) {
|
|
21
|
+
// An EXTERNAL_OUTBOUND contract (apiKind 'external') is an outside system's API: a
|
|
22
|
+
// workspace project that implements it would be a server of ours answering for a vendor.
|
|
23
|
+
for (const ref of relation.implements) {
|
|
24
|
+
if (ref.type === 'external' || contracts[ref.api]?.apiKind === 'external')
|
|
25
|
+
this.fail(`${name}: implements ${owner}#${ref.api}, an EXTERNAL_OUTBOUND contract. No server in this repo may implement an outside system's API — bind a client to it instead.`);
|
|
26
|
+
}
|
|
21
27
|
for (const ref of [...relation.implements, ...relation.uses]) {
|
|
22
28
|
if (ref.type !== 'external' &&
|
|
23
29
|
(contracts[ref.api]?.owner !== owner ||
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-targets.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/service-targets.ts"],"names":[],"mappings":"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","sourcesContent":["import { Option, RuleFailError } from '@webpieces/rules-config';\nimport type { EnhancedGraph } from '../graph-sorter';\nimport type {\n ApiContracts,\n ApiRef,\n ExternalSystemDecl,\n ExternalSystemDecls,\n} from '../api-usage/api-relations';\nimport type { RemoteService, RemoteServiceApi, RemoteServices } from '../remote-services';\n\nconst MIGRATE_CURE =\n 'Migrate canonical src/wiring.ts, tag owners webpieces/webpieces-lib, and review runtime-deps.json candidates before generation. Saved visualizations remain available.';\n\nconst REMOTE_CURE =\n 'A uses may target a workspace project\\'s metadata.webpieces.serviceName, or a service OUTSIDE this workspace declared in the reviewed remoteServices table of architecture/dependencies.json: \"remoteServices\": { \"<serviceName>\": { \"label\"?: \"<display text>\", \"implements\": [{ \"api\": \"<ApiName>\", \"type\": \"rpc\" | \"pubsub\" }] } }. Generation reads that table and never writes or infers it.';\n\n/**\n * Every approved `uses` target must answer to its name and serve what is asked of it (#1203).\n *\n * A target is either a workspace project's `metadata.webpieces.serviceName`, or a REVIEWED remote\n * service (another repo, a VM, partner endpoints) declared in dependencies.json `remoteServices`. The\n * two name spaces must not overlap: a remote name that is also a workspace serviceName or project\n * would make one name mean two services.\n */\nexport class ServiceTargetValidator {\n validate(\n graph: EnhancedGraph,\n contracts: ApiContracts,\n externalSystems: ExternalSystemDecls,\n remoteServices: RemoteServices,\n ): void {\n const hosts = this.hosts(graph);\n this.validateRemoteServices(graph, hosts, contracts, remoteServices);\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 this.validateTarget(graph, hosts, externalSystems, remoteServices, name, owner, ref);\n }\n }\n\n private validateTarget(\n graph: EnhancedGraph,\n hosts: Map<string, string>,\n externalSystems: ExternalSystemDecls,\n remoteServices: RemoteServices,\n name: string,\n owner: string,\n ref: ApiRef,\n ): void {\n const target = ref.targetService;\n if (target === undefined) return;\n if (\n Object.values(externalSystems).some((system: ExternalSystemDecl) =>\n system.apis.includes(ref.api),\n )\n )\n return;\n const provider = hosts.get(target);\n if (provider === undefined) {\n const remote = remoteServices[target];\n if (remote === undefined)\n this.fail(\n `${name}: target ${target} (for ${owner}#${ref.api} (${ref.type})) is neither a workspace serviceName nor a declared remote service in dependencies.json remoteServices.`,\n REMOTE_CURE,\n );\n this.assertRemoteImplements(name, owner, ref, target, remote);\n return;\n }\n const implemented = graph[provider].apiRelations?.[owner]?.implements;\n if (!implemented?.some((api: ApiRef) => api.api === ref.api && api.type === ref.type))\n this.fail(`${name}: target ${target} does not implement ${owner}#${ref.api} (${ref.type}).`);\n }\n\n /** serviceName -> the workspace project declaring it; a name declared twice fails. */\n private hosts(graph: EnhancedGraph): Map<string, string> {\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 return hosts;\n }\n\n /** Each declared remote is outside the workspace and implements only approved contracts. */\n private validateRemoteServices(\n graph: EnhancedGraph,\n hosts: Map<string, string>,\n contracts: ApiContracts,\n remoteServices: RemoteServices,\n ): void {\n for (const [remote, decl] of Object.entries(remoteServices)) {\n const host = hosts.get(remote);\n if (host !== undefined)\n this.fail(\n `remoteServices.${remote} collides with the workspace serviceName of ${host}: a remote service must live OUTSIDE this workspace. Remove the remoteServices entry (targets of ${remote} resolve to ${host}) or rename one of them.`,\n REMOTE_CURE,\n );\n if (graph[remote] !== undefined)\n this.fail(\n `remoteServices.${remote} collides with the workspace project ${remote}: a remote service must live OUTSIDE this workspace. Remove the remoteServices entry or rename it.`,\n REMOTE_CURE,\n );\n for (const api of decl.implements) this.assertApprovedContract(remote, api, contracts);\n }\n }\n\n private assertApprovedContract(remote: string, api: RemoteServiceApi, contracts: ApiContracts): void {\n const contract = contracts[api.api];\n if (contract === undefined)\n this.fail(\n `remoteServices.${remote}: unknown qualified contract ${api.api} (${api.type}) — no approved architecture/apis/${api.api}.json declares it.`,\n REMOTE_CURE,\n );\n if (contract.apiKind !== api.type)\n this.fail(\n `remoteServices.${remote}: unknown qualified contract ${contract.owner}#${api.api} (${api.type}) — the approved contract is ${contract.apiKind}.`,\n REMOTE_CURE,\n );\n }\n\n private assertRemoteImplements(\n user: string,\n owner: string,\n ref: ApiRef,\n target: string,\n remote: RemoteService,\n ): void {\n if (remote.implementsApi(ref.api, ref.type)) return;\n const declared = remote.implements\n .map((entry: RemoteServiceApi) => `${entry.api} (${entry.type})`)\n .join(', ');\n this.fail(\n `${user}: remote service ${target} does not implement ${owner}#${ref.api} (${ref.type}); remoteServices.${target}.implements declares only ${declared}.`,\n REMOTE_CURE,\n );\n }\n\n private fail(message: string, cure: string = MIGRATE_CURE): never {\n throw new RuleFailError('validate-runtime-architecture', message, undefined, undefined, [\n new Option(cure, true),\n ]);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"service-targets.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/service-targets.ts"],"names":[],"mappings":"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","sourcesContent":["import { Option, RuleFailError } from '@webpieces/rules-config';\nimport type { EnhancedGraph } from '../graph-sorter';\nimport type {\n ApiContracts,\n ApiRef,\n ExternalSystemDecl,\n ExternalSystemDecls,\n} from '../api-usage/api-relations';\nimport type { RemoteService, RemoteServiceApi, RemoteServices } from '../remote-services';\n\nconst MIGRATE_CURE =\n 'Migrate canonical src/wiring.ts, tag owners webpieces/webpieces-lib, and review runtime-deps.json candidates before generation. Saved visualizations remain available.';\n\nconst REMOTE_CURE =\n 'A uses may target a workspace project\\'s metadata.webpieces.serviceName, or a service OUTSIDE this workspace declared in the reviewed remoteServices table of architecture/dependencies.json: \"remoteServices\": { \"<serviceName>\": { \"label\"?: \"<display text>\", \"implements\": [{ \"api\": \"<ApiName>\", \"type\": \"rpc\" | \"pubsub\" }] } }. Generation reads that table and never writes or infers it.';\n\n/**\n * Every approved `uses` target must answer to its name and serve what is asked of it (#1203).\n *\n * A target is either a workspace project's `metadata.webpieces.serviceName`, or a REVIEWED remote\n * service (another repo, a VM, partner endpoints) declared in dependencies.json `remoteServices`. The\n * two name spaces must not overlap: a remote name that is also a workspace serviceName or project\n * would make one name mean two services.\n */\nexport class ServiceTargetValidator {\n validate(\n graph: EnhancedGraph,\n contracts: ApiContracts,\n externalSystems: ExternalSystemDecls,\n remoteServices: RemoteServices,\n ): void {\n const hosts = this.hosts(graph);\n this.validateRemoteServices(graph, hosts, contracts, remoteServices);\n for (const [name, entry] of Object.entries(graph))\n for (const [owner, relation] of Object.entries(entry.apiRelations ?? {})) {\n // An EXTERNAL_OUTBOUND contract (apiKind 'external') is an outside system's API: a\n // workspace project that implements it would be a server of ours answering for a vendor.\n for (const ref of relation.implements) {\n if (ref.type === 'external' || contracts[ref.api]?.apiKind === 'external')\n this.fail(\n `${name}: implements ${owner}#${ref.api}, an EXTERNAL_OUTBOUND contract. No server in this repo may implement an outside system's API — bind a client to it instead.`,\n );\n }\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 this.validateTarget(graph, hosts, externalSystems, remoteServices, name, owner, ref);\n }\n }\n\n private validateTarget(\n graph: EnhancedGraph,\n hosts: Map<string, string>,\n externalSystems: ExternalSystemDecls,\n remoteServices: RemoteServices,\n name: string,\n owner: string,\n ref: ApiRef,\n ): void {\n const target = ref.targetService;\n if (target === undefined) return;\n if (\n Object.values(externalSystems).some((system: ExternalSystemDecl) =>\n system.apis.includes(ref.api),\n )\n )\n return;\n const provider = hosts.get(target);\n if (provider === undefined) {\n const remote = remoteServices[target];\n if (remote === undefined)\n this.fail(\n `${name}: target ${target} (for ${owner}#${ref.api} (${ref.type})) is neither a workspace serviceName nor a declared remote service in dependencies.json remoteServices.`,\n REMOTE_CURE,\n );\n this.assertRemoteImplements(name, owner, ref, target, remote);\n return;\n }\n const implemented = graph[provider].apiRelations?.[owner]?.implements;\n if (!implemented?.some((api: ApiRef) => api.api === ref.api && api.type === ref.type))\n this.fail(`${name}: target ${target} does not implement ${owner}#${ref.api} (${ref.type}).`);\n }\n\n /** serviceName -> the workspace project declaring it; a name declared twice fails. */\n private hosts(graph: EnhancedGraph): Map<string, string> {\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 return hosts;\n }\n\n /** Each declared remote is outside the workspace and implements only approved contracts. */\n private validateRemoteServices(\n graph: EnhancedGraph,\n hosts: Map<string, string>,\n contracts: ApiContracts,\n remoteServices: RemoteServices,\n ): void {\n for (const [remote, decl] of Object.entries(remoteServices)) {\n const host = hosts.get(remote);\n if (host !== undefined)\n this.fail(\n `remoteServices.${remote} collides with the workspace serviceName of ${host}: a remote service must live OUTSIDE this workspace. Remove the remoteServices entry (targets of ${remote} resolve to ${host}) or rename one of them.`,\n REMOTE_CURE,\n );\n if (graph[remote] !== undefined)\n this.fail(\n `remoteServices.${remote} collides with the workspace project ${remote}: a remote service must live OUTSIDE this workspace. Remove the remoteServices entry or rename it.`,\n REMOTE_CURE,\n );\n for (const api of decl.implements) this.assertApprovedContract(remote, api, contracts);\n }\n }\n\n private assertApprovedContract(remote: string, api: RemoteServiceApi, contracts: ApiContracts): void {\n const contract = contracts[api.api];\n if (contract === undefined)\n this.fail(\n `remoteServices.${remote}: unknown qualified contract ${api.api} (${api.type}) — no approved architecture/apis/${api.api}.json declares it.`,\n REMOTE_CURE,\n );\n if (contract.apiKind !== api.type)\n this.fail(\n `remoteServices.${remote}: unknown qualified contract ${contract.owner}#${api.api} (${api.type}) — the approved contract is ${contract.apiKind}.`,\n REMOTE_CURE,\n );\n }\n\n private assertRemoteImplements(\n user: string,\n owner: string,\n ref: ApiRef,\n target: string,\n remote: RemoteService,\n ): void {\n if (remote.implementsApi(ref.api, ref.type)) return;\n const declared = remote.implements\n .map((entry: RemoteServiceApi) => `${entry.api} (${entry.type})`)\n .join(', ');\n this.fail(\n `${user}: remote service ${target} does not implement ${owner}#${ref.api} (${ref.type}); remoteServices.${target}.implements declares only ${declared}.`,\n REMOTE_CURE,\n );\n }\n\n private fail(message: string, cure: string = MIGRATE_CURE): never {\n throw new RuleFailError('validate-runtime-architecture', message, undefined, undefined, [\n new Option(cure, true),\n ]);\n }\n}\n"]}
|
|
@@ -31,6 +31,11 @@ export declare class WiringSourceExtractor {
|
|
|
31
31
|
*/
|
|
32
32
|
private recordExternal;
|
|
33
33
|
private recordRelationship;
|
|
34
|
+
/**
|
|
35
|
+
* An EXTERNAL_OUTBOUND contract — an outside system's API. A client bound to it is a `uses` edge
|
|
36
|
+
* to a VENDOR node, never to a service of ours, and no server in this repo may implement it.
|
|
37
|
+
*/
|
|
38
|
+
private recordExternalOutbound;
|
|
34
39
|
private frameworkCall;
|
|
35
40
|
private recordWiring;
|
|
36
41
|
private moduleSelections;
|
|
@@ -97,6 +97,10 @@ class WiringSourceExtractor {
|
|
|
97
97
|
const contract = this.values.identity(api);
|
|
98
98
|
const direction = method === 'addRoutes' ? 'implements' : 'uses';
|
|
99
99
|
const contractTransport = this.values.transport(api);
|
|
100
|
+
if (contractTransport === 'external') {
|
|
101
|
+
this.recordExternalOutbound(call, method, owner, contract);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
100
104
|
const transport = method === 'addRoutes'
|
|
101
105
|
? contractTransport
|
|
102
106
|
: method === 'createPubSubClientAndBind' || method === 'createPubSubClient'
|
|
@@ -113,6 +117,22 @@ class WiringSourceExtractor {
|
|
|
113
117
|
: new declaration_1.UsesFacts(transport, target, this.values.condition(call))));
|
|
114
118
|
this.exported[owner] = exported;
|
|
115
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* An EXTERNAL_OUTBOUND contract — an outside system's API. A client bound to it is a `uses` edge
|
|
122
|
+
* to a VENDOR node, never to a service of ours, and no server in this repo may implement it.
|
|
123
|
+
*/
|
|
124
|
+
recordExternalOutbound(call, method, owner, contract) {
|
|
125
|
+
if (method === 'addRoutes')
|
|
126
|
+
this.fail(`${contract.project}#${contract.exportedName} is EXTERNAL_OUTBOUND — an outside system's API — so no server in this repo may addRoutes it. Bind a client to it, or change its endpoints to RPC / EXTERNAL_INBOUND.`);
|
|
127
|
+
if (method === 'createPubSubClientAndBind' || method === 'createPubSubClient')
|
|
128
|
+
this.fail(`${contract.project}#${contract.exportedName} is EXTERNAL_OUTBOUND, a synchronous outside API; bind it with createRpcClientAndBind.`);
|
|
129
|
+
const exported = this.exported[owner];
|
|
130
|
+
exported.relationships.push(new declaration_1.WiringRelationship(contract, new declaration_1.UsesFacts('external', {
|
|
131
|
+
kind: 'unknown',
|
|
132
|
+
reason: 'EXTERNAL_OUTBOUND contract; destination classified by approved contract metadata',
|
|
133
|
+
}, this.values.condition(call))));
|
|
134
|
+
this.exported[owner] = exported;
|
|
135
|
+
}
|
|
116
136
|
frameworkCall(call) {
|
|
117
137
|
const declaration = this.program.getTypeChecker().getResolvedSignature(call)?.declaration;
|
|
118
138
|
if (declaration === undefined)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-extractor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/source-extractor.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport * as ts from 'typescript';\nimport { Option, RuleFailError } from '@webpieces/rules-config';\nimport type { ProjectInfo } from '../project-info';\nimport { createProjectProgram } from '../di-graph/program';\nimport {\n ContractIdentity,\n ImplementsFacts,\n UsesFacts,\n RuntimeDeclaration,\n WiringExport,\n WiringRelationship,\n WiringSelection,\n} from './declaration';\nimport { WiringSourceValues } from './source-values';\nimport { WiringSourceTypes } from './source-types';\nimport type { WiringKind } from './source-types';\nimport * as fs from 'fs';\n\n/** Build-only extraction. It never imports application modules or invokes their constructors. */\nclass WiringProjectMetadata {\n declare metadata?: WiringProjectMetadataValues;\n}\nclass WiringProjectMetadataValues {\n declare webpieces?: WiringServiceMetadata;\n}\nclass WiringServiceMetadata {\n declare serviceName?: string;\n}\n\nexport class WiringSourceExtractor {\n private readonly values: WiringSourceValues;\n private readonly exported: Record<string, WiringExport> = {};\n private entry: string | undefined;\n private host: string | undefined;\n\n constructor(\n private readonly workspaceRoot: string,\n private readonly info: ProjectInfo,\n private readonly infos: ReadonlyMap<string, ProjectInfo>,\n private readonly program: ts.Program,\n ) {\n this.values = new WiringSourceValues(workspaceRoot, infos, program.getTypeChecker());\n }\n\n /**\n * Reads ONLY the owner's canonical src/wiring.ts. The program still type-checks every file so\n * imports, aliases and re-exports resolve, but no other file's body is visited for wiring facts:\n * a module declared elsewhere can neither add a relationship nor be discovered as a fallback.\n */\n extract(): RuntimeDeclaration {\n const wiring = this.program.getSourceFile(this.wiringPath);\n if (wiring === undefined) this.fail(`Missing canonical ${this.wiringPath}.`);\n for (const statement of wiring!.statements)\n if (ts.isClassDeclaration(statement)) this.recordWiring(statement);\n const framework = this.info.tags.includes('framework:angular')\n ? 'angular'\n : this.info.tags.some((tag) => tag === 'framework:node' || tag === 'framework:express')\n ? 'node'\n : 'browser';\n if (this.info.tags.includes('webpieces') && this.entry === undefined)\n this.fail(`${this.info.name} requires one unambiguous exported AppWiring in src/wiring.ts.`);\n return new RuntimeDeclaration(\n this.info.name,\n framework,\n this.exported,\n this.entry,\n this.host,\n );\n }\n\n /**\n * The registration forms that carry graph facts: binder.createRpcClientAndBind /\n * createPubSubClientAndBind / bindExternal and router.addRoutes (plus the factory calls they wrap).\n */\n private facts(node: ts.Node, owner: string): void {\n if (ts.isCallExpression(node) && this.frameworkCall(node)) {\n const name = this.values.symbolName(node.expression);\n if (name === 'bindExternal') this.recordExternal(node, owner);\n else if (['addRoutes', 'createRpcClient', 'createPubSubClient', 'createRpcClientAndBind', 'createPubSubClientAndBind'].includes(name))\n this.recordRelationship(node, name, owner);\n }\n ts.forEachChild(node, (child: ts.Node) => this.facts(child, owner));\n }\n\n /**\n * binder.bindExternal(Api, VendorImpl) — browser: binder.bindExternal(Api, new UseClass(V)\n * | new UseExisting(T)), recognized by the same name: the vendor contract's identity comes from the resolved\n * symbol, exactly like any other API. An APPLICATION owner must also prove a production business\n * consumer of it; a library module binds an adapter for whichever app selects it, so its\n * consumer lives in that app.\n */\n private recordExternal(call: ts.CallExpression, owner: string): void {\n const api = call.arguments[0];\n if (api === undefined || call.arguments[1] === undefined)\n this.fail('bindExternal requires the external API contract and its vendor implementation.');\n const contract = this.values.identity(api!);\n if (\n this.info.tags.includes('webpieces') &&\n !this.values.hasExternalConsumer(this.info.name, contract.project, contract.exportedName, this.program)\n )\n this.fail(\n `${contract.project}#${contract.exportedName} has no production business consumer in ${this.info.name}; adapters and test doubles do not establish uses.`,\n );\n const exported = this.exported[owner];\n exported.relationships.push(\n new WiringRelationship(\n contract,\n new UsesFacts('external', {\n kind: 'unknown',\n reason: 'Vendor interface; destination classified by approved contract metadata',\n }),\n ),\n );\n this.exported[owner] = exported;\n }\n\n private recordRelationship(call: ts.CallExpression, method: string, owner: string): void {\n const api = call.arguments[0];\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 === 'createPubSubClientAndBind' || 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[1]);\n const exported = this.exported[owner];\n exported.relationships.push(\n new WiringRelationship(\n contract,\n direction === 'implements'\n ? new ImplementsFacts(transport, this.values.condition(call))\n : new UsesFacts(transport, target!, this.values.condition(call)),\n ),\n );\n this.exported[owner] = exported;\n }\n\n private frameworkCall(call: ts.CallExpression): boolean {\n const declaration = this.program.getTypeChecker().getResolvedSignature(call)?.declaration;\n if (declaration === undefined) return false;\n const file = declaration.getSourceFile().fileName.replace(/\\\\/g, '/');\n return /(?:\\/packages\\/(?:http|cloud)\\/|\\/node_modules\\/@webpieces\\/)(?:http-routing|http-client-node|http-client-browser|cloudtasks-client)\\//.test(file);\n }\n\n private recordWiring(declaration: ts.ClassDeclaration): void {\n const types = new WiringSourceTypes(this.program.getTypeChecker());\n const kind = types.kind(declaration);\n const owner = this.exportOwner(declaration);\n if (kind === undefined || owner === undefined) return;\n if (kind === 'binding' || kind === 'routing') {\n this.exported[owner] = new WiringExport(kind, [], []);\n const configure = types.method(declaration, 'configure');\n if (configure === undefined || configure.body === undefined)\n this.fail(`${owner}: named module requires a statically resolvable configure implementation.`);\n if (path.resolve(configure!.getSourceFile().fileName) !== this.wiringPath)\n this.fail(`${owner}: configure is inherited from ${configure!.getSourceFile().fileName}; declare its registrations in ${owner}.configure in ${this.wiringPath}.`);\n this.facts(configure!.body!, owner);\n return;\n }\n const bindings = this.moduleSelections(owner, types.method(declaration, 'getBindModules'), 'binding', kind);\n // The browser has no route channel; a Node Wiring's getRouteModules is required by its type.\n const routeGetter = types.method(declaration, 'getRouteModules');\n const routes = routeGetter === undefined ? [] : this.moduleSelections(owner, routeGetter, 'routing', kind);\n const libraries = kind === 'app' ? this.moduleSelections(owner, types.method(declaration, 'getWirings'), 'wiring', kind) : [];\n if (kind === 'wiring' && types.method(declaration, 'getWirings') !== undefined)\n this.fail(`${owner}: library Wiring cannot select other Wirings.`);\n this.exported[owner] = new WiringExport(kind, [], bindings, routes, libraries);\n if (kind !== 'app') return;\n if (!this.info.tags.includes('webpieces'))\n this.fail(`${owner}: library owners cannot declare an AppWiring entry.`);\n if (this.entry !== undefined) this.fail('Ambiguous AppWiring root; export exactly one application entry.');\n this.entry = owner;\n const projectFile = path.join(this.workspaceRoot, this.info.root, 'project.json');\n if (fs.existsSync(projectFile)) {\n const project = JSON.parse(fs.readFileSync(projectFile, 'utf8')) as WiringProjectMetadata;\n this.host = project.metadata?.webpieces?.serviceName;\n }\n }\n\n private moduleSelections(owner: string, method: ts.MethodDeclaration | undefined, expected: 'binding' | 'routing' | 'wiring', ownerKind: WiringKind): WiringSelection[] {\n if (method !== undefined && path.resolve(method.getSourceFile().fileName) !== this.wiringPath)\n this.fail(`${owner}: its selection getter is declared in ${method.getSourceFile().fileName}; declare getBindModules/getRouteModules/getWirings on ${owner} itself in ${this.wiringPath}.`);\n const statements = method?.body?.statements;\n const expression = statements?.length === 1 && ts.isReturnStatement(statements[0]) ? statements[0].expression : undefined;\n if (expression === undefined || !ts.isArrayLiteralExpression(expression))\n this.fail(`Expected ${expected} getter to contain only return [new NamedModule(preparedInputs)].`);\n const types = new WiringSourceTypes(this.program.getTypeChecker());\n return expression.elements.map((element: ts.Expression) => {\n if (!ts.isNewExpression(element) || types.kind(element.expression) !== expected)\n this.fail(`Wrong ${expected} selection ${element.getText()}; AppWiring children, delegation and nested lists are forbidden.`);\n const identity = this.values.identity(element.expression);\n this.assertCanonicalDeclaration(owner, element.expression, identity, expected, ownerKind);\n return new WiringSelection(identity.project, identity.exportedName, this.values.arguments(element), this.values.policies(element));\n });\n }\n\n /**\n * OWNER-canonical: a selected module is declared in THIS wiring.ts, or - for a BindModule an\n * AppWiring selects, and for a library Wiring - in its library owner's canonical src/wiring.ts.\n * Proven by the resolved declaration (so a re-export resolves to its true file), never by a name,\n * and checked before any argument analysis, so an off-file module body is never read.\n */\n private assertCanonicalDeclaration(\n owner: string,\n selected: ts.Expression,\n identity: ContractIdentity,\n expected: 'binding' | 'routing' | 'wiring',\n ownerKind: WiringKind,\n ): void {\n const declaration = new WiringSourceTypes(this.program.getTypeChecker()).declaration(selected);\n const declaredIn = declaration === undefined ? 'an unresolved file' : path.resolve(declaration.getSourceFile().fileName);\n if (declaredIn === this.wiringPath && expected !== 'wiring') return;\n const library = this.infos.get(identity.project);\n const canonical = library === undefined ? undefined : path.resolve(this.workspaceRoot, library.root, 'src/wiring.ts');\n const fromLibrary = identity.project !== this.info.name && canonical !== undefined && declaredIn === canonical;\n if (expected === 'wiring' && fromLibrary) return;\n if (expected === 'binding' && ownerKind === 'app' && fromLibrary) return;\n if (expected === 'wiring')\n this.fail(\n `${owner} selects library Wiring ${identity.project}#${identity.exportedName}, which is declared in ${declaredIn}. A library Wiring and its modules belong in that library's canonical ${canonical ?? 'src/wiring.ts'}.`,\n );\n const role = expected === 'binding' ? 'BindModule' : 'RouteModule';\n const where = expected === 'binding' && ownerKind === 'app'\n ? ` beside ${owner} in ${this.wiringPath}, or in its library owner's canonical src/wiring.ts`\n : ` beside ${owner} in ${this.wiringPath}`;\n this.fail(\n `${owner} selects ${identity.exportedName}, which is declared in ${declaredIn}. Declare the ${role} class ${identity.exportedName}, with its registrations,${where}; a ContainerModule or a class in any other file is never a module.`,\n );\n }\n\n private exportOwner(node: ts.Node): string | undefined {\n let current: ts.Node | undefined = node;\n while (current !== undefined) {\n if (\n ts.isClassDeclaration(current) &&\n current.name !== undefined &&\n (ts.getModifiers(current) ?? []).some(\n (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword,\n )\n )\n return current.name.text;\n if (\n ts.isFunctionDeclaration(current) &&\n current.name !== undefined &&\n (ts.getModifiers(current) ?? []).some(\n (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword,\n )\n )\n return current.name.text;\n if (ts.isVariableDeclaration(current) && ts.isIdentifier(current.name)) {\n const statement = current.parent.parent;\n if (\n ts.isVariableStatement(statement) &&\n (ts.getModifiers(statement) ?? []).some(\n (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword,\n )\n )\n return current.name.text;\n }\n current = current.parent;\n }\n return undefined;\n }\n\n private get wiringPath(): string {\n return path.resolve(this.workspaceRoot, this.info.root, 'src/wiring.ts');\n }\n\n private fail(message: string): never {\n throw new RuleFailError('validate-runtime-architecture', message, undefined, undefined, [\n new Option(\n 'Declare each owner\\'s Wiring/AppWiring class AND its BindModule/RouteModule classes, with their registrations (binder.createRpcClientAndBind(Api, deployment), binder.createPubSubClientAndBind, binder.bindExternal(Api, VendorImpl) or the browser binder.bindExternal(Api, new UseClass(Vendor) | new UseExisting(Token)), binder.bind chains, browser binder.provide recipes, router.addRoutes/addFilter), together in that owner\\'s canonical src/wiring.ts (an app may also select a BindModule from a library owner\\'s canonical src/wiring.ts), and use the documented getter grammar (getBindModules/getRouteModules/getWirings); extraction reads only canonical wiring.ts files and never executes configuration.',\n true,\n ),\n ]);\n }\n}\n\n/** Factory kept separate so graph assembly cannot accidentally create a compiler. */\nexport class WiringProjectProgram {\n create(workspaceRoot: string, info: ProjectInfo): ts.Program {\n const root = path.resolve(workspaceRoot, info.root);\n const configured = createProjectProgram(root);\n if (configured !== null) return configured;\n const config = ts.findConfigFile(root, ts.sys.fileExists, 'tsconfig.json');\n const parsed =\n config === undefined ? undefined : ts.readConfigFile(config, ts.sys.readFile);\n const options =\n parsed === undefined\n ? {}\n : ts.parseJsonConfigFileContent(parsed.config, ts.sys, root).options;\n const files = ts.sys.readDirectory(\n path.join(root, 'src'),\n ['.ts'],\n ['**/*.spec.ts', '**/*.test.ts'],\n );\n return ts.createProgram(files, options);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"source-extractor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/runtime-wiring/source-extractor.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport * as ts from 'typescript';\nimport { Option, RuleFailError } from '@webpieces/rules-config';\nimport type { ProjectInfo } from '../project-info';\nimport { createProjectProgram } from '../di-graph/program';\nimport {\n ContractIdentity,\n ImplementsFacts,\n UsesFacts,\n RuntimeDeclaration,\n WiringExport,\n WiringRelationship,\n WiringSelection,\n} from './declaration';\nimport { WiringSourceValues } from './source-values';\nimport { WiringSourceTypes } from './source-types';\nimport type { WiringKind } from './source-types';\nimport * as fs from 'fs';\n\n/** Build-only extraction. It never imports application modules or invokes their constructors. */\nclass WiringProjectMetadata {\n declare metadata?: WiringProjectMetadataValues;\n}\nclass WiringProjectMetadataValues {\n declare webpieces?: WiringServiceMetadata;\n}\nclass WiringServiceMetadata {\n declare serviceName?: string;\n}\n\nexport class WiringSourceExtractor {\n private readonly values: WiringSourceValues;\n private readonly exported: Record<string, WiringExport> = {};\n private entry: string | undefined;\n private host: string | undefined;\n\n constructor(\n private readonly workspaceRoot: string,\n private readonly info: ProjectInfo,\n private readonly infos: ReadonlyMap<string, ProjectInfo>,\n private readonly program: ts.Program,\n ) {\n this.values = new WiringSourceValues(workspaceRoot, infos, program.getTypeChecker());\n }\n\n /**\n * Reads ONLY the owner's canonical src/wiring.ts. The program still type-checks every file so\n * imports, aliases and re-exports resolve, but no other file's body is visited for wiring facts:\n * a module declared elsewhere can neither add a relationship nor be discovered as a fallback.\n */\n extract(): RuntimeDeclaration {\n const wiring = this.program.getSourceFile(this.wiringPath);\n if (wiring === undefined) this.fail(`Missing canonical ${this.wiringPath}.`);\n for (const statement of wiring!.statements)\n if (ts.isClassDeclaration(statement)) this.recordWiring(statement);\n const framework = this.info.tags.includes('framework:angular')\n ? 'angular'\n : this.info.tags.some((tag) => tag === 'framework:node' || tag === 'framework:express')\n ? 'node'\n : 'browser';\n if (this.info.tags.includes('webpieces') && this.entry === undefined)\n this.fail(`${this.info.name} requires one unambiguous exported AppWiring in src/wiring.ts.`);\n return new RuntimeDeclaration(\n this.info.name,\n framework,\n this.exported,\n this.entry,\n this.host,\n );\n }\n\n /**\n * The registration forms that carry graph facts: binder.createRpcClientAndBind /\n * createPubSubClientAndBind / bindExternal and router.addRoutes (plus the factory calls they wrap).\n */\n private facts(node: ts.Node, owner: string): void {\n if (ts.isCallExpression(node) && this.frameworkCall(node)) {\n const name = this.values.symbolName(node.expression);\n if (name === 'bindExternal') this.recordExternal(node, owner);\n else if (['addRoutes', 'createRpcClient', 'createPubSubClient', 'createRpcClientAndBind', 'createPubSubClientAndBind'].includes(name))\n this.recordRelationship(node, name, owner);\n }\n ts.forEachChild(node, (child: ts.Node) => this.facts(child, owner));\n }\n\n /**\n * binder.bindExternal(Api, VendorImpl) — browser: binder.bindExternal(Api, new UseClass(V)\n * | new UseExisting(T)), recognized by the same name: the vendor contract's identity comes from the resolved\n * symbol, exactly like any other API. An APPLICATION owner must also prove a production business\n * consumer of it; a library module binds an adapter for whichever app selects it, so its\n * consumer lives in that app.\n */\n private recordExternal(call: ts.CallExpression, owner: string): void {\n const api = call.arguments[0];\n if (api === undefined || call.arguments[1] === undefined)\n this.fail('bindExternal requires the external API contract and its vendor implementation.');\n const contract = this.values.identity(api!);\n if (\n this.info.tags.includes('webpieces') &&\n !this.values.hasExternalConsumer(this.info.name, contract.project, contract.exportedName, this.program)\n )\n this.fail(\n `${contract.project}#${contract.exportedName} has no production business consumer in ${this.info.name}; adapters and test doubles do not establish uses.`,\n );\n const exported = this.exported[owner];\n exported.relationships.push(\n new WiringRelationship(\n contract,\n new UsesFacts('external', {\n kind: 'unknown',\n reason: 'Vendor interface; destination classified by approved contract metadata',\n }),\n ),\n );\n this.exported[owner] = exported;\n }\n\n private recordRelationship(call: ts.CallExpression, method: string, owner: string): void {\n const api = call.arguments[0];\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 if (contractTransport === 'external') {\n this.recordExternalOutbound(call, method, owner, contract);\n return;\n }\n const transport =\n method === 'addRoutes'\n ? contractTransport\n : method === 'createPubSubClientAndBind' || 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[1]);\n const exported = this.exported[owner];\n exported.relationships.push(\n new WiringRelationship(\n contract,\n direction === 'implements'\n ? new ImplementsFacts(transport, this.values.condition(call))\n : new UsesFacts(transport, target!, this.values.condition(call)),\n ),\n );\n this.exported[owner] = exported;\n }\n\n /**\n * An EXTERNAL_OUTBOUND contract — an outside system's API. A client bound to it is a `uses` edge\n * to a VENDOR node, never to a service of ours, and no server in this repo may implement it.\n */\n private recordExternalOutbound(\n call: ts.CallExpression,\n method: string,\n owner: string,\n contract: ContractIdentity,\n ): void {\n if (method === 'addRoutes')\n this.fail(\n `${contract.project}#${contract.exportedName} is EXTERNAL_OUTBOUND — an outside system's API — so no server in this repo may addRoutes it. Bind a client to it, or change its endpoints to RPC / EXTERNAL_INBOUND.`,\n );\n if (method === 'createPubSubClientAndBind' || method === 'createPubSubClient')\n this.fail(\n `${contract.project}#${contract.exportedName} is EXTERNAL_OUTBOUND, a synchronous outside API; bind it with createRpcClientAndBind.`,\n );\n const exported = this.exported[owner];\n exported.relationships.push(\n new WiringRelationship(\n contract,\n new UsesFacts(\n 'external',\n {\n kind: 'unknown',\n reason: 'EXTERNAL_OUTBOUND contract; destination classified by approved contract metadata',\n },\n this.values.condition(call),\n ),\n ),\n );\n this.exported[owner] = exported;\n }\n\n private frameworkCall(call: ts.CallExpression): boolean {\n const declaration = this.program.getTypeChecker().getResolvedSignature(call)?.declaration;\n if (declaration === undefined) return false;\n const file = declaration.getSourceFile().fileName.replace(/\\\\/g, '/');\n return /(?:\\/packages\\/(?:http|cloud)\\/|\\/node_modules\\/@webpieces\\/)(?:http-routing|http-client-node|http-client-browser|cloudtasks-client)\\//.test(file);\n }\n\n private recordWiring(declaration: ts.ClassDeclaration): void {\n const types = new WiringSourceTypes(this.program.getTypeChecker());\n const kind = types.kind(declaration);\n const owner = this.exportOwner(declaration);\n if (kind === undefined || owner === undefined) return;\n if (kind === 'binding' || kind === 'routing') {\n this.exported[owner] = new WiringExport(kind, [], []);\n const configure = types.method(declaration, 'configure');\n if (configure === undefined || configure.body === undefined)\n this.fail(`${owner}: named module requires a statically resolvable configure implementation.`);\n if (path.resolve(configure!.getSourceFile().fileName) !== this.wiringPath)\n this.fail(`${owner}: configure is inherited from ${configure!.getSourceFile().fileName}; declare its registrations in ${owner}.configure in ${this.wiringPath}.`);\n this.facts(configure!.body!, owner);\n return;\n }\n const bindings = this.moduleSelections(owner, types.method(declaration, 'getBindModules'), 'binding', kind);\n // The browser has no route channel; a Node Wiring's getRouteModules is required by its type.\n const routeGetter = types.method(declaration, 'getRouteModules');\n const routes = routeGetter === undefined ? [] : this.moduleSelections(owner, routeGetter, 'routing', kind);\n const libraries = kind === 'app' ? this.moduleSelections(owner, types.method(declaration, 'getWirings'), 'wiring', kind) : [];\n if (kind === 'wiring' && types.method(declaration, 'getWirings') !== undefined)\n this.fail(`${owner}: library Wiring cannot select other Wirings.`);\n this.exported[owner] = new WiringExport(kind, [], bindings, routes, libraries);\n if (kind !== 'app') return;\n if (!this.info.tags.includes('webpieces'))\n this.fail(`${owner}: library owners cannot declare an AppWiring entry.`);\n if (this.entry !== undefined) this.fail('Ambiguous AppWiring root; export exactly one application entry.');\n this.entry = owner;\n const projectFile = path.join(this.workspaceRoot, this.info.root, 'project.json');\n if (fs.existsSync(projectFile)) {\n const project = JSON.parse(fs.readFileSync(projectFile, 'utf8')) as WiringProjectMetadata;\n this.host = project.metadata?.webpieces?.serviceName;\n }\n }\n\n private moduleSelections(owner: string, method: ts.MethodDeclaration | undefined, expected: 'binding' | 'routing' | 'wiring', ownerKind: WiringKind): WiringSelection[] {\n if (method !== undefined && path.resolve(method.getSourceFile().fileName) !== this.wiringPath)\n this.fail(`${owner}: its selection getter is declared in ${method.getSourceFile().fileName}; declare getBindModules/getRouteModules/getWirings on ${owner} itself in ${this.wiringPath}.`);\n const statements = method?.body?.statements;\n const expression = statements?.length === 1 && ts.isReturnStatement(statements[0]) ? statements[0].expression : undefined;\n if (expression === undefined || !ts.isArrayLiteralExpression(expression))\n this.fail(`Expected ${expected} getter to contain only return [new NamedModule(preparedInputs)].`);\n const types = new WiringSourceTypes(this.program.getTypeChecker());\n return expression.elements.map((element: ts.Expression) => {\n if (!ts.isNewExpression(element) || types.kind(element.expression) !== expected)\n this.fail(`Wrong ${expected} selection ${element.getText()}; AppWiring children, delegation and nested lists are forbidden.`);\n const identity = this.values.identity(element.expression);\n this.assertCanonicalDeclaration(owner, element.expression, identity, expected, ownerKind);\n return new WiringSelection(identity.project, identity.exportedName, this.values.arguments(element), this.values.policies(element));\n });\n }\n\n /**\n * OWNER-canonical: a selected module is declared in THIS wiring.ts, or - for a BindModule an\n * AppWiring selects, and for a library Wiring - in its library owner's canonical src/wiring.ts.\n * Proven by the resolved declaration (so a re-export resolves to its true file), never by a name,\n * and checked before any argument analysis, so an off-file module body is never read.\n */\n private assertCanonicalDeclaration(\n owner: string,\n selected: ts.Expression,\n identity: ContractIdentity,\n expected: 'binding' | 'routing' | 'wiring',\n ownerKind: WiringKind,\n ): void {\n const declaration = new WiringSourceTypes(this.program.getTypeChecker()).declaration(selected);\n const declaredIn = declaration === undefined ? 'an unresolved file' : path.resolve(declaration.getSourceFile().fileName);\n if (declaredIn === this.wiringPath && expected !== 'wiring') return;\n const library = this.infos.get(identity.project);\n const canonical = library === undefined ? undefined : path.resolve(this.workspaceRoot, library.root, 'src/wiring.ts');\n const fromLibrary = identity.project !== this.info.name && canonical !== undefined && declaredIn === canonical;\n if (expected === 'wiring' && fromLibrary) return;\n if (expected === 'binding' && ownerKind === 'app' && fromLibrary) return;\n if (expected === 'wiring')\n this.fail(\n `${owner} selects library Wiring ${identity.project}#${identity.exportedName}, which is declared in ${declaredIn}. A library Wiring and its modules belong in that library's canonical ${canonical ?? 'src/wiring.ts'}.`,\n );\n const role = expected === 'binding' ? 'BindModule' : 'RouteModule';\n const where = expected === 'binding' && ownerKind === 'app'\n ? ` beside ${owner} in ${this.wiringPath}, or in its library owner's canonical src/wiring.ts`\n : ` beside ${owner} in ${this.wiringPath}`;\n this.fail(\n `${owner} selects ${identity.exportedName}, which is declared in ${declaredIn}. Declare the ${role} class ${identity.exportedName}, with its registrations,${where}; a ContainerModule or a class in any other file is never a module.`,\n );\n }\n\n private exportOwner(node: ts.Node): string | undefined {\n let current: ts.Node | undefined = node;\n while (current !== undefined) {\n if (\n ts.isClassDeclaration(current) &&\n current.name !== undefined &&\n (ts.getModifiers(current) ?? []).some(\n (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword,\n )\n )\n return current.name.text;\n if (\n ts.isFunctionDeclaration(current) &&\n current.name !== undefined &&\n (ts.getModifiers(current) ?? []).some(\n (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword,\n )\n )\n return current.name.text;\n if (ts.isVariableDeclaration(current) && ts.isIdentifier(current.name)) {\n const statement = current.parent.parent;\n if (\n ts.isVariableStatement(statement) &&\n (ts.getModifiers(statement) ?? []).some(\n (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword,\n )\n )\n return current.name.text;\n }\n current = current.parent;\n }\n return undefined;\n }\n\n private get wiringPath(): string {\n return path.resolve(this.workspaceRoot, this.info.root, 'src/wiring.ts');\n }\n\n private fail(message: string): never {\n throw new RuleFailError('validate-runtime-architecture', message, undefined, undefined, [\n new Option(\n 'Declare each owner\\'s Wiring/AppWiring class AND its BindModule/RouteModule classes, with their registrations (binder.createRpcClientAndBind(Api, deployment), binder.createPubSubClientAndBind, binder.bindExternal(Api, VendorImpl) or the browser binder.bindExternal(Api, new UseClass(Vendor) | new UseExisting(Token)), binder.bind chains, browser binder.provide recipes, router.addRoutes/addFilter), together in that owner\\'s canonical src/wiring.ts (an app may also select a BindModule from a library owner\\'s canonical src/wiring.ts), and use the documented getter grammar (getBindModules/getRouteModules/getWirings); extraction reads only canonical wiring.ts files and never executes configuration.',\n true,\n ),\n ]);\n }\n}\n\n/** Factory kept separate so graph assembly cannot accidentally create a compiler. */\nexport class WiringProjectProgram {\n create(workspaceRoot: string, info: ProjectInfo): ts.Program {\n const root = path.resolve(workspaceRoot, info.root);\n const configured = createProjectProgram(root);\n if (configured !== null) return configured;\n const config = ts.findConfigFile(root, ts.sys.fileExists, 'tsconfig.json');\n const parsed =\n config === undefined ? undefined : ts.readConfigFile(config, ts.sys.readFile);\n const options =\n parsed === undefined\n ? {}\n : ts.parseJsonConfigFileContent(parsed.config, ts.sys, root).options;\n const files = ts.sys.readDirectory(\n path.join(root, 'src'),\n ['.ts'],\n ['**/*.spec.ts', '**/*.test.ts'],\n );\n return ts.createProgram(files, options);\n }\n}\n"]}
|
|
@@ -11,7 +11,12 @@ export declare class WiringSourceValues {
|
|
|
11
11
|
symbolName(node: ts.Node): string;
|
|
12
12
|
identity(node: ts.Node): ContractIdentity;
|
|
13
13
|
target(expression: ts.Expression | undefined, depth?: number): DeclaredTarget;
|
|
14
|
-
transport(expression: ts.Expression): 'rpc' | 'pubsub';
|
|
14
|
+
transport(expression: ts.Expression): 'rpc' | 'pubsub' | 'external';
|
|
15
|
+
/**
|
|
16
|
+
* True when every `@Endpoint` of the contract declares `EXTERNAL_OUTBOUND` (its 4th argument): an
|
|
17
|
+
* outside system's API, which a client reaches as a VENDOR node and no server here implements.
|
|
18
|
+
*/
|
|
19
|
+
private isExternalOutbound;
|
|
15
20
|
arguments(invocation: ts.NewExpression | ts.CallExpression): Record<string, DeclaredTarget>;
|
|
16
21
|
hasExternalConsumer(owner: string, project: string, exportedName: string, program: ts.Program): boolean;
|
|
17
22
|
policies(invocation: ts.NewExpression | ts.CallExpression): Record<string, PolicyValue>;
|
|
@@ -69,6 +69,8 @@ class WiringSourceValues {
|
|
|
69
69
|
const declaration = this.symbol(expression)?.declarations?.[0];
|
|
70
70
|
if (declaration === undefined || !ts.isClassDeclaration(declaration))
|
|
71
71
|
this.fail(`API ${expression.getText()} must resolve to its source contract class.`);
|
|
72
|
+
if (this.isExternalOutbound(declaration))
|
|
73
|
+
return 'external';
|
|
72
74
|
for (const decorator of ts.getDecorators(declaration) ?? []) {
|
|
73
75
|
const expression = decorator.expression;
|
|
74
76
|
const name = this.symbolName(ts.isCallExpression(expression) ? expression.expression : expression);
|
|
@@ -77,6 +79,25 @@ class WiringSourceValues {
|
|
|
77
79
|
}
|
|
78
80
|
return 'rpc';
|
|
79
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* True when every `@Endpoint` of the contract declares `EXTERNAL_OUTBOUND` (its 4th argument): an
|
|
84
|
+
* outside system's API, which a client reaches as a VENDOR node and no server here implements.
|
|
85
|
+
*/
|
|
86
|
+
isExternalOutbound(declaration) {
|
|
87
|
+
let endpoints = 0;
|
|
88
|
+
for (const member of declaration.members) {
|
|
89
|
+
for (const decorator of ts.canHaveDecorators(member) ? (ts.getDecorators(member) ?? []) : []) {
|
|
90
|
+
const call = decorator.expression;
|
|
91
|
+
if (!ts.isCallExpression(call) || this.symbolName(call.expression) !== 'Endpoint')
|
|
92
|
+
continue;
|
|
93
|
+
endpoints++;
|
|
94
|
+
const kind = call.arguments[3];
|
|
95
|
+
if (kind === undefined || this.symbolName(kind) !== 'EXTERNAL_OUTBOUND')
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return endpoints > 0;
|
|
100
|
+
}
|
|
80
101
|
arguments(invocation) {
|
|
81
102
|
const targets = {};
|
|
82
103
|
const signature = this.checker.getResolvedSignature(invocation);
|