@webpieces/core-util 0.4.761 → 0.4.763
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/package.json +1 -1
- package/src/errors/ApiError.d.ts +43 -49
- package/src/errors/ApiError.js +54 -59
- package/src/errors/ApiError.js.map +1 -1
- package/src/errors/ApiErrorCodec.d.ts +11 -6
- package/src/errors/ApiErrorCodec.js +93 -87
- package/src/errors/ApiErrorCodec.js.map +1 -1
- package/src/errors/AuthErrorSubtypes.d.ts +9 -0
- package/src/errors/AuthErrorSubtypes.js +13 -0
- package/src/errors/AuthErrorSubtypes.js.map +1 -0
- package/src/errors/index.d.ts +3 -1
- package/src/errors/index.js +24 -15
- package/src/errors/index.js.map +1 -1
- package/src/http/{TimeoutError.d.ts → ApiCallTimeoutError.d.ts} +1 -1
- package/src/http/{TimeoutError.js → ApiCallTimeoutError.js} +5 -5
- package/src/http/ApiCallTimeoutError.js.map +1 -0
- package/src/http/{HttpErrorStatus.d.ts → ApiErrorHttpStatus.d.ts} +2 -1
- package/src/http/ApiErrorHttpStatus.js +43 -0
- package/src/http/ApiErrorHttpStatus.js.map +1 -0
- package/src/http/CallDeadline.js +2 -2
- package/src/http/CallDeadline.js.map +1 -1
- package/src/http/ErrorTranslators.d.ts +5 -3
- package/src/http/ErrorTranslators.js.map +1 -1
- package/src/http/HttpResponseDto.d.ts +1 -1
- package/src/http/HttpResponseDto.js +2 -2
- package/src/http/HttpResponseDto.js.map +1 -1
- package/src/http/WebpiecesDefaultFailureClassifier.d.ts +6 -6
- package/src/http/WebpiecesDefaultFailureClassifier.js +12 -12
- package/src/http/WebpiecesDefaultFailureClassifier.js.map +1 -1
- package/src/http/decorators.d.ts +1 -1
- package/src/http/decorators.js +1 -1
- package/src/http/decorators.js.map +1 -1
- package/src/http/networkReject.d.ts +2 -2
- package/src/http/networkReject.js +5 -5
- package/src/http/networkReject.js.map +1 -1
- package/src/index.d.ts +5 -4
- package/src/index.js +23 -38
- package/src/index.js.map +1 -1
- package/src/ipc/IpcConnection.js +14 -14
- package/src/ipc/IpcConnection.js.map +1 -1
- package/src/ipc/IpcDecorators.js +9 -9
- package/src/ipc/IpcDecorators.js.map +1 -1
- package/src/ipc/IpcIdentity.js +1 -1
- package/src/ipc/IpcIdentity.js.map +1 -1
- package/src/ipc/IpcProtocol.js +5 -5
- package/src/ipc/IpcProtocol.js.map +1 -1
- package/src/ipc/index.d.ts +1 -1
- package/src/ipc/index.js +3 -3
- package/src/ipc/index.js.map +1 -1
- package/src/http/HttpErrorStatus.js +0 -38
- package/src/http/HttpErrorStatus.js.map +0 -1
- package/src/http/TimeoutError.js.map +0 -1
- package/src/http/errors.d.ts +0 -56
- package/src/http/errors.js +0 -95
- package/src/http/errors.js.map +0 -1
package/src/index.js
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
*/
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
11
|
exports.assertInternalApi = exports.getIpcMaskSpec = exports.getIpcEndpointKind = exports.getIpcEndpoints = exports.getIpcApiId = exports.isInternalApi = exports.WpIpcEndpoint = exports.WpInternal = exports.METADATA_KEYS = exports.validateNoConflictingDecorators = exports.assertEveryWebhookEndpointRetainsRawBody = exports.assertEveryExternalEndpointDeclaresCaller = exports.assertEveryEndpointHasAuthMode = exports.getAuthMode = exports.getAuthMeta = exports.isApiPath = exports.isRawBody = exports.isFormPost = exports.getMaskSpec = exports.getEndpointKinds = exports.getEndpointKind = exports.getEndpointOptions = exports.getEndpoints = exports.getApiPath = exports.MaskLog = exports.WpAuthLocalOnly = exports.WpAuthApiKey = exports.WpAuthWebhook = exports.WpAuthSharedSecret = exports.WpAuthOidc = exports.MISSING_AUTH_DECORATOR_FIX = exports.rolesRequired = exports.WpAuthJwt = exports.WpAuthPublic = exports.Endpoint = exports.ApiPath = exports.GCP_LOG_BUDGET_BYTES = exports.MAX_GCP_LOG_BYTES = exports.LogChunkInfo = exports.LogChunkerImpl = exports.LogChunker = exports.LogManager = exports.ConsoleLoggerFactory = exports.ConsoleLogger = exports.DESIGN_METADATA_KEYS = exports.isDocumentDesign = exports.DocumentDesign = exports.ContextTuple = exports.ContextKey = exports.toError = void 0;
|
|
12
|
-
exports.
|
|
13
|
-
exports.
|
|
12
|
+
exports.ContextMgr = exports.DestinationTrust = exports.WebpiecesCoreHeaders = exports.templateDeriver = exports.WEBPIECES_DEFAULT_FAILURE_CLASSIFIER = exports.WebpiecesDefaultFailureClassifier = exports.KeyedFailureClassifier = exports.HttpResponseDto = exports.HttpResponseStatus = exports.HttpHeader = exports.RuntimeLocality = exports.ServiceInfo = exports.ApiCallTimeoutError = exports.CallContext = exports.CallDeadline = exports.CallRegistry = exports.ClientRegistry = exports.HeaderRegistry = exports.DateTimeUtil = exports.TimeUtil = exports.DateUtil = exports.InstantUtil = exports.NetworkRejectClassifier = exports.NO_REG_CODE = exports.WRONG_COMPANY = exports.WRONG_DOMAIN = exports.EMAIL_NOT_CONFIRMED = exports.NOT_APPROVED = exports.WRONG_LOGIN = exports.WRONG_LOGIN_TYPE = exports.ENTITY_NOT_FOUND = exports.SECRETS = exports.Secrets = exports.getEndpointCaller = exports.isExternalSystemKind = exports.ExternalCaller = exports.DEFAULT_CALLER_KIND = exports.EXTERNAL_SYSTEM_KINDS = exports.getQueueName = exports.assertPubSubConventions = exports.assertApiKind = exports.getApiKind = exports.ENDPOINT_KINDS_BY_API_KIND = exports.Queue = exports.PubSub = exports.Rpc = exports.AuthMeta = exports.RouteMetadata = exports.IPC_METADATA_KEYS = exports.assertNotInternalApi = void 0;
|
|
13
|
+
exports.ApiErrorHttpStatus = exports.ApiErrorPayload = exports.ApiErrorCodec = exports.ApiEndpointNotFoundError = exports.ApiConnectionError = exports.ApiDependencyBackoffError = exports.ApiUnauthorizedError = exports.ApiBadRequestError = exports.ApiEndUserError = exports.ApiRequestTimeoutError = exports.ApiForbiddenError = exports.ApiRateLimitedError = exports.ApiImplementationError = exports.ApiDependencyTimeoutError = exports.ApiUnavailableError = exports.ApiDependencyError = exports.ApiNotFoundError = exports.ApiError = exports.FilterChain = exports.Filter = exports.SerializedError = exports.SerializedMap = exports.RecordSerializer = exports.getDoNotRecordFields = exports.DoNotRecord = exports.RecordedTestCase = exports.RecordedError = exports.RecordedEndpoint = exports.RecorderKeys = exports.ApiMethodInfo = exports.LOG_API_CALL_LOGGER_NAME = exports.ApiCallLogNameImpl = exports.ApiCallLogName = exports.ApiCallInfo = exports.MaskSpec = exports.LogApiCallImpl = void 0;
|
|
14
14
|
var errorUtils_1 = require("./lib/errorUtils");
|
|
15
15
|
Object.defineProperty(exports, "toError", { enumerable: true, get: function () { return errorUtils_1.toError; } });
|
|
16
16
|
var ContextKey_1 = require("./ContextKey");
|
|
@@ -38,7 +38,7 @@ Object.defineProperty(exports, "MAX_GCP_LOG_BYTES", { enumerable: true, get: fun
|
|
|
38
38
|
Object.defineProperty(exports, "GCP_LOG_BUDGET_BYTES", { enumerable: true, get: function () { return LogChunker_1.GCP_LOG_BUDGET_BYTES; } });
|
|
39
39
|
// HTTP API contract (merged from former @webpieces/http-api).
|
|
40
40
|
// Shared HTTP API definition consumed by both client and server: REST
|
|
41
|
-
// decorators, the
|
|
41
|
+
// decorators, the API error taxonomy, datetime DTOs, platform-header
|
|
42
42
|
// registry/readers, ValidateImplementation, and the test-case recorder
|
|
43
43
|
// contract. Pure definitions — express-free, browser + Node safe.
|
|
44
44
|
// API definition decorators
|
|
@@ -112,25 +112,8 @@ Object.defineProperty(exports, "getEndpointCaller", { enumerable: true, get: fun
|
|
|
112
112
|
var Secrets_1 = require("./http/Secrets");
|
|
113
113
|
Object.defineProperty(exports, "Secrets", { enumerable: true, get: function () { return Secrets_1.Secrets; } });
|
|
114
114
|
Object.defineProperty(exports, "SECRETS", { enumerable: true, get: function () { return Secrets_1.SECRETS; } });
|
|
115
|
-
//
|
|
116
|
-
var errors_1 = require("./
|
|
117
|
-
Object.defineProperty(exports, "ProtocolError", { enumerable: true, get: function () { return errors_1.ProtocolError; } });
|
|
118
|
-
Object.defineProperty(exports, "HttpError", { enumerable: true, get: function () { return errors_1.HttpError; } });
|
|
119
|
-
Object.defineProperty(exports, "HttpNotFoundError", { enumerable: true, get: function () { return errors_1.HttpNotFoundError; } });
|
|
120
|
-
Object.defineProperty(exports, "EndpointNotFoundError", { enumerable: true, get: function () { return errors_1.EndpointNotFoundError; } });
|
|
121
|
-
Object.defineProperty(exports, "HttpBadRequestError", { enumerable: true, get: function () { return errors_1.HttpBadRequestError; } });
|
|
122
|
-
Object.defineProperty(exports, "HttpUnauthorizedError", { enumerable: true, get: function () { return errors_1.HttpUnauthorizedError; } });
|
|
123
|
-
Object.defineProperty(exports, "HttpForbiddenError", { enumerable: true, get: function () { return errors_1.HttpForbiddenError; } });
|
|
124
|
-
Object.defineProperty(exports, "HttpTimeoutError", { enumerable: true, get: function () { return errors_1.HttpTimeoutError; } });
|
|
125
|
-
Object.defineProperty(exports, "HttpBadGatewayError", { enumerable: true, get: function () { return errors_1.HttpBadGatewayError; } });
|
|
126
|
-
Object.defineProperty(exports, "HttpServiceUnavailableError", { enumerable: true, get: function () { return errors_1.HttpServiceUnavailableError; } });
|
|
127
|
-
Object.defineProperty(exports, "HttpGatewayTimeoutError", { enumerable: true, get: function () { return errors_1.HttpGatewayTimeoutError; } });
|
|
128
|
-
Object.defineProperty(exports, "HttpInternalServerError", { enumerable: true, get: function () { return errors_1.HttpInternalServerError; } });
|
|
129
|
-
Object.defineProperty(exports, "HttpTooManyRequestsError", { enumerable: true, get: function () { return errors_1.HttpTooManyRequestsError; } });
|
|
130
|
-
Object.defineProperty(exports, "HttpVendorError", { enumerable: true, get: function () { return errors_1.HttpVendorError; } });
|
|
131
|
-
Object.defineProperty(exports, "HttpUserError", { enumerable: true, get: function () { return errors_1.HttpUserError; } });
|
|
132
|
-
Object.defineProperty(exports, "OfflineError", { enumerable: true, get: function () { return errors_1.OfflineError; } });
|
|
133
|
-
// Error subtype constants
|
|
115
|
+
// Authentication subtype constants.
|
|
116
|
+
var errors_1 = require("./errors");
|
|
134
117
|
Object.defineProperty(exports, "ENTITY_NOT_FOUND", { enumerable: true, get: function () { return errors_1.ENTITY_NOT_FOUND; } });
|
|
135
118
|
Object.defineProperty(exports, "WRONG_LOGIN_TYPE", { enumerable: true, get: function () { return errors_1.WRONG_LOGIN_TYPE; } });
|
|
136
119
|
Object.defineProperty(exports, "WRONG_LOGIN", { enumerable: true, get: function () { return errors_1.WRONG_LOGIN; } });
|
|
@@ -158,8 +141,8 @@ var CallDeadline_1 = require("./http/CallDeadline");
|
|
|
158
141
|
Object.defineProperty(exports, "CallDeadline", { enumerable: true, get: function () { return CallDeadline_1.CallDeadline; } });
|
|
159
142
|
var CallStrategy_1 = require("./http/CallStrategy");
|
|
160
143
|
Object.defineProperty(exports, "CallContext", { enumerable: true, get: function () { return CallStrategy_1.CallContext; } });
|
|
161
|
-
var
|
|
162
|
-
Object.defineProperty(exports, "
|
|
144
|
+
var ApiCallTimeoutError_1 = require("./http/ApiCallTimeoutError");
|
|
145
|
+
Object.defineProperty(exports, "ApiCallTimeoutError", { enumerable: true, get: function () { return ApiCallTimeoutError_1.ApiCallTimeoutError; } });
|
|
163
146
|
// "What service am I" — set once at startup, read by the logging backends and by
|
|
164
147
|
// RequestContextHeaders (to stamp requestIdSource on ids this service mints).
|
|
165
148
|
var ServiceInfo_1 = require("./http/ServiceInfo");
|
|
@@ -238,20 +221,22 @@ var FilterChain_1 = require("./filters/FilterChain");
|
|
|
238
221
|
Object.defineProperty(exports, "FilterChain", { enumerable: true, get: function () { return FilterChain_1.FilterChain; } });
|
|
239
222
|
var errors_2 = require("./errors");
|
|
240
223
|
Object.defineProperty(exports, "ApiError", { enumerable: true, get: function () { return errors_2.ApiError; } });
|
|
241
|
-
Object.defineProperty(exports, "
|
|
242
|
-
Object.defineProperty(exports, "
|
|
243
|
-
Object.defineProperty(exports, "
|
|
244
|
-
Object.defineProperty(exports, "
|
|
245
|
-
Object.defineProperty(exports, "
|
|
246
|
-
Object.defineProperty(exports, "
|
|
247
|
-
Object.defineProperty(exports, "
|
|
248
|
-
Object.defineProperty(exports, "
|
|
249
|
-
Object.defineProperty(exports, "
|
|
250
|
-
Object.defineProperty(exports, "
|
|
251
|
-
Object.defineProperty(exports, "
|
|
252
|
-
Object.defineProperty(exports, "
|
|
224
|
+
Object.defineProperty(exports, "ApiNotFoundError", { enumerable: true, get: function () { return errors_2.ApiNotFoundError; } });
|
|
225
|
+
Object.defineProperty(exports, "ApiDependencyError", { enumerable: true, get: function () { return errors_2.ApiDependencyError; } });
|
|
226
|
+
Object.defineProperty(exports, "ApiUnavailableError", { enumerable: true, get: function () { return errors_2.ApiUnavailableError; } });
|
|
227
|
+
Object.defineProperty(exports, "ApiDependencyTimeoutError", { enumerable: true, get: function () { return errors_2.ApiDependencyTimeoutError; } });
|
|
228
|
+
Object.defineProperty(exports, "ApiImplementationError", { enumerable: true, get: function () { return errors_2.ApiImplementationError; } });
|
|
229
|
+
Object.defineProperty(exports, "ApiRateLimitedError", { enumerable: true, get: function () { return errors_2.ApiRateLimitedError; } });
|
|
230
|
+
Object.defineProperty(exports, "ApiForbiddenError", { enumerable: true, get: function () { return errors_2.ApiForbiddenError; } });
|
|
231
|
+
Object.defineProperty(exports, "ApiRequestTimeoutError", { enumerable: true, get: function () { return errors_2.ApiRequestTimeoutError; } });
|
|
232
|
+
Object.defineProperty(exports, "ApiEndUserError", { enumerable: true, get: function () { return errors_2.ApiEndUserError; } });
|
|
233
|
+
Object.defineProperty(exports, "ApiBadRequestError", { enumerable: true, get: function () { return errors_2.ApiBadRequestError; } });
|
|
234
|
+
Object.defineProperty(exports, "ApiUnauthorizedError", { enumerable: true, get: function () { return errors_2.ApiUnauthorizedError; } });
|
|
235
|
+
Object.defineProperty(exports, "ApiDependencyBackoffError", { enumerable: true, get: function () { return errors_2.ApiDependencyBackoffError; } });
|
|
236
|
+
Object.defineProperty(exports, "ApiConnectionError", { enumerable: true, get: function () { return errors_2.ApiConnectionError; } });
|
|
237
|
+
Object.defineProperty(exports, "ApiEndpointNotFoundError", { enumerable: true, get: function () { return errors_2.ApiEndpointNotFoundError; } });
|
|
253
238
|
Object.defineProperty(exports, "ApiErrorCodec", { enumerable: true, get: function () { return errors_2.ApiErrorCodec; } });
|
|
254
239
|
Object.defineProperty(exports, "ApiErrorPayload", { enumerable: true, get: function () { return errors_2.ApiErrorPayload; } });
|
|
255
|
-
var
|
|
256
|
-
Object.defineProperty(exports, "
|
|
240
|
+
var ApiErrorHttpStatus_1 = require("./http/ApiErrorHttpStatus");
|
|
241
|
+
Object.defineProperty(exports, "ApiErrorHttpStatus", { enumerable: true, get: function () { return ApiErrorHttpStatus_1.ApiErrorHttpStatus; } });
|
|
257
242
|
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/core/core-util/src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @webpieces/core-util\n *\n * Utility functions for WebPieces applications.\n * This package works in both browser and Node.js environments.\n *\n * @packageDocumentation\n */\n\nexport { toError } from './lib/errorUtils';\nexport { ContextKey } from './ContextKey';\nexport type {\n AnyContextKey,\n AnyTrustedContextKey,\n AnyUntrustedContextKey,\n Trust,\n} from './ContextKey';\nexport { ContextTuple } from './ContextTuple';\n\n// @DocumentDesign — DI-design-root marker. Applies to ANY project kind (server\n// controllers AND library impl classes), so it lives here (browser + Node) rather\n// than in a server-only routing package.\nexport { DocumentDesign, isDocumentDesign, DESIGN_METADATA_KEYS } from './DocumentDesign';\n\n// Logging (merged from former @webpieces/wp-logging).\n// Pluggable logging interface + a browser-safe console default; apps plug in\n// bunyan/winston/pino/etc. via LogManager.setFactory(...). Browser + Node.\nexport type { Logger, LogLevel } from './logging/Logger';\nexport type { LoggerFactory } from './logging/LoggerFactory';\nexport { ConsoleLogger } from './logging/ConsoleLogger';\nexport { ConsoleLoggerFactory } from './logging/ConsoleLoggerFactory';\nexport { LogManager } from './logging/LogManager';\nexport {\n LogChunker,\n LogChunkerImpl,\n LogChunkInfo,\n MAX_GCP_LOG_BYTES,\n GCP_LOG_BUDGET_BYTES,\n} from './logging/LogChunker';\n\n// HTTP API contract (merged from former @webpieces/http-api).\n// Shared HTTP API definition consumed by both client and server: REST\n// decorators, the HttpError hierarchy, datetime DTOs, platform-header\n// registry/readers, ValidateImplementation, and the test-case recorder\n// contract. Pure definitions — express-free, browser + Node safe.\n\n// API definition decorators\nexport {\n ApiPath,\n Endpoint,\n // Auth mode decorators (clean service-to-service + user JWT model)\n WpAuthPublic,\n WpAuthJwt,\n rolesRequired,\n MISSING_AUTH_DECORATOR_FIX,\n WpAuthOidc,\n WpAuthSharedSecret,\n WpAuthWebhook,\n WpAuthApiKey,\n WpAuthLocalOnly,\n MaskLog,\n getApiPath,\n getEndpoints,\n getEndpointOptions,\n getEndpointKind,\n getEndpointKinds,\n getMaskSpec,\n isFormPost,\n isRawBody,\n isApiPath,\n getAuthMeta,\n getAuthMode,\n assertEveryEndpointHasAuthMode,\n assertEveryExternalEndpointDeclaresCaller,\n assertEveryWebhookEndpointRetainsRawBody,\n validateNoConflictingDecorators,\n METADATA_KEYS,\n} from './http/decorators';\nexport {\n WpInternal,\n WpIpcEndpoint,\n isInternalApi,\n getIpcApiId,\n getIpcEndpoints,\n getIpcEndpointKind,\n getIpcMaskSpec,\n assertInternalApi,\n assertNotInternalApi,\n IPC_METADATA_KEYS,\n} from './ipc/IpcDecorators';\nexport type { IpcApiType, IpcEndpointKind, IpcEndpointOptions } from './ipc/IpcDecorators';\n// The runtime representation of ONE route (split out of decorators.ts for file size only).\nexport { RouteMetadata } from './http/RouteMetadata';\nexport type { EndpointKind, EndpointOptions, ExternalEndpointOptions } from './http/decorators';\n// The TYPE layer of the auth surface — likewise split out of decorators.ts for file size only.\nexport { AuthMeta } from './http/auth-mode';\nexport type {\n AuthMode,\n ApiKeyCredential,\n ApiKeyCredentials,\n JwtRoles,\n JwtRequirement,\n} from './http/auth-mode';\n// API kind (RPC vs PubSub/Cloud Tasks) + queue naming. Split out of decorators.ts for file size only;\n// one-way dependency api-kind -> decorators, and the barrel keeps the surface identical.\nexport {\n Rpc,\n PubSub,\n Queue,\n ENDPOINT_KINDS_BY_API_KIND,\n getApiKind,\n assertApiKind,\n assertPubSubConventions,\n getQueueName,\n} from './http/api-kind';\nexport type { ApiKind } from './http/api-kind';\n// WHO calls an `external` endpoint — the caller declaration @Endpoint(..., 'external', {calledBy})\n// requires, and the reader for it.\nexport {\n EXTERNAL_SYSTEM_KINDS,\n DEFAULT_CALLER_KIND,\n ExternalCaller,\n isExternalSystemKind,\n getEndpointCaller,\n} from './http/external-caller';\nexport type { ExternalSystemKind } from './http/external-caller';\n// Client-side shared-secret store (the value THIS service sends per @WpAuthSharedSecret key).\nexport { Secrets, SECRETS } from './http/Secrets';\n\n// Type validators\nexport { ValidateImplementation } from './http/validators';\n\n// HTTP wire DTO, legacy aliases and subtype constants.\nexport {\n ProtocolError,\n HttpError,\n HttpNotFoundError,\n EndpointNotFoundError,\n HttpBadRequestError,\n HttpUnauthorizedError,\n HttpForbiddenError,\n HttpTimeoutError,\n HttpBadGatewayError,\n HttpServiceUnavailableError,\n HttpGatewayTimeoutError,\n HttpInternalServerError,\n HttpTooManyRequestsError,\n HttpVendorError,\n HttpUserError,\n OfflineError,\n // Error subtype constants\n ENTITY_NOT_FOUND,\n WRONG_LOGIN_TYPE,\n WRONG_LOGIN,\n NOT_APPROVED,\n EMAIL_NOT_CONFIRMED,\n WRONG_DOMAIN,\n WRONG_COMPANY,\n NO_REG_CODE,\n} from './http/errors';\n\nexport { NetworkRejectClassifier } from './http/networkReject';\n\n// Date/Time DTOs and Utilities (inspired by Java Time / JSR-310)\nexport {\n InstantDto,\n DateDto,\n TimeDto,\n DateTimeDto,\n InstantUtil,\n DateUtil,\n TimeUtil,\n DateTimeUtil,\n} from './http/datetime';\n\n// Context keys + registry (the global magic-context header system)\nexport { HeaderRegistry } from './http/HeaderRegistry';\nexport { ClientRegistry } from './http/ClientRegistry';\nexport { CallRegistry } from './http/CallRegistry';\nexport { CallDeadline } from './http/CallDeadline';\nexport { CallContext } from './http/CallStrategy';\nexport type { Attempt, CallStrategy } from './http/CallStrategy';\nexport { TimeoutError } from './http/TimeoutError';\nexport type { ServiceUrlDeriver } from './http/ClientRegistry';\n\n// \"What service am I\" — set once at startup, read by the logging backends and by\n// RequestContextHeaders (to stamp requestIdSource on ids this service mints).\nexport { ServiceInfo } from './http/ServiceInfo';\n// \"Where am I running\" — declared once at startup (setupRuntime, from RuntimeSetupOptions.locality).\n// The ONE input to @WpAuthLocalOnly enforcement. Undeclared reads as DEPLOYED (fail safe).\nexport { RuntimeLocality } from './http/RuntimeLocality';\nexport type { Locality } from './http/RuntimeLocality';\n// The ENTIRE HTTP response as pure data — the ONE form both transports (express, fetch) are\n// normalised into, so an ErrorTranslators implementation is written once and serves both.\nexport { HttpHeader, HttpResponseStatus, HttpResponseDto } from './http/HttpResponseDto';\n// Pluggable, bidirectional error translation (app exception <-> the WHOLE response). Set on\n// ClientRegistry at startup; consulted before the built-in webpieces mapping on BOTH sides.\nexport type { ErrorTranslators } from './http/ErrorTranslators';\n// Pluggable per-client failure classification (is a thrown API-call error a real failure or an\n// expected non-failure?). Registered on ClientRegistry at startup; consulted by LogApiCall.\nexport type { FailureClassifier } from './http/FailureClassifier';\nexport { KeyedFailureClassifier } from './http/FailureClassifier';\nexport {\n WebpiecesDefaultFailureClassifier,\n WEBPIECES_DEFAULT_FAILURE_CLASSIFIER,\n} from './http/WebpiecesDefaultFailureClassifier';\nexport { templateDeriver } from './http/templateDeriver';\nexport { WebpiecesCoreHeaders } from './http/WebpiecesCoreHeaders';\nexport { ContextReader } from './http/ContextReader';\n\n// The OUTBOUND half of the trust model: whether a TRUSTED context key may ride to the endpoint being\n// called. Built ONLY from the destination endpoint's AuthMode — see the class doc.\nexport { DestinationTrust } from './http/DestinationTrust';\n\n// BROWSER-ONLY outbound-header propagation (app-held store + registry -> outbound HTTP headers).\n// Only @webpieces/http-client-browser may name it; the server reads RequestContext directly via\n// RequestContextHeaders in the Node-only @webpieces/core-context.\nexport { ContextMgr } from './http/ContextMgr';\n\n// API-call logging helper (uses LogManager above). NOT a singleton: construct one per environment\n// with that environment's ApiCallContext — `new LogApiCallImpl(new RequestContextApiCallContext())`\n// on node, `new LogApiCallImpl(new BrowserApiCallContext())` in a browser.\nexport { LogApiCallImpl } from './http/LogApiCall';\n\n// Opt-in field masking for the LogApiCall log path — declare per-api sensitive fields so secrets\n// (OAuth refresh tokens, id-token JWTs) are masked in the logs while the real value stays on the wire.\nexport { MaskSpec } from './http/LogFieldMask';\nexport type { MaskMode } from './http/LogFieldMask';\n\n// The structured `api` tag + the context-writer seam LogApiCall stamps through. The Node\n// RequestContext-backed impl lives in @webpieces/core-context, the browser one in\n// @webpieces/http-client-browser; each is CONSTRUCTED by its package, never installed globally.\nexport { ApiCallInfo } from './http/ApiCallInfo';\nexport type { ApiType, ApiResult } from './http/ApiCallInfo';\n// Console-render bridge: turns LogApiCall's [LogApiCall] bracket into [API.{side}.{phase}] locally.\nexport {\n ApiCallLogName,\n ApiCallLogNameImpl,\n LOG_API_CALL_LOGGER_NAME,\n} from './http/ApiCallLogName';\nexport { ApiMethodInfo } from './http/ApiMethodInfo';\nexport type { ApiSide } from './http/ApiMethodInfo';\nexport type { ApiCallContext } from './http/ApiCallContext';\n\n// Test-case recording contract (impl lives in http-server; hooks in http-client)\nexport { TestCaseRecorder, RecorderKeys } from './http/recorder/TestCaseRecorder';\nexport {\n RecordedEndpoint,\n RecordedError,\n RecordedTestCase,\n} from './http/recorder/RecordedEndpoint';\nexport { DoNotRecord, getDoNotRecordFields } from './http/recorder/DoNotRecord';\nexport { RecordSerializer, SerializedMap, SerializedError } from './http/recorder/RecordSerializer';\n\n// ---------------------------------------------------------------------------------------------\n// Filter-chain primitives, shared by BOTH chains: the inbound server chain\n// (`Filter<MethodMeta, WpResponse<unknown>>`, @webpieces/http-routing) and the outbound client\n// chain (`Filter<ClientRequest, Response>`, @webpieces/http-client-core). Declared once, here, in\n// the package both depend on — see the class doc for why a second pair would be a shim.\nexport { Filter } from './filters/Filter';\nexport type { Service } from './filters/Filter';\nexport { FilterChain } from './filters/FilterChain';\n\nexport {\n ApiError,\n NotFoundError,\n BadGatewayError,\n ServiceUnavailableError,\n GatewayTimeoutError,\n InternalError,\n TooManyRequestsError,\n ForbiddenError,\n RequestTimeoutError,\n UserError,\n BadRequestError,\n UnauthorizedError,\n VendorError,\n ApiErrorCodec,\n ApiErrorPayload,\n} from './errors';\nexport { HttpErrorStatus } from './http/HttpErrorStatus';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/core/core-util/src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @webpieces/core-util\n *\n * Utility functions for WebPieces applications.\n * This package works in both browser and Node.js environments.\n *\n * @packageDocumentation\n */\n\nexport { toError } from './lib/errorUtils';\nexport { ContextKey } from './ContextKey';\nexport type {\n AnyContextKey,\n AnyTrustedContextKey,\n AnyUntrustedContextKey,\n Trust,\n} from './ContextKey';\nexport { ContextTuple } from './ContextTuple';\n\n// @DocumentDesign — DI-design-root marker. Applies to ANY project kind (server\n// controllers AND library impl classes), so it lives here (browser + Node) rather\n// than in a server-only routing package.\nexport { DocumentDesign, isDocumentDesign, DESIGN_METADATA_KEYS } from './DocumentDesign';\n\n// Logging (merged from former @webpieces/wp-logging).\n// Pluggable logging interface + a browser-safe console default; apps plug in\n// bunyan/winston/pino/etc. via LogManager.setFactory(...). Browser + Node.\nexport type { Logger, LogLevel } from './logging/Logger';\nexport type { LoggerFactory } from './logging/LoggerFactory';\nexport { ConsoleLogger } from './logging/ConsoleLogger';\nexport { ConsoleLoggerFactory } from './logging/ConsoleLoggerFactory';\nexport { LogManager } from './logging/LogManager';\nexport {\n LogChunker,\n LogChunkerImpl,\n LogChunkInfo,\n MAX_GCP_LOG_BYTES,\n GCP_LOG_BUDGET_BYTES,\n} from './logging/LogChunker';\n\n// HTTP API contract (merged from former @webpieces/http-api).\n// Shared HTTP API definition consumed by both client and server: REST\n// decorators, the API error taxonomy, datetime DTOs, platform-header\n// registry/readers, ValidateImplementation, and the test-case recorder\n// contract. Pure definitions — express-free, browser + Node safe.\n\n// API definition decorators\nexport {\n ApiPath,\n Endpoint,\n // Auth mode decorators (clean service-to-service + user JWT model)\n WpAuthPublic,\n WpAuthJwt,\n rolesRequired,\n MISSING_AUTH_DECORATOR_FIX,\n WpAuthOidc,\n WpAuthSharedSecret,\n WpAuthWebhook,\n WpAuthApiKey,\n WpAuthLocalOnly,\n MaskLog,\n getApiPath,\n getEndpoints,\n getEndpointOptions,\n getEndpointKind,\n getEndpointKinds,\n getMaskSpec,\n isFormPost,\n isRawBody,\n isApiPath,\n getAuthMeta,\n getAuthMode,\n assertEveryEndpointHasAuthMode,\n assertEveryExternalEndpointDeclaresCaller,\n assertEveryWebhookEndpointRetainsRawBody,\n validateNoConflictingDecorators,\n METADATA_KEYS,\n} from './http/decorators';\nexport {\n WpInternal,\n WpIpcEndpoint,\n isInternalApi,\n getIpcApiId,\n getIpcEndpoints,\n getIpcEndpointKind,\n getIpcMaskSpec,\n assertInternalApi,\n assertNotInternalApi,\n IPC_METADATA_KEYS,\n} from './ipc/IpcDecorators';\nexport type { IpcApiType, IpcEndpointKind, IpcEndpointOptions } from './ipc/IpcDecorators';\n// The runtime representation of ONE route (split out of decorators.ts for file size only).\nexport { RouteMetadata } from './http/RouteMetadata';\nexport type { EndpointKind, EndpointOptions, ExternalEndpointOptions } from './http/decorators';\n// The TYPE layer of the auth surface — likewise split out of decorators.ts for file size only.\nexport { AuthMeta } from './http/auth-mode';\nexport type {\n AuthMode,\n ApiKeyCredential,\n ApiKeyCredentials,\n JwtRoles,\n JwtRequirement,\n} from './http/auth-mode';\n// API kind (RPC vs PubSub/Cloud Tasks) + queue naming. Split out of decorators.ts for file size only;\n// one-way dependency api-kind -> decorators, and the barrel keeps the surface identical.\nexport {\n Rpc,\n PubSub,\n Queue,\n ENDPOINT_KINDS_BY_API_KIND,\n getApiKind,\n assertApiKind,\n assertPubSubConventions,\n getQueueName,\n} from './http/api-kind';\nexport type { ApiKind } from './http/api-kind';\n// WHO calls an `external` endpoint — the caller declaration @Endpoint(..., 'external', {calledBy})\n// requires, and the reader for it.\nexport {\n EXTERNAL_SYSTEM_KINDS,\n DEFAULT_CALLER_KIND,\n ExternalCaller,\n isExternalSystemKind,\n getEndpointCaller,\n} from './http/external-caller';\nexport type { ExternalSystemKind } from './http/external-caller';\n// Client-side shared-secret store (the value THIS service sends per @WpAuthSharedSecret key).\nexport { Secrets, SECRETS } from './http/Secrets';\n\n// Type validators\nexport { ValidateImplementation } from './http/validators';\n\n// Authentication subtype constants.\nexport {\n ENTITY_NOT_FOUND,\n WRONG_LOGIN_TYPE,\n WRONG_LOGIN,\n NOT_APPROVED,\n EMAIL_NOT_CONFIRMED,\n WRONG_DOMAIN,\n WRONG_COMPANY,\n NO_REG_CODE,\n} from './errors';\n\nexport { NetworkRejectClassifier } from './http/networkReject';\n\n// Date/Time DTOs and Utilities (inspired by Java Time / JSR-310)\nexport {\n InstantDto,\n DateDto,\n TimeDto,\n DateTimeDto,\n InstantUtil,\n DateUtil,\n TimeUtil,\n DateTimeUtil,\n} from './http/datetime';\n\n// Context keys + registry (the global magic-context header system)\nexport { HeaderRegistry } from './http/HeaderRegistry';\nexport { ClientRegistry } from './http/ClientRegistry';\nexport { CallRegistry } from './http/CallRegistry';\nexport { CallDeadline } from './http/CallDeadline';\nexport { CallContext } from './http/CallStrategy';\nexport type { Attempt, CallStrategy } from './http/CallStrategy';\nexport { ApiCallTimeoutError } from './http/ApiCallTimeoutError';\nexport type { ServiceUrlDeriver } from './http/ClientRegistry';\n\n// \"What service am I\" — set once at startup, read by the logging backends and by\n// RequestContextHeaders (to stamp requestIdSource on ids this service mints).\nexport { ServiceInfo } from './http/ServiceInfo';\n// \"Where am I running\" — declared once at startup (setupRuntime, from RuntimeSetupOptions.locality).\n// The ONE input to @WpAuthLocalOnly enforcement. Undeclared reads as DEPLOYED (fail safe).\nexport { RuntimeLocality } from './http/RuntimeLocality';\nexport type { Locality } from './http/RuntimeLocality';\n// The ENTIRE HTTP response as pure data — the ONE form both transports (express, fetch) are\n// normalised into, so an ErrorTranslators implementation is written once and serves both.\nexport { HttpHeader, HttpResponseStatus, HttpResponseDto } from './http/HttpResponseDto';\n// Pluggable, bidirectional error translation (app exception <-> the WHOLE response). Set on\n// ClientRegistry at startup; consulted before the built-in webpieces mapping on BOTH sides.\nexport type { ErrorTranslators } from './http/ErrorTranslators';\n// Pluggable per-client failure classification (is a thrown API-call error a real failure or an\n// expected non-failure?). Registered on ClientRegistry at startup; consulted by LogApiCall.\nexport type { FailureClassifier } from './http/FailureClassifier';\nexport { KeyedFailureClassifier } from './http/FailureClassifier';\nexport {\n WebpiecesDefaultFailureClassifier,\n WEBPIECES_DEFAULT_FAILURE_CLASSIFIER,\n} from './http/WebpiecesDefaultFailureClassifier';\nexport { templateDeriver } from './http/templateDeriver';\nexport { WebpiecesCoreHeaders } from './http/WebpiecesCoreHeaders';\nexport { ContextReader } from './http/ContextReader';\n\n// The OUTBOUND half of the trust model: whether a TRUSTED context key may ride to the endpoint being\n// called. Built ONLY from the destination endpoint's AuthMode — see the class doc.\nexport { DestinationTrust } from './http/DestinationTrust';\n\n// BROWSER-ONLY outbound-header propagation (app-held store + registry -> outbound HTTP headers).\n// Only @webpieces/http-client-browser may name it; the server reads RequestContext directly via\n// RequestContextHeaders in the Node-only @webpieces/core-context.\nexport { ContextMgr } from './http/ContextMgr';\n\n// API-call logging helper (uses LogManager above). NOT a singleton: construct one per environment\n// with that environment's ApiCallContext — `new LogApiCallImpl(new RequestContextApiCallContext())`\n// on node, `new LogApiCallImpl(new BrowserApiCallContext())` in a browser.\nexport { LogApiCallImpl } from './http/LogApiCall';\n\n// Opt-in field masking for the LogApiCall log path — declare per-api sensitive fields so secrets\n// (OAuth refresh tokens, id-token JWTs) are masked in the logs while the real value stays on the wire.\nexport { MaskSpec } from './http/LogFieldMask';\nexport type { MaskMode } from './http/LogFieldMask';\n\n// The structured `api` tag + the context-writer seam LogApiCall stamps through. The Node\n// RequestContext-backed impl lives in @webpieces/core-context, the browser one in\n// @webpieces/http-client-browser; each is CONSTRUCTED by its package, never installed globally.\nexport { ApiCallInfo } from './http/ApiCallInfo';\nexport type { ApiType, ApiResult } from './http/ApiCallInfo';\n// Console-render bridge: turns LogApiCall's [LogApiCall] bracket into [API.{side}.{phase}] locally.\nexport {\n ApiCallLogName,\n ApiCallLogNameImpl,\n LOG_API_CALL_LOGGER_NAME,\n} from './http/ApiCallLogName';\nexport { ApiMethodInfo } from './http/ApiMethodInfo';\nexport type { ApiSide } from './http/ApiMethodInfo';\nexport type { ApiCallContext } from './http/ApiCallContext';\n\n// Test-case recording contract (impl lives in http-server; hooks in http-client)\nexport { TestCaseRecorder, RecorderKeys } from './http/recorder/TestCaseRecorder';\nexport {\n RecordedEndpoint,\n RecordedError,\n RecordedTestCase,\n} from './http/recorder/RecordedEndpoint';\nexport { DoNotRecord, getDoNotRecordFields } from './http/recorder/DoNotRecord';\nexport { RecordSerializer, SerializedMap, SerializedError } from './http/recorder/RecordSerializer';\n\n// ---------------------------------------------------------------------------------------------\n// Filter-chain primitives, shared by BOTH chains: the inbound server chain\n// (`Filter<MethodMeta, WpResponse<unknown>>`, @webpieces/http-routing) and the outbound client\n// chain (`Filter<ClientRequest, Response>`, @webpieces/http-client-core). Declared once, here, in\n// the package both depend on — see the class doc for why a second pair would be a shim.\nexport { Filter } from './filters/Filter';\nexport type { Service } from './filters/Filter';\nexport { FilterChain } from './filters/FilterChain';\n\nexport {\n ApiError,\n ApiNotFoundError,\n ApiDependencyError,\n ApiUnavailableError,\n ApiDependencyTimeoutError,\n ApiImplementationError,\n ApiRateLimitedError,\n ApiForbiddenError,\n ApiRequestTimeoutError,\n ApiEndUserError,\n ApiBadRequestError,\n ApiUnauthorizedError,\n ApiDependencyBackoffError,\n ApiConnectionError,\n ApiEndpointNotFoundError,\n ApiErrorCodec,\n ApiErrorPayload,\n} from './errors';\nexport type { ApiErrorKind } from './errors';\nexport { ApiErrorHttpStatus } from './http/ApiErrorHttpStatus';\n"]}
|
package/src/ipc/IpcConnection.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.IpcErrors = exports.IpcConnection = exports.IpcConnectionOptions = exports.IpcTransportError = void 0;
|
|
4
4
|
const errorUtils_1 = require("../lib/errorUtils");
|
|
5
|
-
const
|
|
5
|
+
const ApiCallTimeoutError_1 = require("../http/ApiCallTimeoutError");
|
|
6
6
|
const CallStrategy_1 = require("../http/CallStrategy");
|
|
7
7
|
const errors_1 = require("../errors");
|
|
8
8
|
const IpcProtocol_1 = require("./IpcProtocol");
|
|
@@ -36,7 +36,7 @@ class IpcConnectionOptions {
|
|
|
36
36
|
maxMessageCharacters < 1 ||
|
|
37
37
|
!Number.isSafeInteger(settlementHistoryLimit) ||
|
|
38
38
|
settlementHistoryLimit < 1) {
|
|
39
|
-
throw new errors_1.
|
|
39
|
+
throw new errors_1.ApiImplementationError('IPC timeout and message limit must be positive');
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
}
|
|
@@ -81,7 +81,7 @@ class IpcConnection {
|
|
|
81
81
|
/** Install exactly one factory dispatcher BEFORE exposing this connection to the peer. */
|
|
82
82
|
setHandler(handler) {
|
|
83
83
|
if (this.handler)
|
|
84
|
-
throw new errors_1.
|
|
84
|
+
throw new errors_1.ApiImplementationError('An IPC connection already has a dispatcher');
|
|
85
85
|
if (this.closed)
|
|
86
86
|
throw this.closed;
|
|
87
87
|
this.handler = handler;
|
|
@@ -89,7 +89,7 @@ class IpcConnection {
|
|
|
89
89
|
newContext(parent) {
|
|
90
90
|
const id = this.options.nextId();
|
|
91
91
|
if (this.usedIds.has(id))
|
|
92
|
-
throw new errors_1.
|
|
92
|
+
throw new errors_1.ApiImplementationError('IPC identity generator reused a call ID');
|
|
93
93
|
this.usedIds.add(id);
|
|
94
94
|
return new IpcProtocol_1.IpcCallContext(parent?.txId ?? id, id, parent?.callId);
|
|
95
95
|
}
|
|
@@ -97,12 +97,12 @@ class IpcConnection {
|
|
|
97
97
|
if (this.closed)
|
|
98
98
|
return Promise.reject(this.closed);
|
|
99
99
|
if (this.pending.has(request.context.callId))
|
|
100
|
-
return Promise.reject(new errors_1.
|
|
100
|
+
return Promise.reject(new errors_1.ApiImplementationError('Duplicate pending IPC call'));
|
|
101
101
|
return new Promise((resolve, reject) => {
|
|
102
102
|
const pending = new PendingCall(request.context, resolve, reject);
|
|
103
103
|
this.pending.set(request.context.callId, pending);
|
|
104
104
|
pending.cancelTimer = this.options.scheduler.schedule(() => {
|
|
105
|
-
this.settle(request.context.callId, new
|
|
105
|
+
this.settle(request.context.callId, new ApiCallTimeoutError_1.ApiCallTimeoutError(this.options.timeoutMs, new CallStrategy_1.CallContext(request.apiId, request.methodId)), 'expired');
|
|
106
106
|
}, this.options.timeoutMs);
|
|
107
107
|
// This owner observes every async send rejection; a send failure is never a timeout.
|
|
108
108
|
void this.send(request).catch((error) => {
|
|
@@ -120,7 +120,7 @@ class IpcConnection {
|
|
|
120
120
|
throw this.closed;
|
|
121
121
|
const json = JSON.stringify(message);
|
|
122
122
|
if (json.length > this.options.maxMessageCharacters)
|
|
123
|
-
throw new errors_1.
|
|
123
|
+
throw new errors_1.ApiImplementationError('IPC message exceeds configured limit');
|
|
124
124
|
await this.transport.send(json);
|
|
125
125
|
}
|
|
126
126
|
receive(json) {
|
|
@@ -129,11 +129,11 @@ class IpcConnection {
|
|
|
129
129
|
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- transport boundary rejects pending calls or encodes a failure that the client throws
|
|
130
130
|
try {
|
|
131
131
|
if (json.length > this.options.maxMessageCharacters)
|
|
132
|
-
throw new errors_1.
|
|
132
|
+
throw new errors_1.ApiImplementationError('IPC message exceeds configured limit');
|
|
133
133
|
const message = IpcProtocol_1.IpcProtocol.parse(json);
|
|
134
134
|
if (message.type === 'request') {
|
|
135
135
|
if (this.activeRequests.has(message.context.callId))
|
|
136
|
-
throw new errors_1.
|
|
136
|
+
throw new errors_1.ApiImplementationError('Duplicate active IPC request');
|
|
137
137
|
this.activeRequests.add(message.context.callId);
|
|
138
138
|
void this.dispatch(message).catch((error) => this.fail(IpcErrors.normalize(error)));
|
|
139
139
|
return;
|
|
@@ -161,10 +161,10 @@ class IpcConnection {
|
|
|
161
161
|
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- transport boundary rejects pending calls or encodes a failure that the client throws
|
|
162
162
|
try {
|
|
163
163
|
if (!this.handler)
|
|
164
|
-
throw new errors_1.
|
|
164
|
+
throw new errors_1.ApiEndpointNotFoundError('IPC dispatcher is not installed');
|
|
165
165
|
reply = await this.handler(request);
|
|
166
166
|
if (!IpcProtocol_1.IpcProtocol.sameContext(request.context, reply.context))
|
|
167
|
-
throw new errors_1.
|
|
167
|
+
throw new errors_1.ApiImplementationError('IPC handler reply correlation mismatch');
|
|
168
168
|
}
|
|
169
169
|
catch (err) {
|
|
170
170
|
const error = (0, errorUtils_1.toError)(err);
|
|
@@ -207,10 +207,10 @@ class IpcConnection {
|
|
|
207
207
|
const settlement = previous
|
|
208
208
|
? ` terminal=${previous.reason} ageMs=${String(Math.max(0, Date.now() - previous.settledAt))}`
|
|
209
209
|
: '';
|
|
210
|
-
return new errors_1.
|
|
210
|
+
return new errors_1.ApiImplementationError(`Late or unknown IPC reply classification=${classification}${settlement} ${this.correlationFields(reply.context)}`);
|
|
211
211
|
}
|
|
212
212
|
correlationError(reply, expected) {
|
|
213
|
-
return new errors_1.
|
|
213
|
+
return new errors_1.ApiImplementationError(`IPC reply correlation mismatch classification=correlation-mismatched ` +
|
|
214
214
|
`${this.correlationFields(reply.context)} expectedTxId=${JSON.stringify(expected.txId)}`);
|
|
215
215
|
}
|
|
216
216
|
correlationFields(context) {
|
|
@@ -233,7 +233,7 @@ class IpcErrors {
|
|
|
233
233
|
static normalize(value) {
|
|
234
234
|
return value instanceof Error
|
|
235
235
|
? value
|
|
236
|
-
: new errors_1.
|
|
236
|
+
: new errors_1.ApiImplementationError('IPC failed with a non-Error value');
|
|
237
237
|
}
|
|
238
238
|
}
|
|
239
239
|
exports.IpcErrors = IpcErrors;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IpcConnection.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/ipc/IpcConnection.ts"],"names":[],"mappings":"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","sourcesContent":["import { toError } from '../lib/errorUtils';\nimport { TimeoutError } from '../http/TimeoutError';\nimport { CallContext } from '../http/CallStrategy';\nimport { ApiErrorCodec, EndpointNotFoundError, InternalError } from '../errors';\nimport {\n IpcCallContext,\n IpcFailure,\n IpcMessage,\n IpcReply,\n IpcRequest,\n IpcProtocol,\n} from './IpcProtocol';\n\n/** A local connection failed, distinct from a remote implementation's semantic ApiError. */\nexport class IpcTransportError extends Error {\n constructor(message: string, cause?: Error) {\n super(message, { cause });\n this.name = 'IpcTransportError';\n }\n}\n\n/** Implement this at the host transport boundary; no vendor or platform declarations leak out. */\nexport interface IpcTransport {\n send(message: string): Promise<void> | void;\n subscribe(\n receive: (message: string) => void,\n failed: (error: Error) => void,\n closed: (error: Error) => void,\n ): () => void;\n close(): void;\n}\nexport interface IpcScheduler {\n schedule(callback: () => void, delayMs: number): () => void;\n}\nexport interface IpcErrorOwner {\n report(error: Error): void;\n}\nexport class IpcConnectionOptions {\n constructor(\n readonly timeoutMs: number,\n readonly nextId: () => string,\n readonly scheduler: IpcScheduler,\n readonly errors: IpcErrorOwner,\n readonly maxMessageCharacters = 1_000_000,\n readonly settlementHistoryLimit = 100,\n readonly connectionId = 'unspecified',\n ) {\n if (\n !Number.isFinite(timeoutMs) ||\n timeoutMs <= 0 ||\n !Number.isSafeInteger(maxMessageCharacters) ||\n maxMessageCharacters < 1 ||\n !Number.isSafeInteger(settlementHistoryLimit) ||\n settlementHistoryLimit < 1\n ) {\n throw new InternalError('IPC timeout and message limit must be positive');\n }\n }\n}\n\ntype SettlementReason = 'resolved' | 'expired' | 'rejected';\nclass SettlementRecord {\n constructor(\n readonly context: IpcCallContext,\n readonly reason: SettlementReason,\n readonly settledAt: number,\n ) {}\n}\n\nclass PendingCall {\n cancelTimer: () => void = () => {};\n constructor(\n readonly context: IpcCallContext,\n readonly resolve: (reply: IpcReply) => void,\n readonly reject: (error: Error) => void,\n ) {}\n}\n\n/** One connection owns both directions, one dispatcher, and all pending-call lifetimes. */\nexport class IpcConnection {\n private readonly pending = new Map<string, PendingCall>();\n private readonly settlements = new Map<string, SettlementRecord>();\n private readonly activeRequests = new Set<string>();\n private readonly usedIds = new Set<string>();\n private handler?: (request: IpcRequest) => Promise<IpcReply>;\n private closed?: Error;\n private readonly unsubscribe: () => void;\n\n constructor(\n private readonly transport: IpcTransport,\n private readonly options: IpcConnectionOptions,\n ) {\n this.unsubscribe = transport.subscribe(\n (message) => this.receive(message),\n (error) => this.fail(new IpcTransportError('IPC transport failed', error)),\n (error) => this.fail(new IpcTransportError('IPC connection closed', error)),\n );\n }\n\n /** Install exactly one factory dispatcher BEFORE exposing this connection to the peer. */\n setHandler(handler: (request: IpcRequest) => Promise<IpcReply>): void {\n if (this.handler) throw new InternalError('An IPC connection already has a dispatcher');\n if (this.closed) throw this.closed;\n this.handler = handler;\n }\n\n newContext(parent?: IpcCallContext): IpcCallContext {\n const id = this.options.nextId();\n if (this.usedIds.has(id))\n throw new InternalError('IPC identity generator reused a call ID');\n this.usedIds.add(id);\n return new IpcCallContext(parent?.txId ?? id, id, parent?.callId);\n }\n\n request(request: IpcRequest): Promise<IpcReply> {\n if (this.closed) return Promise.reject(this.closed);\n if (this.pending.has(request.context.callId))\n return Promise.reject(new InternalError('Duplicate pending IPC call'));\n return new Promise<IpcReply>((resolve, reject) => {\n const pending = new PendingCall(request.context, resolve, reject);\n this.pending.set(request.context.callId, pending);\n pending.cancelTimer = this.options.scheduler.schedule(() => {\n this.settle(\n request.context.callId,\n new TimeoutError(\n this.options.timeoutMs,\n new CallContext(request.apiId, request.methodId),\n ),\n 'expired',\n );\n }, this.options.timeoutMs);\n // This owner observes every async send rejection; a send failure is never a timeout.\n void this.send(request).catch((error) => {\n this.settle(\n request.context.callId,\n new IpcTransportError('IPC send failed', IpcErrors.normalize(error)),\n 'rejected',\n );\n });\n });\n }\n\n dispose(): void {\n this.fail(new IpcTransportError('IPC connection disposed'));\n this.unsubscribe();\n this.transport.close();\n }\n\n private async send(message: IpcMessage): Promise<void> {\n if (this.closed) throw this.closed;\n const json = JSON.stringify(message);\n if (json.length > this.options.maxMessageCharacters)\n throw new InternalError('IPC message exceeds configured limit');\n await this.transport.send(json);\n }\n\n private receive(json: string): void {\n if (this.closed) return;\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- transport boundary rejects pending calls or encodes a failure that the client throws\n try {\n if (json.length > this.options.maxMessageCharacters)\n throw new InternalError('IPC message exceeds configured limit');\n const message = IpcProtocol.parse(json);\n if (message.type === 'request') {\n if (this.activeRequests.has(message.context.callId))\n throw new InternalError('Duplicate active IPC request');\n this.activeRequests.add(message.context.callId);\n void this.dispatch(message).catch((error) => this.fail(IpcErrors.normalize(error)));\n return;\n }\n const pending = this.pending.get(message.context.callId);\n // Late or unsolicited replies are reported, never resolve a different call or replay work.\n if (!pending) {\n this.options.errors.report(this.lateReplyError(message));\n return;\n }\n if (!IpcProtocol.sameContext(pending.context, message.context))\n throw this.correlationError(message, pending.context);\n this.pending.delete(message.context.callId);\n pending.cancelTimer();\n this.remember(pending.context, 'resolved');\n pending.resolve(message);\n } catch (err: unknown) {\n const error = toError(err);\n this.fail(IpcErrors.normalize(error));\n }\n }\n\n private async dispatch(request: IpcRequest): Promise<void> {\n let reply: IpcReply;\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- transport boundary rejects pending calls or encodes a failure that the client throws\n try {\n if (!this.handler) throw new EndpointNotFoundError('IPC dispatcher is not installed');\n reply = await this.handler(request);\n if (!IpcProtocol.sameContext(request.context, reply.context))\n throw new InternalError('IPC handler reply correlation mismatch');\n } catch (err: unknown) {\n const error = toError(err);\n reply = new IpcFailure(request.context, ApiErrorCodec.encode(error));\n } finally {\n this.activeRequests.delete(request.context.callId);\n }\n await this.send(reply);\n }\n\n private settle(id: string, error: Error, reason: SettlementReason): void {\n const pending = this.pending.get(id);\n if (!pending) return;\n this.pending.delete(id);\n pending.cancelTimer();\n this.remember(pending.context, reason);\n pending.reject(error);\n }\n\n private remember(context: IpcCallContext, reason: SettlementReason): void {\n this.settlements.delete(context.callId);\n this.settlements.set(context.callId, new SettlementRecord(context, reason, Date.now()));\n while (this.settlements.size > this.options.settlementHistoryLimit) {\n const oldest = this.settlements.keys().next().value;\n if (typeof oldest !== 'string') return;\n this.settlements.delete(oldest);\n }\n }\n\n private lateReplyError(reply: IpcReply): InternalError {\n const previous = this.settlements.get(reply.context.callId);\n let classification = 'unknown';\n if (previous) {\n classification = IpcProtocol.sameContext(previous.context, reply.context)\n ? previous.reason === 'expired'\n ? 'expired'\n : 'duplicate-settled'\n : 'correlation-mismatched';\n }\n const settlement = previous\n ? ` terminal=${previous.reason} ageMs=${String(Math.max(0, Date.now() - previous.settledAt))}`\n : '';\n return new InternalError(\n `Late or unknown IPC reply classification=${classification}${settlement} ${this.correlationFields(reply.context)}`,\n );\n }\n\n private correlationError(reply: IpcReply, expected: IpcCallContext): InternalError {\n return new InternalError(\n `IPC reply correlation mismatch classification=correlation-mismatched ` +\n `${this.correlationFields(reply.context)} expectedTxId=${JSON.stringify(expected.txId)}`,\n );\n }\n\n private correlationFields(context: IpcCallContext): string {\n return (\n `callId=${JSON.stringify(context.callId)} txId=${JSON.stringify(context.txId)} ` +\n `parentCallId=${JSON.stringify(context.parentCallId ?? null)} ` +\n `connectionId=${JSON.stringify(this.options.connectionId)}`\n );\n }\n\n private fail(error: Error): void {\n if (this.closed) return;\n this.closed = error;\n for (const id of this.pending.keys()) this.settle(id, error, 'rejected');\n this.options.errors.report(error);\n }\n}\n\nexport class IpcErrors {\n // webpieces-disable no-function-outside-class -- portable stateless IPC primitive; no platform DI container exists on this boundary; webpieces-disable no-any-unknown -- untrusted IPC data is schema-validated; generic dispatch cannot assume a DTO type before validation\n static normalize(value: unknown): Error {\n return value instanceof Error\n ? value\n : new InternalError('IPC failed with a non-Error value');\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"IpcConnection.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/ipc/IpcConnection.ts"],"names":[],"mappings":"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","sourcesContent":["import { toError } from '../lib/errorUtils';\nimport { ApiCallTimeoutError } from '../http/ApiCallTimeoutError';\nimport { CallContext } from '../http/CallStrategy';\nimport { ApiErrorCodec, ApiEndpointNotFoundError, ApiImplementationError } from '../errors';\nimport {\n IpcCallContext,\n IpcFailure,\n IpcMessage,\n IpcReply,\n IpcRequest,\n IpcProtocol,\n} from './IpcProtocol';\n\n/** A local connection failed, distinct from a remote implementation's semantic ApiError. */\nexport class IpcTransportError extends Error {\n constructor(message: string, cause?: Error) {\n super(message, { cause });\n this.name = 'IpcTransportError';\n }\n}\n\n/** Implement this at the host transport boundary; no vendor or platform declarations leak out. */\nexport interface IpcTransport {\n send(message: string): Promise<void> | void;\n subscribe(\n receive: (message: string) => void,\n failed: (error: Error) => void,\n closed: (error: Error) => void,\n ): () => void;\n close(): void;\n}\nexport interface IpcScheduler {\n schedule(callback: () => void, delayMs: number): () => void;\n}\nexport interface IpcErrorOwner {\n report(error: Error): void;\n}\nexport class IpcConnectionOptions {\n constructor(\n readonly timeoutMs: number,\n readonly nextId: () => string,\n readonly scheduler: IpcScheduler,\n readonly errors: IpcErrorOwner,\n readonly maxMessageCharacters = 1_000_000,\n readonly settlementHistoryLimit = 100,\n readonly connectionId = 'unspecified',\n ) {\n if (\n !Number.isFinite(timeoutMs) ||\n timeoutMs <= 0 ||\n !Number.isSafeInteger(maxMessageCharacters) ||\n maxMessageCharacters < 1 ||\n !Number.isSafeInteger(settlementHistoryLimit) ||\n settlementHistoryLimit < 1\n ) {\n throw new ApiImplementationError('IPC timeout and message limit must be positive');\n }\n }\n}\n\ntype SettlementReason = 'resolved' | 'expired' | 'rejected';\nclass SettlementRecord {\n constructor(\n readonly context: IpcCallContext,\n readonly reason: SettlementReason,\n readonly settledAt: number,\n ) {}\n}\n\nclass PendingCall {\n cancelTimer: () => void = () => {};\n constructor(\n readonly context: IpcCallContext,\n readonly resolve: (reply: IpcReply) => void,\n readonly reject: (error: Error) => void,\n ) {}\n}\n\n/** One connection owns both directions, one dispatcher, and all pending-call lifetimes. */\nexport class IpcConnection {\n private readonly pending = new Map<string, PendingCall>();\n private readonly settlements = new Map<string, SettlementRecord>();\n private readonly activeRequests = new Set<string>();\n private readonly usedIds = new Set<string>();\n private handler?: (request: IpcRequest) => Promise<IpcReply>;\n private closed?: Error;\n private readonly unsubscribe: () => void;\n\n constructor(\n private readonly transport: IpcTransport,\n private readonly options: IpcConnectionOptions,\n ) {\n this.unsubscribe = transport.subscribe(\n (message) => this.receive(message),\n (error) => this.fail(new IpcTransportError('IPC transport failed', error)),\n (error) => this.fail(new IpcTransportError('IPC connection closed', error)),\n );\n }\n\n /** Install exactly one factory dispatcher BEFORE exposing this connection to the peer. */\n setHandler(handler: (request: IpcRequest) => Promise<IpcReply>): void {\n if (this.handler)\n throw new ApiImplementationError('An IPC connection already has a dispatcher');\n if (this.closed) throw this.closed;\n this.handler = handler;\n }\n\n newContext(parent?: IpcCallContext): IpcCallContext {\n const id = this.options.nextId();\n if (this.usedIds.has(id))\n throw new ApiImplementationError('IPC identity generator reused a call ID');\n this.usedIds.add(id);\n return new IpcCallContext(parent?.txId ?? id, id, parent?.callId);\n }\n\n request(request: IpcRequest): Promise<IpcReply> {\n if (this.closed) return Promise.reject(this.closed);\n if (this.pending.has(request.context.callId))\n return Promise.reject(new ApiImplementationError('Duplicate pending IPC call'));\n return new Promise<IpcReply>((resolve, reject) => {\n const pending = new PendingCall(request.context, resolve, reject);\n this.pending.set(request.context.callId, pending);\n pending.cancelTimer = this.options.scheduler.schedule(() => {\n this.settle(\n request.context.callId,\n new ApiCallTimeoutError(\n this.options.timeoutMs,\n new CallContext(request.apiId, request.methodId),\n ),\n 'expired',\n );\n }, this.options.timeoutMs);\n // This owner observes every async send rejection; a send failure is never a timeout.\n void this.send(request).catch((error) => {\n this.settle(\n request.context.callId,\n new IpcTransportError('IPC send failed', IpcErrors.normalize(error)),\n 'rejected',\n );\n });\n });\n }\n\n dispose(): void {\n this.fail(new IpcTransportError('IPC connection disposed'));\n this.unsubscribe();\n this.transport.close();\n }\n\n private async send(message: IpcMessage): Promise<void> {\n if (this.closed) throw this.closed;\n const json = JSON.stringify(message);\n if (json.length > this.options.maxMessageCharacters)\n throw new ApiImplementationError('IPC message exceeds configured limit');\n await this.transport.send(json);\n }\n\n private receive(json: string): void {\n if (this.closed) return;\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- transport boundary rejects pending calls or encodes a failure that the client throws\n try {\n if (json.length > this.options.maxMessageCharacters)\n throw new ApiImplementationError('IPC message exceeds configured limit');\n const message = IpcProtocol.parse(json);\n if (message.type === 'request') {\n if (this.activeRequests.has(message.context.callId))\n throw new ApiImplementationError('Duplicate active IPC request');\n this.activeRequests.add(message.context.callId);\n void this.dispatch(message).catch((error) => this.fail(IpcErrors.normalize(error)));\n return;\n }\n const pending = this.pending.get(message.context.callId);\n // Late or unsolicited replies are reported, never resolve a different call or replay work.\n if (!pending) {\n this.options.errors.report(this.lateReplyError(message));\n return;\n }\n if (!IpcProtocol.sameContext(pending.context, message.context))\n throw this.correlationError(message, pending.context);\n this.pending.delete(message.context.callId);\n pending.cancelTimer();\n this.remember(pending.context, 'resolved');\n pending.resolve(message);\n } catch (err: unknown) {\n const error = toError(err);\n this.fail(IpcErrors.normalize(error));\n }\n }\n\n private async dispatch(request: IpcRequest): Promise<void> {\n let reply: IpcReply;\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- transport boundary rejects pending calls or encodes a failure that the client throws\n try {\n if (!this.handler)\n throw new ApiEndpointNotFoundError('IPC dispatcher is not installed');\n reply = await this.handler(request);\n if (!IpcProtocol.sameContext(request.context, reply.context))\n throw new ApiImplementationError('IPC handler reply correlation mismatch');\n } catch (err: unknown) {\n const error = toError(err);\n reply = new IpcFailure(request.context, ApiErrorCodec.encode(error));\n } finally {\n this.activeRequests.delete(request.context.callId);\n }\n await this.send(reply);\n }\n\n private settle(id: string, error: Error, reason: SettlementReason): void {\n const pending = this.pending.get(id);\n if (!pending) return;\n this.pending.delete(id);\n pending.cancelTimer();\n this.remember(pending.context, reason);\n pending.reject(error);\n }\n\n private remember(context: IpcCallContext, reason: SettlementReason): void {\n this.settlements.delete(context.callId);\n this.settlements.set(context.callId, new SettlementRecord(context, reason, Date.now()));\n while (this.settlements.size > this.options.settlementHistoryLimit) {\n const oldest = this.settlements.keys().next().value;\n if (typeof oldest !== 'string') return;\n this.settlements.delete(oldest);\n }\n }\n\n private lateReplyError(reply: IpcReply): ApiImplementationError {\n const previous = this.settlements.get(reply.context.callId);\n let classification = 'unknown';\n if (previous) {\n classification = IpcProtocol.sameContext(previous.context, reply.context)\n ? previous.reason === 'expired'\n ? 'expired'\n : 'duplicate-settled'\n : 'correlation-mismatched';\n }\n const settlement = previous\n ? ` terminal=${previous.reason} ageMs=${String(Math.max(0, Date.now() - previous.settledAt))}`\n : '';\n return new ApiImplementationError(\n `Late or unknown IPC reply classification=${classification}${settlement} ${this.correlationFields(reply.context)}`,\n );\n }\n\n private correlationError(reply: IpcReply, expected: IpcCallContext): ApiImplementationError {\n return new ApiImplementationError(\n `IPC reply correlation mismatch classification=correlation-mismatched ` +\n `${this.correlationFields(reply.context)} expectedTxId=${JSON.stringify(expected.txId)}`,\n );\n }\n\n private correlationFields(context: IpcCallContext): string {\n return (\n `callId=${JSON.stringify(context.callId)} txId=${JSON.stringify(context.txId)} ` +\n `parentCallId=${JSON.stringify(context.parentCallId ?? null)} ` +\n `connectionId=${JSON.stringify(this.options.connectionId)}`\n );\n }\n\n private fail(error: Error): void {\n if (this.closed) return;\n this.closed = error;\n for (const id of this.pending.keys()) this.settle(id, error, 'rejected');\n this.options.errors.report(error);\n }\n}\n\nexport class IpcErrors {\n // webpieces-disable no-function-outside-class -- portable stateless IPC primitive; no platform DI container exists on this boundary; webpieces-disable no-any-unknown -- untrusted IPC data is schema-validated; generic dispatch cannot assume a DTO type before validation\n static normalize(value: unknown): Error {\n return value instanceof Error\n ? value\n : new ApiImplementationError('IPC failed with a non-Error value');\n }\n}\n"]}
|
package/src/ipc/IpcDecorators.js
CHANGED
|
@@ -27,11 +27,11 @@ function WpInternal(apiId) {
|
|
|
27
27
|
const className = target.name || 'Unknown';
|
|
28
28
|
if (Reflect.hasMetadata(decorators_1.METADATA_KEYS.API_PATH, target) ||
|
|
29
29
|
Reflect.hasMetadata(decorators_1.METADATA_KEYS.ENDPOINTS, target)) {
|
|
30
|
-
throw new errors_1.
|
|
30
|
+
throw new errors_1.ApiImplementationError(`Internal API ${className} cannot use @ApiPath or @Endpoint.`);
|
|
31
31
|
}
|
|
32
32
|
const authMethods = Reflect.getMetadata(decorators_1.METADATA_KEYS.AUTH_METHODS, target) || [];
|
|
33
33
|
if (authMethods.length > 0 || Reflect.hasMetadata(decorators_1.METADATA_KEYS.AUTH_META, target)) {
|
|
34
|
-
throw new errors_1.
|
|
34
|
+
throw new errors_1.ApiImplementationError(`Internal API ${className} cannot use HTTP authorization decorators.`);
|
|
35
35
|
}
|
|
36
36
|
Reflect.defineMetadata(exports.IPC_METADATA_KEYS.API_ID, apiId, target);
|
|
37
37
|
};
|
|
@@ -42,16 +42,16 @@ function WpIpcEndpoint(methodId, options = {}) {
|
|
|
42
42
|
IpcIdentity_1.IpcIdentity.assert(methodId, 'method');
|
|
43
43
|
const kind = options.kind ?? 'request';
|
|
44
44
|
if (kind !== 'request' && kind !== 'notification')
|
|
45
|
-
throw new errors_1.
|
|
45
|
+
throw new errors_1.ApiBadRequestError('Invalid IPC endpoint kind');
|
|
46
46
|
return (target, propertyKey) => {
|
|
47
47
|
const apiClass = target.constructor;
|
|
48
48
|
const key = propertyKey;
|
|
49
49
|
if (['then', 'constructor', '__proto__'].includes(key)) {
|
|
50
|
-
throw new errors_1.
|
|
50
|
+
throw new errors_1.ApiBadRequestError(`Invalid IPC method name: ${key}`);
|
|
51
51
|
}
|
|
52
52
|
const endpoints = Reflect.getMetadata(exports.IPC_METADATA_KEYS.ENDPOINTS, apiClass) || {};
|
|
53
53
|
if (Object.values(endpoints).includes(methodId)) {
|
|
54
|
-
throw new errors_1.
|
|
54
|
+
throw new errors_1.ApiBadRequestError(`Duplicate IPC method identity: ${methodId}`);
|
|
55
55
|
}
|
|
56
56
|
endpoints[key] = methodId;
|
|
57
57
|
Reflect.defineMetadata(exports.IPC_METADATA_KEYS.ENDPOINTS, endpoints, apiClass);
|
|
@@ -85,20 +85,20 @@ function getIpcMaskSpec(apiClass, methodName) {
|
|
|
85
85
|
function assertInternalApi(apiClass) {
|
|
86
86
|
const apiId = getIpcApiId(apiClass);
|
|
87
87
|
if (!apiId)
|
|
88
|
-
throw new errors_1.
|
|
88
|
+
throw new errors_1.ApiImplementationError(`Class ${apiClass.name || 'Unknown'} must be decorated with @WpInternal(apiId).`);
|
|
89
89
|
if (Reflect.hasMetadata(decorators_1.METADATA_KEYS.API_PATH, apiClass) ||
|
|
90
90
|
Reflect.hasMetadata(decorators_1.METADATA_KEYS.ENDPOINTS, apiClass)) {
|
|
91
|
-
throw new errors_1.
|
|
91
|
+
throw new errors_1.ApiImplementationError(`Internal API ${apiClass.name || 'Unknown'} cannot use @ApiPath or @Endpoint.`);
|
|
92
92
|
}
|
|
93
93
|
if (Object.keys(getIpcEndpoints(apiClass)).length === 0) {
|
|
94
|
-
throw new errors_1.
|
|
94
|
+
throw new errors_1.ApiImplementationError(`Internal API ${apiClass.name || 'Unknown'} must declare at least one @WpIpcEndpoint.`);
|
|
95
95
|
}
|
|
96
96
|
return apiId;
|
|
97
97
|
}
|
|
98
98
|
// webpieces-disable no-function-outside-class -- IPC decorator or immutable reflection metadata helper
|
|
99
99
|
function assertNotInternalApi(apiClass, transport) {
|
|
100
100
|
if (isInternalApi(apiClass)) {
|
|
101
|
-
throw new errors_1.
|
|
101
|
+
throw new errors_1.ApiImplementationError(`${transport} cannot use @WpInternal API ${apiClass.name || 'Unknown'}; use the IPC factories.`);
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
//# sourceMappingURL=IpcDecorators.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IpcDecorators.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/ipc/IpcDecorators.ts"],"names":[],"mappings":";;;AAoBA,
|
|
1
|
+
{"version":3,"file":"IpcDecorators.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/ipc/IpcDecorators.ts"],"names":[],"mappings":"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","sourcesContent":["import 'reflect-metadata';\nimport { ApiBadRequestError, ApiImplementationError } from '../errors';\nimport { getMaskSpec, METADATA_KEYS } from '../http/decorators';\nimport { MaskSpec } from '../http/LogFieldMask';\nimport { IpcIdentity } from './IpcIdentity';\n\nexport type IpcEndpointKind = 'request' | 'notification';\nexport interface IpcEndpointOptions {\n kind?: IpcEndpointKind;\n}\nexport type IpcApiType<T> = abstract new (...args: never[]) => T;\n\nexport const IPC_METADATA_KEYS = {\n API_ID: 'webpieces:ipc-api-id',\n ENDPOINTS: 'webpieces:ipc-endpoints',\n KINDS: 'webpieces:ipc-kinds',\n} as const;\n\n/** Marks a contract as IPC-only. HTTP routers and clients must reject it. */\n// webpieces-disable no-function-outside-class -- IPC decorator or immutable reflection metadata helper\nexport function WpInternal(apiId: string): ClassDecorator {\n IpcIdentity.assert(apiId, 'API');\n return (target: Function) => {\n const className = target.name || 'Unknown';\n if (\n Reflect.hasMetadata(METADATA_KEYS.API_PATH, target) ||\n Reflect.hasMetadata(METADATA_KEYS.ENDPOINTS, target)\n ) {\n throw new ApiImplementationError(\n `Internal API ${className} cannot use @ApiPath or @Endpoint.`,\n );\n }\n const authMethods: string[] = Reflect.getMetadata(METADATA_KEYS.AUTH_METHODS, target) || [];\n if (authMethods.length > 0 || Reflect.hasMetadata(METADATA_KEYS.AUTH_META, target)) {\n throw new ApiImplementationError(\n `Internal API ${className} cannot use HTTP authorization decorators.`,\n );\n }\n Reflect.defineMetadata(IPC_METADATA_KEYS.API_ID, apiId, target);\n };\n}\n\n/** Declares the stable wire method ID for one method on an IPC-only contract. */\n// webpieces-disable no-function-outside-class -- IPC decorator or immutable reflection metadata helper\nexport function WpIpcEndpoint(methodId: string, options: IpcEndpointOptions = {}): MethodDecorator {\n IpcIdentity.assert(methodId, 'method');\n const kind = options.kind ?? 'request';\n if (kind !== 'request' && kind !== 'notification')\n throw new ApiBadRequestError('Invalid IPC endpoint kind');\n return (target: object, propertyKey: string | symbol) => {\n const apiClass = target.constructor;\n const key = propertyKey as string;\n if (['then', 'constructor', '__proto__'].includes(key)) {\n throw new ApiBadRequestError(`Invalid IPC method name: ${key}`);\n }\n const endpoints: Record<string, string> =\n Reflect.getMetadata(IPC_METADATA_KEYS.ENDPOINTS, apiClass) || {};\n if (Object.values(endpoints).includes(methodId)) {\n throw new ApiBadRequestError(`Duplicate IPC method identity: ${methodId}`);\n }\n endpoints[key] = methodId;\n Reflect.defineMetadata(IPC_METADATA_KEYS.ENDPOINTS, endpoints, apiClass);\n const kinds: Record<string, IpcEndpointKind> =\n Reflect.getMetadata(IPC_METADATA_KEYS.KINDS, apiClass) || {};\n kinds[key] = kind;\n Reflect.defineMetadata(IPC_METADATA_KEYS.KINDS, kinds, apiClass);\n };\n}\n\n// webpieces-disable no-function-outside-class -- IPC decorator or immutable reflection metadata helper\nexport function isInternalApi(apiClass: Function): boolean {\n return Reflect.hasMetadata(IPC_METADATA_KEYS.API_ID, apiClass);\n}\n\n// webpieces-disable no-function-outside-class -- IPC decorator or immutable reflection metadata helper\nexport function getIpcApiId(apiClass: Function): string | undefined {\n return Reflect.getMetadata(IPC_METADATA_KEYS.API_ID, apiClass);\n}\n\n// webpieces-disable no-function-outside-class -- IPC decorator or immutable reflection metadata helper\nexport function getIpcEndpoints(apiClass: Function): Readonly<Record<string, string>> {\n return Reflect.getMetadata(IPC_METADATA_KEYS.ENDPOINTS, apiClass) || {};\n}\n\n// webpieces-disable no-function-outside-class -- IPC decorator or immutable reflection metadata helper\nexport function getIpcEndpointKind(apiClass: Function, methodName: string): IpcEndpointKind {\n const kinds: Record<string, IpcEndpointKind> =\n Reflect.getMetadata(IPC_METADATA_KEYS.KINDS, apiClass) || {};\n return kinds[methodName] ?? 'request';\n}\n\n// webpieces-disable no-function-outside-class -- IPC decorator or immutable reflection metadata helper\nexport function getIpcMaskSpec(apiClass: Function, methodName: string): MaskSpec | undefined {\n return getMaskSpec(apiClass, methodName);\n}\n\n// webpieces-disable no-function-outside-class -- IPC decorator or immutable reflection metadata helper\nexport function assertInternalApi(apiClass: Function): string {\n const apiId = getIpcApiId(apiClass);\n if (!apiId)\n throw new ApiImplementationError(\n `Class ${apiClass.name || 'Unknown'} must be decorated with @WpInternal(apiId).`,\n );\n if (\n Reflect.hasMetadata(METADATA_KEYS.API_PATH, apiClass) ||\n Reflect.hasMetadata(METADATA_KEYS.ENDPOINTS, apiClass)\n ) {\n throw new ApiImplementationError(\n `Internal API ${apiClass.name || 'Unknown'} cannot use @ApiPath or @Endpoint.`,\n );\n }\n if (Object.keys(getIpcEndpoints(apiClass)).length === 0) {\n throw new ApiImplementationError(\n `Internal API ${apiClass.name || 'Unknown'} must declare at least one @WpIpcEndpoint.`,\n );\n }\n return apiId;\n}\n\n// webpieces-disable no-function-outside-class -- IPC decorator or immutable reflection metadata helper\nexport function assertNotInternalApi(apiClass: Function, transport: string): void {\n if (isInternalApi(apiClass)) {\n throw new ApiImplementationError(\n `${transport} cannot use @WpInternal API ${apiClass.name || 'Unknown'}; use the IPC factories.`,\n );\n }\n}\n"]}
|
package/src/ipc/IpcIdentity.js
CHANGED
|
@@ -6,7 +6,7 @@ class IpcIdentity {
|
|
|
6
6
|
// webpieces-disable no-function-outside-class -- portable stateless IPC primitive; no platform DI container exists on this boundary; webpieces-disable no-any-unknown -- untrusted IPC data is schema-validated; generic dispatch cannot assume a DTO type before validation
|
|
7
7
|
static assert(value, label) {
|
|
8
8
|
if (typeof value !== 'string' || !/^[a-zA-Z0-9][a-zA-Z0-9_.:-]{0,127}$/.test(value)) {
|
|
9
|
-
throw new errors_1.
|
|
9
|
+
throw new errors_1.ApiBadRequestError(`Invalid IPC ${label} identity`);
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IpcIdentity.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/ipc/IpcIdentity.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"IpcIdentity.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/ipc/IpcIdentity.ts"],"names":[],"mappings":";;;AAAA,sCAA+C;AAE/C,MAAa,WAAW;IACpB,6QAA6Q;IAC7Q,MAAM,CAAC,MAAM,CAAC,KAAc,EAAE,KAAa;QACvC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,qCAAqC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAClF,MAAM,IAAI,2BAAkB,CAAC,eAAe,KAAK,WAAW,CAAC,CAAC;QAClE,CAAC;IACL,CAAC;CACJ;AAPD,kCAOC","sourcesContent":["import { ApiBadRequestError } from '../errors';\n\nexport class IpcIdentity {\n // webpieces-disable no-function-outside-class -- portable stateless IPC primitive; no platform DI container exists on this boundary; webpieces-disable no-any-unknown -- untrusted IPC data is schema-validated; generic dispatch cannot assume a DTO type before validation\n static assert(value: unknown, label: string): asserts value is string {\n if (typeof value !== 'string' || !/^[a-zA-Z0-9][a-zA-Z0-9_.:-]{0,127}$/.test(value)) {\n throw new ApiBadRequestError(`Invalid IPC ${label} identity`);\n }\n }\n}\n"]}
|
package/src/ipc/IpcProtocol.js
CHANGED
|
@@ -63,7 +63,7 @@ class IpcProtocol {
|
|
|
63
63
|
// webpieces-disable no-function-outside-class -- portable stateless IPC primitive; no platform DI container exists on this boundary; webpieces-disable no-any-unknown -- untrusted IPC data is schema-validated; generic dispatch cannot assume a DTO type before validation
|
|
64
64
|
static record(value) {
|
|
65
65
|
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
66
|
-
throw new errors_1.
|
|
66
|
+
throw new errors_1.ApiImplementationError('Malformed IPC envelope');
|
|
67
67
|
}
|
|
68
68
|
// webpieces-disable no-any-unknown -- untrusted IPC data is schema-validated; generic dispatch cannot assume a DTO type before validation
|
|
69
69
|
return value;
|
|
@@ -72,7 +72,7 @@ class IpcProtocol {
|
|
|
72
72
|
static parse(json) {
|
|
73
73
|
const value = IpcProtocol.record(JSON.parse(json));
|
|
74
74
|
if (value['version'] !== 1)
|
|
75
|
-
throw new errors_1.
|
|
75
|
+
throw new errors_1.ApiImplementationError('Unsupported IPC protocol version');
|
|
76
76
|
const raw = IpcProtocol.record(value['context']);
|
|
77
77
|
const context = new IpcCallContext(raw['txId'], raw['callId'], raw['parentCallId']);
|
|
78
78
|
switch (value['type']) {
|
|
@@ -80,18 +80,18 @@ class IpcProtocol {
|
|
|
80
80
|
IpcIdentity_1.IpcIdentity.assert(value['apiId'], 'API');
|
|
81
81
|
IpcIdentity_1.IpcIdentity.assert(value['methodId'], 'method');
|
|
82
82
|
if (!Object.prototype.hasOwnProperty.call(value, 'body'))
|
|
83
|
-
throw new errors_1.
|
|
83
|
+
throw new errors_1.ApiImplementationError('Missing IPC request body');
|
|
84
84
|
return new IpcRequest(value['apiId'], value['methodId'], context, value['body']);
|
|
85
85
|
case 'success':
|
|
86
86
|
if (!Object.prototype.hasOwnProperty.call(value, 'body'))
|
|
87
|
-
throw new errors_1.
|
|
87
|
+
throw new errors_1.ApiImplementationError('Missing IPC success body');
|
|
88
88
|
return new IpcSuccess(context, value['body']);
|
|
89
89
|
case 'failure':
|
|
90
90
|
return new IpcFailure(context,
|
|
91
91
|
// webpieces-disable no-any-unknown -- untrusted IPC data is schema-validated; generic dispatch cannot assume a DTO type before validation
|
|
92
92
|
IpcProtocol.record(value['error']));
|
|
93
93
|
default:
|
|
94
|
-
throw new errors_1.
|
|
94
|
+
throw new errors_1.ApiImplementationError('Invalid IPC message discriminator');
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
// webpieces-disable no-function-outside-class -- portable stateless IPC primitive; no platform DI container exists on this boundary
|