@webpieces/nx-webpieces-rules 0.4.957 → 0.4.959

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/package.json +7 -7
  2. package/src/lib/api-usage/api-ast.d.ts +11 -3
  3. package/src/lib/api-usage/api-ast.js +109 -14
  4. package/src/lib/api-usage/api-ast.js.map +1 -1
  5. package/src/lib/api-usage/api-contract-errors.d.ts +6 -1
  6. package/src/lib/api-usage/api-contract-errors.js +24 -6
  7. package/src/lib/api-usage/api-contract-errors.js.map +1 -1
  8. package/src/lib/api-usage/api-contract-evidence.js +1 -0
  9. package/src/lib/api-usage/api-contract-evidence.js.map +1 -1
  10. package/src/lib/api-usage/api-doc-rules-scan.d.ts +8 -8
  11. package/src/lib/api-usage/api-doc-rules-scan.js +8 -8
  12. package/src/lib/api-usage/api-doc-rules-scan.js.map +1 -1
  13. package/src/lib/api-usage/api-doc-rules-verdicts.d.ts +9 -7
  14. package/src/lib/api-usage/api-doc-rules-verdicts.js +15 -14
  15. package/src/lib/api-usage/api-doc-rules-verdicts.js.map +1 -1
  16. package/src/lib/api-usage/api-relations.d.ts +33 -8
  17. package/src/lib/api-usage/api-relations.js +32 -1
  18. package/src/lib/api-usage/api-relations.js.map +1 -1
  19. package/src/lib/api-usage/api-scanner.d.ts +3 -1
  20. package/src/lib/api-usage/api-scanner.js +7 -2
  21. package/src/lib/api-usage/api-scanner.js.map +1 -1
  22. package/src/lib/runtime-graph-model.d.ts +2 -2
  23. package/src/lib/runtime-graph-model.js.map +1 -1
  24. package/src/lib/runtime-graph.js +6 -4
  25. package/src/lib/runtime-graph.js.map +1 -1
  26. package/src/lib/runtime-wiring/service-targets.js +6 -0
  27. package/src/lib/runtime-wiring/service-targets.js.map +1 -1
  28. package/src/lib/runtime-wiring/source-extractor.d.ts +5 -0
  29. package/src/lib/runtime-wiring/source-extractor.js +20 -0
  30. package/src/lib/runtime-wiring/source-extractor.js.map +1 -1
  31. package/src/lib/runtime-wiring/source-values.d.ts +6 -1
  32. package/src/lib/runtime-wiring/source-values.js +21 -0
  33. package/src/lib/runtime-wiring/source-values.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.957",
3
+ "version": "0.4.959",
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.957",
24
- "@webpieces/core-util": "0.4.957",
25
- "@webpieces/eslint-rules": "0.4.957",
26
- "@webpieces/rules-config": "0.4.957",
23
+ "@webpieces/api-doc-model": "0.4.959",
24
+ "@webpieces/core-util": "0.4.959",
25
+ "@webpieces/eslint-rules": "0.4.959",
26
+ "@webpieces/rules-config": "0.4.959",
27
27
  "madge": "8.0.0",
28
- "@webpieces/rules-sdk": "0.4.957"
28
+ "@webpieces/rules-sdk": "0.4.959"
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.957"
44
+ "@webpieces/tooling-testkit": "0.4.959"
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 } from './api-relations';
3
+ import { ApiClassInfo, ApiMethodMeta, ApiParameterMeta, ContractHttpMethod, ApiTransport, EmptiedApiContract, EndpointOperation, ExternalSystemDeclaration, NonLiteralDecoratorArg, UndeclaredExternalCaller, UndeclaredEndpointOperation, UnresolvedEndpointPath, VoidResponseMismatch } 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;
@@ -27,6 +27,7 @@ export declare class DecoratorArgDiagnostics {
27
27
  private readonly emptied;
28
28
  private readonly undeclaredCallers;
29
29
  private readonly undeclaredOperations;
30
+ private readonly voidMismatches;
30
31
  constructor(workspaceRoot: string);
31
32
  /** Record `argument` (as written) as unresolvable at `node`'s location. */
32
33
  record(api: string, decorator: string, method: string | null, argument: string, node: ts.Node): void;
@@ -38,6 +39,9 @@ export declare class DecoratorArgDiagnostics {
38
39
  recordUndeclaredCaller(api: string, method: string, argument: string, node: ts.Node): void;
39
40
  /** Record an `@Endpoint` whose required operation is missing or unreadable. */
40
41
  recordUndeclaredOperation(api: string, method: string, argument: string, node: ts.Node): void;
42
+ /** Record an `@Endpoint` whose `responseBody: NONE` disagrees with its `Promise<void>` signature. */
43
+ recordVoidMismatch(api: string, method: string, declaresNone: boolean, node: ts.Node): void;
44
+ voidResponseMismatches(): VoidResponseMismatch[];
41
45
  all(): NonLiteralDecoratorArg[];
42
46
  unresolvedEndpointPaths(): UnresolvedEndpointPath[];
43
47
  emptiedContracts(): EmptiedApiContract[];
@@ -56,9 +60,13 @@ export declare function endpointOperationOf(operationArgument: ts.Expression | u
56
60
  export declare function httpMethodOf(methodArgument: ts.Expression | undefined, constants: ModuleStringConstants, diagnostics: DecoratorArgDiagnostics | null, api: string, method: string, node: ts.Node): ContractHttpMethod | null;
57
61
  /** Only the non-default full-response marker needs an architecture field. */
58
62
  export declare function endpointResponseTypeOf(options: ts.Expression | undefined, constants: ModuleStringConstants): 'body' | 'full';
59
- /** Explicit `@PathParam` / `@QueryParam` mappings in source declaration order. */
63
+ /** `{ responseBody: NONE }` (the enum member, or its `'none'` value) in `@Endpoint`'s options. */
64
+ export declare function endpointResponseBodyIsNone(options: ts.Expression | undefined, constants: ModuleStringConstants): boolean;
65
+ /** True when the method is declared `Promise<void>` (or `Promise<undefined>`). */
66
+ export declare function returnsPromiseOfVoid(member: ts.MethodDeclaration): boolean;
67
+ /** Explicit `@PathParam` / `@QueryParam` / `@QueryString` mappings in source declaration order. */
60
68
  export declare function httpParametersOf(member: ts.MethodDeclaration, httpMethod: ContractHttpMethod, constants: ModuleStringConstants, diagnostics: DecoratorArgDiagnostics | null, api: string, method: string): ApiParameterMeta[];
61
- /** Resolved EXTERNAL caller declaration, or the source problem that prevented resolution. */
69
+ /** Resolved EXTERNAL_INBOUND caller declaration, or the source problem that prevented resolution. */
62
70
  export declare class ExternalCallerRead {
63
71
  readonly declaration: ExternalSystemDeclaration | null;
64
72
  /** What was wrong, as written, for the diagnostic. Null exactly when `declaration` is set. */
@@ -11,6 +11,8 @@ exports.endpointMethodsOf = endpointMethodsOf;
11
11
  exports.endpointOperationOf = endpointOperationOf;
12
12
  exports.httpMethodOf = httpMethodOf;
13
13
  exports.endpointResponseTypeOf = endpointResponseTypeOf;
14
+ exports.endpointResponseBodyIsNone = endpointResponseBodyIsNone;
15
+ exports.returnsPromiseOfVoid = returnsPromiseOfVoid;
14
16
  exports.httpParametersOf = httpParametersOf;
15
17
  exports.externalCallerOf = externalCallerOf;
16
18
  exports.objectPropertyValue = objectPropertyValue;
@@ -40,18 +42,28 @@ const path = tslib_1.__importStar(require("path"));
40
42
  const bindings_1 = require("../di-graph/bindings");
41
43
  const api_relations_1 = require("./api-relations");
42
44
  /** Legal enum-backed `@Endpoint` symbols; tooling reads source without importing application code. */
43
- const ENDPOINT_KINDS = ['rpc', 'cloudtasks', 'cron', 'external'];
45
+ const ENDPOINT_KINDS = [
46
+ 'rpc',
47
+ 'cloudtasks',
48
+ 'cron',
49
+ 'external-inbound',
50
+ 'external-outbound',
51
+ ];
44
52
  const ENDPOINT_OPERATIONS = ['read', 'write-idempotent', 'write'];
45
53
  const ENDPOINT_SYMBOLS = {
46
54
  GET: 'GET',
47
55
  POST: 'POST',
56
+ PUT: 'PUT',
57
+ PATCH: 'PATCH',
58
+ DELETE: 'DELETE',
48
59
  READ: 'read',
49
60
  WRITE_IDEMPOTENT: 'write-idempotent',
50
61
  WRITE: 'write',
51
62
  RPC: 'rpc',
52
63
  CLOUDTASKS: 'cloudtasks',
53
64
  CRON: 'cron',
54
- EXTERNAL: 'external',
65
+ EXTERNAL_INBOUND: 'external-inbound',
66
+ EXTERNAL_OUTBOUND: 'external-outbound',
55
67
  };
56
68
  /**
57
69
  * Name suffix that marks an exported type in an `externalApiPaths` project as a vendor CONTRACT
@@ -159,6 +171,7 @@ class DecoratorArgDiagnostics {
159
171
  emptied = [];
160
172
  undeclaredCallers = [];
161
173
  undeclaredOperations = [];
174
+ voidMismatches = [];
162
175
  constructor(workspaceRoot) {
163
176
  this.workspaceRoot = workspaceRoot;
164
177
  }
@@ -182,6 +195,13 @@ class DecoratorArgDiagnostics {
182
195
  recordUndeclaredOperation(api, method, argument, node) {
183
196
  this.undeclaredOperations.push(new api_relations_1.UndeclaredEndpointOperation(api, method, argument, this.locate(node)));
184
197
  }
198
+ /** Record an `@Endpoint` whose `responseBody: NONE` disagrees with its `Promise<void>` signature. */
199
+ recordVoidMismatch(api, method, declaresNone, node) {
200
+ this.voidMismatches.push(new api_relations_1.VoidResponseMismatch(api, method, declaresNone, this.locate(node)));
201
+ }
202
+ voidResponseMismatches() {
203
+ return this.voidMismatches;
204
+ }
185
205
  all() {
186
206
  return this.found;
187
207
  }
@@ -211,12 +231,24 @@ function apiClassInfoFrom(cls, project, diagnostics = null) {
211
231
  return null;
212
232
  const api = cls.name.text;
213
233
  const constants = stringConstantsOf(cls.getSourceFile());
234
+ const methods = endpointMethodsOf(cls, api, constants, diagnostics);
235
+ const outbound = methods.length > 0 &&
236
+ methods.every((method) => method.kind === 'external-outbound');
214
237
  const info = {
215
238
  api,
216
239
  owner: project,
217
- type: apiTransport(cls),
218
- methods: endpointMethodsOf(cls, api, constants, diagnostics),
240
+ type: outbound ? 'external' : apiTransport(cls),
241
+ methods,
219
242
  };
243
+ // An EXTERNAL_OUTBOUND contract is an outside system's API: it is a VENDOR node on the runtime
244
+ // graph, named by its `@externalSystem <kind> [label]` JSDoc tag or, without one, a `saas` box
245
+ // labelled with the contract name minus `Api`.
246
+ if (outbound) {
247
+ info.externalSystem = externalSystemTagFrom(cls, api) ?? {
248
+ kind: 'saas',
249
+ label: api.replace(/Api$/, ''),
250
+ };
251
+ }
220
252
  const basePath = decoratorStringArg(cls, 'ApiPath', constants, diagnostics, api);
221
253
  if (basePath !== null)
222
254
  info.basePath = basePath;
@@ -254,9 +286,11 @@ function endpointMethodsOf(cls, api, constants = new ModuleStringConstants(new M
254
286
  diagnostics.recordUnresolvedPath(api, name, pathArg.unresolvedName, endpoint);
255
287
  }
256
288
  const httpMethod = methodArg.value;
289
+ reportUnknownVerb(diagnostics, api, name, httpMethod, endpoint);
257
290
  const operation = endpointOperationOf(args[2], constants, diagnostics, api, name, endpoint);
258
291
  const kind = kindArg.value;
259
- if ((httpMethod !== 'GET' && httpMethod !== 'POST') ||
292
+ if (httpMethod === null ||
293
+ !api_relations_1.CONTRACT_HTTP_METHODS.includes(httpMethod) ||
260
294
  pathArg.value === null ||
261
295
  operation === null ||
262
296
  kind === null ||
@@ -267,17 +301,16 @@ function endpointMethodsOf(cls, api, constants = new ModuleStringConstants(new M
267
301
  path: pathArg.value,
268
302
  kind: kind,
269
303
  operation,
270
- httpMethod,
304
+ httpMethod: httpMethod,
271
305
  };
272
306
  const parameters = httpParametersOf(member, httpMethod, constants, diagnostics, api, name);
273
307
  if (parameters.length > 0)
274
308
  method.parameters = parameters;
275
- if (endpointResponseTypeOf(args[4], constants) === 'full')
276
- method.responseType = 'full';
309
+ readResponseShape(method, member, args[4], constants, diagnostics, api, endpoint);
277
310
  if (QUEUED_KINDS.includes(method.kind)) {
278
311
  method.queueName = queueNameOf(member, api, name, constants, diagnostics);
279
312
  }
280
- if (method.kind === 'external') {
313
+ if (method.kind === 'external-inbound') {
281
314
  const caller = externalCallerOf(args[4], constants);
282
315
  if (caller.declaration !== null)
283
316
  method.caller = caller.declaration;
@@ -291,6 +324,30 @@ function endpointMethodsOf(cls, api, constants = new ModuleStringConstants(new M
291
324
  }
292
325
  return methods;
293
326
  }
327
+ /** An unknown verb must fail generation, never silently drop the endpoint from the graph. */
328
+ // webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers
329
+ function reportUnknownVerb(diagnostics, api, name, httpMethod, endpoint) {
330
+ if (diagnostics === null || httpMethod === null)
331
+ return;
332
+ if (api_relations_1.CONTRACT_HTTP_METHODS.includes(httpMethod))
333
+ return;
334
+ diagnostics.record(api, 'Endpoint.httpMethod', name, httpMethod, endpoint);
335
+ }
336
+ /**
337
+ * The response-shape options: `responseType: 'full'`, and `responseBody: NONE`, which must agree with
338
+ * a `Promise<void>` signature in both directions (a mismatch is a fatal diagnostic).
339
+ */
340
+ // webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers
341
+ function readResponseShape(method, member, options, constants, diagnostics, api, endpoint) {
342
+ if (endpointResponseTypeOf(options, constants) === 'full')
343
+ method.responseType = 'full';
344
+ const declaresNone = endpointResponseBodyIsNone(options, constants);
345
+ if (declaresNone)
346
+ method.responseBody = 'none';
347
+ if (diagnostics !== null && declaresNone !== returnsPromiseOfVoid(member)) {
348
+ diagnostics.recordVoidMismatch(api, method.name, declaresNone, endpoint);
349
+ }
350
+ }
294
351
  /** Required side-effect declaration; no inference from GET/POST is permitted. */
295
352
  // webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers
296
353
  function endpointOperationOf(operationArgument, constants, diagnostics, api, method, node) {
@@ -312,8 +369,9 @@ function endpointOperationOf(operationArgument, constants, diagnostics, api, met
312
369
  function httpMethodOf(methodArgument, constants, diagnostics, api, method, node) {
313
370
  const declared = endpointSymbolArgValue(methodArgument, constants);
314
371
  reportUnresolved(diagnostics, api, 'Endpoint.httpMethod', method, declared, node);
315
- if (declared.value === 'GET' || declared.value === 'POST')
372
+ if (api_relations_1.CONTRACT_HTTP_METHODS.includes(declared.value)) {
316
373
  return declared.value;
374
+ }
317
375
  return null;
318
376
  }
319
377
  /** Only the non-default full-response marker needs an architecture field. */
@@ -325,12 +383,49 @@ function endpointResponseTypeOf(options, constants) {
325
383
  ? 'full'
326
384
  : 'body';
327
385
  }
328
- /** Explicit `@PathParam` / `@QueryParam` mappings in source declaration order. */
386
+ /** `{ responseBody: NONE }` (the enum member, or its `'none'` value) in `@Endpoint`'s options. */
387
+ // webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers
388
+ function endpointResponseBodyIsNone(options, constants) {
389
+ if (options === undefined || !ts.isObjectLiteralExpression(options))
390
+ return false;
391
+ for (const property of options.properties) {
392
+ if (!ts.isPropertyAssignment(property) || !ts.isIdentifier(property.name))
393
+ continue;
394
+ if (property.name.text !== 'responseBody')
395
+ continue;
396
+ const value = property.initializer;
397
+ if (ts.isIdentifier(value) && value.text === 'NONE')
398
+ return true;
399
+ return decoratorArgValue(value, constants).value === 'none';
400
+ }
401
+ return false;
402
+ }
403
+ /** True when the method is declared `Promise<void>` (or `Promise<undefined>`). */
404
+ // webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers
405
+ function returnsPromiseOfVoid(member) {
406
+ const type = member.type;
407
+ if (type === undefined || !ts.isTypeReferenceNode(type))
408
+ return false;
409
+ if (!ts.isIdentifier(type.typeName) || type.typeName.text !== 'Promise')
410
+ return false;
411
+ const argument = type.typeArguments?.[0];
412
+ if (argument === undefined)
413
+ return false;
414
+ if (argument.kind === ts.SyntaxKind.VoidKeyword || argument.kind === ts.SyntaxKind.UndefinedKeyword) {
415
+ return true;
416
+ }
417
+ return false;
418
+ }
419
+ /** Explicit `@PathParam` / `@QueryParam` / `@QueryString` mappings in source declaration order. */
329
420
  // webpieces-disable no-function-outside-class -- pure AST accessor, matching the sibling helpers
330
421
  function httpParametersOf(member, httpMethod, constants, diagnostics, api, method) {
331
422
  const parameters = [];
332
423
  member.parameters.forEach((parameter, index) => {
333
424
  let mapped = false;
425
+ if (decoratorOn(parameter, 'QueryString') !== null) {
426
+ parameters.push({ index, source: 'query-map' });
427
+ return;
428
+ }
334
429
  for (const source of ['path', 'query']) {
335
430
  const decoratorNameWanted = source === 'path' ? 'PathParam' : 'QueryParam';
336
431
  const decorator = decoratorOn(parameter, decoratorNameWanted);
@@ -343,14 +438,14 @@ function httpParametersOf(member, httpMethod, constants, diagnostics, api, metho
343
438
  parameters.push({ index, source, wireName: wireName.value });
344
439
  }
345
440
  }
346
- if (!mapped && httpMethod === 'POST')
441
+ if (!mapped && (0, api_relations_1.contractVerbCarriesBody)(httpMethod))
347
442
  parameters.push({ index, source: 'body' });
348
443
  });
349
444
  return parameters;
350
445
  }
351
- /** Default `callerKind` when an `external` endpoint declares `calledBy` alone — mirrors core-util. */
446
+ /** Default `callerKind` when an `external-inbound` endpoint declares `calledBy` alone — mirrors core-util. */
352
447
  const DEFAULT_CALLER_KIND = 'saas';
353
- /** Resolved EXTERNAL caller declaration, or the source problem that prevented resolution. */
448
+ /** Resolved EXTERNAL_INBOUND caller declaration, or the source problem that prevented resolution. */
354
449
  class ExternalCallerRead {
355
450
  declaration;
356
451
  problem;
@@ -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 ContractHttpMethod,\n ApiTransport,\n EmptiedApiContract,\n EndpointKind,\n EndpointOperation,\n ExternalSystemDeclaration,\n isExternalSystemKind,\n NonLiteralDecoratorArg,\n UndeclaredExternalCaller,\n UndeclaredEndpointOperation,\n UnresolvedEndpointPath,\n} from './api-relations';\n\n/** Legal enum-backed `@Endpoint` symbols; tooling reads source without importing application code. */\nconst ENDPOINT_KINDS: readonly EndpointKind[] = ['rpc', 'cloudtasks', 'cron', 'external'];\nconst ENDPOINT_OPERATIONS: readonly EndpointOperation[] = ['read', 'write-idempotent', 'write'];\nconst ENDPOINT_SYMBOLS: Readonly<Record<string, string>> = {\n GET: 'GET',\n POST: 'POST',\n READ: 'read',\n WRITE_IDEMPOTENT: 'write-idempotent',\n WRITE: 'write',\n RPC: 'rpc',\n CLOUDTASKS: 'cloudtasks',\n CRON: 'cron',\n EXTERNAL: 'external',\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\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 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 info: ApiClassInfo = {\n api,\n owner: project,\n type: apiTransport(cls),\n methods: endpointMethodsOf(cls, api, constants, diagnostics),\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 const operation = endpointOperationOf(args[2], constants, diagnostics, api, name, endpoint);\n const kind = kindArg.value;\n if (\n (httpMethod !== 'GET' && httpMethod !== 'POST') ||\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,\n };\n const parameters = httpParametersOf(member, httpMethod, constants, diagnostics, api, name);\n if (parameters.length > 0) method.parameters = parameters;\n if (endpointResponseTypeOf(args[4], constants) === 'full') method.responseType = 'full';\n if (QUEUED_KINDS.includes(method.kind)) {\n method.queueName = queueNameOf(member, api, name, constants, diagnostics);\n }\n if (method.kind === 'external') {\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/** 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 (declared.value === 'GET' || declared.value === 'POST') return declared.value;\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/** Explicit `@PathParam` / `@QueryParam` 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 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 && httpMethod === 'POST') parameters.push({ index, source: 'body' });\n });\n return parameters;\n}\n\n/** Default `callerKind` when an `external` endpoint declares `calledBy` alone — mirrors core-util. */\nconst DEFAULT_CALLER_KIND = 'saas';\n\n/** Resolved EXTERNAL 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} 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"]}
@@ -10,7 +10,7 @@
10
10
  *
11
11
  * Split out of api-scanner.ts, which owns the scan itself and is at its file-size limit.
12
12
  */
13
- import { EmptiedApiContract, UndeclaredEndpointOperation, UndeclaredExternalCaller, UnresolvedApiCall, UnresolvedEndpointPath } from './api-relations';
13
+ import { EmptiedApiContract, UndeclaredEndpointOperation, UndeclaredExternalCaller, UnresolvedApiCall, UnresolvedEndpointPath, VoidResponseMismatch } from './api-relations';
14
14
  import { RootUnionFindings } from './root-union-scan';
15
15
  import { ApiRuleFindings, McpExclusion } from './api-doc-rules';
16
16
  /**
@@ -94,6 +94,11 @@ export declare class RootUnionApiTypeError extends Error {
94
94
  constructor(findings: RootUnionFindings);
95
95
  private static render;
96
96
  }
97
+ /** Endpoints whose `responseBody: NONE` and `Promise<void>` signature disagree (#1339). */
98
+ export declare class VoidResponseMismatchError extends Error {
99
+ readonly endpoints: readonly VoidResponseMismatch[];
100
+ constructor(endpoints: readonly VoidResponseMismatch[]);
101
+ }
97
102
  /** Endpoints missing the operation declaration that drives retry safety and MCP annotations. */
98
103
  export declare class UndeclaredEndpointOperationError extends Error {
99
104
  readonly endpoints: readonly UndeclaredEndpointOperation[];