@webpieces/nx-webpieces-rules 0.4.962 → 0.4.964
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 +3 -3
- package/src/lib/api-usage/api-ast.js +41 -8
- 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 +32 -7
- package/src/lib/api-usage/api-contract-errors.js.map +1 -1
- package/src/lib/api-usage/api-relations.d.ts +31 -10
- package/src/lib/api-usage/api-relations.js +29 -10
- package/src/lib/api-usage/api-relations.js.map +1 -1
- package/src/lib/api-usage/api-scanner.d.ts +1 -1
- package/src/lib/api-usage/api-scanner.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webpieces/nx-webpieces-rules",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.964",
|
|
4
4
|
"description": "Nx-specific webpieces validation rules, graph tooling, executors, and inference plugin.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -20,12 +20,12 @@
|
|
|
20
20
|
"README.md"
|
|
21
21
|
],
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@webpieces/api-doc-model": "0.4.
|
|
24
|
-
"@webpieces/core-util": "0.4.
|
|
25
|
-
"@webpieces/eslint-rules": "0.4.
|
|
26
|
-
"@webpieces/rules-config": "0.4.
|
|
23
|
+
"@webpieces/api-doc-model": "0.4.964",
|
|
24
|
+
"@webpieces/core-util": "0.4.964",
|
|
25
|
+
"@webpieces/eslint-rules": "0.4.964",
|
|
26
|
+
"@webpieces/rules-config": "0.4.964",
|
|
27
27
|
"madge": "8.0.0",
|
|
28
|
-
"@webpieces/rules-sdk": "0.4.
|
|
28
|
+
"@webpieces/rules-sdk": "0.4.964"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
31
|
"@nx/devkit": ">=18.0.0"
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"access": "public"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@webpieces/tooling-testkit": "0.4.
|
|
44
|
+
"@webpieces/tooling-testkit": "0.4.964"
|
|
45
45
|
},
|
|
46
46
|
"types": "./src/index.d.ts",
|
|
47
47
|
"bin": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Parser-only API contract AST accessors; deliberately avoids module resolution and erased d.ts. */
|
|
2
2
|
import * as ts from 'typescript';
|
|
3
|
-
import { ApiClassInfo, ApiMethodMeta, ApiParameterMeta, ContractHttpMethod, ApiTransport, EmptiedApiContract, EndpointOperation, ExternalSystemDeclaration, NonLiteralDecoratorArg, UndeclaredExternalCaller, UndeclaredEndpointOperation, UnresolvedEndpointPath, VoidResponseMismatch } from './api-relations';
|
|
3
|
+
import { ApiClassInfo, ApiMethodMeta, ApiParameterMeta, ContractHttpMethod, ApiTransport, EmptiedApiContract, EndpointKind, EndpointOperation, ExternalSystemDeclaration, NonLiteralDecoratorArg, UndeclaredExternalCaller, UndeclaredEndpointOperation, UnresolvedEndpointPath, VoidResponseMismatch, VoidResponseProblem } from './api-relations';
|
|
4
4
|
/** Same-module string constants that parser-only decorator scanning can safely resolve. */
|
|
5
5
|
export declare class ModuleStringConstants {
|
|
6
6
|
private readonly byName;
|
|
@@ -39,8 +39,8 @@ export declare class DecoratorArgDiagnostics {
|
|
|
39
39
|
recordUndeclaredCaller(api: string, method: string, argument: string, node: ts.Node): void;
|
|
40
40
|
/** Record an `@Endpoint` whose required operation is missing or unreadable. */
|
|
41
41
|
recordUndeclaredOperation(api: string, method: string, argument: string, node: ts.Node): void;
|
|
42
|
-
/** Record an `@Endpoint` whose
|
|
43
|
-
recordVoidMismatch(api: string, method: string,
|
|
42
|
+
/** Record an `@Endpoint` whose response-body declaration disagrees with its kind or signature. */
|
|
43
|
+
recordVoidMismatch(api: string, method: string, problem: VoidResponseProblem, kind: EndpointKind, node: ts.Node): void;
|
|
44
44
|
voidResponseMismatches(): VoidResponseMismatch[];
|
|
45
45
|
all(): NonLiteralDecoratorArg[];
|
|
46
46
|
unresolvedEndpointPaths(): UnresolvedEndpointPath[];
|
|
@@ -195,9 +195,9 @@ class DecoratorArgDiagnostics {
|
|
|
195
195
|
recordUndeclaredOperation(api, method, argument, node) {
|
|
196
196
|
this.undeclaredOperations.push(new api_relations_1.UndeclaredEndpointOperation(api, method, argument, this.locate(node)));
|
|
197
197
|
}
|
|
198
|
-
/** Record an `@Endpoint` whose
|
|
199
|
-
recordVoidMismatch(api, method,
|
|
200
|
-
this.voidMismatches.push(new api_relations_1.VoidResponseMismatch(api, method,
|
|
198
|
+
/** Record an `@Endpoint` whose response-body declaration disagrees with its kind or signature. */
|
|
199
|
+
recordVoidMismatch(api, method, problem, kind, node) {
|
|
200
|
+
this.voidMismatches.push(new api_relations_1.VoidResponseMismatch(api, method, problem, kind, this.locate(node)));
|
|
201
201
|
}
|
|
202
202
|
voidResponseMismatches() {
|
|
203
203
|
return this.voidMismatches;
|
|
@@ -334,20 +334,53 @@ function reportUnknownVerb(diagnostics, api, name, httpMethod, endpoint) {
|
|
|
334
334
|
diagnostics.record(api, 'Endpoint.httpMethod', name, httpMethod, endpoint);
|
|
335
335
|
}
|
|
336
336
|
/**
|
|
337
|
-
* The response-shape options: `responseType: 'full'`, and
|
|
338
|
-
*
|
|
337
|
+
* The response-shape options: `responseType: 'full'`, and the response body (a mismatch is a fatal
|
|
338
|
+
* diagnostic). A CLOUDTASKS / CRON endpoint has no response body BY KIND (#1348): it must return
|
|
339
|
+
* `Promise<void>`, and an explicit `responseBody: NONE` on it is a redundant second spelling. An
|
|
340
|
+
* EXTERNAL_OUTBOUND endpoint's response is shaped by the VENDOR, so NONE (what OUR server sends) is
|
|
341
|
+
* refused there and not required on `Promise<void>`. RPC and EXTERNAL_INBOUND declare
|
|
342
|
+
* `responseBody: NONE`, which must agree with a `Promise<void>` signature in both directions.
|
|
339
343
|
*/
|
|
340
344
|
// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers
|
|
341
345
|
function readResponseShape(method, member, options, constants, diagnostics, api, endpoint) {
|
|
342
346
|
if (endpointResponseTypeOf(options, constants) === 'full')
|
|
343
347
|
method.responseType = 'full';
|
|
344
348
|
const declaresNone = endpointResponseBodyIsNone(options, constants);
|
|
345
|
-
|
|
349
|
+
const returnsVoid = returnsPromiseOfVoid(member);
|
|
350
|
+
const problem = responseBodyProblem(method.kind, declaresNone, returnsVoid);
|
|
351
|
+
if (declaresNone && problem === null)
|
|
346
352
|
method.responseBody = 'none';
|
|
347
|
-
if (diagnostics !== null &&
|
|
348
|
-
diagnostics.recordVoidMismatch(api, method.name,
|
|
353
|
+
if (diagnostics !== null && problem !== null) {
|
|
354
|
+
diagnostics.recordVoidMismatch(api, method.name, problem, method.kind, endpoint);
|
|
349
355
|
}
|
|
350
356
|
}
|
|
357
|
+
/** The one response-body rule per kind (#1348). */
|
|
358
|
+
// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers
|
|
359
|
+
function responseBodyProblem(kind, declaresNone, returnsVoid) {
|
|
360
|
+
if (QUEUED_KINDS.includes(kind))
|
|
361
|
+
return triggerVoidProblem(declaresNone, returnsVoid);
|
|
362
|
+
if (kind === 'external-outbound')
|
|
363
|
+
return declaresNone ? api_relations_1.VoidResponseProblem.OUTBOUND_NONE : null;
|
|
364
|
+
return declaredVoidProblem(declaresNone, returnsVoid);
|
|
365
|
+
}
|
|
366
|
+
/** CLOUDTASKS / CRON: void by kind, so NONE is redundant and a non-void signature is refused. */
|
|
367
|
+
// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers
|
|
368
|
+
function triggerVoidProblem(declaresNone, returnsVoid) {
|
|
369
|
+
if (declaresNone)
|
|
370
|
+
return api_relations_1.VoidResponseProblem.REDUNDANT_NONE;
|
|
371
|
+
if (!returnsVoid)
|
|
372
|
+
return api_relations_1.VoidResponseProblem.TRIGGER_NOT_VOID;
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
375
|
+
/** RPC / EXTERNAL_INBOUND: `responseBody: NONE` and `Promise<void>` must agree in both directions. */
|
|
376
|
+
// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers
|
|
377
|
+
function declaredVoidProblem(declaresNone, returnsVoid) {
|
|
378
|
+
if (declaresNone && !returnsVoid)
|
|
379
|
+
return api_relations_1.VoidResponseProblem.NONE_WITHOUT_VOID;
|
|
380
|
+
if (!declaresNone && returnsVoid)
|
|
381
|
+
return api_relations_1.VoidResponseProblem.VOID_WITHOUT_NONE;
|
|
382
|
+
return null;
|
|
383
|
+
}
|
|
351
384
|
/** Required side-effect declaration; no inference from GET/POST is permitted. */
|
|
352
385
|
// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers
|
|
353
386
|
function endpointOperationOf(operationArgument, constants, diagnostics, api, method, node) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-ast.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/api-usage/api-ast.ts"],"names":[],"mappings":"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","sourcesContent":["/** Parser-only API contract AST accessors; deliberately avoids module resolution and erased d.ts. */\n\nimport * as ts from 'typescript';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { classDecorators, decoratorName } from '../di-graph/bindings';\nimport {\n ApiClassInfo,\n ApiMethodMeta,\n ApiParameterMeta,\n CONTRACT_HTTP_METHODS,\n ContractHttpMethod,\n contractVerbCarriesBody,\n ApiTransport,\n EmptiedApiContract,\n EndpointKind,\n EndpointOperation,\n ExternalSystemDeclaration,\n isExternalSystemKind,\n NonLiteralDecoratorArg,\n UndeclaredExternalCaller,\n UndeclaredEndpointOperation,\n UnresolvedEndpointPath,\n VoidResponseMismatch,\n} from './api-relations';\n\n/** Legal enum-backed `@Endpoint` symbols; tooling reads source without importing application code. */\nconst ENDPOINT_KINDS: readonly EndpointKind[] = [\n 'rpc',\n 'cloudtasks',\n 'cron',\n 'external-inbound',\n 'external-outbound',\n];\nconst ENDPOINT_OPERATIONS: readonly EndpointOperation[] = ['read', 'write-idempotent', 'write'];\nconst ENDPOINT_SYMBOLS: Readonly<Record<string, string>> = {\n GET: 'GET',\n POST: 'POST',\n PUT: 'PUT',\n PATCH: 'PATCH',\n DELETE: 'DELETE',\n READ: 'read',\n WRITE_IDEMPOTENT: 'write-idempotent',\n WRITE: 'write',\n RPC: 'rpc',\n CLOUDTASKS: 'cloudtasks',\n CRON: 'cron',\n EXTERNAL_INBOUND: 'external-inbound',\n EXTERNAL_OUTBOUND: 'external-outbound',\n};\n\n/**\n * Name suffix that marks an exported type in an `externalApiPaths` project as a vendor CONTRACT\n * (`GmailApi`, `StorageApi`) rather than one of the DTOs, configs or clients sitting beside it.\n * The same convention the in-repo contracts already follow, applied where no decorator can be read.\n */\nconst EXTERNAL_CONTRACT_SUFFIX = 'Api';\n\n/** JSDoc tag a vendor contract uses to declare WHAT it is a seam to: `@externalSystem database Firestore`. */\nconst EXTERNAL_SYSTEM_TAG = 'externalSystem';\n\n/**\n * Client-config class-name suffix whose FIRST constructor argument is the target service name —\n * `ClientConfig('helper-fsdb')` (rpc) and `TaskClientConfig('helper-fsdb')` (pubsub) both take\n * `svcName` first, and a consumer's own `XxxClientConfig` follows the same shape.\n */\nconst CLIENT_CONFIG_SUFFIX = 'ClientConfig';\n\n/** Same-module string constants that parser-only decorator scanning can safely resolve. */\nexport class ModuleStringConstants {\n constructor(private readonly byName: Map<string, string>) {}\n\n lookup(name: string): string | null {\n return this.byName.get(name) ?? null;\n }\n}\n\n/** Parsed constants per source file — every class in a file shares one table. */\nconst CONSTANTS_BY_FILE = new WeakMap<ts.SourceFile, ModuleStringConstants>();\n\n/** The module-scope string constants of `sourceFile`, parsed once per file. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function stringConstantsOf(sourceFile: ts.SourceFile): ModuleStringConstants {\n const cached = CONSTANTS_BY_FILE.get(sourceFile);\n if (cached !== undefined) return cached;\n const byName = new Map<string, string>();\n for (const statement of sourceFile.statements) {\n if (!ts.isVariableStatement(statement)) continue;\n if ((statement.declarationList.flags & ts.NodeFlags.Const) === 0) continue;\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name)) continue;\n const text = stringValueOf(declaration.initializer);\n if (text !== null) byName.set(declaration.name.text, text);\n }\n }\n const constants = new ModuleStringConstants(byName);\n CONSTANTS_BY_FILE.set(sourceFile, constants);\n return constants;\n}\n\n/** The string an initializer denotes, unwrapping `as const` / parentheses, else null. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function stringValueOf(expr: ts.Expression | undefined): string | null {\n if (expr === undefined) return null;\n if (ts.isStringLiteral(expr) || ts.isNoSubstitutionTemplateLiteral(expr)) return expr.text;\n if (ts.isAsExpression(expr) || ts.isParenthesizedExpression(expr))\n return stringValueOf(expr.expression);\n return null;\n}\n\n/** A resolved decorator string, or the source spelling that could not be reduced. */\nexport class DecoratorArgValue {\n constructor(\n public readonly value: string | null,\n public readonly unresolvedName: string | null,\n ) {}\n}\n\n/** Read one decorator argument as a string, resolving same-module constants. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function decoratorArgValue(\n expr: ts.Expression | undefined,\n constants: ModuleStringConstants,\n): DecoratorArgValue {\n if (expr === undefined) return new DecoratorArgValue(null, null);\n const literal = stringValueOf(expr);\n if (literal !== null) return new DecoratorArgValue(literal, null);\n if (ts.isIdentifier(expr)) {\n const resolved = constants.lookup(expr.text);\n if (resolved !== null) return new DecoratorArgValue(resolved, null);\n return new DecoratorArgValue(null, expr.text);\n }\n return new DecoratorArgValue(null, expr.getText());\n}\n\n/** Resolve the enum-backed constants intentionally allowed in @Endpoint positional arguments. */\n// webpieces-disable no-function-outside-class -- pure AST accessor for decorator source\nfunction endpointSymbolArgValue(\n expr: ts.Expression | undefined,\n constants: ModuleStringConstants,\n): DecoratorArgValue {\n if (expr && ts.isIdentifier(expr)) {\n const builtin = ENDPOINT_SYMBOLS[expr.text];\n if (builtin !== undefined) return new DecoratorArgValue(builtin, null);\n }\n return decoratorArgValue(expr, constants);\n}\n\n/** Aggregates parser-only scan losses so generation can fail loudly instead of dropping routes. */\nexport class DecoratorArgDiagnostics {\n private readonly found: NonLiteralDecoratorArg[] = [];\n private readonly unresolvedPaths: UnresolvedEndpointPath[] = [];\n private readonly emptied: EmptiedApiContract[] = [];\n private readonly undeclaredCallers: UndeclaredExternalCaller[] = [];\n private readonly undeclaredOperations: UndeclaredEndpointOperation[] = [];\n private readonly voidMismatches: VoidResponseMismatch[] = [];\n\n constructor(private readonly workspaceRoot: string) {}\n\n /** Record `argument` (as written) as unresolvable at `node`'s location. */\n record(\n api: string,\n decorator: string,\n method: string | null,\n argument: string,\n node: ts.Node,\n ): void {\n this.found.push(\n new NonLiteralDecoratorArg(api, decorator, method, argument, this.locate(node)),\n );\n }\n\n /** Record an `@Endpoint` whose path argument is unreadable — fatal, see UnresolvedEndpointPathError. */\n recordUnresolvedPath(api: string, method: string, argument: string, node: ts.Node): void {\n this.unresolvedPaths.push(\n new UnresolvedEndpointPath(api, method, argument, this.locate(node)),\n );\n }\n\n /** Record a class that declared `declared` `@Endpoint` methods and kept none of them. */\n recordEmptiedContract(api: string, declared: number, node: ts.Node): void {\n this.emptied.push(new EmptiedApiContract(api, declared, this.locate(node)));\n }\n\n /** Record an `external` `@Endpoint` whose caller is unreadable — fatal, see UndeclaredExternalCallerError. */\n recordUndeclaredCaller(api: string, method: string, argument: string, node: ts.Node): void {\n this.undeclaredCallers.push(\n new UndeclaredExternalCaller(api, method, argument, this.locate(node)),\n );\n }\n\n /** Record an `@Endpoint` whose required operation is missing or unreadable. */\n recordUndeclaredOperation(api: string, method: string, argument: string, node: ts.Node): void {\n this.undeclaredOperations.push(\n new UndeclaredEndpointOperation(api, method, argument, this.locate(node)),\n );\n }\n\n /** Record an `@Endpoint` whose `responseBody: NONE` disagrees with its `Promise<void>` signature. */\n recordVoidMismatch(api: string, method: string, declaresNone: boolean, node: ts.Node): void {\n this.voidMismatches.push(new VoidResponseMismatch(api, method, declaresNone, this.locate(node)));\n }\n\n voidResponseMismatches(): VoidResponseMismatch[] {\n return this.voidMismatches;\n }\n\n all(): NonLiteralDecoratorArg[] {\n return this.found;\n }\n\n unresolvedEndpointPaths(): UnresolvedEndpointPath[] {\n return this.unresolvedPaths;\n }\n\n emptiedContracts(): EmptiedApiContract[] {\n return this.emptied;\n }\n\n undeclaredExternalCallers(): UndeclaredExternalCaller[] {\n return this.undeclaredCallers;\n }\n\n undeclaredEndpointOperations(): UndeclaredEndpointOperation[] {\n return this.undeclaredOperations;\n }\n\n private locate(node: ts.Node): string {\n const sourceFile = node.getSourceFile();\n const position = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n return `${path.relative(this.workspaceRoot, sourceFile.fileName)}:${position.line + 1}`;\n }\n}\n\n/** {api, owner: `project`, type} when `cls` is an `abstract class` carrying `@ApiPath`, else null. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function apiClassInfoFrom(\n cls: ts.ClassDeclaration,\n project: string,\n diagnostics: DecoratorArgDiagnostics | null = null,\n): ApiClassInfo | null {\n if (!isAbstractClass(cls) || !hasClassDecorator(cls, 'ApiPath') || !cls.name) return null;\n const api = cls.name.text;\n const constants = stringConstantsOf(cls.getSourceFile());\n const methods = endpointMethodsOf(cls, api, constants, diagnostics);\n const outbound =\n methods.length > 0 &&\n methods.every((method: ApiMethodMeta) => method.kind === 'external-outbound');\n const info: ApiClassInfo = {\n api,\n owner: project,\n type: outbound ? 'external' : apiTransport(cls),\n methods,\n };\n // An EXTERNAL_OUTBOUND contract is an outside system's API: it is a VENDOR node on the runtime\n // graph, named by its `@externalSystem <kind> [label]` JSDoc tag or, without one, a `saas` box\n // labelled with the contract name minus `Api`.\n if (outbound) {\n info.externalSystem = externalSystemTagFrom(cls, api) ?? {\n kind: 'saas',\n label: api.replace(/Api$/, ''),\n };\n }\n const basePath = decoratorStringArg(cls, 'ApiPath', constants, diagnostics, api);\n if (basePath !== null) info.basePath = basePath;\n return info;\n}\n\n// webpieces-disable no-function-outside-class -- pure AST predicate, matching the sibling helpers in di-graph/bindings.ts\nexport function apiTransport(cls: ts.ClassDeclaration): ApiTransport {\n return hasClassDecorator(cls, 'PubSub') ? 'pubsub' : 'rpc';\n}\n\n/** The @Endpoint kinds that are actually DELIVERED through a named queue or schedule. */\nconst QUEUED_KINDS: readonly EndpointKind[] = ['cloudtasks', 'cron'];\n\n/** Reads required `(method, path, operation, kind, options?)` endpoint declarations in order. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function endpointMethodsOf(\n cls: ts.ClassDeclaration,\n api: string,\n constants: ModuleStringConstants = new ModuleStringConstants(new Map<string, string>()),\n diagnostics: DecoratorArgDiagnostics | null = null,\n): ApiMethodMeta[] {\n const methods: ApiMethodMeta[] = [];\n let declared = 0;\n for (const member of cls.members) {\n if (!ts.isMethodDeclaration(member) || !ts.isIdentifier(member.name)) continue;\n const endpoint = memberDecorator(member, 'Endpoint');\n if (endpoint === null) continue;\n declared++;\n const name = member.name.text;\n const args = decoratorArgs(endpoint);\n const methodArg = endpointSymbolArgValue(args[0], constants);\n const pathArg = decoratorArgValue(args[1], constants);\n const operationArg = endpointSymbolArgValue(args[2], constants);\n const kindArg = endpointSymbolArgValue(args[3], constants);\n reportUnresolved(diagnostics, api, 'Endpoint', name, methodArg, endpoint);\n reportUnresolved(diagnostics, api, 'Endpoint', name, pathArg, endpoint);\n reportUnresolved(diagnostics, api, 'Endpoint', name, operationArg, endpoint);\n reportUnresolved(diagnostics, api, 'Endpoint', name, kindArg, endpoint);\n if (diagnostics !== null && pathArg.unresolvedName !== null) {\n diagnostics.recordUnresolvedPath(api, name, pathArg.unresolvedName, endpoint);\n }\n const httpMethod = methodArg.value;\n reportUnknownVerb(diagnostics, api, name, httpMethod, endpoint);\n const operation = endpointOperationOf(args[2], constants, diagnostics, api, name, endpoint);\n const kind = kindArg.value;\n if (\n httpMethod === null ||\n !CONTRACT_HTTP_METHODS.includes(httpMethod as ContractHttpMethod) ||\n pathArg.value === null ||\n operation === null ||\n kind === null ||\n !ENDPOINT_KINDS.includes(kind as EndpointKind)\n )\n continue;\n const method: ApiMethodMeta = {\n name,\n path: pathArg.value,\n kind: kind as EndpointKind,\n operation,\n httpMethod: httpMethod as ContractHttpMethod,\n };\n const parameters = httpParametersOf(member, httpMethod as ContractHttpMethod, constants, diagnostics, api, name);\n if (parameters.length > 0) method.parameters = parameters;\n readResponseShape(method, member, args[4], constants, diagnostics, api, endpoint);\n if (QUEUED_KINDS.includes(method.kind)) {\n method.queueName = queueNameOf(member, api, name, constants, diagnostics);\n }\n if (method.kind === 'external-inbound') {\n const caller = externalCallerOf(args[4], constants);\n if (caller.declaration !== null) method.caller = caller.declaration;\n else if (diagnostics !== null)\n diagnostics.recordUndeclaredCaller(api, name, caller.problem!, endpoint);\n }\n methods.push(method);\n }\n if (diagnostics !== null && declared > 0 && methods.length === 0) {\n diagnostics.recordEmptiedContract(api, declared, cls);\n }\n return methods;\n}\n\n/** An unknown verb must fail generation, never silently drop the endpoint from the graph. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers\nfunction reportUnknownVerb(\n diagnostics: DecoratorArgDiagnostics | null,\n api: string,\n name: string,\n httpMethod: string | null,\n endpoint: ts.Node,\n): void {\n if (diagnostics === null || httpMethod === null) return;\n if (CONTRACT_HTTP_METHODS.includes(httpMethod as ContractHttpMethod)) return;\n diagnostics.record(api, 'Endpoint.httpMethod', name, httpMethod, endpoint);\n}\n\n/**\n * The response-shape options: `responseType: 'full'`, and `responseBody: NONE`, which must agree with\n * a `Promise<void>` signature in both directions (a mismatch is a fatal diagnostic).\n */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers\nfunction readResponseShape(\n method: ApiMethodMeta,\n member: ts.MethodDeclaration,\n options: ts.Expression | undefined,\n constants: ModuleStringConstants,\n diagnostics: DecoratorArgDiagnostics | null,\n api: string,\n endpoint: ts.Node,\n): void {\n if (endpointResponseTypeOf(options, constants) === 'full') method.responseType = 'full';\n const declaresNone = endpointResponseBodyIsNone(options, constants);\n if (declaresNone) method.responseBody = 'none';\n if (diagnostics !== null && declaresNone !== returnsPromiseOfVoid(member)) {\n diagnostics.recordVoidMismatch(api, method.name, declaresNone, endpoint);\n }\n}\n\n/** Required side-effect declaration; no inference from GET/POST is permitted. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers\nexport function endpointOperationOf(\n operationArgument: ts.Expression | undefined,\n constants: ModuleStringConstants,\n diagnostics: DecoratorArgDiagnostics | null,\n api: string,\n method: string,\n node: ts.Node,\n): EndpointOperation | null {\n const declared = endpointSymbolArgValue(operationArgument, constants);\n if (declared.value === null) {\n diagnostics?.recordUndeclaredOperation(\n api,\n method,\n declared.unresolvedName ?? '<missing>',\n node,\n );\n return null;\n }\n reportUnresolved(diagnostics, api, 'Endpoint.operation', method, declared, node);\n if (\n declared.value !== null &&\n ENDPOINT_OPERATIONS.includes(declared.value as EndpointOperation)\n ) {\n return declared.value as EndpointOperation;\n }\n diagnostics?.recordUndeclaredOperation(\n api,\n method,\n declared.unresolvedName ?? declared.value ?? '<missing>',\n node,\n );\n return null;\n}\n\n/** Required first positional HTTP method. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers\nexport function httpMethodOf(\n methodArgument: ts.Expression | undefined,\n constants: ModuleStringConstants,\n diagnostics: DecoratorArgDiagnostics | null,\n api: string,\n method: string,\n node: ts.Node,\n): ContractHttpMethod | null {\n const declared = endpointSymbolArgValue(methodArgument, constants);\n reportUnresolved(diagnostics, api, 'Endpoint.httpMethod', method, declared, node);\n if (CONTRACT_HTTP_METHODS.includes(declared.value as ContractHttpMethod)) {\n return declared.value as ContractHttpMethod;\n }\n return null;\n}\n\n/** Only the non-default full-response marker needs an architecture field. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers\nexport function endpointResponseTypeOf(\n options: ts.Expression | undefined,\n constants: ModuleStringConstants,\n): 'body' | 'full' {\n if (options === undefined || !ts.isObjectLiteralExpression(options)) return 'body';\n return objectPropertyValue(options, 'responseType', constants).value === 'full'\n ? 'full'\n : 'body';\n}\n\n/** `{ responseBody: NONE }` (the enum member, or its `'none'` value) in `@Endpoint`'s options. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers\nexport function endpointResponseBodyIsNone(\n options: ts.Expression | undefined,\n constants: ModuleStringConstants,\n): boolean {\n if (options === undefined || !ts.isObjectLiteralExpression(options)) return false;\n for (const property of options.properties) {\n if (!ts.isPropertyAssignment(property) || !ts.isIdentifier(property.name)) continue;\n if (property.name.text !== 'responseBody') continue;\n const value = property.initializer;\n if (ts.isIdentifier(value) && value.text === 'NONE') return true;\n return decoratorArgValue(value, constants).value === 'none';\n }\n return false;\n}\n\n/** True when the method is declared `Promise<void>` (or `Promise<undefined>`). */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers\nexport function returnsPromiseOfVoid(member: ts.MethodDeclaration): boolean {\n const type = member.type;\n if (type === undefined || !ts.isTypeReferenceNode(type)) return false;\n if (!ts.isIdentifier(type.typeName) || type.typeName.text !== 'Promise') return false;\n const argument = type.typeArguments?.[0];\n if (argument === undefined) return false;\n if (argument.kind === ts.SyntaxKind.VoidKeyword || argument.kind === ts.SyntaxKind.UndefinedKeyword) {\n return true;\n }\n return false;\n}\n\n/** Explicit `@PathParam` / `@QueryParam` / `@QueryString` mappings in source declaration order. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers\nexport function httpParametersOf(\n member: ts.MethodDeclaration,\n httpMethod: ContractHttpMethod,\n constants: ModuleStringConstants,\n diagnostics: DecoratorArgDiagnostics | null,\n api: string,\n method: string,\n): ApiParameterMeta[] {\n const parameters: ApiParameterMeta[] = [];\n member.parameters.forEach((parameter: ts.ParameterDeclaration, index: number) => {\n let mapped = false;\n if (decoratorOn(parameter, 'QueryString') !== null) {\n parameters.push({ index, source: 'query-map' });\n return;\n }\n for (const source of ['path', 'query'] as const) {\n const decoratorNameWanted = source === 'path' ? 'PathParam' : 'QueryParam';\n const decorator = decoratorOn(parameter, decoratorNameWanted);\n if (decorator === null) continue;\n mapped = true;\n const wireName = decoratorArgValue(decoratorArgs(decorator)[0], constants);\n reportUnresolved(diagnostics, api, decoratorNameWanted, method, wireName, decorator);\n if (wireName.value !== null) {\n parameters.push({ index, source, wireName: wireName.value });\n }\n }\n if (!mapped && contractVerbCarriesBody(httpMethod)) parameters.push({ index, source: 'body' });\n });\n return parameters;\n}\n\n/** Default `callerKind` when an `external-inbound` endpoint declares `calledBy` alone — mirrors core-util. */\nconst DEFAULT_CALLER_KIND = 'saas';\n\n/** Resolved EXTERNAL_INBOUND caller declaration, or the source problem that prevented resolution. */\nexport class ExternalCallerRead {\n constructor(\n public readonly declaration: ExternalSystemDeclaration | null,\n /** What was wrong, as written, for the diagnostic. Null exactly when `declaration` is set. */\n public readonly problem: string | null,\n ) {}\n}\n\n/** Reads `calledBy` and optional `callerKind` from the fifth positional options argument. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function externalCallerOf(\n arg: ts.Expression | undefined,\n constants: ModuleStringConstants,\n): ExternalCallerRead {\n if (arg === undefined) return new ExternalCallerRead(null, '<no options argument>');\n if (!ts.isObjectLiteralExpression(arg)) return new ExternalCallerRead(null, arg.getText());\n const calledBy = objectPropertyValue(arg, 'calledBy', constants);\n if (calledBy.value === null || calledBy.value === '') {\n return new ExternalCallerRead(null, calledBy.unresolvedName ?? '<no calledBy>');\n }\n const callerKind = objectPropertyValue(arg, 'callerKind', constants);\n if (callerKind.value === null && callerKind.unresolvedName !== null) {\n return new ExternalCallerRead(null, `callerKind: ${callerKind.unresolvedName}`);\n }\n const kind = callerKind.value ?? DEFAULT_CALLER_KIND;\n if (!isExternalSystemKind(kind)) return new ExternalCallerRead(null, `callerKind: '${kind}'`);\n return new ExternalCallerRead({ kind, label: calledBy.value }, null);\n}\n\n/** One property of an object literal, read as a string through the same constant folding as an argument. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function objectPropertyValue(\n literal: ts.ObjectLiteralExpression,\n name: string,\n constants: ModuleStringConstants,\n): DecoratorArgValue {\n for (const property of literal.properties) {\n if (!ts.isPropertyAssignment(property) || property.name === undefined) continue;\n const key =\n ts.isIdentifier(property.name) || ts.isStringLiteral(property.name)\n ? property.name.text\n : null;\n if (key !== name) continue;\n return decoratorArgValue(property.initializer, constants);\n }\n return new DecoratorArgValue(null, null);\n}\n\n/** `@Queue('...')` override when present and resolvable, else the derived `${Api}-${method}`. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function queueNameOf(\n member: ts.MethodDeclaration,\n api: string,\n name: string,\n constants: ModuleStringConstants,\n diagnostics: DecoratorArgDiagnostics | null,\n): string {\n const override = memberDecorator(member, 'Queue');\n if (override === null) return `${api}-${name}`;\n const queueArg = decoratorArgValue(decoratorArgs(override)[0], constants);\n reportUnresolved(diagnostics, api, 'Queue', name, queueArg, override);\n return queueArg.value ?? `${api}-${name}`;\n}\n\n/** Record an argument that is present but unresolvable; a resolved or absent one is silent. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function reportUnresolved(\n diagnostics: DecoratorArgDiagnostics | null,\n api: string,\n decorator: string,\n method: string | null,\n arg: DecoratorArgValue,\n node: ts.Node,\n): void {\n if (diagnostics === null || arg.unresolvedName === null) return;\n diagnostics.record(api, decorator, method, arg.unresolvedName, node);\n}\n\n/** The arguments of a decorator's call expression, or [] when it is a bare `@Foo` reference. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function decoratorArgs(\n decorator: ts.Decorator,\n): ts.NodeArray<ts.Expression> | ts.Expression[] {\n return ts.isCallExpression(decorator.expression) ? decorator.expression.arguments : [];\n}\n\n/** The named decorator on a class member, or null. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function memberDecorator(member: ts.ClassElement, name: string): ts.Decorator | null {\n const decorators = ts.getDecorators(member as ts.HasDecorators) ?? [];\n return decorators.find((d: ts.Decorator) => decoratorName(d) === name) ?? null;\n}\n\n/** The named decorator on any decorator-capable AST node (notably a method parameter). */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching memberDecorator\nexport function decoratorOn(node: ts.HasDecorators, name: string): ts.Decorator | null {\n const decorators = ts.getDecorators(node) ?? [];\n return decorators.find((decorator: ts.Decorator) => decoratorName(decorator) === name) ?? null;\n}\n\n/**\n * The first argument of a class decorator as a string (`@ApiPath('/x')`, `@ApiPath(X_PATH)`), else\n * null. A same-module constant resolves; anything else is recorded on `diagnostics`.\n */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function decoratorStringArg(\n cls: ts.ClassDeclaration,\n name: string,\n constants: ModuleStringConstants = new ModuleStringConstants(new Map<string, string>()),\n diagnostics: DecoratorArgDiagnostics | null = null,\n api: string = name,\n): string | null {\n const decorator = classDecorators(cls).find((d: ts.Decorator) => decoratorName(d) === name);\n if (decorator === undefined) return null;\n const arg = decoratorArgValue(decoratorArgs(decorator)[0], constants);\n reportUnresolved(diagnostics, api, name, null, arg, decorator);\n return arg.value;\n}\n\n/** The constructor's parameters, or [] when the class declares no constructor. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function constructorParamsOf(cls: ts.ClassDeclaration): readonly ts.ParameterDeclaration[] {\n for (const member of cls.members) {\n if (ts.isConstructorDeclaration(member)) return member.parameters;\n }\n return [];\n}\n\n/**\n * The bare name of a type reference (`GmailApi`, or `gmail.GmailApi` -> `GmailApi`), else null.\n * Generic wrappers are deliberately NOT unwrapped: `Provider<GmailApi>` hands out the contract\n * lazily, which is still a use, but it is not the shape any of these seams take today and guessing\n * at type arguments would start matching things that merely mention a contract.\n */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function typeReferenceName(type: ts.TypeNode | undefined): string | null {\n if (type === undefined || !ts.isTypeReferenceNode(type)) return null;\n const name = type.typeName;\n if (ts.isIdentifier(name)) return name.text;\n return ts.isQualifiedName(name) && ts.isIdentifier(name.right) ? name.right.text : null;\n}\n\n/** Every type name in the class's `implements` clause — the contracts this class IS, not ones it calls. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function implementedTypeNames(cls: ts.ClassDeclaration): Set<string> {\n const names = new Set<string>();\n for (const clause of cls.heritageClauses ?? []) {\n if (clause.token !== ts.SyntaxKind.ImplementsKeyword) continue;\n for (const type of clause.types) {\n if (ts.isIdentifier(type.expression)) names.add(type.expression.text);\n }\n }\n return names;\n}\n\n// webpieces-disable no-function-outside-class -- pure AST predicate, matching the sibling helpers in di-graph/bindings.ts\nexport function isAbstractClass(cls: ts.ClassDeclaration): boolean {\n return (ts.getModifiers(cls) ?? []).some(\n (m: ts.Modifier) => m.kind === ts.SyntaxKind.AbstractKeyword,\n );\n}\n\n// webpieces-disable no-function-outside-class -- pure AST predicate, matching the sibling helpers in di-graph/bindings.ts\nexport function hasClassDecorator(cls: ts.ClassDeclaration, name: string): boolean {\n return classDecorators(cls).some((d: ts.Decorator) => decoratorName(d) === name);\n}\n\n/**\n * The service a client-factory call aims at, from its config argument:\n * `createRpcClient(WarmupApi, new ClientConfig('helper-fsdb'))` → `'helper-fsdb'`.\n *\n * Only a `new <Xxx>ClientConfig('<string literal>')` yields a name. A variable, a template string\n * or a computed expression yields null — the target is genuinely unknown at scan time, and the\n * runtime graph must fall back to fan-out (loudly) rather than guess.\n */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function targetServiceOf(call: ts.CallExpression): string | null {\n if (call.arguments.length < 2) return null;\n const config = call.arguments[1];\n if (!ts.isNewExpression(config) || !ts.isIdentifier(config.expression)) return null;\n if (!config.expression.text.endsWith(CLIENT_CONFIG_SUFFIX)) return null;\n const first = config.arguments?.[0];\n if (first === undefined || !ts.isStringLiteral(first)) return null;\n return first.text.length > 0 ? first.text : null;\n}\n\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function calleeMethodName(call: ts.CallExpression): string | null {\n const callee = call.expression;\n if (ts.isPropertyAccessExpression(callee)) return callee.name.text;\n if (ts.isIdentifier(callee)) return callee.text;\n return null;\n}\n\n// webpieces-disable no-function-outside-class -- pure path predicate, matching the sibling helpers in di-graph/bindings.ts\nexport function isTestFile(fileName: string): boolean {\n return (\n fileName.includes('/__tests__/') ||\n fileName.includes('.spec.') ||\n fileName.includes('.test.')\n );\n}\n\n/** {api, owner, type:'rpc'|'pubsub'} for an in-repo contract class, else null. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function apiClassInfoFromNode(\n node: ts.Node,\n project: string,\n diagnostics: DecoratorArgDiagnostics | null = null,\n): ApiClassInfo | null {\n return ts.isClassDeclaration(node) ? apiClassInfoFrom(node, project, diagnostics) : null;\n}\n\n/**\n * {api, owner, type:'external'} for a VENDOR contract, else null.\n *\n * A vendor contract cannot be detected the way an in-repo one is. It carries no @ApiPath (there is\n * no route — the call leaves through a vendor SDK), and it is usually a plain `interface` bound to a\n * Symbol token, which is not even a class. So inside a project the workspace has DECLARED external\n * (`runtime-architecture.externalApiPaths`) the signal is structural instead: an exported\n * `interface`/`abstract class` whose name ends in `Api`. That deliberately picks up `GmailApi` and\n * `StorageApi` while leaving their DTOs, `*Config` types and `*Client` implementations alone.\n */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function externalApiInfoFrom(node: ts.Node, project: string): ApiClassInfo | null {\n const named =\n ts.isInterfaceDeclaration(node) || (ts.isClassDeclaration(node) && isAbstractClass(node));\n if (!named || !node.name || !isExported(node)) return null;\n const api = node.name.text;\n if (!api.endsWith(EXTERNAL_CONTRACT_SUFFIX)) return null;\n const externalSystem = externalSystemTagFrom(node, api);\n return externalSystem === null\n ? { api, owner: project, type: 'external', methods: [] }\n : { api, owner: project, type: 'external', methods: [], externalSystem };\n}\n\n/**\n * The `@externalSystem <kind> [label]` JSDoc tag on a vendor contract, or null when absent.\n *\n * JSDoc rather than a decorator is not a style choice: these seams are TS `interface`s, and TS has\n * no interface decorators. Without the tag the contract still renders — as the generic dashed box it\n * always was — so this is purely additive and nothing needs migrating.\n *\n * The label defaults to the contract name minus its `Api` suffix (`FirestoreAdminApi` →\n * `FirestoreAdmin`), because the label is the node IDENTITY: two contracts that mean the same system\n * must be given the SAME explicit label to converge on one node.\n *\n * An unrecognised kind is ignored rather than defaulted. Silently drawing a `@externalSystem\n * databse` typo as a generic box is recoverable; drawing it as the wrong shape teaches the reader\n * something false about the architecture.\n */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function externalSystemTagFrom(\n node: ts.Node,\n api: string,\n): ExternalSystemDeclaration | null {\n for (const tag of ts.getJSDocTags(node)) {\n if (tag.tagName.text !== EXTERNAL_SYSTEM_TAG) continue;\n const comment = typeof tag.comment === 'string' ? tag.comment : '';\n const parts = comment\n .trim()\n .split(/\\s+/)\n .filter((part: string) => part !== '');\n if (parts.length === 0) continue;\n const kind = parts[0].toLowerCase();\n if (!isExternalSystemKind(kind)) continue;\n const label = parts.slice(1).join(' ').trim();\n return { kind, label: label === '' ? api.replace(/Api$/, '') : label };\n }\n return null;\n}\n\n/** True when the declaration carries an `export` modifier. */\n// webpieces-disable no-function-outside-class -- pure AST predicate, matching the sibling helpers in di-graph/bindings.ts\nexport function isExported(node: ts.InterfaceDeclaration | ts.ClassDeclaration): boolean {\n return (ts.getModifiers(node) ?? []).some(\n (m: ts.Modifier) => m.kind === ts.SyntaxKind.ExportKeyword,\n );\n}\n\n// webpieces-disable no-function-outside-class -- recursive fs walker, matching the AST-helper style here\nexport function collectTsFiles(dir: string): string[] {\n const out: string[] = [];\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (entry.name !== 'node_modules') out.push(...collectTsFiles(full));\n } else if (entry.name.endsWith('.ts') && !entry.name.endsWith('.d.ts')) {\n out.push(full);\n }\n }\n return out;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"api-ast.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/lib/api-usage/api-ast.ts"],"names":[],"mappings":"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","sourcesContent":["/** Parser-only API contract AST accessors; deliberately avoids module resolution and erased d.ts. */\n\nimport * as ts from 'typescript';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { classDecorators, decoratorName } from '../di-graph/bindings';\nimport {\n ApiClassInfo,\n ApiMethodMeta,\n ApiParameterMeta,\n CONTRACT_HTTP_METHODS,\n ContractHttpMethod,\n contractVerbCarriesBody,\n ApiTransport,\n EmptiedApiContract,\n EndpointKind,\n EndpointOperation,\n ExternalSystemDeclaration,\n isExternalSystemKind,\n NonLiteralDecoratorArg,\n UndeclaredExternalCaller,\n UndeclaredEndpointOperation,\n UnresolvedEndpointPath,\n VoidResponseMismatch,\n VoidResponseProblem,\n} from './api-relations';\n\n/** Legal enum-backed `@Endpoint` symbols; tooling reads source without importing application code. */\nconst ENDPOINT_KINDS: readonly EndpointKind[] = [\n 'rpc',\n 'cloudtasks',\n 'cron',\n 'external-inbound',\n 'external-outbound',\n];\nconst ENDPOINT_OPERATIONS: readonly EndpointOperation[] = ['read', 'write-idempotent', 'write'];\nconst ENDPOINT_SYMBOLS: Readonly<Record<string, string>> = {\n GET: 'GET',\n POST: 'POST',\n PUT: 'PUT',\n PATCH: 'PATCH',\n DELETE: 'DELETE',\n READ: 'read',\n WRITE_IDEMPOTENT: 'write-idempotent',\n WRITE: 'write',\n RPC: 'rpc',\n CLOUDTASKS: 'cloudtasks',\n CRON: 'cron',\n EXTERNAL_INBOUND: 'external-inbound',\n EXTERNAL_OUTBOUND: 'external-outbound',\n};\n\n/**\n * Name suffix that marks an exported type in an `externalApiPaths` project as a vendor CONTRACT\n * (`GmailApi`, `StorageApi`) rather than one of the DTOs, configs or clients sitting beside it.\n * The same convention the in-repo contracts already follow, applied where no decorator can be read.\n */\nconst EXTERNAL_CONTRACT_SUFFIX = 'Api';\n\n/** JSDoc tag a vendor contract uses to declare WHAT it is a seam to: `@externalSystem database Firestore`. */\nconst EXTERNAL_SYSTEM_TAG = 'externalSystem';\n\n/**\n * Client-config class-name suffix whose FIRST constructor argument is the target service name —\n * `ClientConfig('helper-fsdb')` (rpc) and `TaskClientConfig('helper-fsdb')` (pubsub) both take\n * `svcName` first, and a consumer's own `XxxClientConfig` follows the same shape.\n */\nconst CLIENT_CONFIG_SUFFIX = 'ClientConfig';\n\n/** Same-module string constants that parser-only decorator scanning can safely resolve. */\nexport class ModuleStringConstants {\n constructor(private readonly byName: Map<string, string>) {}\n\n lookup(name: string): string | null {\n return this.byName.get(name) ?? null;\n }\n}\n\n/** Parsed constants per source file — every class in a file shares one table. */\nconst CONSTANTS_BY_FILE = new WeakMap<ts.SourceFile, ModuleStringConstants>();\n\n/** The module-scope string constants of `sourceFile`, parsed once per file. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function stringConstantsOf(sourceFile: ts.SourceFile): ModuleStringConstants {\n const cached = CONSTANTS_BY_FILE.get(sourceFile);\n if (cached !== undefined) return cached;\n const byName = new Map<string, string>();\n for (const statement of sourceFile.statements) {\n if (!ts.isVariableStatement(statement)) continue;\n if ((statement.declarationList.flags & ts.NodeFlags.Const) === 0) continue;\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name)) continue;\n const text = stringValueOf(declaration.initializer);\n if (text !== null) byName.set(declaration.name.text, text);\n }\n }\n const constants = new ModuleStringConstants(byName);\n CONSTANTS_BY_FILE.set(sourceFile, constants);\n return constants;\n}\n\n/** The string an initializer denotes, unwrapping `as const` / parentheses, else null. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function stringValueOf(expr: ts.Expression | undefined): string | null {\n if (expr === undefined) return null;\n if (ts.isStringLiteral(expr) || ts.isNoSubstitutionTemplateLiteral(expr)) return expr.text;\n if (ts.isAsExpression(expr) || ts.isParenthesizedExpression(expr))\n return stringValueOf(expr.expression);\n return null;\n}\n\n/** A resolved decorator string, or the source spelling that could not be reduced. */\nexport class DecoratorArgValue {\n constructor(\n public readonly value: string | null,\n public readonly unresolvedName: string | null,\n ) {}\n}\n\n/** Read one decorator argument as a string, resolving same-module constants. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function decoratorArgValue(\n expr: ts.Expression | undefined,\n constants: ModuleStringConstants,\n): DecoratorArgValue {\n if (expr === undefined) return new DecoratorArgValue(null, null);\n const literal = stringValueOf(expr);\n if (literal !== null) return new DecoratorArgValue(literal, null);\n if (ts.isIdentifier(expr)) {\n const resolved = constants.lookup(expr.text);\n if (resolved !== null) return new DecoratorArgValue(resolved, null);\n return new DecoratorArgValue(null, expr.text);\n }\n return new DecoratorArgValue(null, expr.getText());\n}\n\n/** Resolve the enum-backed constants intentionally allowed in @Endpoint positional arguments. */\n// webpieces-disable no-function-outside-class -- pure AST accessor for decorator source\nfunction endpointSymbolArgValue(\n expr: ts.Expression | undefined,\n constants: ModuleStringConstants,\n): DecoratorArgValue {\n if (expr && ts.isIdentifier(expr)) {\n const builtin = ENDPOINT_SYMBOLS[expr.text];\n if (builtin !== undefined) return new DecoratorArgValue(builtin, null);\n }\n return decoratorArgValue(expr, constants);\n}\n\n/** Aggregates parser-only scan losses so generation can fail loudly instead of dropping routes. */\nexport class DecoratorArgDiagnostics {\n private readonly found: NonLiteralDecoratorArg[] = [];\n private readonly unresolvedPaths: UnresolvedEndpointPath[] = [];\n private readonly emptied: EmptiedApiContract[] = [];\n private readonly undeclaredCallers: UndeclaredExternalCaller[] = [];\n private readonly undeclaredOperations: UndeclaredEndpointOperation[] = [];\n private readonly voidMismatches: VoidResponseMismatch[] = [];\n\n constructor(private readonly workspaceRoot: string) {}\n\n /** Record `argument` (as written) as unresolvable at `node`'s location. */\n record(\n api: string,\n decorator: string,\n method: string | null,\n argument: string,\n node: ts.Node,\n ): void {\n this.found.push(\n new NonLiteralDecoratorArg(api, decorator, method, argument, this.locate(node)),\n );\n }\n\n /** Record an `@Endpoint` whose path argument is unreadable — fatal, see UnresolvedEndpointPathError. */\n recordUnresolvedPath(api: string, method: string, argument: string, node: ts.Node): void {\n this.unresolvedPaths.push(\n new UnresolvedEndpointPath(api, method, argument, this.locate(node)),\n );\n }\n\n /** Record a class that declared `declared` `@Endpoint` methods and kept none of them. */\n recordEmptiedContract(api: string, declared: number, node: ts.Node): void {\n this.emptied.push(new EmptiedApiContract(api, declared, this.locate(node)));\n }\n\n /** Record an `external` `@Endpoint` whose caller is unreadable — fatal, see UndeclaredExternalCallerError. */\n recordUndeclaredCaller(api: string, method: string, argument: string, node: ts.Node): void {\n this.undeclaredCallers.push(\n new UndeclaredExternalCaller(api, method, argument, this.locate(node)),\n );\n }\n\n /** Record an `@Endpoint` whose required operation is missing or unreadable. */\n recordUndeclaredOperation(api: string, method: string, argument: string, node: ts.Node): void {\n this.undeclaredOperations.push(\n new UndeclaredEndpointOperation(api, method, argument, this.locate(node)),\n );\n }\n\n /** Record an `@Endpoint` whose response-body declaration disagrees with its kind or signature. */\n recordVoidMismatch(\n api: string,\n method: string,\n problem: VoidResponseProblem,\n kind: EndpointKind,\n node: ts.Node,\n ): void {\n this.voidMismatches.push(new VoidResponseMismatch(api, method, problem, kind, this.locate(node)));\n }\n\n voidResponseMismatches(): VoidResponseMismatch[] {\n return this.voidMismatches;\n }\n\n all(): NonLiteralDecoratorArg[] {\n return this.found;\n }\n\n unresolvedEndpointPaths(): UnresolvedEndpointPath[] {\n return this.unresolvedPaths;\n }\n\n emptiedContracts(): EmptiedApiContract[] {\n return this.emptied;\n }\n\n undeclaredExternalCallers(): UndeclaredExternalCaller[] {\n return this.undeclaredCallers;\n }\n\n undeclaredEndpointOperations(): UndeclaredEndpointOperation[] {\n return this.undeclaredOperations;\n }\n\n private locate(node: ts.Node): string {\n const sourceFile = node.getSourceFile();\n const position = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n return `${path.relative(this.workspaceRoot, sourceFile.fileName)}:${position.line + 1}`;\n }\n}\n\n/** {api, owner: `project`, type} when `cls` is an `abstract class` carrying `@ApiPath`, else null. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function apiClassInfoFrom(\n cls: ts.ClassDeclaration,\n project: string,\n diagnostics: DecoratorArgDiagnostics | null = null,\n): ApiClassInfo | null {\n if (!isAbstractClass(cls) || !hasClassDecorator(cls, 'ApiPath') || !cls.name) return null;\n const api = cls.name.text;\n const constants = stringConstantsOf(cls.getSourceFile());\n const methods = endpointMethodsOf(cls, api, constants, diagnostics);\n const outbound =\n methods.length > 0 &&\n methods.every((method: ApiMethodMeta) => method.kind === 'external-outbound');\n const info: ApiClassInfo = {\n api,\n owner: project,\n type: outbound ? 'external' : apiTransport(cls),\n methods,\n };\n // An EXTERNAL_OUTBOUND contract is an outside system's API: it is a VENDOR node on the runtime\n // graph, named by its `@externalSystem <kind> [label]` JSDoc tag or, without one, a `saas` box\n // labelled with the contract name minus `Api`.\n if (outbound) {\n info.externalSystem = externalSystemTagFrom(cls, api) ?? {\n kind: 'saas',\n label: api.replace(/Api$/, ''),\n };\n }\n const basePath = decoratorStringArg(cls, 'ApiPath', constants, diagnostics, api);\n if (basePath !== null) info.basePath = basePath;\n return info;\n}\n\n// webpieces-disable no-function-outside-class -- pure AST predicate, matching the sibling helpers in di-graph/bindings.ts\nexport function apiTransport(cls: ts.ClassDeclaration): ApiTransport {\n return hasClassDecorator(cls, 'PubSub') ? 'pubsub' : 'rpc';\n}\n\n/** The @Endpoint kinds that are actually DELIVERED through a named queue or schedule. */\nconst QUEUED_KINDS: readonly EndpointKind[] = ['cloudtasks', 'cron'];\n\n/** Reads required `(method, path, operation, kind, options?)` endpoint declarations in order. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function endpointMethodsOf(\n cls: ts.ClassDeclaration,\n api: string,\n constants: ModuleStringConstants = new ModuleStringConstants(new Map<string, string>()),\n diagnostics: DecoratorArgDiagnostics | null = null,\n): ApiMethodMeta[] {\n const methods: ApiMethodMeta[] = [];\n let declared = 0;\n for (const member of cls.members) {\n if (!ts.isMethodDeclaration(member) || !ts.isIdentifier(member.name)) continue;\n const endpoint = memberDecorator(member, 'Endpoint');\n if (endpoint === null) continue;\n declared++;\n const name = member.name.text;\n const args = decoratorArgs(endpoint);\n const methodArg = endpointSymbolArgValue(args[0], constants);\n const pathArg = decoratorArgValue(args[1], constants);\n const operationArg = endpointSymbolArgValue(args[2], constants);\n const kindArg = endpointSymbolArgValue(args[3], constants);\n reportUnresolved(diagnostics, api, 'Endpoint', name, methodArg, endpoint);\n reportUnresolved(diagnostics, api, 'Endpoint', name, pathArg, endpoint);\n reportUnresolved(diagnostics, api, 'Endpoint', name, operationArg, endpoint);\n reportUnresolved(diagnostics, api, 'Endpoint', name, kindArg, endpoint);\n if (diagnostics !== null && pathArg.unresolvedName !== null) {\n diagnostics.recordUnresolvedPath(api, name, pathArg.unresolvedName, endpoint);\n }\n const httpMethod = methodArg.value;\n reportUnknownVerb(diagnostics, api, name, httpMethod, endpoint);\n const operation = endpointOperationOf(args[2], constants, diagnostics, api, name, endpoint);\n const kind = kindArg.value;\n if (\n httpMethod === null ||\n !CONTRACT_HTTP_METHODS.includes(httpMethod as ContractHttpMethod) ||\n pathArg.value === null ||\n operation === null ||\n kind === null ||\n !ENDPOINT_KINDS.includes(kind as EndpointKind)\n )\n continue;\n const method: ApiMethodMeta = {\n name,\n path: pathArg.value,\n kind: kind as EndpointKind,\n operation,\n httpMethod: httpMethod as ContractHttpMethod,\n };\n const parameters = httpParametersOf(member, httpMethod as ContractHttpMethod, constants, diagnostics, api, name);\n if (parameters.length > 0) method.parameters = parameters;\n readResponseShape(method, member, args[4], constants, diagnostics, api, endpoint);\n if (QUEUED_KINDS.includes(method.kind)) {\n method.queueName = queueNameOf(member, api, name, constants, diagnostics);\n }\n if (method.kind === 'external-inbound') {\n const caller = externalCallerOf(args[4], constants);\n if (caller.declaration !== null) method.caller = caller.declaration;\n else if (diagnostics !== null)\n diagnostics.recordUndeclaredCaller(api, name, caller.problem!, endpoint);\n }\n methods.push(method);\n }\n if (diagnostics !== null && declared > 0 && methods.length === 0) {\n diagnostics.recordEmptiedContract(api, declared, cls);\n }\n return methods;\n}\n\n/** An unknown verb must fail generation, never silently drop the endpoint from the graph. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers\nfunction reportUnknownVerb(\n diagnostics: DecoratorArgDiagnostics | null,\n api: string,\n name: string,\n httpMethod: string | null,\n endpoint: ts.Node,\n): void {\n if (diagnostics === null || httpMethod === null) return;\n if (CONTRACT_HTTP_METHODS.includes(httpMethod as ContractHttpMethod)) return;\n diagnostics.record(api, 'Endpoint.httpMethod', name, httpMethod, endpoint);\n}\n\n/**\n * The response-shape options: `responseType: 'full'`, and the response body (a mismatch is a fatal\n * diagnostic). A CLOUDTASKS / CRON endpoint has no response body BY KIND (#1348): it must return\n * `Promise<void>`, and an explicit `responseBody: NONE` on it is a redundant second spelling. An\n * EXTERNAL_OUTBOUND endpoint's response is shaped by the VENDOR, so NONE (what OUR server sends) is\n * refused there and not required on `Promise<void>`. RPC and EXTERNAL_INBOUND declare\n * `responseBody: NONE`, which must agree with a `Promise<void>` signature in both directions.\n */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers\nfunction readResponseShape(\n method: ApiMethodMeta,\n member: ts.MethodDeclaration,\n options: ts.Expression | undefined,\n constants: ModuleStringConstants,\n diagnostics: DecoratorArgDiagnostics | null,\n api: string,\n endpoint: ts.Node,\n): void {\n if (endpointResponseTypeOf(options, constants) === 'full') method.responseType = 'full';\n const declaresNone = endpointResponseBodyIsNone(options, constants);\n const returnsVoid = returnsPromiseOfVoid(member);\n const problem = responseBodyProblem(method.kind, declaresNone, returnsVoid);\n if (declaresNone && problem === null) method.responseBody = 'none';\n if (diagnostics !== null && problem !== null) {\n diagnostics.recordVoidMismatch(api, method.name, problem, method.kind, endpoint);\n }\n}\n\n/** The one response-body rule per kind (#1348). */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers\nfunction responseBodyProblem(\n kind: EndpointKind,\n declaresNone: boolean,\n returnsVoid: boolean,\n): VoidResponseProblem | null {\n if (QUEUED_KINDS.includes(kind)) return triggerVoidProblem(declaresNone, returnsVoid);\n if (kind === 'external-outbound') return declaresNone ? VoidResponseProblem.OUTBOUND_NONE : null;\n return declaredVoidProblem(declaresNone, returnsVoid);\n}\n\n/** CLOUDTASKS / CRON: void by kind, so NONE is redundant and a non-void signature is refused. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers\nfunction triggerVoidProblem(declaresNone: boolean, returnsVoid: boolean): VoidResponseProblem | null {\n if (declaresNone) return VoidResponseProblem.REDUNDANT_NONE;\n if (!returnsVoid) return VoidResponseProblem.TRIGGER_NOT_VOID;\n return null;\n}\n\n/** RPC / EXTERNAL_INBOUND: `responseBody: NONE` and `Promise<void>` must agree in both directions. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers\nfunction declaredVoidProblem(declaresNone: boolean, returnsVoid: boolean): VoidResponseProblem | null {\n if (declaresNone && !returnsVoid) return VoidResponseProblem.NONE_WITHOUT_VOID;\n if (!declaresNone && returnsVoid) return VoidResponseProblem.VOID_WITHOUT_NONE;\n return null;\n}\n\n/** Required side-effect declaration; no inference from GET/POST is permitted. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers\nexport function endpointOperationOf(\n operationArgument: ts.Expression | undefined,\n constants: ModuleStringConstants,\n diagnostics: DecoratorArgDiagnostics | null,\n api: string,\n method: string,\n node: ts.Node,\n): EndpointOperation | null {\n const declared = endpointSymbolArgValue(operationArgument, constants);\n if (declared.value === null) {\n diagnostics?.recordUndeclaredOperation(\n api,\n method,\n declared.unresolvedName ?? '<missing>',\n node,\n );\n return null;\n }\n reportUnresolved(diagnostics, api, 'Endpoint.operation', method, declared, node);\n if (\n declared.value !== null &&\n ENDPOINT_OPERATIONS.includes(declared.value as EndpointOperation)\n ) {\n return declared.value as EndpointOperation;\n }\n diagnostics?.recordUndeclaredOperation(\n api,\n method,\n declared.unresolvedName ?? declared.value ?? '<missing>',\n node,\n );\n return null;\n}\n\n/** Required first positional HTTP method. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers\nexport function httpMethodOf(\n methodArgument: ts.Expression | undefined,\n constants: ModuleStringConstants,\n diagnostics: DecoratorArgDiagnostics | null,\n api: string,\n method: string,\n node: ts.Node,\n): ContractHttpMethod | null {\n const declared = endpointSymbolArgValue(methodArgument, constants);\n reportUnresolved(diagnostics, api, 'Endpoint.httpMethod', method, declared, node);\n if (CONTRACT_HTTP_METHODS.includes(declared.value as ContractHttpMethod)) {\n return declared.value as ContractHttpMethod;\n }\n return null;\n}\n\n/** Only the non-default full-response marker needs an architecture field. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers\nexport function endpointResponseTypeOf(\n options: ts.Expression | undefined,\n constants: ModuleStringConstants,\n): 'body' | 'full' {\n if (options === undefined || !ts.isObjectLiteralExpression(options)) return 'body';\n return objectPropertyValue(options, 'responseType', constants).value === 'full'\n ? 'full'\n : 'body';\n}\n\n/** `{ responseBody: NONE }` (the enum member, or its `'none'` value) in `@Endpoint`'s options. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers\nexport function endpointResponseBodyIsNone(\n options: ts.Expression | undefined,\n constants: ModuleStringConstants,\n): boolean {\n if (options === undefined || !ts.isObjectLiteralExpression(options)) return false;\n for (const property of options.properties) {\n if (!ts.isPropertyAssignment(property) || !ts.isIdentifier(property.name)) continue;\n if (property.name.text !== 'responseBody') continue;\n const value = property.initializer;\n if (ts.isIdentifier(value) && value.text === 'NONE') return true;\n return decoratorArgValue(value, constants).value === 'none';\n }\n return false;\n}\n\n/** True when the method is declared `Promise<void>` (or `Promise<undefined>`). */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers\nexport function returnsPromiseOfVoid(member: ts.MethodDeclaration): boolean {\n const type = member.type;\n if (type === undefined || !ts.isTypeReferenceNode(type)) return false;\n if (!ts.isIdentifier(type.typeName) || type.typeName.text !== 'Promise') return false;\n const argument = type.typeArguments?.[0];\n if (argument === undefined) return false;\n if (argument.kind === ts.SyntaxKind.VoidKeyword || argument.kind === ts.SyntaxKind.UndefinedKeyword) {\n return true;\n }\n return false;\n}\n\n/** Explicit `@PathParam` / `@QueryParam` / `@QueryString` mappings in source declaration order. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers\nexport function httpParametersOf(\n member: ts.MethodDeclaration,\n httpMethod: ContractHttpMethod,\n constants: ModuleStringConstants,\n diagnostics: DecoratorArgDiagnostics | null,\n api: string,\n method: string,\n): ApiParameterMeta[] {\n const parameters: ApiParameterMeta[] = [];\n member.parameters.forEach((parameter: ts.ParameterDeclaration, index: number) => {\n let mapped = false;\n if (decoratorOn(parameter, 'QueryString') !== null) {\n parameters.push({ index, source: 'query-map' });\n return;\n }\n for (const source of ['path', 'query'] as const) {\n const decoratorNameWanted = source === 'path' ? 'PathParam' : 'QueryParam';\n const decorator = decoratorOn(parameter, decoratorNameWanted);\n if (decorator === null) continue;\n mapped = true;\n const wireName = decoratorArgValue(decoratorArgs(decorator)[0], constants);\n reportUnresolved(diagnostics, api, decoratorNameWanted, method, wireName, decorator);\n if (wireName.value !== null) {\n parameters.push({ index, source, wireName: wireName.value });\n }\n }\n if (!mapped && contractVerbCarriesBody(httpMethod)) parameters.push({ index, source: 'body' });\n });\n return parameters;\n}\n\n/** Default `callerKind` when an `external-inbound` endpoint declares `calledBy` alone — mirrors core-util. */\nconst DEFAULT_CALLER_KIND = 'saas';\n\n/** Resolved EXTERNAL_INBOUND caller declaration, or the source problem that prevented resolution. */\nexport class ExternalCallerRead {\n constructor(\n public readonly declaration: ExternalSystemDeclaration | null,\n /** What was wrong, as written, for the diagnostic. Null exactly when `declaration` is set. */\n public readonly problem: string | null,\n ) {}\n}\n\n/** Reads `calledBy` and optional `callerKind` from the fifth positional options argument. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function externalCallerOf(\n arg: ts.Expression | undefined,\n constants: ModuleStringConstants,\n): ExternalCallerRead {\n if (arg === undefined) return new ExternalCallerRead(null, '<no options argument>');\n if (!ts.isObjectLiteralExpression(arg)) return new ExternalCallerRead(null, arg.getText());\n const calledBy = objectPropertyValue(arg, 'calledBy', constants);\n if (calledBy.value === null || calledBy.value === '') {\n return new ExternalCallerRead(null, calledBy.unresolvedName ?? '<no calledBy>');\n }\n const callerKind = objectPropertyValue(arg, 'callerKind', constants);\n if (callerKind.value === null && callerKind.unresolvedName !== null) {\n return new ExternalCallerRead(null, `callerKind: ${callerKind.unresolvedName}`);\n }\n const kind = callerKind.value ?? DEFAULT_CALLER_KIND;\n if (!isExternalSystemKind(kind)) return new ExternalCallerRead(null, `callerKind: '${kind}'`);\n return new ExternalCallerRead({ kind, label: calledBy.value }, null);\n}\n\n/** One property of an object literal, read as a string through the same constant folding as an argument. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function objectPropertyValue(\n literal: ts.ObjectLiteralExpression,\n name: string,\n constants: ModuleStringConstants,\n): DecoratorArgValue {\n for (const property of literal.properties) {\n if (!ts.isPropertyAssignment(property) || property.name === undefined) continue;\n const key =\n ts.isIdentifier(property.name) || ts.isStringLiteral(property.name)\n ? property.name.text\n : null;\n if (key !== name) continue;\n return decoratorArgValue(property.initializer, constants);\n }\n return new DecoratorArgValue(null, null);\n}\n\n/** `@Queue('...')` override when present and resolvable, else the derived `${Api}-${method}`. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function queueNameOf(\n member: ts.MethodDeclaration,\n api: string,\n name: string,\n constants: ModuleStringConstants,\n diagnostics: DecoratorArgDiagnostics | null,\n): string {\n const override = memberDecorator(member, 'Queue');\n if (override === null) return `${api}-${name}`;\n const queueArg = decoratorArgValue(decoratorArgs(override)[0], constants);\n reportUnresolved(diagnostics, api, 'Queue', name, queueArg, override);\n return queueArg.value ?? `${api}-${name}`;\n}\n\n/** Record an argument that is present but unresolvable; a resolved or absent one is silent. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function reportUnresolved(\n diagnostics: DecoratorArgDiagnostics | null,\n api: string,\n decorator: string,\n method: string | null,\n arg: DecoratorArgValue,\n node: ts.Node,\n): void {\n if (diagnostics === null || arg.unresolvedName === null) return;\n diagnostics.record(api, decorator, method, arg.unresolvedName, node);\n}\n\n/** The arguments of a decorator's call expression, or [] when it is a bare `@Foo` reference. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function decoratorArgs(\n decorator: ts.Decorator,\n): ts.NodeArray<ts.Expression> | ts.Expression[] {\n return ts.isCallExpression(decorator.expression) ? decorator.expression.arguments : [];\n}\n\n/** The named decorator on a class member, or null. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function memberDecorator(member: ts.ClassElement, name: string): ts.Decorator | null {\n const decorators = ts.getDecorators(member as ts.HasDecorators) ?? [];\n return decorators.find((d: ts.Decorator) => decoratorName(d) === name) ?? null;\n}\n\n/** The named decorator on any decorator-capable AST node (notably a method parameter). */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching memberDecorator\nexport function decoratorOn(node: ts.HasDecorators, name: string): ts.Decorator | null {\n const decorators = ts.getDecorators(node) ?? [];\n return decorators.find((decorator: ts.Decorator) => decoratorName(decorator) === name) ?? null;\n}\n\n/**\n * The first argument of a class decorator as a string (`@ApiPath('/x')`, `@ApiPath(X_PATH)`), else\n * null. A same-module constant resolves; anything else is recorded on `diagnostics`.\n */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function decoratorStringArg(\n cls: ts.ClassDeclaration,\n name: string,\n constants: ModuleStringConstants = new ModuleStringConstants(new Map<string, string>()),\n diagnostics: DecoratorArgDiagnostics | null = null,\n api: string = name,\n): string | null {\n const decorator = classDecorators(cls).find((d: ts.Decorator) => decoratorName(d) === name);\n if (decorator === undefined) return null;\n const arg = decoratorArgValue(decoratorArgs(decorator)[0], constants);\n reportUnresolved(diagnostics, api, name, null, arg, decorator);\n return arg.value;\n}\n\n/** The constructor's parameters, or [] when the class declares no constructor. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function constructorParamsOf(cls: ts.ClassDeclaration): readonly ts.ParameterDeclaration[] {\n for (const member of cls.members) {\n if (ts.isConstructorDeclaration(member)) return member.parameters;\n }\n return [];\n}\n\n/**\n * The bare name of a type reference (`GmailApi`, or `gmail.GmailApi` -> `GmailApi`), else null.\n * Generic wrappers are deliberately NOT unwrapped: `Provider<GmailApi>` hands out the contract\n * lazily, which is still a use, but it is not the shape any of these seams take today and guessing\n * at type arguments would start matching things that merely mention a contract.\n */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function typeReferenceName(type: ts.TypeNode | undefined): string | null {\n if (type === undefined || !ts.isTypeReferenceNode(type)) return null;\n const name = type.typeName;\n if (ts.isIdentifier(name)) return name.text;\n return ts.isQualifiedName(name) && ts.isIdentifier(name.right) ? name.right.text : null;\n}\n\n/** Every type name in the class's `implements` clause — the contracts this class IS, not ones it calls. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function implementedTypeNames(cls: ts.ClassDeclaration): Set<string> {\n const names = new Set<string>();\n for (const clause of cls.heritageClauses ?? []) {\n if (clause.token !== ts.SyntaxKind.ImplementsKeyword) continue;\n for (const type of clause.types) {\n if (ts.isIdentifier(type.expression)) names.add(type.expression.text);\n }\n }\n return names;\n}\n\n// webpieces-disable no-function-outside-class -- pure AST predicate, matching the sibling helpers in di-graph/bindings.ts\nexport function isAbstractClass(cls: ts.ClassDeclaration): boolean {\n return (ts.getModifiers(cls) ?? []).some(\n (m: ts.Modifier) => m.kind === ts.SyntaxKind.AbstractKeyword,\n );\n}\n\n// webpieces-disable no-function-outside-class -- pure AST predicate, matching the sibling helpers in di-graph/bindings.ts\nexport function hasClassDecorator(cls: ts.ClassDeclaration, name: string): boolean {\n return classDecorators(cls).some((d: ts.Decorator) => decoratorName(d) === name);\n}\n\n/**\n * The service a client-factory call aims at, from its config argument:\n * `createRpcClient(WarmupApi, new ClientConfig('helper-fsdb'))` → `'helper-fsdb'`.\n *\n * Only a `new <Xxx>ClientConfig('<string literal>')` yields a name. A variable, a template string\n * or a computed expression yields null — the target is genuinely unknown at scan time, and the\n * runtime graph must fall back to fan-out (loudly) rather than guess.\n */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function targetServiceOf(call: ts.CallExpression): string | null {\n if (call.arguments.length < 2) return null;\n const config = call.arguments[1];\n if (!ts.isNewExpression(config) || !ts.isIdentifier(config.expression)) return null;\n if (!config.expression.text.endsWith(CLIENT_CONFIG_SUFFIX)) return null;\n const first = config.arguments?.[0];\n if (first === undefined || !ts.isStringLiteral(first)) return null;\n return first.text.length > 0 ? first.text : null;\n}\n\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function calleeMethodName(call: ts.CallExpression): string | null {\n const callee = call.expression;\n if (ts.isPropertyAccessExpression(callee)) return callee.name.text;\n if (ts.isIdentifier(callee)) return callee.text;\n return null;\n}\n\n// webpieces-disable no-function-outside-class -- pure path predicate, matching the sibling helpers in di-graph/bindings.ts\nexport function isTestFile(fileName: string): boolean {\n return (\n fileName.includes('/__tests__/') ||\n fileName.includes('.spec.') ||\n fileName.includes('.test.')\n );\n}\n\n/** {api, owner, type:'rpc'|'pubsub'} for an in-repo contract class, else null. */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function apiClassInfoFromNode(\n node: ts.Node,\n project: string,\n diagnostics: DecoratorArgDiagnostics | null = null,\n): ApiClassInfo | null {\n return ts.isClassDeclaration(node) ? apiClassInfoFrom(node, project, diagnostics) : null;\n}\n\n/**\n * {api, owner, type:'external'} for a VENDOR contract, else null.\n *\n * A vendor contract cannot be detected the way an in-repo one is. It carries no @ApiPath (there is\n * no route — the call leaves through a vendor SDK), and it is usually a plain `interface` bound to a\n * Symbol token, which is not even a class. So inside a project the workspace has DECLARED external\n * (`runtime-architecture.externalApiPaths`) the signal is structural instead: an exported\n * `interface`/`abstract class` whose name ends in `Api`. That deliberately picks up `GmailApi` and\n * `StorageApi` while leaving their DTOs, `*Config` types and `*Client` implementations alone.\n */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function externalApiInfoFrom(node: ts.Node, project: string): ApiClassInfo | null {\n const named =\n ts.isInterfaceDeclaration(node) || (ts.isClassDeclaration(node) && isAbstractClass(node));\n if (!named || !node.name || !isExported(node)) return null;\n const api = node.name.text;\n if (!api.endsWith(EXTERNAL_CONTRACT_SUFFIX)) return null;\n const externalSystem = externalSystemTagFrom(node, api);\n return externalSystem === null\n ? { api, owner: project, type: 'external', methods: [] }\n : { api, owner: project, type: 'external', methods: [], externalSystem };\n}\n\n/**\n * The `@externalSystem <kind> [label]` JSDoc tag on a vendor contract, or null when absent.\n *\n * JSDoc rather than a decorator is not a style choice: these seams are TS `interface`s, and TS has\n * no interface decorators. Without the tag the contract still renders — as the generic dashed box it\n * always was — so this is purely additive and nothing needs migrating.\n *\n * The label defaults to the contract name minus its `Api` suffix (`FirestoreAdminApi` →\n * `FirestoreAdmin`), because the label is the node IDENTITY: two contracts that mean the same system\n * must be given the SAME explicit label to converge on one node.\n *\n * An unrecognised kind is ignored rather than defaulted. Silently drawing a `@externalSystem\n * databse` typo as a generic box is recoverable; drawing it as the wrong shape teaches the reader\n * something false about the architecture.\n */\n// webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers in di-graph/bindings.ts\nexport function externalSystemTagFrom(\n node: ts.Node,\n api: string,\n): ExternalSystemDeclaration | null {\n for (const tag of ts.getJSDocTags(node)) {\n if (tag.tagName.text !== EXTERNAL_SYSTEM_TAG) continue;\n const comment = typeof tag.comment === 'string' ? tag.comment : '';\n const parts = comment\n .trim()\n .split(/\\s+/)\n .filter((part: string) => part !== '');\n if (parts.length === 0) continue;\n const kind = parts[0].toLowerCase();\n if (!isExternalSystemKind(kind)) continue;\n const label = parts.slice(1).join(' ').trim();\n return { kind, label: label === '' ? api.replace(/Api$/, '') : label };\n }\n return null;\n}\n\n/** True when the declaration carries an `export` modifier. */\n// webpieces-disable no-function-outside-class -- pure AST predicate, matching the sibling helpers in di-graph/bindings.ts\nexport function isExported(node: ts.InterfaceDeclaration | ts.ClassDeclaration): boolean {\n return (ts.getModifiers(node) ?? []).some(\n (m: ts.Modifier) => m.kind === ts.SyntaxKind.ExportKeyword,\n );\n}\n\n// webpieces-disable no-function-outside-class -- recursive fs walker, matching the AST-helper style here\nexport function collectTsFiles(dir: string): string[] {\n const out: string[] = [];\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (entry.name !== 'node_modules') out.push(...collectTsFiles(full));\n } else if (entry.name.endsWith('.ts') && !entry.name.endsWith('.d.ts')) {\n out.push(full);\n }\n }\n return out;\n}\n"]}
|
|
@@ -94,10 +94,15 @@ export declare class RootUnionApiTypeError extends Error {
|
|
|
94
94
|
constructor(findings: RootUnionFindings);
|
|
95
95
|
private static render;
|
|
96
96
|
}
|
|
97
|
-
/**
|
|
97
|
+
/**
|
|
98
|
+
* Endpoints whose response-body declaration disagrees with their kind or their signature (#1339,
|
|
99
|
+
* #1348): CLOUDTASKS / CRON are void BY KIND, EXTERNAL_OUTBOUND is the vendor's to shape, and RPC /
|
|
100
|
+
* EXTERNAL_INBOUND declare `responseBody: NONE`.
|
|
101
|
+
*/
|
|
98
102
|
export declare class VoidResponseMismatchError extends Error {
|
|
99
103
|
readonly endpoints: readonly VoidResponseMismatch[];
|
|
100
104
|
constructor(endpoints: readonly VoidResponseMismatch[]);
|
|
105
|
+
private static line;
|
|
101
106
|
}
|
|
102
107
|
/** Endpoints missing the operation declaration that drives retry safety and MCP annotations. */
|
|
103
108
|
export declare class UndeclaredEndpointOperationError extends Error {
|
|
@@ -15,6 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.EmptiedApiContractError = exports.UndeclaredExternalCallerError = exports.UnresolvedEndpointPathError = exports.MissingBasePathError = exports.UndeclaredEndpointOperationError = exports.VoidResponseMismatchError = exports.RootUnionApiTypeError = exports.ApiRulesForMcpError = exports.ApiRulesForOpenApiError = void 0;
|
|
16
16
|
exports.describeMcpExclusions = describeMcpExclusions;
|
|
17
17
|
exports.describeUnresolvedApiCalls = describeUnresolvedApiCalls;
|
|
18
|
+
const api_relations_1 = require("./api-relations");
|
|
18
19
|
const root_union_scan_1 = require("./root-union-scan");
|
|
19
20
|
const api_doc_rules_1 = require("./api-doc-rules");
|
|
20
21
|
/**
|
|
@@ -215,22 +216,46 @@ class RootUnionApiTypeError extends Error {
|
|
|
215
216
|
}
|
|
216
217
|
}
|
|
217
218
|
exports.RootUnionApiTypeError = RootUnionApiTypeError;
|
|
218
|
-
/**
|
|
219
|
+
/**
|
|
220
|
+
* Endpoints whose response-body declaration disagrees with their kind or their signature (#1339,
|
|
221
|
+
* #1348): CLOUDTASKS / CRON are void BY KIND, EXTERNAL_OUTBOUND is the vendor's to shape, and RPC /
|
|
222
|
+
* EXTERNAL_INBOUND declare `responseBody: NONE`.
|
|
223
|
+
*/
|
|
219
224
|
class VoidResponseMismatchError extends Error {
|
|
220
225
|
endpoints;
|
|
221
226
|
constructor(endpoints) {
|
|
222
|
-
super(`${endpoints.length} @Endpoint(s) disagree with their return type about a response body:\n` +
|
|
227
|
+
super(`${endpoints.length} @Endpoint(s) disagree with their kind or return type about a response body:\n` +
|
|
223
228
|
endpoints
|
|
224
|
-
.map((e) => e.
|
|
225
|
-
? ` • ${e.api}.${e.method} declares responseBody: NONE but does not return Promise<void> — at ${e.at}`
|
|
226
|
-
: ` • ${e.api}.${e.method} returns Promise<void> but does not declare responseBody: NONE — at ${e.at}`)
|
|
229
|
+
.map((e) => ` • ${VoidResponseMismatchError.line(e)} — at ${e.at}`)
|
|
227
230
|
.join('\n') +
|
|
228
231
|
`\n A Promise<void> endpoint answers 204 with 0 bytes, and the runtime cannot see 'void'\n` +
|
|
229
|
-
` (design:returntype is just Promise).
|
|
230
|
-
`
|
|
232
|
+
` (design:returntype is just Promise). A CLOUDTASKS or CRON endpoint is fire-and-forget, so its\n` +
|
|
233
|
+
` KIND already means no response body: it returns Promise<void> and writes no responseBody option.\n` +
|
|
234
|
+
` An EXTERNAL_OUTBOUND endpoint is served by the vendor, which shapes its own responses, so it writes\n` +
|
|
235
|
+
` no responseBody option either (its client accepts any 2xx). RPC and EXTERNAL_INBOUND add\n` +
|
|
236
|
+
` { responseBody: NONE } to @Endpoint's options on every Promise<void> method, and only on those.`);
|
|
231
237
|
this.endpoints = endpoints;
|
|
232
238
|
this.name = 'VoidResponseMismatchError';
|
|
233
239
|
}
|
|
240
|
+
// webpieces-disable no-function-outside-class -- builds the super() message, which runs before `this` exists (parameter property)
|
|
241
|
+
static line(e) {
|
|
242
|
+
const kind = e.kind.toUpperCase();
|
|
243
|
+
switch (e.problem) {
|
|
244
|
+
case api_relations_1.VoidResponseProblem.NONE_WITHOUT_VOID:
|
|
245
|
+
return `${e.api}.${e.method} declares responseBody: NONE but does not return Promise<void>`;
|
|
246
|
+
case api_relations_1.VoidResponseProblem.VOID_WITHOUT_NONE:
|
|
247
|
+
return `${e.api}.${e.method} returns Promise<void> but does not declare responseBody: NONE`;
|
|
248
|
+
case api_relations_1.VoidResponseProblem.REDUNDANT_NONE:
|
|
249
|
+
return (`${e.api}.${e.method} is a ${kind} endpoint and declares responseBody: NONE, which is redundant: ` +
|
|
250
|
+
`the ${kind} kind already means no response body — delete responseBody: NONE`);
|
|
251
|
+
case api_relations_1.VoidResponseProblem.OUTBOUND_NONE:
|
|
252
|
+
return (`${e.api}.${e.method} is an EXTERNAL_OUTBOUND endpoint and declares responseBody: NONE, which does not apply: ` +
|
|
253
|
+
`NONE describes what OUR server sends, and the vendor shapes an outbound response — delete responseBody: NONE`);
|
|
254
|
+
case api_relations_1.VoidResponseProblem.TRIGGER_NOT_VOID:
|
|
255
|
+
return (`${e.api}.${e.method} is a ${kind} endpoint but does not return Promise<void>: ` +
|
|
256
|
+
`a ${kind} endpoint is fire-and-forget and its caller reads only the status — return Promise<void>`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
234
259
|
}
|
|
235
260
|
exports.VoidResponseMismatchError = VoidResponseMismatchError;
|
|
236
261
|
/** Endpoints missing the operation declaration that drives retry safety and MCP annotations. */
|