@webpieces/core-util 0.4.956 → 0.4.958

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/package.json +1 -1
  2. package/src/http/ApiCallInfo.d.ts +71 -11
  3. package/src/http/ApiCallInfo.js +81 -7
  4. package/src/http/ApiCallInfo.js.map +1 -1
  5. package/src/http/ApiMethodInfo.d.ts +14 -0
  6. package/src/http/ApiMethodInfo.js +3 -0
  7. package/src/http/ApiMethodInfo.js.map +1 -1
  8. package/src/http/CallRegistry.d.ts +5 -10
  9. package/src/http/CallRegistry.js +21 -43
  10. package/src/http/CallRegistry.js.map +1 -1
  11. package/src/http/CallRegistryCompileAssertions.js +1 -1
  12. package/src/http/CallRegistryCompileAssertions.js.map +1 -1
  13. package/src/http/CallScope.d.ts +33 -0
  14. package/src/http/CallScope.js +70 -0
  15. package/src/http/CallScope.js.map +1 -0
  16. package/src/http/CallStrategy.d.ts +13 -1
  17. package/src/http/CallStrategy.js +4 -1
  18. package/src/http/CallStrategy.js.map +1 -1
  19. package/src/http/ClientRegistry.d.ts +54 -58
  20. package/src/http/ClientRegistry.js +72 -73
  21. package/src/http/ClientRegistry.js.map +1 -1
  22. package/src/http/ContextMgr.js +12 -2
  23. package/src/http/ContextMgr.js.map +1 -1
  24. package/src/http/DeletedAuthCompileAssertions.js +3 -1
  25. package/src/http/DeletedAuthCompileAssertions.js.map +1 -1
  26. package/src/http/DestinationTrust.d.ts +33 -4
  27. package/src/http/DestinationTrust.js +54 -11
  28. package/src/http/DestinationTrust.js.map +1 -1
  29. package/src/http/EndpointCompileAssertions.js +12 -6
  30. package/src/http/EndpointCompileAssertions.js.map +1 -1
  31. package/src/http/ErrorClassifier.d.ts +20 -27
  32. package/src/http/ErrorClassifier.js +1 -15
  33. package/src/http/ErrorClassifier.js.map +1 -1
  34. package/src/http/ErrorLadderCompileAssertions.d.ts +1 -0
  35. package/src/http/ErrorLadderCompileAssertions.js +42 -0
  36. package/src/http/ErrorLadderCompileAssertions.js.map +1 -0
  37. package/src/http/ErrorTranslator.d.ts +8 -4
  38. package/src/http/ErrorTranslator.js.map +1 -1
  39. package/src/http/ExternalContextKeys.d.ts +31 -0
  40. package/src/http/ExternalContextKeys.js +77 -0
  41. package/src/http/ExternalContextKeys.js.map +1 -0
  42. package/src/http/HttpContract.d.ts +45 -7
  43. package/src/http/HttpContract.js +84 -6
  44. package/src/http/HttpContract.js.map +1 -1
  45. package/src/http/HttpEndpointOptions.d.ts +22 -3
  46. package/src/http/HttpEndpointOptions.js +8 -1
  47. package/src/http/HttpEndpointOptions.js.map +1 -1
  48. package/src/http/LogApiCall.d.ts +4 -1
  49. package/src/http/LogApiCall.js +9 -7
  50. package/src/http/LogApiCall.js.map +1 -1
  51. package/src/http/QueryParams.d.ts +47 -0
  52. package/src/http/QueryParams.js +89 -0
  53. package/src/http/QueryParams.js.map +1 -0
  54. package/src/http/RetryStrategy.js +1 -1
  55. package/src/http/RetryStrategy.js.map +1 -1
  56. package/src/http/RouteMetadata.d.ts +16 -2
  57. package/src/http/RouteMetadata.js +19 -3
  58. package/src/http/RouteMetadata.js.map +1 -1
  59. package/src/http/RouteMetadataFactory.d.ts +25 -0
  60. package/src/http/RouteMetadataFactory.js +97 -12
  61. package/src/http/RouteMetadataFactory.js.map +1 -1
  62. package/src/http/StreamErrorControl.d.ts +9 -1
  63. package/src/http/StreamErrorControl.js +14 -3
  64. package/src/http/StreamErrorControl.js.map +1 -1
  65. package/src/http/WebpiecesDefaultErrorClassifier.d.ts +2 -2
  66. package/src/http/WebpiecesDefaultErrorClassifier.js +2 -2
  67. package/src/http/WebpiecesDefaultErrorClassifier.js.map +1 -1
  68. package/src/http/WebpiecesDefaultErrorTranslator.d.ts +2 -1
  69. package/src/http/WebpiecesDefaultErrorTranslator.js +2 -1
  70. package/src/http/WebpiecesDefaultErrorTranslator.js.map +1 -1
  71. package/src/http/WpAuthApiKeyCompileAssertions.js +2 -2
  72. package/src/http/WpAuthApiKeyCompileAssertions.js.map +1 -1
  73. package/src/http/api-kind.d.ts +3 -2
  74. package/src/http/api-kind.js +5 -4
  75. package/src/http/api-kind.js.map +1 -1
  76. package/src/http/auth-mode.d.ts +8 -2
  77. package/src/http/auth-mode.js +11 -5
  78. package/src/http/auth-mode.js.map +1 -1
  79. package/src/http/decorators.d.ts +39 -21
  80. package/src/http/decorators.js +69 -37
  81. package/src/http/decorators.js.map +1 -1
  82. package/src/http/external-caller.d.ts +12 -17
  83. package/src/http/external-caller.js +12 -17
  84. package/src/http/external-caller.js.map +1 -1
  85. package/src/http/http-parameter-decorators.d.ts +17 -3
  86. package/src/http/http-parameter-decorators.js +27 -6
  87. package/src/http/http-parameter-decorators.js.map +1 -1
  88. package/src/index.d.ts +14 -9
  89. package/src/index.js +32 -13
  90. package/src/index.js.map +1 -1
  91. package/src/ipc/IpcConnection.js +1 -1
  92. package/src/ipc/IpcConnection.js.map +1 -1
  93. package/src/ipc/IpcLogging.js +1 -1
  94. package/src/ipc/IpcLogging.js.map +1 -1
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MISSING_AUTH_DECORATOR_FIX = exports.EXTERNAL = exports.CRON = exports.CLOUDTASKS = exports.RPC = exports.METADATA_KEYS = exports.getHttpParameterDeclarations = exports.QueryParam = exports.PathParam = exports.POST = exports.GET = exports.WRITE = exports.WRITE_IDEMPOTENT = exports.READ = void 0;
3
+ exports.MISSING_AUTH_DECORATOR_FIX = exports.EXTERNAL_OUTBOUND = exports.EXTERNAL_INBOUND = exports.CRON = exports.CLOUDTASKS = exports.RPC = exports.METADATA_KEYS = exports.getHttpParameterDeclarations = exports.QueryString = exports.QueryParam = exports.PathParam = exports.DELETE = exports.PATCH = exports.PUT = exports.POST = exports.GET = exports.NONE = exports.WRITE = exports.WRITE_IDEMPOTENT = exports.READ = void 0;
4
4
  exports.ApiPath = ApiPath;
5
5
  exports.Endpoint = Endpoint;
6
6
  exports.MaskLog = MaskLog;
@@ -16,10 +16,11 @@ exports.getEndpointKind = getEndpointKind;
16
16
  exports.getEndpointHttpMethod = getEndpointHttpMethod;
17
17
  exports.getEndpointOptions = getEndpointOptions;
18
18
  exports.getEndpointOperation = getEndpointOperation;
19
- exports.assertEveryExternalEndpointDeclaresCaller = assertEveryExternalEndpointDeclaresCaller;
19
+ exports.assertExternalEndpointKinds = assertExternalEndpointKinds;
20
+ exports.isExternalOutboundApi = isExternalOutboundApi;
20
21
  exports.isFormPost = isFormPost;
21
22
  exports.isRawBody = isRawBody;
22
- exports.assertEveryWebhookEndpointRetainsRawBody = assertEveryWebhookEndpointRetainsRawBody;
23
+ exports.assertEveryVendorAuthEndpointRetainsRawBody = assertEveryVendorAuthEndpointRetainsRawBody;
23
24
  exports.isApiPath = isApiPath;
24
25
  exports.getAuthMeta = getAuthMeta;
25
26
  exports.assertEveryEndpointHasAuthMode = assertEveryEndpointHasAuthMode;
@@ -37,12 +38,17 @@ var HttpEndpointOptions_2 = require("./HttpEndpointOptions");
37
38
  Object.defineProperty(exports, "READ", { enumerable: true, get: function () { return HttpEndpointOptions_2.READ; } });
38
39
  Object.defineProperty(exports, "WRITE_IDEMPOTENT", { enumerable: true, get: function () { return HttpEndpointOptions_2.WRITE_IDEMPOTENT; } });
39
40
  Object.defineProperty(exports, "WRITE", { enumerable: true, get: function () { return HttpEndpointOptions_2.WRITE; } });
41
+ Object.defineProperty(exports, "NONE", { enumerable: true, get: function () { return HttpEndpointOptions_2.NONE; } });
40
42
  var HttpContract_2 = require("./HttpContract");
41
43
  Object.defineProperty(exports, "GET", { enumerable: true, get: function () { return HttpContract_2.GET; } });
42
44
  Object.defineProperty(exports, "POST", { enumerable: true, get: function () { return HttpContract_2.POST; } });
45
+ Object.defineProperty(exports, "PUT", { enumerable: true, get: function () { return HttpContract_2.PUT; } });
46
+ Object.defineProperty(exports, "PATCH", { enumerable: true, get: function () { return HttpContract_2.PATCH; } });
47
+ Object.defineProperty(exports, "DELETE", { enumerable: true, get: function () { return HttpContract_2.DELETE; } });
43
48
  var http_parameter_decorators_2 = require("./http-parameter-decorators");
44
49
  Object.defineProperty(exports, "PathParam", { enumerable: true, get: function () { return http_parameter_decorators_2.PathParam; } });
45
50
  Object.defineProperty(exports, "QueryParam", { enumerable: true, get: function () { return http_parameter_decorators_2.QueryParam; } });
51
+ Object.defineProperty(exports, "QueryString", { enumerable: true, get: function () { return http_parameter_decorators_2.QueryString; } });
46
52
  Object.defineProperty(exports, "getHttpParameterDeclarations", { enumerable: true, get: function () { return http_parameter_decorators_2.getHttpParameterDeclarations; } });
47
53
  /**
48
54
  * Metadata keys for storing API routing information.
@@ -64,9 +70,9 @@ exports.METADATA_KEYS = {
64
70
  ENDPOINT_HTTP_METHOD: 'webpieces:endpoint-http-method',
65
71
  /** Per-method required read/write semantics, parallel to ENDPOINTS. */
66
72
  ENDPOINT_OPERATION: 'webpieces:endpoint-operation',
67
- /** Per-method @Endpoint trigger kind (rpc | cloudtasks | cron | external), parallel to ENDPOINTS. */
73
+ /** Per-method @Endpoint trigger kind (rpc | cloudtasks | cron | external-inbound | external-outbound), parallel to ENDPOINTS. */
68
74
  ENDPOINT_KIND: 'webpieces:endpoint-kind',
69
- /** Per-method declared external CALLER (only for kind 'external'), parallel to ENDPOINTS. */
75
+ /** Per-method declared external CALLER (only for kind 'external-inbound'), parallel to ENDPOINTS. */
70
76
  ENDPOINT_CALLER: external_caller_1.ENDPOINT_CALLER_KEY,
71
77
  /** Per-method @MaskLog spec (which DTO fields the LogApiCall path masks). */
72
78
  MASK_LOG: 'webpieces:mask-log',
@@ -87,13 +93,24 @@ var EndpointKindValue;
87
93
  EndpointKindValue["RPC"] = "rpc";
88
94
  EndpointKindValue["CLOUDTASKS"] = "cloudtasks";
89
95
  EndpointKindValue["CRON"] = "cron";
90
- EndpointKindValue["EXTERNAL"] = "external";
96
+ EndpointKindValue["EXTERNAL_INBOUND"] = "external-inbound";
97
+ EndpointKindValue["EXTERNAL_OUTBOUND"] = "external-outbound";
91
98
  })(EndpointKindValue || (EndpointKindValue = {}));
92
99
  /** Short, statically importable decorator arguments. */
93
100
  exports.RPC = EndpointKindValue.RPC;
94
101
  exports.CLOUDTASKS = EndpointKindValue.CLOUDTASKS;
95
102
  exports.CRON = EndpointKindValue.CRON;
96
- exports.EXTERNAL = EndpointKindValue.EXTERNAL;
103
+ /**
104
+ * An OUTSIDE system calls US (a vendor webhook, a push subscription). Requires `calledBy`, which names
105
+ * that system on the runtime architecture graph.
106
+ */
107
+ exports.EXTERNAL_INBOUND = EndpointKindValue.EXTERNAL_INBOUND;
108
+ /**
109
+ * WE call an OUTSIDE system (a vendor API, a partner's webhook receiver). No server in this repo
110
+ * implements it, every method of the contract must be this kind, and the client sends ONLY the
111
+ * context keys listed with `@ExternalContextKeys(...)` and merges no response header into our context.
112
+ */
113
+ exports.EXTERNAL_OUTBOUND = EndpointKindValue.EXTERNAL_OUTBOUND;
97
114
  /** Class decorator that sets the shared base path for all endpoints. */
98
115
  function ApiPath(basePath) {
99
116
  return (target) => {
@@ -118,14 +135,14 @@ function Endpoint(httpMethod, path, operation, kind, options = {}) {
118
135
  }
119
136
  // webpieces-disable no-function-outside-class -- runtime validation backs up nominal TS enums
120
137
  function validateEndpointClassification(httpMethod, operation, kind) {
121
- if (!isHttpMethod(httpMethod)) {
122
- throw new Error(`@Endpoint httpMethod must be GET or POST, received '${String(httpMethod)}'.`);
138
+ if (!(0, HttpContract_1.isHttpMethod)(httpMethod)) {
139
+ throw new Error(`@Endpoint httpMethod must be one of ${HttpContract_1.HTTP_METHODS.join(', ')}, received '${String(httpMethod)}'.`);
123
140
  }
124
141
  if (!isEndpointOperation(operation)) {
125
142
  throw new Error(`@Endpoint operation must be READ, WRITE_IDEMPOTENT, or WRITE, received '${String(operation)}'.`);
126
143
  }
127
144
  if (!isEndpointKind(kind)) {
128
- throw new Error(`@Endpoint trigger must be RPC, CLOUDTASKS, CRON, or EXTERNAL, received '${String(kind)}'.`);
145
+ throw new Error(`@Endpoint trigger must be RPC, CLOUDTASKS, CRON, EXTERNAL_INBOUND, or EXTERNAL_OUTBOUND, received '${String(kind)}'.`);
129
146
  }
130
147
  }
131
148
  // webpieces-disable no-function-outside-class -- one metadata write shared by the decorator overloads
@@ -146,7 +163,7 @@ function recordEndpointMetadata(metadataTarget, propertyKey, httpMethod, path, o
146
163
  opts[propertyKey] = options;
147
164
  Reflect.defineMetadata(exports.METADATA_KEYS.ENDPOINT_OPTIONS, opts, metadataTarget);
148
165
  const declared = options;
149
- if (kind !== exports.EXTERNAL ||
166
+ if (kind !== exports.EXTERNAL_INBOUND ||
150
167
  typeof declared.calledBy !== 'string' ||
151
168
  declared.calledBy === '')
152
169
  return;
@@ -267,8 +284,8 @@ function getEndpointKind(apiClass, methodName) {
267
284
  function getEndpointHttpMethod(apiClass, methodName) {
268
285
  const methods = Reflect.getMetadata(exports.METADATA_KEYS.ENDPOINT_HTTP_METHOD, apiClass) || {};
269
286
  const method = methods[methodName];
270
- if (!isHttpMethod(method)) {
271
- throw new Error(`@Endpoint ${apiClass.name || 'Unknown'}.${methodName} must declare GET or POST.`);
287
+ if (!(0, HttpContract_1.isHttpMethod)(method)) {
288
+ throw new Error(`@Endpoint ${apiClass.name || 'Unknown'}.${methodName} must declare one of ${HttpContract_1.HTTP_METHODS.join(', ')}.`);
272
289
  }
273
290
  return method;
274
291
  }
@@ -302,35 +319,50 @@ function isEndpointOperation(value) {
302
319
  value === HttpEndpointOptions_1.WRITE_IDEMPOTENT ||
303
320
  value === HttpEndpointOptions_1.WRITE);
304
321
  }
305
- // webpieces-disable no-function-outside-class -- runtime backstop for JavaScript and `as any` callers; webpieces-disable no-any-unknown -- untrusted runtime value is narrowed to an HTTP method
306
- function isHttpMethod(value) {
307
- return value === HttpContract_1.GET || value === HttpContract_1.POST;
308
- }
309
322
  // webpieces-disable no-function-outside-class -- runtime backstop for JavaScript and `as any` callers; webpieces-disable no-any-unknown -- untrusted runtime value is narrowed to an endpoint kind
310
323
  function isEndpointKind(value) {
311
324
  return (value === exports.RPC ||
312
325
  value === exports.CLOUDTASKS ||
313
326
  value === exports.CRON ||
314
- value === exports.EXTERNAL);
327
+ value === exports.EXTERNAL_INBOUND ||
328
+ value === exports.EXTERNAL_OUTBOUND);
315
329
  }
316
330
  /**
317
- * Fail-fast at wiring time when an `external` endpoint declared no caller. The {@link Endpoint}
318
- * overloads already make that a COMPILE error; this is the backstop for the ways TS is bypassed —
319
- * a JS caller, an `as any` options object, a hand-rolled Reflect.defineMetadata.
320
- * @throws Error naming the first external endpoint with no `calledBy`.
331
+ * Fail-fast at wiring time on the two EXTERNAL_* rules, called by `RouteMetadataFactory` for every
332
+ * transport (server routes and every client). The {@link Endpoint} overloads already make a missing
333
+ * `calledBy` a COMPILE error; this is the backstop for the ways TS is bypassed — a JS caller, an
334
+ * `as any` options object, a hand-rolled Reflect.defineMetadata. The second rule cannot be a type:
335
+ * "every method of this class" spans several decorators.
336
+ *
337
+ * @throws Error naming the first EXTERNAL_INBOUND endpoint with no `calledBy`, or the first method of
338
+ * a contract that mixes EXTERNAL_OUTBOUND with any other kind.
321
339
  */
322
340
  // webpieces-disable no-function-outside-class -- wiring-time assert, sibling of assertEveryEndpointHasAuthMode
323
- function assertEveryExternalEndpointDeclaresCaller(apiClass) {
341
+ function assertExternalEndpointKinds(apiClass) {
324
342
  const kinds = getEndpointKinds(apiClass);
325
- for (const methodName of Object.keys(kinds)) {
326
- if (kinds[methodName] !== 'external' ||
327
- (0, external_caller_1.getEndpointCaller)(apiClass, methodName) !== undefined)
343
+ const apiName = apiClass.name || 'Unknown';
344
+ const methods = Object.keys(kinds);
345
+ const outbound = methods.filter((methodName) => kinds[methodName] === exports.EXTERNAL_OUTBOUND);
346
+ if (outbound.length > 0 && outbound.length !== methods.length) {
347
+ const other = methods.find((methodName) => kinds[methodName] !== exports.EXTERNAL_OUTBOUND);
348
+ throw new Error(`${apiName} mixes EXTERNAL_OUTBOUND (${outbound[0]}) with ${String(kinds[other]).toUpperCase()} (${other}). ` +
349
+ `An EXTERNAL_OUTBOUND contract is an outside system's API that no server in this repo implements, so ` +
350
+ `EVERY method of it must be EXTERNAL_OUTBOUND; move the other methods to their own contract.`);
351
+ }
352
+ for (const methodName of methods) {
353
+ if (kinds[methodName] !== exports.EXTERNAL_INBOUND || (0, external_caller_1.getEndpointCaller)(apiClass, methodName) !== undefined)
328
354
  continue;
329
- throw new Error(`External endpoint '${methodName}' in ${apiClass.name || 'Unknown'} declares no caller. Say WHO ` +
330
- `posts to it: @Endpoint(POST, path, WRITE, EXTERNAL, { calledBy: '<vendor>' }) — the runtime architecture ` +
355
+ throw new Error(`External endpoint '${methodName}' in ${apiName} declares no caller. Say WHO ` +
356
+ `posts to it: @Endpoint(POST, path, WRITE, EXTERNAL_INBOUND, { calledBy: '<vendor>' }) — the runtime architecture ` +
331
357
  `graph cannot name an inbound caller it was never told about.`);
332
358
  }
333
359
  }
360
+ /** True when the contract is an outside system's API: every method is EXTERNAL_OUTBOUND. */
361
+ // webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpointKinds
362
+ function isExternalOutboundApi(apiClass) {
363
+ const kinds = Object.values(getEndpointKinds(apiClass));
364
+ return kinds.length > 0 && kinds.every((kind) => kind === exports.EXTERNAL_OUTBOUND);
365
+ }
334
366
  /**
335
367
  * True when the method's @Endpoint declared `{ formPost: true }` — its body is
336
368
  * application/x-www-form-urlencoded (flat), not JSON.
@@ -341,33 +373,33 @@ function isFormPost(apiClass, methodName) {
341
373
  }
342
374
  /**
343
375
  * True when the method's @Endpoint declared `{ rawBody: true }` — the transport must retain the
344
- * verbatim bytes + absolute url for an {@link WebhookAuthCallback} hook to verify.
376
+ * verbatim bytes + absolute url for a `VendorAuthHook.verify` to check.
345
377
  */
346
378
  // webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of isFormPost
347
379
  function isRawBody(apiClass, methodName) {
348
380
  return getEndpointOptions(apiClass, methodName).rawBody === true;
349
381
  }
350
382
  /**
351
- * Fail-fast at wiring time when an `webhook(...)` endpoint did not ask the transport to keep the
383
+ * Fail-fast at wiring time when a SERVED `vendorAuth(...)` endpoint did not ask the transport to keep the
352
384
  * bytes it is supposed to verify. A hook with nothing to verify is a MISCONFIGURATION, and it must
353
385
  * surface at startup, naming the fix — not as a 401 in production on exactly the traffic the endpoint
354
386
  * exists for.
355
387
  *
356
388
  * This pairing is a runtime assert rather than a type because the two halves live on DIFFERENT
357
- * decorators (`webhook(...)` and `@Endpoint`), and no union over one decorator's argument can say
389
+ * decorators (`vendorAuth(...)` and `@Endpoint`), and no union over one decorator's argument can say
358
390
  * anything about the other's.
359
391
  *
360
- * @throws Error naming the first `webhook(...)` endpoint missing `{ rawBody: true }`.
392
+ * @throws Error naming the first `vendorAuth(...)` endpoint missing `{ rawBody: true }`.
361
393
  */
362
394
  // webpieces-disable no-function-outside-class -- wiring-time assert, sibling of assertEveryEndpointHasAuthMode
363
- function assertEveryWebhookEndpointRetainsRawBody(apiClass) {
395
+ function assertEveryVendorAuthEndpointRetainsRawBody(apiClass) {
364
396
  const endpoints = getEndpoints(apiClass) || {};
365
397
  for (const methodName of Object.keys(endpoints)) {
366
- if (!getAuthMeta(apiClass, methodName)?.methods.some((method) => method.kind === 'webhook') ||
398
+ if (!getAuthMeta(apiClass, methodName)?.methods.some((method) => method.kind === 'vendorAuth') ||
367
399
  isRawBody(apiClass, methodName))
368
400
  continue;
369
- throw new Error(`Endpoint '${methodName}' in ${apiClass.name || 'Unknown'} is webhook(...) but its @Endpoint ` +
370
- `does not declare { rawBody: true }. A webhook hook verifies a signature over the bytes and ` +
401
+ throw new Error(`Endpoint '${methodName}' in ${apiClass.name || 'Unknown'} is vendorAuth(...) but its @Endpoint ` +
402
+ `does not declare { rawBody: true }. VendorAuthHook.verify checks a credential over the bytes and ` +
371
403
  `the url the SENDER transmitted, and without that option the transport parses the body and ` +
372
404
  `throws them away — leaving the hook nothing to check.`);
373
405
  }
@@ -392,7 +424,7 @@ function getAuthMeta(apiClass, methodName) {
392
424
  * the caller hits becomes the API they believe exists. It leads with the ROLE-GATED member on purpose —
393
425
  * the first thing offered should not be the widest grant.
394
426
  */
395
- exports.MISSING_AUTH_DECORATOR_FIX = "Declare @WpAuth([jwt(), oidcSameProject() or oidcSvcs(['svc-a']), sharedSecret(key), webhook(name), apiKey('regime', [{in: 'header', key: MyKeys.API_KEY}])]) " +
427
+ exports.MISSING_AUTH_DECORATOR_FIX = "Declare @WpAuth([jwt(), oidcSameProject() or oidcSvcs(['svc-a']), sharedSecret(key), vendorAuth(name), apiKey('regime', [{in: 'header', key: MyKeys.API_KEY}])]) " +
396
428
  "or @WpAuthPublic('reason'), and exactly one @WpAuthorization on every endpoint. Add @WpLocalOnly() separately when locality is required.";
397
429
  /**
398
430
  * Fail-fast at wiring time if any endpoint lacks an auth mode. Both the server
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/http/decorators.ts"],"names":[],"mappings":"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","sourcesContent":["import 'reflect-metadata';\nimport { MaskSpec, MaskMode } from './LogFieldMask';\nimport {\n DEFAULT_CALLER_KIND,\n ENDPOINT_CALLER_KEY,\n ExternalCaller,\n getEndpointCaller,\n} from './external-caller';\n// The TYPE layer these decorators attach — split out for file size only (see auth-mode.ts).\nimport { AuthMeta, AuthMethods, AuthMode } from './auth-mode';\nimport {\n EndpointOperation,\n EndpointOptions,\n ExternalEndpointOptions,\n READ,\n WRITE_IDEMPOTENT,\n WRITE,\n} from './HttpEndpointOptions';\nimport { GET, HttpMethod, POST } from './HttpContract';\nimport { AuthorizationDeclaration, AuthorizationType, AUTHORIZATION_METHODS_KEY, getAuthorization } from './authorization';\nimport { HTTP_PARAMETERS_METADATA_KEY } from './http-parameter-decorators';\n\nexport type { EndpointOptions, ExternalEndpointOptions } from './HttpEndpointOptions';\nexport type { EndpointOperation } from './HttpEndpointOptions';\nexport { READ, WRITE_IDEMPOTENT, WRITE } from './HttpEndpointOptions';\nexport type { HttpMethod } from './HttpContract';\nexport { GET, POST } from './HttpContract';\nexport { PathParam, QueryParam, getHttpParameterDeclarations } from './http-parameter-decorators';\n\n/**\n * Metadata keys for storing API routing information.\n * These keys are used by both server-side (routing) and client-side (client generation).\n */\nexport const METADATA_KEYS = {\n API_PATH: 'webpieces:api-path',\n ENDPOINTS: 'webpieces:endpoints',\n AUTH_META: 'webpieces:auth-meta',\n /** Method names carrying one of the canonical authorization decorators. */\n AUTH_METHODS: 'webpieces:auth-methods',\n /** 'rpc' (default, sync request/response) vs 'pubsub' (fire-and-forget cloud task). */\n API_KIND: 'webpieces:api-kind',\n /** Per-method Cloud Tasks queue-name override (set via @Queue). */\n QUEUE_OVERRIDE: 'webpieces:queue-override',\n /** Per-method @Endpoint options (e.g. formPost), parallel to ENDPOINTS. */\n ENDPOINT_OPTIONS: 'webpieces:endpoint-options',\n /** Per-method required HTTP method, parallel to ENDPOINTS. */\n ENDPOINT_HTTP_METHOD: 'webpieces:endpoint-http-method',\n /** Per-method required read/write semantics, parallel to ENDPOINTS. */\n ENDPOINT_OPERATION: 'webpieces:endpoint-operation',\n /** Per-method @Endpoint trigger kind (rpc | cloudtasks | cron | external), parallel to ENDPOINTS. */\n ENDPOINT_KIND: 'webpieces:endpoint-kind',\n /** Per-method declared external CALLER (only for kind 'external'), parallel to ENDPOINTS. */\n ENDPOINT_CALLER: ENDPOINT_CALLER_KEY,\n /** Per-method @MaskLog spec (which DTO fields the LogApiCall path masks). */\n MASK_LOG: 'webpieces:mask-log',\n /** Per-method opt-in metadata for publishing an RPC endpoint as an MCP tool. */\n MCP_TOOLS: 'webpieces:mcp-tools',\n /** Per-method PERMANENT exclusion from MCP, with the reason — see @InvalidEndpointForMcp. */\n MCP_INVALID: 'webpieces:mcp-invalid',\n /** Per-method request/response event metadata for a typed streaming endpoint. */\n STREAM_ENDPOINTS: 'webpieces:stream-endpoints',\n /** Per-method MCP-user authorization, intentionally separate from HTTP hop auth. */\n LOCAL_ONLY: 'webpieces:local-only',\n /** Per-method explicit path/query parameter declarations, keyed by parameter index. */\n HTTP_PARAMETERS: HTTP_PARAMETERS_METADATA_KEY,\n};\n\n/** Nominal backing keeps raw string literals out of endpoint declarations. */\nenum EndpointKindValue {\n RPC = 'rpc',\n CLOUDTASKS = 'cloudtasks',\n CRON = 'cron',\n EXTERNAL = 'external',\n}\n\n/** Short, statically importable decorator arguments. */\nexport const RPC = EndpointKindValue.RPC;\nexport const CLOUDTASKS = EndpointKindValue.CLOUDTASKS;\nexport const CRON = EndpointKindValue.CRON;\nexport const EXTERNAL = EndpointKindValue.EXTERNAL;\n\n/** Runtime trigger/delivery owner used by validation, architecture, and infrastructure tooling. */\nexport type EndpointKind = typeof RPC | typeof CLOUDTASKS | typeof CRON | typeof EXTERNAL;\n\n/** Class decorator that sets the shared base path for all endpoints. */\nexport function ApiPath(basePath: string): ClassDecorator {\n return (target: Function) => {\n if (Reflect.hasMetadata('webpieces:ipc-api-id', target)) {\n throw new Error(\n `Class ${target.name || 'Unknown'} cannot combine @ApiPath with @WpInternal.`,\n );\n }\n Reflect.defineMetadata(METADATA_KEYS.API_PATH, basePath, target);\n\n // Initialize endpoints map if not exists\n if (!Reflect.hasMetadata(METADATA_KEYS.ENDPOINTS, target)) {\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINTS, {}, target);\n }\n };\n}\n\n/**\n * Registers `@Endpoint(POST, path, WRITE, RPC)`. Method, operation, and trigger are required enum\n * values. Operation is independent of the HTTP verb. EXTERNAL additionally requires `calledBy`.\n * Each classification rides a parallel metadata map while ENDPOINTS remains method-name -> path.\n */\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nexport function Endpoint(\n httpMethod: HttpMethod,\n path: string,\n operation: EndpointOperation,\n kind: typeof EXTERNAL,\n options: ExternalEndpointOptions,\n): MethodDecorator;\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nexport function Endpoint(\n httpMethod: HttpMethod,\n path: string,\n operation: EndpointOperation,\n kind: Exclude<EndpointKind, typeof EXTERNAL>,\n options?: EndpointOptions,\n): MethodDecorator;\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nexport function Endpoint(\n httpMethod: HttpMethod,\n path: string,\n operation: EndpointOperation,\n kind: EndpointKind,\n options: EndpointOptions = {},\n): MethodDecorator {\n validateEndpointClassification(httpMethod, operation, kind);\n // webpieces-disable no-any-unknown -- reflect-metadata decorator API requires any\n return (target: any, propertyKey: string | symbol, _descriptor: PropertyDescriptor) => {\n const metadataTarget = typeof target === 'function' ? target : target.constructor;\n recordEndpointMetadata(\n metadataTarget,\n propertyKey as string,\n httpMethod,\n path,\n operation,\n kind,\n options,\n );\n };\n}\n\n// webpieces-disable no-function-outside-class -- runtime validation backs up nominal TS enums\nfunction validateEndpointClassification(\n httpMethod: HttpMethod,\n operation: EndpointOperation,\n kind: EndpointKind,\n): void {\n if (!isHttpMethod(httpMethod)) {\n throw new Error(\n `@Endpoint httpMethod must be GET or POST, received '${String(httpMethod)}'.`,\n );\n }\n if (!isEndpointOperation(operation)) {\n throw new Error(\n `@Endpoint operation must be READ, WRITE_IDEMPOTENT, or WRITE, received '${String(operation)}'.`,\n );\n }\n if (!isEndpointKind(kind)) {\n throw new Error(\n `@Endpoint trigger must be RPC, CLOUDTASKS, CRON, or EXTERNAL, received '${String(kind)}'.`,\n );\n }\n}\n\n// webpieces-disable no-function-outside-class -- one metadata write shared by the decorator overloads\nfunction recordEndpointMetadata(\n metadataTarget: Function,\n propertyKey: string,\n httpMethod: HttpMethod,\n path: string,\n operation: EndpointOperation,\n kind: EndpointKind,\n options: EndpointOptions,\n): void {\n const endpoints: Record<string, string> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINTS, metadataTarget) || {};\n\n endpoints[propertyKey] = path;\n\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINTS, endpoints, metadataTarget);\n\n const methods: Record<string, HttpMethod> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_HTTP_METHOD, metadataTarget) || {};\n methods[propertyKey] = httpMethod;\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINT_HTTP_METHOD, methods, metadataTarget);\n\n const operations: Record<string, EndpointOperation> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_OPERATION, metadataTarget) || {};\n operations[propertyKey] = operation;\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINT_OPERATION, operations, metadataTarget);\n\n const kinds: Record<string, EndpointKind> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_KIND, metadataTarget) || {};\n kinds[propertyKey] = kind;\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINT_KIND, kinds, metadataTarget);\n\n const opts: Record<string, EndpointOptions> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_OPTIONS, metadataTarget) || {};\n opts[propertyKey] = options;\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINT_OPTIONS, opts, metadataTarget);\n\n const declared = options as ExternalEndpointOptions;\n if (\n kind !== EXTERNAL ||\n typeof declared.calledBy !== 'string' ||\n declared.calledBy === ''\n )\n return;\n const callers: Record<string, ExternalCaller> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_CALLER, metadataTarget) || {};\n callers[propertyKey] = new ExternalCaller(\n declared.callerKind ?? DEFAULT_CALLER_KIND,\n declared.calledBy,\n );\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINT_CALLER, callers, metadataTarget);\n}\n\n/** Declares request/response DTO field names that API logging must mask at any depth. */\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nexport function MaskLog(fields: Record<string, MaskMode>): MethodDecorator {\n const spec = new MaskSpec(fields);\n // webpieces-disable no-any-unknown -- reflect-metadata decorator API requires any\n return (target: any, propertyKey: string | symbol, _descriptor: PropertyDescriptor) => {\n const metadataTarget = typeof target === 'function' ? target : target.constructor;\n const specs: Record<string, MaskSpec> =\n Reflect.getMetadata(METADATA_KEYS.MASK_LOG, metadataTarget) || {};\n specs[propertyKey as string] = spec;\n Reflect.defineMetadata(METADATA_KEYS.MASK_LOG, specs, metadataTarget);\n };\n}\n\n/**\n * The @MaskLog spec for one method, or undefined if the method declared none (the common case — the\n * caller then logs the DTO verbatim on the plain JSON.stringify fast path).\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpointOptions\nexport function getMaskSpec(apiClass: Function, methodName: string): MaskSpec | undefined {\n const specs: Record<string, MaskSpec> =\n Reflect.getMetadata(METADATA_KEYS.MASK_LOG, apiClass) || {};\n return specs[methodName];\n}\n\n/**\n * Shared implementation for every auth decorator. Authorization is deliberately\n * method-only: a class-level default is too easy to miss when reviewing one endpoint.\n */\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nfunction defineAuthMetadata(authMeta: AuthMeta): MethodDecorator {\n\n // webpieces-disable no-any-unknown -- reflect-metadata decorator API requires any\n return (target: any, propertyKey?: string | symbol, _descriptor?: PropertyDescriptor) => {\n if (propertyKey === undefined) {\n throw new Error(\n 'Authorization decorators are method-only; annotate every @Endpoint explicitly.',\n );\n }\n const metadataTarget = typeof target === 'function' ? target : target.constructor;\n if (Reflect.hasMetadata('webpieces:ipc-api-id', metadataTarget)) {\n throw new Error(\n `Internal API ${metadataTarget.name || 'Unknown'} cannot use HTTP authorization decorators.`,\n );\n }\n validateNoConflictingDecorators(metadataTarget, propertyKey as string);\n Reflect.defineMetadata(METADATA_KEYS.AUTH_META, authMeta, metadataTarget, propertyKey);\n const methods = new Set<string>(\n Reflect.getMetadata(METADATA_KEYS.AUTH_METHODS, metadataTarget) || [],\n );\n methods.add(propertyKey as string);\n Reflect.defineMetadata(METADATA_KEYS.AUTH_METHODS, [...methods], metadataTarget);\n };\n}\n\n/**\n * @WpAuthPublic(reason) - endpoint intentionally requires no authentication.\n * The non-empty reason makes anonymous exposure an explicit review decision.\n */\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nexport function WpAuthPublic(reason: string): MethodDecorator {\n if (typeof reason !== 'string' || reason.trim() === '') {\n throw new Error(\n '@WpAuthPublic requires a non-empty reason explaining why anonymous access is required.',\n );\n }\n return defineAuthMetadata(new AuthMeta([{ kind: 'public' }], reason));\n}\n\n/** Protected network ingress: authenticate one declared credential, then authorize independently. */\n// webpieces-disable no-function-outside-class -- canonical method decorator factory\nexport function WpAuth(methods: AuthMethods): MethodDecorator {\n return defineAuthMetadata(new AuthMeta(methods, undefined));\n}\n\n/** Locality is independent of authentication and cannot prove a user or machine identity. */\n// webpieces-disable no-function-outside-class -- canonical method decorator factory\nexport function WpLocalOnly(): MethodDecorator {\n return (target: object, methodName: string | symbol) => {\n if (methodName === undefined) throw new Error('@WpLocalOnly is method-only.');\n Reflect.defineMetadata(METADATA_KEYS.LOCAL_ONLY, true, target.constructor, methodName);\n };\n}\n\n// webpieces-disable no-function-outside-class -- canonical metadata reader\nexport function isLocalOnly(apiClass: Function, methodName: string): boolean {\n return Reflect.getMetadata(METADATA_KEYS.LOCAL_ONLY, apiClass, methodName) === true;\n}\n\n// ============================================================\n// Helper functions\n// ============================================================\n\n/**\n * Get the base path from @ApiPath decorator.\n */\nexport function getApiPath(apiClass: Function): string | undefined {\n return Reflect.getMetadata(METADATA_KEYS.API_PATH, apiClass);\n}\n\n/**\n * Get all endpoints from @Endpoint decorators.\n * Returns a record of methodName -> endpoint path.\n */\nexport function getEndpoints(apiClass: Function): Record<string, string> | undefined {\n return Reflect.getMetadata(METADATA_KEYS.ENDPOINTS, apiClass);\n}\n\n/**\n * Every method's declared trigger kind, as `methodName -> kind`. Parallel to {@link getEndpoints}.\n * Empty for a class carrying no @Endpoint at all.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpoints\nexport function getEndpointKinds(apiClass: Function): Record<string, EndpointKind> {\n return Reflect.getMetadata(METADATA_KEYS.ENDPOINT_KIND, apiClass) || {};\n}\n\n/**\n * What triggers ONE method, or undefined when the method carries no @Endpoint.\n *\n * Defaults to nothing rather than to 'rpc': `kind` is a required argument, so a missing entry means\n * \"this is not an endpoint\", never \"an endpoint that forgot to say\". Silently defaulting here would\n * put an undeclared cron or webhook back into the graph as a normal rpc call — the exact blindness\n * the required argument exists to remove.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpoints\nexport function getEndpointKind(apiClass: Function, methodName: string): EndpointKind | undefined {\n return getEndpointKinds(apiClass)[methodName];\n}\n\n/** The required HTTP method for one endpoint. */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpointKind\nexport function getEndpointHttpMethod(apiClass: Function, methodName: string): HttpMethod {\n const methods: Record<string, HttpMethod> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_HTTP_METHOD, apiClass) || {};\n const method = methods[methodName];\n if (!isHttpMethod(method)) {\n throw new Error(\n `@Endpoint ${apiClass.name || 'Unknown'}.${methodName} must declare GET or POST.`,\n );\n }\n return method;\n}\n\n/**\n * Get the @Endpoint options for one method (empty object if the method had no options).\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpoints\nexport function getEndpointOptions(apiClass: Function, methodName: string): EndpointOptions {\n const opts: Record<string, EndpointOptions> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_OPTIONS, apiClass) || {};\n const options = opts[methodName];\n if (!options && getEndpoints(apiClass)?.[methodName] === undefined) {\n // Preserve the historical helper behavior for a method that is not an endpoint at all.\n return {} as EndpointOptions;\n }\n return options ?? {};\n}\n\n/** Read one endpoint's required side-effect semantics. */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpointOptions\nexport function getEndpointOperation(apiClass: Function, methodName: string): EndpointOperation {\n const operations: Record<string, EndpointOperation> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_OPERATION, apiClass) || {};\n const operation = operations[methodName];\n if (!isEndpointOperation(operation)) {\n throw new Error(\n `@Endpoint ${apiClass.name || 'Unknown'}.${methodName} must declare READ, ` +\n 'WRITE_IDEMPOTENT, or WRITE.',\n );\n }\n return operation;\n}\n\n// webpieces-disable no-function-outside-class -- runtime backstop for JavaScript and `as any` callers; webpieces-disable no-any-unknown -- untrusted runtime value is narrowed to an endpoint operation\nfunction isEndpointOperation(value: unknown): value is EndpointOperation {\n return (\n value === READ ||\n value === WRITE_IDEMPOTENT ||\n value === WRITE\n );\n}\n\n// webpieces-disable no-function-outside-class -- runtime backstop for JavaScript and `as any` callers; webpieces-disable no-any-unknown -- untrusted runtime value is narrowed to an HTTP method\nfunction isHttpMethod(value: unknown): value is HttpMethod {\n return value === GET || value === POST;\n}\n\n// webpieces-disable no-function-outside-class -- runtime backstop for JavaScript and `as any` callers; webpieces-disable no-any-unknown -- untrusted runtime value is narrowed to an endpoint kind\nfunction isEndpointKind(value: unknown): value is EndpointKind {\n return (\n value === RPC ||\n value === CLOUDTASKS ||\n value === CRON ||\n value === EXTERNAL\n );\n}\n\n/**\n * Fail-fast at wiring time when an `external` endpoint declared no caller. The {@link Endpoint}\n * overloads already make that a COMPILE error; this is the backstop for the ways TS is bypassed —\n * a JS caller, an `as any` options object, a hand-rolled Reflect.defineMetadata.\n * @throws Error naming the first external endpoint with no `calledBy`.\n */\n// webpieces-disable no-function-outside-class -- wiring-time assert, sibling of assertEveryEndpointHasAuthMode\nexport function assertEveryExternalEndpointDeclaresCaller(apiClass: Function): void {\n const kinds = getEndpointKinds(apiClass);\n for (const methodName of Object.keys(kinds)) {\n if (\n kinds[methodName] !== 'external' ||\n getEndpointCaller(apiClass, methodName) !== undefined\n )\n continue;\n throw new Error(\n `External endpoint '${methodName}' in ${apiClass.name || 'Unknown'} declares no caller. Say WHO ` +\n `posts to it: @Endpoint(POST, path, WRITE, EXTERNAL, { calledBy: '<vendor>' }) — the runtime architecture ` +\n `graph cannot name an inbound caller it was never told about.`,\n );\n }\n}\n\n/**\n * True when the method's @Endpoint declared `{ formPost: true }` — its body is\n * application/x-www-form-urlencoded (flat), not JSON.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpoints\nexport function isFormPost(apiClass: Function, methodName: string): boolean {\n return getEndpointOptions(apiClass, methodName).formPost === true;\n}\n\n/**\n * True when the method's @Endpoint declared `{ rawBody: true }` — the transport must retain the\n * verbatim bytes + absolute url for an {@link WebhookAuthCallback} hook to verify.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of isFormPost\nexport function isRawBody(apiClass: Function, methodName: string): boolean {\n return getEndpointOptions(apiClass, methodName).rawBody === true;\n}\n\n/**\n * Fail-fast at wiring time when an `webhook(...)` endpoint did not ask the transport to keep the\n * bytes it is supposed to verify. A hook with nothing to verify is a MISCONFIGURATION, and it must\n * surface at startup, naming the fix — not as a 401 in production on exactly the traffic the endpoint\n * exists for.\n *\n * This pairing is a runtime assert rather than a type because the two halves live on DIFFERENT\n * decorators (`webhook(...)` and `@Endpoint`), and no union over one decorator's argument can say\n * anything about the other's.\n *\n * @throws Error naming the first `webhook(...)` endpoint missing `{ rawBody: true }`.\n */\n// webpieces-disable no-function-outside-class -- wiring-time assert, sibling of assertEveryEndpointHasAuthMode\nexport function assertEveryWebhookEndpointRetainsRawBody(apiClass: Function): void {\n const endpoints = getEndpoints(apiClass) || {};\n for (const methodName of Object.keys(endpoints)) {\n if (\n !getAuthMeta(apiClass, methodName)?.methods.some((method: AuthMode) => method.kind === 'webhook') ||\n isRawBody(apiClass, methodName)\n )\n continue;\n throw new Error(\n `Endpoint '${methodName}' in ${apiClass.name || 'Unknown'} is webhook(...) but its @Endpoint ` +\n `does not declare { rawBody: true }. A webhook hook verifies a signature over the bytes and ` +\n `the url the SENDER transmitted, and without that option the transport parses the body and ` +\n `throws them away — leaving the hook nothing to check.`,\n );\n }\n}\n\n/**\n * Check if a class has @ApiPath decorator.\n */\nexport function isApiPath(apiClass: Function): boolean {\n return Reflect.hasMetadata(METADATA_KEYS.API_PATH, apiClass);\n}\n\n/**\n * Get method-level auth metadata. Class-level authorization is forbidden.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader paired with the decorator API\nexport function getAuthMeta(apiClass: Function, methodName: string): AuthMeta | undefined {\n return Reflect.getMetadata(METADATA_KEYS.AUTH_META, apiClass, methodName);\n}\n\n/**\n * The ONE prescription for \"this endpoint declares no auth\", shared by the two places that raise it\n * (here and http-routing's ApiRoutingFactory) because they had drifted into teaching different menus.\n * A message teaching an incomplete API is the same defect as an API with two spellings: whichever menu\n * the caller hits becomes the API they believe exists. It leads with the ROLE-GATED member on purpose —\n * the first thing offered should not be the widest grant.\n */\nexport const MISSING_AUTH_DECORATOR_FIX =\n \"Declare @WpAuth([jwt(), oidcSameProject() or oidcSvcs(['svc-a']), sharedSecret(key), webhook(name), apiKey('regime', [{in: 'header', key: MyKeys.API_KEY}])]) \" +\n \"or @WpAuthPublic('reason'), and exactly one @WpAuthorization on every endpoint. Add @WpLocalOnly() separately when locality is required.\";\n\n/**\n * Fail-fast at wiring time if any endpoint lacks an auth mode. Both the server\n * (ApiRoutingFactory) and the task/rpc clients call this so a missing auth\n * decorator is a startup error, never a silent open endpoint.\n * @throws Error naming the first endpoint with no auth decorator, via {@link MISSING_AUTH_DECORATOR_FIX}.\n */\nexport function assertEveryEndpointHasAuthMode(apiClass: Function): void {\n const apiName = apiClass.name || 'Unknown';\n const endpoints = getEndpoints(apiClass) || {};\n for (const methodName of Object.keys(endpoints)) {\n if (!getAuthMeta(apiClass, methodName)) {\n throw new Error(\n `Endpoint '${methodName}' in ${apiName} has no auth decorator. ` +\n MISSING_AUTH_DECORATOR_FIX,\n );\n }\n const policy = getAuthorization(apiClass, methodName);\n if (!policy) throw new Error(`Endpoint '${methodName}' in ${apiName} requires @WpAuthorization.`);\n AuthorizationDeclaration.validate(policy);\n const auth = getAuthMeta(apiClass, methodName)!;\n const isPublic = auth.methods.some((method: AuthMode) => method.kind === 'public');\n if (isPublic !== (policy.authType === AuthorizationType.ANONYMOUS)) {\n throw new Error(`Endpoint '${methodName}' must pair public authentication with ANONYMOUS authorization, or protected authentication with protected/CUSTOM authorization.`);\n }\n }\n const policyMethods: string[] = Reflect.getMetadata(AUTHORIZATION_METHODS_KEY, apiClass) ?? [];\n for (const methodName of policyMethods) {\n if (!(methodName in endpoints)) throw new Error(`Orphan @WpAuthorization on ${apiName}.${methodName}; declare @Endpoint.`);\n }\n}\n\n/**\n * Validate that a class/method doesn't have conflicting auth decorators.\n * @throws Error if multiple auth decorators are found on the same target.\n */\n// webpieces-disable no-function-outside-class -- shared decorator metadata validation\nexport function validateNoConflictingDecorators(\n apiClass: Function,\n methodName: string | undefined,\n): void {\n const existing = methodName\n ? Reflect.getMetadata(METADATA_KEYS.AUTH_META, apiClass, methodName)\n : Reflect.getMetadata(METADATA_KEYS.AUTH_META, apiClass);\n\n if (existing) {\n const targetName = apiClass.name || 'Unknown';\n const location = methodName\n ? `method '${methodName}' of ${targetName}`\n : `class ${targetName}`;\n throw new Error(\n `Conflicting auth decorator on ${location}. ` +\n `Exactly one @WpAuth([...]) or @WpAuthPublic('reason') is allowed per endpoint.`,\n );\n }\n}\n"]}
1
+ {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/http/decorators.ts"],"names":[],"mappings":"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","sourcesContent":["import 'reflect-metadata';\nimport { MaskSpec, MaskMode } from './LogFieldMask';\nimport {\n DEFAULT_CALLER_KIND,\n ENDPOINT_CALLER_KEY,\n ExternalCaller,\n getEndpointCaller,\n} from './external-caller';\n// The TYPE layer these decorators attach — split out for file size only (see auth-mode.ts).\nimport { AuthMeta, AuthMethods, AuthMode } from './auth-mode';\nimport {\n EndpointOperation,\n EndpointOptions,\n ExternalEndpointOptions,\n READ,\n WRITE_IDEMPOTENT,\n WRITE,\n} from './HttpEndpointOptions';\nimport { HTTP_METHODS, HttpMethod, isHttpMethod } from './HttpContract';\nimport { AuthorizationDeclaration, AuthorizationType, AUTHORIZATION_METHODS_KEY, getAuthorization } from './authorization';\nimport { HTTP_PARAMETERS_METADATA_KEY } from './http-parameter-decorators';\n\nexport type { EndpointOptions, ExternalEndpointOptions } from './HttpEndpointOptions';\nexport type { EndpointOperation } from './HttpEndpointOptions';\nexport { READ, WRITE_IDEMPOTENT, WRITE, NONE } from './HttpEndpointOptions';\nexport type { ResponseBodyKind } from './HttpEndpointOptions';\nexport type { HttpMethod } from './HttpContract';\nexport { GET, POST, PUT, PATCH, DELETE } from './HttpContract';\nexport { PathParam, QueryParam, QueryString, getHttpParameterDeclarations } from './http-parameter-decorators';\n\n/**\n * Metadata keys for storing API routing information.\n * These keys are used by both server-side (routing) and client-side (client generation).\n */\nexport const METADATA_KEYS = {\n API_PATH: 'webpieces:api-path',\n ENDPOINTS: 'webpieces:endpoints',\n AUTH_META: 'webpieces:auth-meta',\n /** Method names carrying one of the canonical authorization decorators. */\n AUTH_METHODS: 'webpieces:auth-methods',\n /** 'rpc' (default, sync request/response) vs 'pubsub' (fire-and-forget cloud task). */\n API_KIND: 'webpieces:api-kind',\n /** Per-method Cloud Tasks queue-name override (set via @Queue). */\n QUEUE_OVERRIDE: 'webpieces:queue-override',\n /** Per-method @Endpoint options (e.g. formPost), parallel to ENDPOINTS. */\n ENDPOINT_OPTIONS: 'webpieces:endpoint-options',\n /** Per-method required HTTP method, parallel to ENDPOINTS. */\n ENDPOINT_HTTP_METHOD: 'webpieces:endpoint-http-method',\n /** Per-method required read/write semantics, parallel to ENDPOINTS. */\n ENDPOINT_OPERATION: 'webpieces:endpoint-operation',\n /** Per-method @Endpoint trigger kind (rpc | cloudtasks | cron | external-inbound | external-outbound), parallel to ENDPOINTS. */\n ENDPOINT_KIND: 'webpieces:endpoint-kind',\n /** Per-method declared external CALLER (only for kind 'external-inbound'), parallel to ENDPOINTS. */\n ENDPOINT_CALLER: ENDPOINT_CALLER_KEY,\n /** Per-method @MaskLog spec (which DTO fields the LogApiCall path masks). */\n MASK_LOG: 'webpieces:mask-log',\n /** Per-method opt-in metadata for publishing an RPC endpoint as an MCP tool. */\n MCP_TOOLS: 'webpieces:mcp-tools',\n /** Per-method PERMANENT exclusion from MCP, with the reason — see @InvalidEndpointForMcp. */\n MCP_INVALID: 'webpieces:mcp-invalid',\n /** Per-method request/response event metadata for a typed streaming endpoint. */\n STREAM_ENDPOINTS: 'webpieces:stream-endpoints',\n /** Per-method MCP-user authorization, intentionally separate from HTTP hop auth. */\n LOCAL_ONLY: 'webpieces:local-only',\n /** Per-method explicit path/query parameter declarations, keyed by parameter index. */\n HTTP_PARAMETERS: HTTP_PARAMETERS_METADATA_KEY,\n};\n\n/** Nominal backing keeps raw string literals out of endpoint declarations. */\nenum EndpointKindValue {\n RPC = 'rpc',\n CLOUDTASKS = 'cloudtasks',\n CRON = 'cron',\n EXTERNAL_INBOUND = 'external-inbound',\n EXTERNAL_OUTBOUND = 'external-outbound',\n}\n\n/** Short, statically importable decorator arguments. */\nexport const RPC = EndpointKindValue.RPC;\nexport const CLOUDTASKS = EndpointKindValue.CLOUDTASKS;\nexport const CRON = EndpointKindValue.CRON;\n/**\n * An OUTSIDE system calls US (a vendor webhook, a push subscription). Requires `calledBy`, which names\n * that system on the runtime architecture graph.\n */\nexport const EXTERNAL_INBOUND = EndpointKindValue.EXTERNAL_INBOUND;\n/**\n * WE call an OUTSIDE system (a vendor API, a partner's webhook receiver). No server in this repo\n * implements it, every method of the contract must be this kind, and the client sends ONLY the\n * context keys listed with `@ExternalContextKeys(...)` and merges no response header into our context.\n */\nexport const EXTERNAL_OUTBOUND = EndpointKindValue.EXTERNAL_OUTBOUND;\n\n/** Runtime trigger/delivery owner used by validation, architecture, and infrastructure tooling. */\nexport type EndpointKind =\n | typeof RPC\n | typeof CLOUDTASKS\n | typeof CRON\n | typeof EXTERNAL_INBOUND\n | typeof EXTERNAL_OUTBOUND;\n\n/** Class decorator that sets the shared base path for all endpoints. */\nexport function ApiPath(basePath: string): ClassDecorator {\n return (target: Function) => {\n if (Reflect.hasMetadata('webpieces:ipc-api-id', target)) {\n throw new Error(\n `Class ${target.name || 'Unknown'} cannot combine @ApiPath with @WpInternal.`,\n );\n }\n Reflect.defineMetadata(METADATA_KEYS.API_PATH, basePath, target);\n\n // Initialize endpoints map if not exists\n if (!Reflect.hasMetadata(METADATA_KEYS.ENDPOINTS, target)) {\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINTS, {}, target);\n }\n };\n}\n\n/**\n * Registers `@Endpoint(POST, path, WRITE, RPC)`. Method, operation, and trigger are required enum\n * values. Operation is independent of the HTTP verb. EXTERNAL_INBOUND additionally requires `calledBy`.\n * Each classification rides a parallel metadata map while ENDPOINTS remains method-name -> path.\n */\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nexport function Endpoint(\n httpMethod: HttpMethod,\n path: string,\n operation: EndpointOperation,\n kind: typeof EXTERNAL_INBOUND,\n options: ExternalEndpointOptions,\n): MethodDecorator;\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nexport function Endpoint(\n httpMethod: HttpMethod,\n path: string,\n operation: EndpointOperation,\n kind: Exclude<EndpointKind, typeof EXTERNAL_INBOUND>,\n options?: EndpointOptions,\n): MethodDecorator;\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nexport function Endpoint(\n httpMethod: HttpMethod,\n path: string,\n operation: EndpointOperation,\n kind: EndpointKind,\n options: EndpointOptions = {},\n): MethodDecorator {\n validateEndpointClassification(httpMethod, operation, kind);\n // webpieces-disable no-any-unknown -- reflect-metadata decorator API requires any\n return (target: any, propertyKey: string | symbol, _descriptor: PropertyDescriptor) => {\n const metadataTarget = typeof target === 'function' ? target : target.constructor;\n recordEndpointMetadata(\n metadataTarget,\n propertyKey as string,\n httpMethod,\n path,\n operation,\n kind,\n options,\n );\n };\n}\n\n// webpieces-disable no-function-outside-class -- runtime validation backs up nominal TS enums\nfunction validateEndpointClassification(\n httpMethod: HttpMethod,\n operation: EndpointOperation,\n kind: EndpointKind,\n): void {\n if (!isHttpMethod(httpMethod)) {\n throw new Error(\n `@Endpoint httpMethod must be one of ${HTTP_METHODS.join(', ')}, received '${String(httpMethod)}'.`,\n );\n }\n if (!isEndpointOperation(operation)) {\n throw new Error(\n `@Endpoint operation must be READ, WRITE_IDEMPOTENT, or WRITE, received '${String(operation)}'.`,\n );\n }\n if (!isEndpointKind(kind)) {\n throw new Error(\n `@Endpoint trigger must be RPC, CLOUDTASKS, CRON, EXTERNAL_INBOUND, or EXTERNAL_OUTBOUND, received '${String(kind)}'.`,\n );\n }\n}\n\n// webpieces-disable no-function-outside-class -- one metadata write shared by the decorator overloads\nfunction recordEndpointMetadata(\n metadataTarget: Function,\n propertyKey: string,\n httpMethod: HttpMethod,\n path: string,\n operation: EndpointOperation,\n kind: EndpointKind,\n options: EndpointOptions,\n): void {\n const endpoints: Record<string, string> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINTS, metadataTarget) || {};\n\n endpoints[propertyKey] = path;\n\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINTS, endpoints, metadataTarget);\n\n const methods: Record<string, HttpMethod> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_HTTP_METHOD, metadataTarget) || {};\n methods[propertyKey] = httpMethod;\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINT_HTTP_METHOD, methods, metadataTarget);\n\n const operations: Record<string, EndpointOperation> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_OPERATION, metadataTarget) || {};\n operations[propertyKey] = operation;\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINT_OPERATION, operations, metadataTarget);\n\n const kinds: Record<string, EndpointKind> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_KIND, metadataTarget) || {};\n kinds[propertyKey] = kind;\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINT_KIND, kinds, metadataTarget);\n\n const opts: Record<string, EndpointOptions> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_OPTIONS, metadataTarget) || {};\n opts[propertyKey] = options;\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINT_OPTIONS, opts, metadataTarget);\n\n const declared = options as ExternalEndpointOptions;\n if (\n kind !== EXTERNAL_INBOUND ||\n typeof declared.calledBy !== 'string' ||\n declared.calledBy === ''\n )\n return;\n const callers: Record<string, ExternalCaller> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_CALLER, metadataTarget) || {};\n callers[propertyKey] = new ExternalCaller(\n declared.callerKind ?? DEFAULT_CALLER_KIND,\n declared.calledBy,\n );\n Reflect.defineMetadata(METADATA_KEYS.ENDPOINT_CALLER, callers, metadataTarget);\n}\n\n/** Declares request/response DTO field names that API logging must mask at any depth. */\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nexport function MaskLog(fields: Record<string, MaskMode>): MethodDecorator {\n const spec = new MaskSpec(fields);\n // webpieces-disable no-any-unknown -- reflect-metadata decorator API requires any\n return (target: any, propertyKey: string | symbol, _descriptor: PropertyDescriptor) => {\n const metadataTarget = typeof target === 'function' ? target : target.constructor;\n const specs: Record<string, MaskSpec> =\n Reflect.getMetadata(METADATA_KEYS.MASK_LOG, metadataTarget) || {};\n specs[propertyKey as string] = spec;\n Reflect.defineMetadata(METADATA_KEYS.MASK_LOG, specs, metadataTarget);\n };\n}\n\n/**\n * The @MaskLog spec for one method, or undefined if the method declared none (the common case — the\n * caller then logs the DTO verbatim on the plain JSON.stringify fast path).\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpointOptions\nexport function getMaskSpec(apiClass: Function, methodName: string): MaskSpec | undefined {\n const specs: Record<string, MaskSpec> =\n Reflect.getMetadata(METADATA_KEYS.MASK_LOG, apiClass) || {};\n return specs[methodName];\n}\n\n/**\n * Shared implementation for every auth decorator. Authorization is deliberately\n * method-only: a class-level default is too easy to miss when reviewing one endpoint.\n */\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nfunction defineAuthMetadata(authMeta: AuthMeta): MethodDecorator {\n\n // webpieces-disable no-any-unknown -- reflect-metadata decorator API requires any\n return (target: any, propertyKey?: string | symbol, _descriptor?: PropertyDescriptor) => {\n if (propertyKey === undefined) {\n throw new Error(\n 'Authorization decorators are method-only; annotate every @Endpoint explicitly.',\n );\n }\n const metadataTarget = typeof target === 'function' ? target : target.constructor;\n if (Reflect.hasMetadata('webpieces:ipc-api-id', metadataTarget)) {\n throw new Error(\n `Internal API ${metadataTarget.name || 'Unknown'} cannot use HTTP authorization decorators.`,\n );\n }\n validateNoConflictingDecorators(metadataTarget, propertyKey as string);\n Reflect.defineMetadata(METADATA_KEYS.AUTH_META, authMeta, metadataTarget, propertyKey);\n const methods = new Set<string>(\n Reflect.getMetadata(METADATA_KEYS.AUTH_METHODS, metadataTarget) || [],\n );\n methods.add(propertyKey as string);\n Reflect.defineMetadata(METADATA_KEYS.AUTH_METHODS, [...methods], metadataTarget);\n };\n}\n\n/**\n * @WpAuthPublic(reason) - endpoint intentionally requires no authentication.\n * The non-empty reason makes anonymous exposure an explicit review decision.\n */\n// webpieces-disable no-function-outside-class -- decorator factory; decorators are inherently module-scope\nexport function WpAuthPublic(reason: string): MethodDecorator {\n if (typeof reason !== 'string' || reason.trim() === '') {\n throw new Error(\n '@WpAuthPublic requires a non-empty reason explaining why anonymous access is required.',\n );\n }\n return defineAuthMetadata(new AuthMeta([{ kind: 'public' }], reason));\n}\n\n/** Protected network ingress: authenticate one declared credential, then authorize independently. */\n// webpieces-disable no-function-outside-class -- canonical method decorator factory\nexport function WpAuth(methods: AuthMethods): MethodDecorator {\n return defineAuthMetadata(new AuthMeta(methods, undefined));\n}\n\n/** Locality is independent of authentication and cannot prove a user or machine identity. */\n// webpieces-disable no-function-outside-class -- canonical method decorator factory\nexport function WpLocalOnly(): MethodDecorator {\n return (target: object, methodName: string | symbol) => {\n if (methodName === undefined) throw new Error('@WpLocalOnly is method-only.');\n Reflect.defineMetadata(METADATA_KEYS.LOCAL_ONLY, true, target.constructor, methodName);\n };\n}\n\n// webpieces-disable no-function-outside-class -- canonical metadata reader\nexport function isLocalOnly(apiClass: Function, methodName: string): boolean {\n return Reflect.getMetadata(METADATA_KEYS.LOCAL_ONLY, apiClass, methodName) === true;\n}\n\n// ============================================================\n// Helper functions\n// ============================================================\n\n/**\n * Get the base path from @ApiPath decorator.\n */\nexport function getApiPath(apiClass: Function): string | undefined {\n return Reflect.getMetadata(METADATA_KEYS.API_PATH, apiClass);\n}\n\n/**\n * Get all endpoints from @Endpoint decorators.\n * Returns a record of methodName -> endpoint path.\n */\nexport function getEndpoints(apiClass: Function): Record<string, string> | undefined {\n return Reflect.getMetadata(METADATA_KEYS.ENDPOINTS, apiClass);\n}\n\n/**\n * Every method's declared trigger kind, as `methodName -> kind`. Parallel to {@link getEndpoints}.\n * Empty for a class carrying no @Endpoint at all.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpoints\nexport function getEndpointKinds(apiClass: Function): Record<string, EndpointKind> {\n return Reflect.getMetadata(METADATA_KEYS.ENDPOINT_KIND, apiClass) || {};\n}\n\n/**\n * What triggers ONE method, or undefined when the method carries no @Endpoint.\n *\n * Defaults to nothing rather than to 'rpc': `kind` is a required argument, so a missing entry means\n * \"this is not an endpoint\", never \"an endpoint that forgot to say\". Silently defaulting here would\n * put an undeclared cron or webhook back into the graph as a normal rpc call — the exact blindness\n * the required argument exists to remove.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpoints\nexport function getEndpointKind(apiClass: Function, methodName: string): EndpointKind | undefined {\n return getEndpointKinds(apiClass)[methodName];\n}\n\n/** The required HTTP method for one endpoint. */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpointKind\nexport function getEndpointHttpMethod(apiClass: Function, methodName: string): HttpMethod {\n const methods: Record<string, HttpMethod> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_HTTP_METHOD, apiClass) || {};\n const method = methods[methodName];\n if (!isHttpMethod(method)) {\n throw new Error(\n `@Endpoint ${apiClass.name || 'Unknown'}.${methodName} must declare one of ${HTTP_METHODS.join(', ')}.`,\n );\n }\n return method;\n}\n\n/**\n * Get the @Endpoint options for one method (empty object if the method had no options).\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpoints\nexport function getEndpointOptions(apiClass: Function, methodName: string): EndpointOptions {\n const opts: Record<string, EndpointOptions> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_OPTIONS, apiClass) || {};\n const options = opts[methodName];\n if (!options && getEndpoints(apiClass)?.[methodName] === undefined) {\n // Preserve the historical helper behavior for a method that is not an endpoint at all.\n return {} as EndpointOptions;\n }\n return options ?? {};\n}\n\n/** Read one endpoint's required side-effect semantics. */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpointOptions\nexport function getEndpointOperation(apiClass: Function, methodName: string): EndpointOperation {\n const operations: Record<string, EndpointOperation> =\n Reflect.getMetadata(METADATA_KEYS.ENDPOINT_OPERATION, apiClass) || {};\n const operation = operations[methodName];\n if (!isEndpointOperation(operation)) {\n throw new Error(\n `@Endpoint ${apiClass.name || 'Unknown'}.${methodName} must declare READ, ` +\n 'WRITE_IDEMPOTENT, or WRITE.',\n );\n }\n return operation;\n}\n\n// webpieces-disable no-function-outside-class -- runtime backstop for JavaScript and `as any` callers; webpieces-disable no-any-unknown -- untrusted runtime value is narrowed to an endpoint operation\nfunction isEndpointOperation(value: unknown): value is EndpointOperation {\n return (\n value === READ ||\n value === WRITE_IDEMPOTENT ||\n value === WRITE\n );\n}\n\n// webpieces-disable no-function-outside-class -- runtime backstop for JavaScript and `as any` callers; webpieces-disable no-any-unknown -- untrusted runtime value is narrowed to an endpoint kind\nfunction isEndpointKind(value: unknown): value is EndpointKind {\n return (\n value === RPC ||\n value === CLOUDTASKS ||\n value === CRON ||\n value === EXTERNAL_INBOUND ||\n value === EXTERNAL_OUTBOUND\n );\n}\n\n/**\n * Fail-fast at wiring time on the two EXTERNAL_* rules, called by `RouteMetadataFactory` for every\n * transport (server routes and every client). The {@link Endpoint} overloads already make a missing\n * `calledBy` a COMPILE error; this is the backstop for the ways TS is bypassed — a JS caller, an\n * `as any` options object, a hand-rolled Reflect.defineMetadata. The second rule cannot be a type:\n * \"every method of this class\" spans several decorators.\n *\n * @throws Error naming the first EXTERNAL_INBOUND endpoint with no `calledBy`, or the first method of\n * a contract that mixes EXTERNAL_OUTBOUND with any other kind.\n */\n// webpieces-disable no-function-outside-class -- wiring-time assert, sibling of assertEveryEndpointHasAuthMode\nexport function assertExternalEndpointKinds(apiClass: Function): void {\n const kinds = getEndpointKinds(apiClass);\n const apiName = apiClass.name || 'Unknown';\n const methods = Object.keys(kinds);\n const outbound = methods.filter((methodName: string) => kinds[methodName] === EXTERNAL_OUTBOUND);\n if (outbound.length > 0 && outbound.length !== methods.length) {\n const other = methods.find((methodName: string) => kinds[methodName] !== EXTERNAL_OUTBOUND)!;\n throw new Error(\n `${apiName} mixes EXTERNAL_OUTBOUND (${outbound[0]}) with ${String(kinds[other]).toUpperCase()} (${other}). ` +\n `An EXTERNAL_OUTBOUND contract is an outside system's API that no server in this repo implements, so ` +\n `EVERY method of it must be EXTERNAL_OUTBOUND; move the other methods to their own contract.`,\n );\n }\n for (const methodName of methods) {\n if (kinds[methodName] !== EXTERNAL_INBOUND || getEndpointCaller(apiClass, methodName) !== undefined)\n continue;\n throw new Error(\n `External endpoint '${methodName}' in ${apiName} declares no caller. Say WHO ` +\n `posts to it: @Endpoint(POST, path, WRITE, EXTERNAL_INBOUND, { calledBy: '<vendor>' }) — the runtime architecture ` +\n `graph cannot name an inbound caller it was never told about.`,\n );\n }\n}\n\n/** True when the contract is an outside system's API: every method is EXTERNAL_OUTBOUND. */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpointKinds\nexport function isExternalOutboundApi(apiClass: Function): boolean {\n const kinds = Object.values(getEndpointKinds(apiClass));\n return kinds.length > 0 && kinds.every((kind: EndpointKind) => kind === EXTERNAL_OUTBOUND);\n}\n\n/**\n * True when the method's @Endpoint declared `{ formPost: true }` — its body is\n * application/x-www-form-urlencoded (flat), not JSON.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpoints\nexport function isFormPost(apiClass: Function, methodName: string): boolean {\n return getEndpointOptions(apiClass, methodName).formPost === true;\n}\n\n/**\n * True when the method's @Endpoint declared `{ rawBody: true }` — the transport must retain the\n * verbatim bytes + absolute url for a `VendorAuthHook.verify` to check.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of isFormPost\nexport function isRawBody(apiClass: Function, methodName: string): boolean {\n return getEndpointOptions(apiClass, methodName).rawBody === true;\n}\n\n/**\n * Fail-fast at wiring time when a SERVED `vendorAuth(...)` endpoint did not ask the transport to keep the\n * bytes it is supposed to verify. A hook with nothing to verify is a MISCONFIGURATION, and it must\n * surface at startup, naming the fix — not as a 401 in production on exactly the traffic the endpoint\n * exists for.\n *\n * This pairing is a runtime assert rather than a type because the two halves live on DIFFERENT\n * decorators (`vendorAuth(...)` and `@Endpoint`), and no union over one decorator's argument can say\n * anything about the other's.\n *\n * @throws Error naming the first `vendorAuth(...)` endpoint missing `{ rawBody: true }`.\n */\n// webpieces-disable no-function-outside-class -- wiring-time assert, sibling of assertEveryEndpointHasAuthMode\nexport function assertEveryVendorAuthEndpointRetainsRawBody(apiClass: Function): void {\n const endpoints = getEndpoints(apiClass) || {};\n for (const methodName of Object.keys(endpoints)) {\n if (\n !getAuthMeta(apiClass, methodName)?.methods.some((method: AuthMode) => method.kind === 'vendorAuth') ||\n isRawBody(apiClass, methodName)\n )\n continue;\n throw new Error(\n `Endpoint '${methodName}' in ${apiClass.name || 'Unknown'} is vendorAuth(...) but its @Endpoint ` +\n `does not declare { rawBody: true }. VendorAuthHook.verify checks a credential over the bytes and ` +\n `the url the SENDER transmitted, and without that option the transport parses the body and ` +\n `throws them away — leaving the hook nothing to check.`,\n );\n }\n}\n\n/**\n * Check if a class has @ApiPath decorator.\n */\nexport function isApiPath(apiClass: Function): boolean {\n return Reflect.hasMetadata(METADATA_KEYS.API_PATH, apiClass);\n}\n\n/**\n * Get method-level auth metadata. Class-level authorization is forbidden.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader paired with the decorator API\nexport function getAuthMeta(apiClass: Function, methodName: string): AuthMeta | undefined {\n return Reflect.getMetadata(METADATA_KEYS.AUTH_META, apiClass, methodName);\n}\n\n/**\n * The ONE prescription for \"this endpoint declares no auth\", shared by the two places that raise it\n * (here and http-routing's ApiRoutingFactory) because they had drifted into teaching different menus.\n * A message teaching an incomplete API is the same defect as an API with two spellings: whichever menu\n * the caller hits becomes the API they believe exists. It leads with the ROLE-GATED member on purpose —\n * the first thing offered should not be the widest grant.\n */\nexport const MISSING_AUTH_DECORATOR_FIX =\n \"Declare @WpAuth([jwt(), oidcSameProject() or oidcSvcs(['svc-a']), sharedSecret(key), vendorAuth(name), apiKey('regime', [{in: 'header', key: MyKeys.API_KEY}])]) \" +\n \"or @WpAuthPublic('reason'), and exactly one @WpAuthorization on every endpoint. Add @WpLocalOnly() separately when locality is required.\";\n\n/**\n * Fail-fast at wiring time if any endpoint lacks an auth mode. Both the server\n * (ApiRoutingFactory) and the task/rpc clients call this so a missing auth\n * decorator is a startup error, never a silent open endpoint.\n * @throws Error naming the first endpoint with no auth decorator, via {@link MISSING_AUTH_DECORATOR_FIX}.\n */\nexport function assertEveryEndpointHasAuthMode(apiClass: Function): void {\n const apiName = apiClass.name || 'Unknown';\n const endpoints = getEndpoints(apiClass) || {};\n for (const methodName of Object.keys(endpoints)) {\n if (!getAuthMeta(apiClass, methodName)) {\n throw new Error(\n `Endpoint '${methodName}' in ${apiName} has no auth decorator. ` +\n MISSING_AUTH_DECORATOR_FIX,\n );\n }\n const policy = getAuthorization(apiClass, methodName);\n if (!policy) throw new Error(`Endpoint '${methodName}' in ${apiName} requires @WpAuthorization.`);\n AuthorizationDeclaration.validate(policy);\n const auth = getAuthMeta(apiClass, methodName)!;\n const isPublic = auth.methods.some((method: AuthMode) => method.kind === 'public');\n if (isPublic !== (policy.authType === AuthorizationType.ANONYMOUS)) {\n throw new Error(`Endpoint '${methodName}' must pair public authentication with ANONYMOUS authorization, or protected authentication with protected/CUSTOM authorization.`);\n }\n }\n const policyMethods: string[] = Reflect.getMetadata(AUTHORIZATION_METHODS_KEY, apiClass) ?? [];\n for (const methodName of policyMethods) {\n if (!(methodName in endpoints)) throw new Error(`Orphan @WpAuthorization on ${apiName}.${methodName}; declare @Endpoint.`);\n }\n}\n\n/**\n * Validate that a class/method doesn't have conflicting auth decorators.\n * @throws Error if multiple auth decorators are found on the same target.\n */\n// webpieces-disable no-function-outside-class -- shared decorator metadata validation\nexport function validateNoConflictingDecorators(\n apiClass: Function,\n methodName: string | undefined,\n): void {\n const existing = methodName\n ? Reflect.getMetadata(METADATA_KEYS.AUTH_META, apiClass, methodName)\n : Reflect.getMetadata(METADATA_KEYS.AUTH_META, apiClass);\n\n if (existing) {\n const targetName = apiClass.name || 'Unknown';\n const location = methodName\n ? `method '${methodName}' of ${targetName}`\n : `class ${targetName}`;\n throw new Error(\n `Conflicting auth decorator on ${location}. ` +\n `Exactly one @WpAuth([...]) or @WpAuthPublic('reason') is allowed per endpoint.`,\n );\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * WHO calls us from outside — the vocabulary an `external` @Endpoint uses to name its caller.
2
+ * WHO calls us from outside — the vocabulary an `EXTERNAL_INBOUND` @Endpoint uses to name its caller.
3
3
  *
4
4
  * Deliberately the SAME `(kind, label)` vocabulary the runtime architecture graph already uses for
5
5
  * OUTBOUND vendor seams (`@externalSystem saas twilio`). An inbound `saas twilio` and an outbound
@@ -10,24 +10,19 @@
10
10
  * anything in that file, and decorators.ts is near its file-size limit. The dependency is strictly
11
11
  * one-way (decorators.ts imports this; this imports only reflect-metadata), so no cycle is possible.
12
12
  *
13
- * ## MIGRATION (breaking, 0.5.x)
13
+ * ## `calledBy` is REQUIRED on every `EXTERNAL_INBOUND` endpoint
14
14
  *
15
- * `calledBy` is REQUIRED on every `EXTERNAL` endpoint — `@Endpoint(POST, path, WRITE, EXTERNAL, options)` no
16
- * longer compiles without it. That is the point: a lint rule can be ignored, a compile error cannot,
17
- * and the alternative was a graph that names our own contract where the vendor belongs. One property
18
- * per endpoint migrates it:
15
+ * `@Endpoint(POST, path, WRITE, EXTERNAL_INBOUND, options)` does not compile without it. A lint rule
16
+ * can be ignored, a compile error cannot, and the alternative was a graph that names our own contract
17
+ * where the vendor belongs:
19
18
  *
20
19
  * ```ts
21
- * // before
22
- * @Endpoint(POST, '/inbound', WRITE, EXTERNAL, { formPost: true })
23
- * // after
24
- * @Endpoint(POST, '/inbound', WRITE, EXTERNAL, { formPost: true, calledBy: 'twilio' })
20
+ * @Endpoint(POST, '/inbound', WRITE, EXTERNAL_INBOUND, { formPost: true, calledBy: 'twilio' })
25
21
  * // infrastructure rather than a vendor product:
26
- * @Endpoint(POST, '/push', WRITE, EXTERNAL, { calledBy: 'pubsub-push', callerKind: 'system' })
22
+ * @Endpoint(POST, '/push', WRITE, EXTERNAL_INBOUND, { calledBy: 'pubsub-push', callerKind: 'system' })
27
23
  * ```
28
24
  *
29
- * Nothing else changes: `rpc` / `cloudtasks` / `cron` endpoints keep their exact signature, options
30
- * stay optional there, and the ENDPOINTS path map every consumer iterates is untouched.
25
+ * `rpc` / `cloudtasks` / `cron` / `external-outbound` endpoints keep options optional.
31
26
  */
32
27
  import 'reflect-metadata';
33
28
  /**
@@ -42,7 +37,7 @@ export type ExternalSystemKind = (typeof EXTERNAL_SYSTEM_KINDS)[number];
42
37
  /** True for a string that names one of {@link EXTERNAL_SYSTEM_KINDS}. */
43
38
  export declare function isExternalSystemKind(value: string): value is ExternalSystemKind;
44
39
  /**
45
- * The declared caller of ONE `external` endpoint, normalized: `callerKind` defaulted, `calledBy`
40
+ * The declared caller of ONE `EXTERNAL_INBOUND` endpoint, normalized: `callerKind` defaulted, `calledBy`
46
41
  * carried as the label.
47
42
  *
48
43
  * `label` is the node IDENTITY on the runtime graph, not merely display text — two endpoints
@@ -53,7 +48,7 @@ export declare class ExternalCaller {
53
48
  readonly label: string;
54
49
  constructor(kind: ExternalSystemKind, label: string);
55
50
  }
56
- /** The kind an `external` @Endpoint gets when it declares `calledBy` but no `callerKind`. */
51
+ /** The kind an `EXTERNAL_INBOUND` @Endpoint gets when it declares `calledBy` but no `callerKind`. */
57
52
  export declare const DEFAULT_CALLER_KIND: ExternalSystemKind;
58
53
  /**
59
54
  * Metadata key of the per-method caller map, `methodName -> ExternalCaller`. Parallel to ENDPOINTS,
@@ -62,7 +57,7 @@ export declare const DEFAULT_CALLER_KIND: ExternalSystemKind;
62
57
  */
63
58
  export declare const ENDPOINT_CALLER_KEY = "webpieces:endpoint-caller";
64
59
  /**
65
- * The DECLARED caller of one method, or undefined when it is not `external` (or is `external` but
66
- * bypassed TS — see `assertEveryExternalEndpointDeclaresCaller`). Mirrors `getEndpointOptions`.
60
+ * The DECLARED caller of one method, or undefined when it is not `EXTERNAL_INBOUND` (or is, but
61
+ * bypassed TS — see `assertExternalEndpointKinds`). Mirrors `getEndpointOptions`.
67
62
  */
68
63
  export declare function getEndpointCaller(apiClass: Function, methodName: string): ExternalCaller | undefined;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /**
3
- * WHO calls us from outside — the vocabulary an `external` @Endpoint uses to name its caller.
3
+ * WHO calls us from outside — the vocabulary an `EXTERNAL_INBOUND` @Endpoint uses to name its caller.
4
4
  *
5
5
  * Deliberately the SAME `(kind, label)` vocabulary the runtime architecture graph already uses for
6
6
  * OUTBOUND vendor seams (`@externalSystem saas twilio`). An inbound `saas twilio` and an outbound
@@ -11,24 +11,19 @@
11
11
  * anything in that file, and decorators.ts is near its file-size limit. The dependency is strictly
12
12
  * one-way (decorators.ts imports this; this imports only reflect-metadata), so no cycle is possible.
13
13
  *
14
- * ## MIGRATION (breaking, 0.5.x)
14
+ * ## `calledBy` is REQUIRED on every `EXTERNAL_INBOUND` endpoint
15
15
  *
16
- * `calledBy` is REQUIRED on every `EXTERNAL` endpoint — `@Endpoint(POST, path, WRITE, EXTERNAL, options)` no
17
- * longer compiles without it. That is the point: a lint rule can be ignored, a compile error cannot,
18
- * and the alternative was a graph that names our own contract where the vendor belongs. One property
19
- * per endpoint migrates it:
16
+ * `@Endpoint(POST, path, WRITE, EXTERNAL_INBOUND, options)` does not compile without it. A lint rule
17
+ * can be ignored, a compile error cannot, and the alternative was a graph that names our own contract
18
+ * where the vendor belongs:
20
19
  *
21
20
  * ```ts
22
- * // before
23
- * @Endpoint(POST, '/inbound', WRITE, EXTERNAL, { formPost: true })
24
- * // after
25
- * @Endpoint(POST, '/inbound', WRITE, EXTERNAL, { formPost: true, calledBy: 'twilio' })
21
+ * @Endpoint(POST, '/inbound', WRITE, EXTERNAL_INBOUND, { formPost: true, calledBy: 'twilio' })
26
22
  * // infrastructure rather than a vendor product:
27
- * @Endpoint(POST, '/push', WRITE, EXTERNAL, { calledBy: 'pubsub-push', callerKind: 'system' })
23
+ * @Endpoint(POST, '/push', WRITE, EXTERNAL_INBOUND, { calledBy: 'pubsub-push', callerKind: 'system' })
28
24
  * ```
29
25
  *
30
- * Nothing else changes: `rpc` / `cloudtasks` / `cron` endpoints keep their exact signature, options
31
- * stay optional there, and the ENDPOINTS path map every consumer iterates is untouched.
26
+ * `rpc` / `cloudtasks` / `cron` / `external-outbound` endpoints keep options optional.
32
27
  */
33
28
  Object.defineProperty(exports, "__esModule", { value: true });
34
29
  exports.ENDPOINT_CALLER_KEY = exports.DEFAULT_CALLER_KIND = exports.ExternalCaller = exports.EXTERNAL_SYSTEM_KINDS = void 0;
@@ -56,7 +51,7 @@ function isExternalSystemKind(value) {
56
51
  return exports.EXTERNAL_SYSTEM_KINDS.includes(value);
57
52
  }
58
53
  /**
59
- * The declared caller of ONE `external` endpoint, normalized: `callerKind` defaulted, `calledBy`
54
+ * The declared caller of ONE `EXTERNAL_INBOUND` endpoint, normalized: `callerKind` defaulted, `calledBy`
60
55
  * carried as the label.
61
56
  *
62
57
  * `label` is the node IDENTITY on the runtime graph, not merely display text — two endpoints
@@ -71,7 +66,7 @@ class ExternalCaller {
71
66
  }
72
67
  }
73
68
  exports.ExternalCaller = ExternalCaller;
74
- /** The kind an `external` @Endpoint gets when it declares `calledBy` but no `callerKind`. */
69
+ /** The kind an `EXTERNAL_INBOUND` @Endpoint gets when it declares `calledBy` but no `callerKind`. */
75
70
  exports.DEFAULT_CALLER_KIND = 'saas';
76
71
  /**
77
72
  * Metadata key of the per-method caller map, `methodName -> ExternalCaller`. Parallel to ENDPOINTS,
@@ -80,8 +75,8 @@ exports.DEFAULT_CALLER_KIND = 'saas';
80
75
  */
81
76
  exports.ENDPOINT_CALLER_KEY = 'webpieces:endpoint-caller';
82
77
  /**
83
- * The DECLARED caller of one method, or undefined when it is not `external` (or is `external` but
84
- * bypassed TS — see `assertEveryExternalEndpointDeclaresCaller`). Mirrors `getEndpointOptions`.
78
+ * The DECLARED caller of one method, or undefined when it is not `EXTERNAL_INBOUND` (or is, but
79
+ * bypassed TS — see `assertExternalEndpointKinds`). Mirrors `getEndpointOptions`.
85
80
  */
86
81
  // webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpointOptions
87
82
  function getEndpointCaller(apiClass, methodName) {
@@ -1 +1 @@
1
- {"version":3,"file":"external-caller.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/http/external-caller.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;;;AAwBH,oDAEC;AA+BD,8CAOC;AA9DD,4BAA0B;AAE1B;;;;;;GAMG;AACU,QAAA,qBAAqB,GAAG;IACjC,UAAU;IACV,OAAO;IACP,OAAO;IACP,SAAS;IACT,MAAM;IACN,QAAQ;CACF,CAAC;AAIX,yEAAyE;AACzE,sFAAsF;AACtF,SAAgB,oBAAoB,CAAC,KAAa;IAC9C,OAAQ,6BAA2C,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACxE,CAAC;AAED;;;;;;GAMG;AACH,MAAa,cAAc;IAEH;IACA;IAFpB,YACoB,IAAwB,EACxB,KAAa;QADb,SAAI,GAAJ,IAAI,CAAoB;QACxB,UAAK,GAAL,KAAK,CAAQ;IAC9B,CAAC;CACP;AALD,wCAKC;AAED,6FAA6F;AAChF,QAAA,mBAAmB,GAAuB,MAAM,CAAC;AAE9D;;;;GAIG;AACU,QAAA,mBAAmB,GAAG,2BAA2B,CAAC;AAE/D;;;GAGG;AACH,wGAAwG;AACxG,SAAgB,iBAAiB,CAC7B,QAAkB,EAClB,UAAkB;IAElB,MAAM,OAAO,GACT,OAAO,CAAC,WAAW,CAAC,2BAAmB,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC7D,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC;AAC/B,CAAC","sourcesContent":["/**\n * WHO calls us from outside — the vocabulary an `external` @Endpoint uses to name its caller.\n *\n * Deliberately the SAME `(kind, label)` vocabulary the runtime architecture graph already uses for\n * OUTBOUND vendor seams (`@externalSystem saas twilio`). An inbound `saas twilio` and an outbound\n * `saas twilio` are the same vendor, so sharing the vocabulary makes them share an IDENTITY and\n * converge on ONE node instead of drawing twilio twice, facing opposite directions.\n *\n * Its own module rather than a block in decorators.ts: this is a data model with no dependency on\n * anything in that file, and decorators.ts is near its file-size limit. The dependency is strictly\n * one-way (decorators.ts imports this; this imports only reflect-metadata), so no cycle is possible.\n *\n * ## MIGRATION (breaking, 0.5.x)\n *\n * `calledBy` is REQUIRED on every `EXTERNAL` endpoint — `@Endpoint(POST, path, WRITE, EXTERNAL, options)` no\n * longer compiles without it. That is the point: a lint rule can be ignored, a compile error cannot,\n * and the alternative was a graph that names our own contract where the vendor belongs. One property\n * per endpoint migrates it:\n *\n * ```ts\n * // before\n * @Endpoint(POST, '/inbound', WRITE, EXTERNAL, { formPost: true })\n * // after\n * @Endpoint(POST, '/inbound', WRITE, EXTERNAL, { formPost: true, calledBy: 'twilio' })\n * // infrastructure rather than a vendor product:\n * @Endpoint(POST, '/push', WRITE, EXTERNAL, { calledBy: 'pubsub-push', callerKind: 'system' })\n * ```\n *\n * Nothing else changes: `rpc` / `cloudtasks` / `cron` endpoints keep their exact signature, options\n * stay optional there, and the ENDPOINTS path map every consumer iterates is untouched.\n */\n\nimport 'reflect-metadata';\n\n/**\n * What KIND of system an external caller IS. Drives the shape the runtime graph draws it with, so a\n * push-subscription stops looking like a vendor SaaS.\n *\n * Most inbound webhooks are `saas` (Twilio, Gmail, Stripe). A GCP Pub/Sub push subscription is\n * `system` — it is infrastructure, not a vendor product.\n */\nexport const EXTERNAL_SYSTEM_KINDS = [\n 'database',\n 'cache',\n 'queue',\n 'storage',\n 'saas',\n 'system',\n] as const;\n\nexport type ExternalSystemKind = (typeof EXTERNAL_SYSTEM_KINDS)[number];\n\n/** True for a string that names one of {@link EXTERNAL_SYSTEM_KINDS}. */\n// webpieces-disable no-function-outside-class -- type guard beside the type it guards\nexport function isExternalSystemKind(value: string): value is ExternalSystemKind {\n return (EXTERNAL_SYSTEM_KINDS as readonly string[]).includes(value);\n}\n\n/**\n * The declared caller of ONE `external` endpoint, normalized: `callerKind` defaulted, `calledBy`\n * carried as the label.\n *\n * `label` is the node IDENTITY on the runtime graph, not merely display text — two endpoints\n * declaring `twilio` converge on one box with two arrows into it.\n */\nexport class ExternalCaller {\n constructor(\n public readonly kind: ExternalSystemKind,\n public readonly label: string,\n ) {}\n}\n\n/** The kind an `external` @Endpoint gets when it declares `calledBy` but no `callerKind`. */\nexport const DEFAULT_CALLER_KIND: ExternalSystemKind = 'saas';\n\n/**\n * Metadata key of the per-method caller map, `methodName -> ExternalCaller`. Parallel to ENDPOINTS,\n * exactly like ENDPOINT_KIND and ENDPOINT_OPTIONS, and re-exported as `METADATA_KEYS.ENDPOINT_CALLER`\n * — declared HERE so the reader below needs no import from decorators.ts (which would close a cycle).\n */\nexport const ENDPOINT_CALLER_KEY = 'webpieces:endpoint-caller';\n\n/**\n * The DECLARED caller of one method, or undefined when it is not `external` (or is `external` but\n * bypassed TS — see `assertEveryExternalEndpointDeclaresCaller`). Mirrors `getEndpointOptions`.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpointOptions\nexport function getEndpointCaller(\n apiClass: Function,\n methodName: string,\n): ExternalCaller | undefined {\n const callers: Record<string, ExternalCaller> =\n Reflect.getMetadata(ENDPOINT_CALLER_KEY, apiClass) || {};\n return callers[methodName];\n}\n"]}
1
+ {"version":3,"file":"external-caller.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/http/external-caller.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;;;AAwBH,oDAEC;AA+BD,8CAOC;AA9DD,4BAA0B;AAE1B;;;;;;GAMG;AACU,QAAA,qBAAqB,GAAG;IACjC,UAAU;IACV,OAAO;IACP,OAAO;IACP,SAAS;IACT,MAAM;IACN,QAAQ;CACF,CAAC;AAIX,yEAAyE;AACzE,sFAAsF;AACtF,SAAgB,oBAAoB,CAAC,KAAa;IAC9C,OAAQ,6BAA2C,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACxE,CAAC;AAED;;;;;;GAMG;AACH,MAAa,cAAc;IAEH;IACA;IAFpB,YACoB,IAAwB,EACxB,KAAa;QADb,SAAI,GAAJ,IAAI,CAAoB;QACxB,UAAK,GAAL,KAAK,CAAQ;IAC9B,CAAC;CACP;AALD,wCAKC;AAED,qGAAqG;AACxF,QAAA,mBAAmB,GAAuB,MAAM,CAAC;AAE9D;;;;GAIG;AACU,QAAA,mBAAmB,GAAG,2BAA2B,CAAC;AAE/D;;;GAGG;AACH,wGAAwG;AACxG,SAAgB,iBAAiB,CAC7B,QAAkB,EAClB,UAAkB;IAElB,MAAM,OAAO,GACT,OAAO,CAAC,WAAW,CAAC,2BAAmB,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC7D,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC;AAC/B,CAAC","sourcesContent":["/**\n * WHO calls us from outside — the vocabulary an `EXTERNAL_INBOUND` @Endpoint uses to name its caller.\n *\n * Deliberately the SAME `(kind, label)` vocabulary the runtime architecture graph already uses for\n * OUTBOUND vendor seams (`@externalSystem saas twilio`). An inbound `saas twilio` and an outbound\n * `saas twilio` are the same vendor, so sharing the vocabulary makes them share an IDENTITY and\n * converge on ONE node instead of drawing twilio twice, facing opposite directions.\n *\n * Its own module rather than a block in decorators.ts: this is a data model with no dependency on\n * anything in that file, and decorators.ts is near its file-size limit. The dependency is strictly\n * one-way (decorators.ts imports this; this imports only reflect-metadata), so no cycle is possible.\n *\n * ## `calledBy` is REQUIRED on every `EXTERNAL_INBOUND` endpoint\n *\n * `@Endpoint(POST, path, WRITE, EXTERNAL_INBOUND, options)` does not compile without it. A lint rule\n * can be ignored, a compile error cannot, and the alternative was a graph that names our own contract\n * where the vendor belongs:\n *\n * ```ts\n * @Endpoint(POST, '/inbound', WRITE, EXTERNAL_INBOUND, { formPost: true, calledBy: 'twilio' })\n * // infrastructure rather than a vendor product:\n * @Endpoint(POST, '/push', WRITE, EXTERNAL_INBOUND, { calledBy: 'pubsub-push', callerKind: 'system' })\n * ```\n *\n * `rpc` / `cloudtasks` / `cron` / `external-outbound` endpoints keep options optional.\n */\n\nimport 'reflect-metadata';\n\n/**\n * What KIND of system an external caller IS. Drives the shape the runtime graph draws it with, so a\n * push-subscription stops looking like a vendor SaaS.\n *\n * Most inbound webhooks are `saas` (Twilio, Gmail, Stripe). A GCP Pub/Sub push subscription is\n * `system` — it is infrastructure, not a vendor product.\n */\nexport const EXTERNAL_SYSTEM_KINDS = [\n 'database',\n 'cache',\n 'queue',\n 'storage',\n 'saas',\n 'system',\n] as const;\n\nexport type ExternalSystemKind = (typeof EXTERNAL_SYSTEM_KINDS)[number];\n\n/** True for a string that names one of {@link EXTERNAL_SYSTEM_KINDS}. */\n// webpieces-disable no-function-outside-class -- type guard beside the type it guards\nexport function isExternalSystemKind(value: string): value is ExternalSystemKind {\n return (EXTERNAL_SYSTEM_KINDS as readonly string[]).includes(value);\n}\n\n/**\n * The declared caller of ONE `EXTERNAL_INBOUND` endpoint, normalized: `callerKind` defaulted, `calledBy`\n * carried as the label.\n *\n * `label` is the node IDENTITY on the runtime graph, not merely display text — two endpoints\n * declaring `twilio` converge on one box with two arrows into it.\n */\nexport class ExternalCaller {\n constructor(\n public readonly kind: ExternalSystemKind,\n public readonly label: string,\n ) {}\n}\n\n/** The kind an `EXTERNAL_INBOUND` @Endpoint gets when it declares `calledBy` but no `callerKind`. */\nexport const DEFAULT_CALLER_KIND: ExternalSystemKind = 'saas';\n\n/**\n * Metadata key of the per-method caller map, `methodName -> ExternalCaller`. Parallel to ENDPOINTS,\n * exactly like ENDPOINT_KIND and ENDPOINT_OPTIONS, and re-exported as `METADATA_KEYS.ENDPOINT_CALLER`\n * — declared HERE so the reader below needs no import from decorators.ts (which would close a cycle).\n */\nexport const ENDPOINT_CALLER_KEY = 'webpieces:endpoint-caller';\n\n/**\n * The DECLARED caller of one method, or undefined when it is not `EXTERNAL_INBOUND` (or is, but\n * bypassed TS — see `assertExternalEndpointKinds`). Mirrors `getEndpointOptions`.\n */\n// webpieces-disable no-function-outside-class -- reflect-metadata reader, sibling of getEndpointOptions\nexport function getEndpointCaller(\n apiClass: Function,\n methodName: string,\n): ExternalCaller | undefined {\n const callers: Record<string, ExternalCaller> =\n Reflect.getMetadata(ENDPOINT_CALLER_KEY, apiClass) || {};\n return callers[methodName];\n}\n"]}