@classytic/arc 1.1.0 → 2.1.2
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 +247 -794
- package/bin/arc.js +91 -52
- package/dist/EventTransport-BD2U0BTc.d.mts +100 -0
- package/dist/EventTransport-BD2U0BTc.d.mts.map +1 -0
- package/dist/HookSystem-BsGV-j2l.mjs +405 -0
- package/dist/HookSystem-BsGV-j2l.mjs.map +1 -0
- package/dist/ResourceRegistry-DsN4KJjV.mjs +250 -0
- package/dist/ResourceRegistry-DsN4KJjV.mjs.map +1 -0
- package/dist/adapters/index.d.mts +5 -0
- package/dist/adapters/index.mjs +3 -0
- package/dist/audit/index.d.mts +82 -0
- package/dist/audit/index.d.mts.map +1 -0
- package/dist/audit/index.mjs +276 -0
- package/dist/audit/index.mjs.map +1 -0
- package/dist/audit/mongodb.d.mts +5 -0
- package/dist/audit/mongodb.mjs +3 -0
- package/dist/audited-C3T5DTUx.mjs +141 -0
- package/dist/audited-C3T5DTUx.mjs.map +1 -0
- package/dist/auth/index.d.mts +189 -0
- package/dist/auth/index.d.mts.map +1 -0
- package/dist/auth/index.mjs +1102 -0
- package/dist/auth/index.mjs.map +1 -0
- package/dist/auth/redis-session.d.mts +44 -0
- package/dist/auth/redis-session.d.mts.map +1 -0
- package/dist/auth/redis-session.mjs +76 -0
- package/dist/auth/redis-session.mjs.map +1 -0
- package/dist/betterAuthOpenApi-BrHKeSAx.mjs +250 -0
- package/dist/betterAuthOpenApi-BrHKeSAx.mjs.map +1 -0
- package/dist/cache/index.d.mts +146 -0
- package/dist/cache/index.d.mts.map +1 -0
- package/dist/cache/index.mjs +92 -0
- package/dist/cache/index.mjs.map +1 -0
- package/dist/caching-Bl28lYsR.mjs +94 -0
- package/dist/caching-Bl28lYsR.mjs.map +1 -0
- package/dist/chunk-C7Uep-_p.mjs +20 -0
- package/dist/circuitBreaker-DeY4FCjs.mjs +1097 -0
- package/dist/circuitBreaker-DeY4FCjs.mjs.map +1 -0
- package/dist/cli/commands/describe.d.mts +19 -0
- package/dist/cli/commands/describe.d.mts.map +1 -0
- package/dist/cli/commands/describe.mjs +239 -0
- package/dist/cli/commands/describe.mjs.map +1 -0
- package/dist/cli/commands/docs.d.mts +14 -0
- package/dist/cli/commands/docs.d.mts.map +1 -0
- package/dist/cli/commands/docs.mjs +53 -0
- package/dist/cli/commands/docs.mjs.map +1 -0
- package/dist/cli/commands/{generate.d.ts → generate.d.mts} +3 -1
- package/dist/cli/commands/generate.d.mts.map +1 -0
- package/dist/cli/commands/generate.mjs +358 -0
- package/dist/cli/commands/generate.mjs.map +1 -0
- package/dist/cli/commands/{init.d.ts → init.d.mts} +12 -8
- package/dist/cli/commands/init.d.mts.map +1 -0
- package/dist/cli/commands/{init.js → init.mjs} +807 -616
- package/dist/cli/commands/init.mjs.map +1 -0
- package/dist/cli/commands/introspect.d.mts +11 -0
- package/dist/cli/commands/introspect.d.mts.map +1 -0
- package/dist/cli/commands/introspect.mjs +76 -0
- package/dist/cli/commands/introspect.mjs.map +1 -0
- package/dist/cli/index.d.mts +17 -0
- package/dist/cli/index.d.mts.map +1 -0
- package/dist/cli/index.mjs +157 -0
- package/dist/cli/index.mjs.map +1 -0
- package/dist/constants-DdXFXQtN.mjs +85 -0
- package/dist/constants-DdXFXQtN.mjs.map +1 -0
- package/dist/core/index.d.mts +5 -0
- package/dist/core/index.mjs +4 -0
- package/dist/createApp-CUgNqegw.mjs +560 -0
- package/dist/createApp-CUgNqegw.mjs.map +1 -0
- package/dist/defineResource-k0_BDn8v.mjs +2197 -0
- package/dist/defineResource-k0_BDn8v.mjs.map +1 -0
- package/dist/discovery/index.d.mts +47 -0
- package/dist/discovery/index.d.mts.map +1 -0
- package/dist/discovery/index.mjs +110 -0
- package/dist/discovery/index.mjs.map +1 -0
- package/dist/docs/index.d.mts +163 -0
- package/dist/docs/index.d.mts.map +1 -0
- package/dist/docs/index.mjs +73 -0
- package/dist/docs/index.mjs.map +1 -0
- package/dist/elevation-BRy3yFWT.mjs +113 -0
- package/dist/elevation-BRy3yFWT.mjs.map +1 -0
- package/dist/elevation-B_2dRLVP.d.mts +88 -0
- package/dist/elevation-B_2dRLVP.d.mts.map +1 -0
- package/dist/errorHandler-BbcgBmIH.d.mts +73 -0
- package/dist/errorHandler-BbcgBmIH.d.mts.map +1 -0
- package/dist/errorHandler-C1okiriz.mjs +109 -0
- package/dist/errorHandler-C1okiriz.mjs.map +1 -0
- package/dist/errors-B9bZok84.mjs +212 -0
- package/dist/errors-B9bZok84.mjs.map +1 -0
- package/dist/errors-ChKiFz62.d.mts +125 -0
- package/dist/errors-ChKiFz62.d.mts.map +1 -0
- package/dist/eventPlugin-CTrLH3mt.d.mts +125 -0
- package/dist/eventPlugin-CTrLH3mt.d.mts.map +1 -0
- package/dist/eventPlugin-DGR_B2on.mjs +230 -0
- package/dist/eventPlugin-DGR_B2on.mjs.map +1 -0
- package/dist/events/index.d.mts +54 -0
- package/dist/events/index.d.mts.map +1 -0
- package/dist/events/index.mjs +52 -0
- package/dist/events/index.mjs.map +1 -0
- package/dist/events/transports/redis-stream-entry.d.mts +2 -0
- package/dist/events/transports/redis-stream-entry.mjs +178 -0
- package/dist/events/transports/redis-stream-entry.mjs.map +1 -0
- package/dist/events/transports/redis.d.mts +77 -0
- package/dist/events/transports/redis.d.mts.map +1 -0
- package/dist/events/transports/redis.mjs +125 -0
- package/dist/events/transports/redis.mjs.map +1 -0
- package/dist/externalPaths-DlINfKbP.d.mts +51 -0
- package/dist/externalPaths-DlINfKbP.d.mts.map +1 -0
- package/dist/factory/index.d.mts +64 -0
- package/dist/factory/index.d.mts.map +1 -0
- package/dist/factory/index.mjs +3 -0
- package/dist/fastifyAdapter-BkrGrlFi.d.mts +217 -0
- package/dist/fastifyAdapter-BkrGrlFi.d.mts.map +1 -0
- package/dist/fields-DyaDVX4J.d.mts +110 -0
- package/dist/fields-DyaDVX4J.d.mts.map +1 -0
- package/dist/fields-iagOozy0.mjs +115 -0
- package/dist/fields-iagOozy0.mjs.map +1 -0
- package/dist/hooks/index.d.mts +4 -0
- package/dist/hooks/index.mjs +3 -0
- package/dist/idempotency/index.d.mts +97 -0
- package/dist/idempotency/index.d.mts.map +1 -0
- package/dist/idempotency/index.mjs +320 -0
- package/dist/idempotency/index.mjs.map +1 -0
- package/dist/idempotency/mongodb.d.mts +2 -0
- package/dist/idempotency/mongodb.mjs +115 -0
- package/dist/idempotency/mongodb.mjs.map +1 -0
- package/dist/idempotency/redis.d.mts +2 -0
- package/dist/idempotency/redis.mjs +104 -0
- package/dist/idempotency/redis.mjs.map +1 -0
- package/dist/index.d.mts +261 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +105 -0
- package/dist/index.mjs.map +1 -0
- package/dist/integrations/event-gateway.d.mts +47 -0
- package/dist/integrations/event-gateway.d.mts.map +1 -0
- package/dist/integrations/event-gateway.mjs +44 -0
- package/dist/integrations/event-gateway.mjs.map +1 -0
- package/dist/integrations/index.d.mts +5 -0
- package/dist/integrations/index.mjs +1 -0
- package/dist/integrations/jobs.d.mts +104 -0
- package/dist/integrations/jobs.d.mts.map +1 -0
- package/dist/integrations/jobs.mjs +124 -0
- package/dist/integrations/jobs.mjs.map +1 -0
- package/dist/integrations/streamline.d.mts +61 -0
- package/dist/integrations/streamline.d.mts.map +1 -0
- package/dist/integrations/streamline.mjs +126 -0
- package/dist/integrations/streamline.mjs.map +1 -0
- package/dist/integrations/websocket.d.mts +83 -0
- package/dist/integrations/websocket.d.mts.map +1 -0
- package/dist/integrations/websocket.mjs +289 -0
- package/dist/integrations/websocket.mjs.map +1 -0
- package/dist/interface-B01JvPVc.d.mts +78 -0
- package/dist/interface-B01JvPVc.d.mts.map +1 -0
- package/dist/interface-CZe8IkMf.d.mts +55 -0
- package/dist/interface-CZe8IkMf.d.mts.map +1 -0
- package/dist/interface-Ch8HU9uM.d.mts +1098 -0
- package/dist/interface-Ch8HU9uM.d.mts.map +1 -0
- package/dist/introspectionPlugin-rFdO8ZUa.mjs +54 -0
- package/dist/introspectionPlugin-rFdO8ZUa.mjs.map +1 -0
- package/dist/keys-BqNejWup.mjs +43 -0
- package/dist/keys-BqNejWup.mjs.map +1 -0
- package/dist/logger-Df2O2WsW.mjs +79 -0
- package/dist/logger-Df2O2WsW.mjs.map +1 -0
- package/dist/memory-cQgelFOj.mjs +144 -0
- package/dist/memory-cQgelFOj.mjs.map +1 -0
- package/dist/migrations/index.d.mts +157 -0
- package/dist/migrations/index.d.mts.map +1 -0
- package/dist/migrations/index.mjs +261 -0
- package/dist/migrations/index.mjs.map +1 -0
- package/dist/mongodb-BfJVlUJH.mjs +94 -0
- package/dist/mongodb-BfJVlUJH.mjs.map +1 -0
- package/dist/mongodb-CGzRbfAK.d.mts +119 -0
- package/dist/mongodb-CGzRbfAK.d.mts.map +1 -0
- package/dist/mongodb-JN-9JA7K.d.mts +72 -0
- package/dist/mongodb-JN-9JA7K.d.mts.map +1 -0
- package/dist/openapi-G3Cw7XuM.mjs +524 -0
- package/dist/openapi-G3Cw7XuM.mjs.map +1 -0
- package/dist/org/index.d.mts +69 -0
- package/dist/org/index.d.mts.map +1 -0
- package/dist/org/index.mjs +514 -0
- package/dist/org/index.mjs.map +1 -0
- package/dist/org/types.d.mts +83 -0
- package/dist/org/types.d.mts.map +1 -0
- package/dist/org/types.mjs +1 -0
- package/dist/permissions/index.d.mts +279 -0
- package/dist/permissions/index.d.mts.map +1 -0
- package/dist/permissions/index.mjs +579 -0
- package/dist/permissions/index.mjs.map +1 -0
- package/dist/plugins/index.d.mts +173 -0
- package/dist/plugins/index.d.mts.map +1 -0
- package/dist/plugins/index.mjs +523 -0
- package/dist/plugins/index.mjs.map +1 -0
- package/dist/plugins/response-cache.d.mts +88 -0
- package/dist/plugins/response-cache.d.mts.map +1 -0
- package/dist/plugins/response-cache.mjs +284 -0
- package/dist/plugins/response-cache.mjs.map +1 -0
- package/dist/plugins/tracing-entry.d.mts +2 -0
- package/dist/plugins/tracing-entry.mjs +186 -0
- package/dist/plugins/tracing-entry.mjs.map +1 -0
- package/dist/pluralize-CEweyOEm.mjs +87 -0
- package/dist/pluralize-CEweyOEm.mjs.map +1 -0
- package/dist/policies/{index.d.ts → index.d.mts} +204 -169
- package/dist/policies/index.d.mts.map +1 -0
- package/dist/policies/index.mjs +322 -0
- package/dist/policies/index.mjs.map +1 -0
- package/dist/presets/{index.d.ts → index.d.mts} +63 -131
- package/dist/presets/index.d.mts.map +1 -0
- package/dist/presets/index.mjs +144 -0
- package/dist/presets/index.mjs.map +1 -0
- package/dist/presets/multiTenant.d.mts +25 -0
- package/dist/presets/multiTenant.d.mts.map +1 -0
- package/dist/presets/multiTenant.mjs +114 -0
- package/dist/presets/multiTenant.mjs.map +1 -0
- package/dist/presets-BITljm96.mjs +120 -0
- package/dist/presets-BITljm96.mjs.map +1 -0
- package/dist/presets-DzSMwlKj.d.mts +58 -0
- package/dist/presets-DzSMwlKj.d.mts.map +1 -0
- package/dist/prisma-DJbMt3yf.mjs +628 -0
- package/dist/prisma-DJbMt3yf.mjs.map +1 -0
- package/dist/prisma-Dg9GoVdj.d.mts +275 -0
- package/dist/prisma-Dg9GoVdj.d.mts.map +1 -0
- package/dist/queryCachePlugin-7THaI5mt.d.mts +72 -0
- package/dist/queryCachePlugin-7THaI5mt.d.mts.map +1 -0
- package/dist/queryCachePlugin-DMBnp2Q0.mjs +139 -0
- package/dist/queryCachePlugin-DMBnp2Q0.mjs.map +1 -0
- package/dist/redis-D-JAeLtm.d.mts +50 -0
- package/dist/redis-D-JAeLtm.d.mts.map +1 -0
- package/dist/redis-stream-Bdh_vUU8.d.mts +104 -0
- package/dist/redis-stream-Bdh_vUU8.d.mts.map +1 -0
- package/dist/registry/index.d.mts +12 -0
- package/dist/registry/index.d.mts.map +1 -0
- package/dist/registry/index.mjs +4 -0
- package/dist/requestContext-QQD6ROJc.mjs +56 -0
- package/dist/requestContext-QQD6ROJc.mjs.map +1 -0
- package/dist/schemaConverter-BwrmWroW.mjs +99 -0
- package/dist/schemaConverter-BwrmWroW.mjs.map +1 -0
- package/dist/schemas/index.d.mts +64 -0
- package/dist/schemas/index.d.mts.map +1 -0
- package/dist/schemas/index.mjs +83 -0
- package/dist/schemas/index.mjs.map +1 -0
- package/dist/scope/index.d.mts +22 -0
- package/dist/scope/index.d.mts.map +1 -0
- package/dist/scope/index.mjs +66 -0
- package/dist/scope/index.mjs.map +1 -0
- package/dist/sessionManager-jPKLbHE0.d.mts +187 -0
- package/dist/sessionManager-jPKLbHE0.d.mts.map +1 -0
- package/dist/sse-B3c3_yZp.mjs +124 -0
- package/dist/sse-B3c3_yZp.mjs.map +1 -0
- package/dist/testing/index.d.mts +908 -0
- package/dist/testing/index.d.mts.map +1 -0
- package/dist/testing/index.mjs +1977 -0
- package/dist/testing/index.mjs.map +1 -0
- package/dist/tracing-Cc7vVQPp.d.mts +71 -0
- package/dist/tracing-Cc7vVQPp.d.mts.map +1 -0
- package/dist/typeGuards-DhMNLuvU.mjs +10 -0
- package/dist/typeGuards-DhMNLuvU.mjs.map +1 -0
- package/dist/types/index.d.mts +947 -0
- package/dist/types/index.d.mts.map +1 -0
- package/dist/types/index.mjs +15 -0
- package/dist/types/index.mjs.map +1 -0
- package/dist/types-Beqn1Un7.mjs +39 -0
- package/dist/types-Beqn1Un7.mjs.map +1 -0
- package/dist/types-CIgB7UUl.d.mts +446 -0
- package/dist/types-CIgB7UUl.d.mts.map +1 -0
- package/dist/types-aYB4V7uN.d.mts +87 -0
- package/dist/types-aYB4V7uN.d.mts.map +1 -0
- package/dist/utils/index.d.mts +748 -0
- package/dist/utils/index.d.mts.map +1 -0
- package/dist/utils/index.mjs +6 -0
- package/package.json +194 -68
- package/dist/BaseController-DVAiHxEQ.d.ts +0 -233
- package/dist/adapters/index.d.ts +0 -237
- package/dist/adapters/index.js +0 -668
- package/dist/arcCorePlugin-CsShQdyP.d.ts +0 -273
- package/dist/audit/index.d.ts +0 -195
- package/dist/audit/index.js +0 -319
- package/dist/auth/index.d.ts +0 -47
- package/dist/auth/index.js +0 -174
- package/dist/cli/commands/docs.d.ts +0 -11
- package/dist/cli/commands/docs.js +0 -474
- package/dist/cli/commands/generate.js +0 -334
- package/dist/cli/commands/introspect.d.ts +0 -8
- package/dist/cli/commands/introspect.js +0 -338
- package/dist/cli/index.d.ts +0 -4
- package/dist/cli/index.js +0 -3269
- package/dist/core/index.d.ts +0 -220
- package/dist/core/index.js +0 -2786
- package/dist/createApp-Ce9wl8W9.d.ts +0 -77
- package/dist/docs/index.d.ts +0 -166
- package/dist/docs/index.js +0 -658
- package/dist/errors-8WIxGS_6.d.ts +0 -122
- package/dist/events/index.d.ts +0 -117
- package/dist/events/index.js +0 -89
- package/dist/factory/index.d.ts +0 -38
- package/dist/factory/index.js +0 -1652
- package/dist/hooks/index.d.ts +0 -4
- package/dist/hooks/index.js +0 -199
- package/dist/idempotency/index.d.ts +0 -323
- package/dist/idempotency/index.js +0 -500
- package/dist/index-B4t03KQ0.d.ts +0 -1366
- package/dist/index.d.ts +0 -135
- package/dist/index.js +0 -4756
- package/dist/migrations/index.d.ts +0 -185
- package/dist/migrations/index.js +0 -274
- package/dist/org/index.d.ts +0 -129
- package/dist/org/index.js +0 -220
- package/dist/permissions/index.d.ts +0 -144
- package/dist/permissions/index.js +0 -103
- package/dist/plugins/index.d.ts +0 -46
- package/dist/plugins/index.js +0 -1069
- package/dist/policies/index.js +0 -196
- package/dist/presets/index.js +0 -384
- package/dist/presets/multiTenant.d.ts +0 -39
- package/dist/presets/multiTenant.js +0 -112
- package/dist/registry/index.d.ts +0 -16
- package/dist/registry/index.js +0 -253
- package/dist/testing/index.d.ts +0 -618
- package/dist/testing/index.js +0 -48020
- package/dist/types/index.d.ts +0 -4
- package/dist/types/index.js +0 -8
- package/dist/types-B99TBmFV.d.ts +0 -76
- package/dist/types-BvckRbs2.d.ts +0 -143
- package/dist/utils/index.d.ts +0 -679
- package/dist/utils/index.js +0 -931
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { t as __exportAll } from "./chunk-C7Uep-_p.mjs";
|
|
2
|
+
import { f as isArcError } from "./errors-B9bZok84.mjs";
|
|
3
|
+
import fp from "fastify-plugin";
|
|
4
|
+
|
|
5
|
+
//#region src/plugins/errorHandler.ts
|
|
6
|
+
var errorHandler_exports = /* @__PURE__ */ __exportAll({
|
|
7
|
+
default: () => errorHandlerPlugin,
|
|
8
|
+
errorHandlerPlugin: () => errorHandlerPlugin
|
|
9
|
+
});
|
|
10
|
+
async function errorHandlerPluginFn(fastify, options = {}) {
|
|
11
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
12
|
+
const { includeStack = !isProduction, onError, errorMap = {} } = options;
|
|
13
|
+
fastify.setErrorHandler(async (error, request, reply) => {
|
|
14
|
+
if (onError) try {
|
|
15
|
+
await onError(error, request);
|
|
16
|
+
} catch (callbackError) {
|
|
17
|
+
request.log.error({ err: callbackError }, "Error in onError callback");
|
|
18
|
+
}
|
|
19
|
+
const requestId = request.id;
|
|
20
|
+
const response = {
|
|
21
|
+
success: false,
|
|
22
|
+
error: error.message || "Internal Server Error",
|
|
23
|
+
code: "INTERNAL_ERROR",
|
|
24
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
25
|
+
...requestId && { requestId }
|
|
26
|
+
};
|
|
27
|
+
let statusCode = 500;
|
|
28
|
+
if (isArcError(error)) {
|
|
29
|
+
statusCode = error.statusCode;
|
|
30
|
+
response.code = error.code;
|
|
31
|
+
if (error.details) response.details = error.details;
|
|
32
|
+
if (error.requestId) response.requestId = error.requestId;
|
|
33
|
+
if (error.cause) request.log.error({ cause: error.cause }, "Error cause chain");
|
|
34
|
+
} else if ("validation" in error && Array.isArray(error.validation)) {
|
|
35
|
+
statusCode = 400;
|
|
36
|
+
response.code = "VALIDATION_ERROR";
|
|
37
|
+
response.error = "Validation failed";
|
|
38
|
+
response.details = { errors: error.validation?.map((v) => ({
|
|
39
|
+
field: v.instancePath?.replace(/^\//, "") || v.params?.missingProperty || "unknown",
|
|
40
|
+
message: v.message || "Invalid value",
|
|
41
|
+
keyword: v.keyword
|
|
42
|
+
})) };
|
|
43
|
+
} else if ("statusCode" in error && typeof error.statusCode === "number") {
|
|
44
|
+
statusCode = error.statusCode;
|
|
45
|
+
response.code = statusCodeToCode(statusCode);
|
|
46
|
+
} else if (error.name && errorMap[error.name]) {
|
|
47
|
+
const mapping = errorMap[error.name];
|
|
48
|
+
statusCode = mapping.statusCode;
|
|
49
|
+
response.code = mapping.code;
|
|
50
|
+
if (mapping.message) response.error = mapping.message;
|
|
51
|
+
} else if (error.name === "ValidationError" && "errors" in error) {
|
|
52
|
+
statusCode = 400;
|
|
53
|
+
response.code = "VALIDATION_ERROR";
|
|
54
|
+
const mongooseErrors = error.errors;
|
|
55
|
+
if (includeStack) response.details = { errors: Object.entries(mongooseErrors).map(([field, err]) => ({
|
|
56
|
+
field: err.path || field,
|
|
57
|
+
message: err.message
|
|
58
|
+
})) };
|
|
59
|
+
else response.details = { errorCount: Object.keys(mongooseErrors).length };
|
|
60
|
+
} else if (error.name === "CastError") {
|
|
61
|
+
statusCode = 400;
|
|
62
|
+
response.code = "INVALID_ID";
|
|
63
|
+
response.error = "Invalid identifier format";
|
|
64
|
+
} else if (error.name === "MongoServerError" && error.code === 11e3) {
|
|
65
|
+
statusCode = 409;
|
|
66
|
+
response.code = "DUPLICATE_KEY";
|
|
67
|
+
response.error = "Resource already exists";
|
|
68
|
+
const keyValue = error.keyValue;
|
|
69
|
+
if (keyValue && includeStack) response.details = { duplicateFields: Object.keys(keyValue) };
|
|
70
|
+
}
|
|
71
|
+
if (includeStack && error.stack) response.stack = error.stack;
|
|
72
|
+
if (statusCode >= 500) request.log.error({
|
|
73
|
+
err: error,
|
|
74
|
+
statusCode
|
|
75
|
+
}, "Server error");
|
|
76
|
+
else if (statusCode >= 400) request.log.warn({
|
|
77
|
+
err: error,
|
|
78
|
+
statusCode
|
|
79
|
+
}, "Client error");
|
|
80
|
+
return reply.status(statusCode).send(response);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Map HTTP status code to error code
|
|
85
|
+
*/
|
|
86
|
+
function statusCodeToCode(statusCode) {
|
|
87
|
+
return {
|
|
88
|
+
400: "BAD_REQUEST",
|
|
89
|
+
401: "UNAUTHORIZED",
|
|
90
|
+
403: "FORBIDDEN",
|
|
91
|
+
404: "NOT_FOUND",
|
|
92
|
+
405: "METHOD_NOT_ALLOWED",
|
|
93
|
+
409: "CONFLICT",
|
|
94
|
+
422: "UNPROCESSABLE_ENTITY",
|
|
95
|
+
429: "RATE_LIMITED",
|
|
96
|
+
500: "INTERNAL_ERROR",
|
|
97
|
+
502: "BAD_GATEWAY",
|
|
98
|
+
503: "SERVICE_UNAVAILABLE",
|
|
99
|
+
504: "GATEWAY_TIMEOUT"
|
|
100
|
+
}[statusCode] ?? "ERROR";
|
|
101
|
+
}
|
|
102
|
+
const errorHandlerPlugin = fp(errorHandlerPluginFn, {
|
|
103
|
+
name: "arc-error-handler",
|
|
104
|
+
fastify: "5.x"
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
//#endregion
|
|
108
|
+
export { errorHandler_exports as n, errorHandlerPlugin as t };
|
|
109
|
+
//# sourceMappingURL=errorHandler-C1okiriz.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errorHandler-C1okiriz.mjs","names":[],"sources":["../src/plugins/errorHandler.ts"],"sourcesContent":["/**\n * Error Handler Plugin\n *\n * Global error handling for Arc applications.\n * Catches all errors and returns a consistent JSON response.\n *\n * @example\n * import { errorHandlerPlugin } from '@classytic/arc/plugins';\n *\n * await fastify.register(errorHandlerPlugin, {\n * includeStack: process.env.NODE_ENV !== 'production',\n * onError: (error, request) => {\n * // Log to external service (Sentry, etc.)\n * Sentry.captureException(error);\n * }\n * });\n */\n\nimport type { FastifyInstance, FastifyRequest, FastifyReply, FastifyError } from 'fastify';\nimport fp from 'fastify-plugin';\nimport { ArcError, isArcError, ValidationError } from '../utils/errors.js';\n\nexport interface ErrorHandlerOptions {\n /**\n * Include stack trace in error responses (default: false in production)\n */\n includeStack?: boolean;\n\n /**\n * Custom error callback for logging to external services\n */\n onError?: (error: Error, request: FastifyRequest) => void | Promise<void>;\n\n /**\n * Map specific error types to custom responses\n */\n errorMap?: Record<string, {\n statusCode: number;\n code: string;\n message?: string;\n }>;\n}\n\ninterface ErrorResponse {\n success: false;\n error: string;\n code: string;\n timestamp: string;\n requestId?: string;\n details?: Record<string, unknown>;\n stack?: string;\n}\n\nasync function errorHandlerPluginFn(\n fastify: FastifyInstance,\n options: ErrorHandlerOptions = {}\n): Promise<void> {\n const isProduction = process.env.NODE_ENV === 'production';\n const {\n includeStack = !isProduction,\n onError,\n errorMap = {},\n } = options;\n\n fastify.setErrorHandler(async (error: FastifyError | Error, request: FastifyRequest, reply: FastifyReply) => {\n // Call custom error handler if provided\n if (onError) {\n try {\n await onError(error, request);\n } catch (callbackError) {\n request.log.error({ err: callbackError }, 'Error in onError callback');\n }\n }\n\n // Get request ID if available\n const requestId = (request as { id?: string }).id;\n\n // Build base response\n const response: ErrorResponse = {\n success: false,\n error: error.message || 'Internal Server Error',\n code: 'INTERNAL_ERROR',\n timestamp: new Date().toISOString(),\n ...(requestId && { requestId }),\n };\n\n let statusCode = 500;\n\n // Handle ArcError (our error classes)\n if (isArcError(error)) {\n statusCode = error.statusCode;\n response.code = error.code;\n if (error.details) {\n response.details = error.details;\n }\n if (error.requestId) {\n response.requestId = error.requestId;\n }\n // Log cause chain for debugging (cause is now properly serialized via toJSON)\n if (error.cause) {\n request.log.error({ cause: error.cause }, 'Error cause chain');\n }\n }\n // Handle Fastify validation errors\n else if ('validation' in error && Array.isArray((error as FastifyError).validation)) {\n statusCode = 400;\n response.code = 'VALIDATION_ERROR';\n response.error = 'Validation failed';\n response.details = {\n errors: (error as FastifyError).validation?.map((v) => ({\n field: v.instancePath?.replace(/^\\//, '') || v.params?.missingProperty || 'unknown',\n message: v.message || 'Invalid value',\n keyword: v.keyword,\n })),\n };\n }\n // Handle Fastify errors with statusCode\n else if ('statusCode' in error && typeof (error as FastifyError).statusCode === 'number') {\n statusCode = (error as FastifyError).statusCode!;\n response.code = statusCodeToCode(statusCode);\n }\n // Handle mapped error types\n else if (error.name && errorMap[error.name]) {\n const mapping = errorMap[error.name]!;\n statusCode = mapping.statusCode;\n response.code = mapping.code;\n if (mapping.message) {\n response.error = mapping.message;\n }\n }\n // Handle Mongoose validation errors\n else if (error.name === 'ValidationError' && 'errors' in error) {\n statusCode = 400;\n response.code = 'VALIDATION_ERROR';\n const mongooseErrors = (error as { errors: Record<string, { message: string; path: string }> }).errors;\n\n // Security: Don't expose schema field names when details are hidden\n if (includeStack) {\n response.details = {\n errors: Object.entries(mongooseErrors).map(([field, err]) => ({\n field: err.path || field,\n message: err.message,\n })),\n };\n } else {\n response.details = { errorCount: Object.keys(mongooseErrors).length };\n }\n }\n // Handle Mongoose CastError (invalid ObjectId, etc.)\n else if (error.name === 'CastError') {\n statusCode = 400;\n response.code = 'INVALID_ID';\n response.error = 'Invalid identifier format';\n }\n // Handle duplicate key errors (MongoDB)\n else if (error.name === 'MongoServerError' && (error as { code?: number }).code === 11000) {\n statusCode = 409;\n response.code = 'DUPLICATE_KEY';\n response.error = 'Resource already exists';\n const keyValue = (error as { keyValue?: Record<string, unknown> }).keyValue;\n\n // Security: Don't expose schema field names when details are hidden\n if (keyValue && includeStack) {\n response.details = { duplicateFields: Object.keys(keyValue) };\n }\n }\n\n // Include stack trace if enabled\n if (includeStack && error.stack) {\n response.stack = error.stack;\n }\n\n // Log server errors\n if (statusCode >= 500) {\n request.log.error({ err: error, statusCode }, 'Server error');\n } else if (statusCode >= 400) {\n request.log.warn({ err: error, statusCode }, 'Client error');\n }\n\n return reply.status(statusCode).send(response);\n });\n}\n\n/**\n * Map HTTP status code to error code\n */\nfunction statusCodeToCode(statusCode: number): string {\n const codes: Record<number, string> = {\n 400: 'BAD_REQUEST',\n 401: 'UNAUTHORIZED',\n 403: 'FORBIDDEN',\n 404: 'NOT_FOUND',\n 405: 'METHOD_NOT_ALLOWED',\n 409: 'CONFLICT',\n 422: 'UNPROCESSABLE_ENTITY',\n 429: 'RATE_LIMITED',\n 500: 'INTERNAL_ERROR',\n 502: 'BAD_GATEWAY',\n 503: 'SERVICE_UNAVAILABLE',\n 504: 'GATEWAY_TIMEOUT',\n };\n return codes[statusCode] ?? 'ERROR';\n}\n\nexport const errorHandlerPlugin = fp(errorHandlerPluginFn, {\n name: 'arc-error-handler',\n fastify: '5.x',\n});\n\nexport default errorHandlerPlugin;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
//#region src/utils/errors.ts
|
|
2
|
+
/**
|
|
3
|
+
* Base Arc Error
|
|
4
|
+
*
|
|
5
|
+
* All Arc errors extend this class and produce a consistent error envelope:
|
|
6
|
+
* {
|
|
7
|
+
* success: false,
|
|
8
|
+
* error: "Human-readable message",
|
|
9
|
+
* code: "MACHINE_CODE",
|
|
10
|
+
* requestId: "uuid", // For tracing
|
|
11
|
+
* timestamp: "ISO date", // When error occurred
|
|
12
|
+
* details: { ... } // Additional context
|
|
13
|
+
* }
|
|
14
|
+
*/
|
|
15
|
+
var ArcError = class ArcError extends Error {
|
|
16
|
+
name;
|
|
17
|
+
code;
|
|
18
|
+
statusCode;
|
|
19
|
+
details;
|
|
20
|
+
cause;
|
|
21
|
+
timestamp;
|
|
22
|
+
requestId;
|
|
23
|
+
constructor(message, options = {}) {
|
|
24
|
+
super(message, options.cause ? { cause: options.cause } : void 0);
|
|
25
|
+
this.name = "ArcError";
|
|
26
|
+
this.code = options.code ?? "ARC_ERROR";
|
|
27
|
+
this.statusCode = options.statusCode ?? 500;
|
|
28
|
+
this.details = options.details;
|
|
29
|
+
this.cause = options.cause;
|
|
30
|
+
this.timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
31
|
+
this.requestId = options.requestId;
|
|
32
|
+
if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Set request ID (typically from request context)
|
|
36
|
+
*/
|
|
37
|
+
withRequestId(requestId) {
|
|
38
|
+
this.requestId = requestId;
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Convert to JSON response.
|
|
43
|
+
* Includes cause chain when present for debugging visibility.
|
|
44
|
+
*/
|
|
45
|
+
toJSON() {
|
|
46
|
+
return {
|
|
47
|
+
success: false,
|
|
48
|
+
error: this.message,
|
|
49
|
+
code: this.code,
|
|
50
|
+
timestamp: this.timestamp,
|
|
51
|
+
...this.requestId && { requestId: this.requestId },
|
|
52
|
+
...this.details && { details: this.details },
|
|
53
|
+
...this.cause && { cause: this.cause instanceof ArcError ? this.cause.toJSON() : {
|
|
54
|
+
message: this.cause.message,
|
|
55
|
+
name: this.cause.name
|
|
56
|
+
} }
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Not Found Error - 404
|
|
62
|
+
*/
|
|
63
|
+
var NotFoundError = class extends ArcError {
|
|
64
|
+
constructor(resource, identifier) {
|
|
65
|
+
const message = identifier ? `${resource} with identifier '${identifier}' not found` : `${resource} not found`;
|
|
66
|
+
super(message, {
|
|
67
|
+
code: "NOT_FOUND",
|
|
68
|
+
statusCode: 404,
|
|
69
|
+
details: {
|
|
70
|
+
resource,
|
|
71
|
+
identifier
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
this.name = "NotFoundError";
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Validation Error - 400
|
|
79
|
+
*/
|
|
80
|
+
var ValidationError = class extends ArcError {
|
|
81
|
+
errors;
|
|
82
|
+
constructor(message, errors = []) {
|
|
83
|
+
super(message, {
|
|
84
|
+
code: "VALIDATION_ERROR",
|
|
85
|
+
statusCode: 400,
|
|
86
|
+
details: { errors }
|
|
87
|
+
});
|
|
88
|
+
this.name = "ValidationError";
|
|
89
|
+
this.errors = errors;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Unauthorized Error - 401
|
|
94
|
+
*/
|
|
95
|
+
var UnauthorizedError = class extends ArcError {
|
|
96
|
+
constructor(message = "Authentication required") {
|
|
97
|
+
super(message, {
|
|
98
|
+
code: "UNAUTHORIZED",
|
|
99
|
+
statusCode: 401
|
|
100
|
+
});
|
|
101
|
+
this.name = "UnauthorizedError";
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Forbidden Error - 403
|
|
106
|
+
*/
|
|
107
|
+
var ForbiddenError = class extends ArcError {
|
|
108
|
+
constructor(message = "Access denied") {
|
|
109
|
+
super(message, {
|
|
110
|
+
code: "FORBIDDEN",
|
|
111
|
+
statusCode: 403
|
|
112
|
+
});
|
|
113
|
+
this.name = "ForbiddenError";
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Conflict Error - 409
|
|
118
|
+
*/
|
|
119
|
+
var ConflictError = class extends ArcError {
|
|
120
|
+
constructor(message, field) {
|
|
121
|
+
super(message, {
|
|
122
|
+
code: "CONFLICT",
|
|
123
|
+
statusCode: 409,
|
|
124
|
+
details: field ? { field } : void 0
|
|
125
|
+
});
|
|
126
|
+
this.name = "ConflictError";
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Organization Required Error - 403
|
|
131
|
+
*/
|
|
132
|
+
var OrgRequiredError = class extends ArcError {
|
|
133
|
+
organizations;
|
|
134
|
+
constructor(message, organizations) {
|
|
135
|
+
super(message, {
|
|
136
|
+
code: "ORG_SELECTION_REQUIRED",
|
|
137
|
+
statusCode: 403,
|
|
138
|
+
details: organizations ? { organizations } : void 0
|
|
139
|
+
});
|
|
140
|
+
this.name = "OrgRequiredError";
|
|
141
|
+
this.organizations = organizations;
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Organization Access Denied Error - 403
|
|
146
|
+
*/
|
|
147
|
+
var OrgAccessDeniedError = class extends ArcError {
|
|
148
|
+
constructor(orgId) {
|
|
149
|
+
super("Organization access denied", {
|
|
150
|
+
code: "ORG_ACCESS_DENIED",
|
|
151
|
+
statusCode: 403,
|
|
152
|
+
details: orgId ? { organizationId: orgId } : void 0
|
|
153
|
+
});
|
|
154
|
+
this.name = "OrgAccessDeniedError";
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* Rate Limit Error - 429
|
|
159
|
+
*/
|
|
160
|
+
var RateLimitError = class extends ArcError {
|
|
161
|
+
retryAfter;
|
|
162
|
+
constructor(message = "Too many requests", retryAfter) {
|
|
163
|
+
super(message, {
|
|
164
|
+
code: "RATE_LIMITED",
|
|
165
|
+
statusCode: 429,
|
|
166
|
+
details: retryAfter ? { retryAfter } : void 0
|
|
167
|
+
});
|
|
168
|
+
this.name = "RateLimitError";
|
|
169
|
+
this.retryAfter = retryAfter;
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* Service Unavailable Error - 503
|
|
174
|
+
*/
|
|
175
|
+
var ServiceUnavailableError = class extends ArcError {
|
|
176
|
+
constructor(message = "Service temporarily unavailable") {
|
|
177
|
+
super(message, {
|
|
178
|
+
code: "SERVICE_UNAVAILABLE",
|
|
179
|
+
statusCode: 503
|
|
180
|
+
});
|
|
181
|
+
this.name = "ServiceUnavailableError";
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
/**
|
|
185
|
+
* Create error from status code
|
|
186
|
+
*/
|
|
187
|
+
function createError(statusCode, message, details) {
|
|
188
|
+
return new ArcError(message, {
|
|
189
|
+
code: {
|
|
190
|
+
400: "BAD_REQUEST",
|
|
191
|
+
401: "UNAUTHORIZED",
|
|
192
|
+
403: "FORBIDDEN",
|
|
193
|
+
404: "NOT_FOUND",
|
|
194
|
+
409: "CONFLICT",
|
|
195
|
+
429: "RATE_LIMITED",
|
|
196
|
+
500: "INTERNAL_ERROR",
|
|
197
|
+
503: "SERVICE_UNAVAILABLE"
|
|
198
|
+
}[statusCode] ?? "ERROR",
|
|
199
|
+
statusCode,
|
|
200
|
+
details
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Check if error is an Arc error
|
|
205
|
+
*/
|
|
206
|
+
function isArcError(error) {
|
|
207
|
+
return error instanceof ArcError;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
//#endregion
|
|
211
|
+
export { OrgAccessDeniedError as a, ServiceUnavailableError as c, createError as d, isArcError as f, NotFoundError as i, UnauthorizedError as l, ConflictError as n, OrgRequiredError as o, ForbiddenError as r, RateLimitError as s, ArcError as t, ValidationError as u };
|
|
212
|
+
//# sourceMappingURL=errors-B9bZok84.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors-B9bZok84.mjs","names":[],"sources":["../src/utils/errors.ts"],"sourcesContent":["/**\n * Error Classes\n *\n * Standard error types for the Arc framework.\n */\n\nexport interface ErrorDetails {\n code?: string;\n statusCode?: number;\n details?: Record<string, unknown>;\n cause?: Error;\n requestId?: string;\n}\n\n/**\n * Base Arc Error\n *\n * All Arc errors extend this class and produce a consistent error envelope:\n * {\n * success: false,\n * error: \"Human-readable message\",\n * code: \"MACHINE_CODE\",\n * requestId: \"uuid\", // For tracing\n * timestamp: \"ISO date\", // When error occurred\n * details: { ... } // Additional context\n * }\n */\nexport class ArcError extends Error {\n override name: string;\n readonly code: string;\n readonly statusCode: number;\n readonly details?: Record<string, unknown>;\n override readonly cause?: Error;\n readonly timestamp: string;\n requestId?: string;\n\n constructor(message: string, options: ErrorDetails = {}) {\n // Pass cause to native Error for proper chain support (Node 16.9+)\n super(message, options.cause ? { cause: options.cause } : undefined);\n this.name = 'ArcError';\n this.code = options.code ?? 'ARC_ERROR';\n this.statusCode = options.statusCode ?? 500;\n this.details = options.details;\n // cause is now set by super() — keep explicit assignment for TypeScript override\n this.cause = options.cause;\n this.timestamp = new Date().toISOString();\n this.requestId = options.requestId;\n\n // Maintain proper stack trace\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n /**\n * Set request ID (typically from request context)\n */\n withRequestId(requestId: string): this {\n this.requestId = requestId;\n return this;\n }\n\n /**\n * Convert to JSON response.\n * Includes cause chain when present for debugging visibility.\n */\n toJSON(): Record<string, unknown> {\n return {\n success: false,\n error: this.message,\n code: this.code,\n timestamp: this.timestamp,\n ...(this.requestId && { requestId: this.requestId }),\n ...(this.details && { details: this.details }),\n ...(this.cause && {\n cause: this.cause instanceof ArcError\n ? this.cause.toJSON()\n : { message: (this.cause as Error).message, name: (this.cause as Error).name },\n }),\n };\n }\n}\n\n/**\n * Not Found Error - 404\n */\nexport class NotFoundError extends ArcError {\n constructor(resource: string, identifier?: string) {\n const message = identifier\n ? `${resource} with identifier '${identifier}' not found`\n : `${resource} not found`;\n\n super(message, {\n code: 'NOT_FOUND',\n statusCode: 404,\n details: { resource, identifier },\n });\n this.name = 'NotFoundError';\n }\n}\n\n/**\n * Validation Error - 400\n */\nexport class ValidationError extends ArcError {\n readonly errors: Array<{ field: string; message: string }>;\n\n constructor(\n message: string,\n errors: Array<{ field: string; message: string }> = []\n ) {\n super(message, {\n code: 'VALIDATION_ERROR',\n statusCode: 400,\n details: { errors },\n });\n this.name = 'ValidationError';\n this.errors = errors;\n }\n}\n\n/**\n * Unauthorized Error - 401\n */\nexport class UnauthorizedError extends ArcError {\n constructor(message = 'Authentication required') {\n super(message, {\n code: 'UNAUTHORIZED',\n statusCode: 401,\n });\n this.name = 'UnauthorizedError';\n }\n}\n\n/**\n * Forbidden Error - 403\n */\nexport class ForbiddenError extends ArcError {\n constructor(message = 'Access denied') {\n super(message, {\n code: 'FORBIDDEN',\n statusCode: 403,\n });\n this.name = 'ForbiddenError';\n }\n}\n\n/**\n * Conflict Error - 409\n */\nexport class ConflictError extends ArcError {\n constructor(message: string, field?: string) {\n super(message, {\n code: 'CONFLICT',\n statusCode: 409,\n details: field ? { field } : undefined,\n });\n this.name = 'ConflictError';\n }\n}\n\n/**\n * Organization Required Error - 403\n */\nexport class OrgRequiredError extends ArcError {\n readonly organizations?: Array<{ id: string; roles?: string[] }>;\n\n constructor(\n message: string,\n organizations?: Array<{ id: string; roles?: string[] }>\n ) {\n super(message, {\n code: 'ORG_SELECTION_REQUIRED',\n statusCode: 403,\n details: organizations ? { organizations } : undefined,\n });\n this.name = 'OrgRequiredError';\n this.organizations = organizations;\n }\n}\n\n/**\n * Organization Access Denied Error - 403\n */\nexport class OrgAccessDeniedError extends ArcError {\n constructor(orgId?: string) {\n super('Organization access denied', {\n code: 'ORG_ACCESS_DENIED',\n statusCode: 403,\n details: orgId ? { organizationId: orgId } : undefined,\n });\n this.name = 'OrgAccessDeniedError';\n }\n}\n\n/**\n * Rate Limit Error - 429\n */\nexport class RateLimitError extends ArcError {\n readonly retryAfter?: number;\n\n constructor(message = 'Too many requests', retryAfter?: number) {\n super(message, {\n code: 'RATE_LIMITED',\n statusCode: 429,\n details: retryAfter ? { retryAfter } : undefined,\n });\n this.name = 'RateLimitError';\n this.retryAfter = retryAfter;\n }\n}\n\n/**\n * Service Unavailable Error - 503\n */\nexport class ServiceUnavailableError extends ArcError {\n constructor(message = 'Service temporarily unavailable') {\n super(message, {\n code: 'SERVICE_UNAVAILABLE',\n statusCode: 503,\n });\n this.name = 'ServiceUnavailableError';\n }\n}\n\n/**\n * Create error from status code\n */\nexport function createError(\n statusCode: number,\n message: string,\n details?: Record<string, unknown>\n): ArcError {\n const codes: Record<number, string> = {\n 400: 'BAD_REQUEST',\n 401: 'UNAUTHORIZED',\n 403: 'FORBIDDEN',\n 404: 'NOT_FOUND',\n 409: 'CONFLICT',\n 429: 'RATE_LIMITED',\n 500: 'INTERNAL_ERROR',\n 503: 'SERVICE_UNAVAILABLE',\n };\n\n return new ArcError(message, {\n code: codes[statusCode] ?? 'ERROR',\n statusCode,\n details,\n });\n}\n\n/**\n * Check if error is an Arc error\n */\nexport function isArcError(error: unknown): error is ArcError {\n return error instanceof ArcError;\n}\n"],"mappings":";;;;;;;;;;;;;;AA2BA,IAAa,WAAb,MAAa,iBAAiB,MAAM;CAClC,AAAS;CACT,AAAS;CACT,AAAS;CACT,AAAS;CACT,AAAkB;CAClB,AAAS;CACT;CAEA,YAAY,SAAiB,UAAwB,EAAE,EAAE;AAEvD,QAAM,SAAS,QAAQ,QAAQ,EAAE,OAAO,QAAQ,OAAO,GAAG,OAAU;AACpE,OAAK,OAAO;AACZ,OAAK,OAAO,QAAQ,QAAQ;AAC5B,OAAK,aAAa,QAAQ,cAAc;AACxC,OAAK,UAAU,QAAQ;AAEvB,OAAK,QAAQ,QAAQ;AACrB,OAAK,6BAAY,IAAI,MAAM,EAAC,aAAa;AACzC,OAAK,YAAY,QAAQ;AAGzB,MAAI,MAAM,kBACR,OAAM,kBAAkB,MAAM,KAAK,YAAY;;;;;CAOnD,cAAc,WAAyB;AACrC,OAAK,YAAY;AACjB,SAAO;;;;;;CAOT,SAAkC;AAChC,SAAO;GACL,SAAS;GACT,OAAO,KAAK;GACZ,MAAM,KAAK;GACX,WAAW,KAAK;GAChB,GAAI,KAAK,aAAa,EAAE,WAAW,KAAK,WAAW;GACnD,GAAI,KAAK,WAAW,EAAE,SAAS,KAAK,SAAS;GAC7C,GAAI,KAAK,SAAS,EAChB,OAAO,KAAK,iBAAiB,WACzB,KAAK,MAAM,QAAQ,GACnB;IAAE,SAAU,KAAK,MAAgB;IAAS,MAAO,KAAK,MAAgB;IAAM,EACjF;GACF;;;;;;AAOL,IAAa,gBAAb,cAAmC,SAAS;CAC1C,YAAY,UAAkB,YAAqB;EACjD,MAAM,UAAU,aACZ,GAAG,SAAS,oBAAoB,WAAW,eAC3C,GAAG,SAAS;AAEhB,QAAM,SAAS;GACb,MAAM;GACN,YAAY;GACZ,SAAS;IAAE;IAAU;IAAY;GAClC,CAAC;AACF,OAAK,OAAO;;;;;;AAOhB,IAAa,kBAAb,cAAqC,SAAS;CAC5C,AAAS;CAET,YACE,SACA,SAAoD,EAAE,EACtD;AACA,QAAM,SAAS;GACb,MAAM;GACN,YAAY;GACZ,SAAS,EAAE,QAAQ;GACpB,CAAC;AACF,OAAK,OAAO;AACZ,OAAK,SAAS;;;;;;AAOlB,IAAa,oBAAb,cAAuC,SAAS;CAC9C,YAAY,UAAU,2BAA2B;AAC/C,QAAM,SAAS;GACb,MAAM;GACN,YAAY;GACb,CAAC;AACF,OAAK,OAAO;;;;;;AAOhB,IAAa,iBAAb,cAAoC,SAAS;CAC3C,YAAY,UAAU,iBAAiB;AACrC,QAAM,SAAS;GACb,MAAM;GACN,YAAY;GACb,CAAC;AACF,OAAK,OAAO;;;;;;AAOhB,IAAa,gBAAb,cAAmC,SAAS;CAC1C,YAAY,SAAiB,OAAgB;AAC3C,QAAM,SAAS;GACb,MAAM;GACN,YAAY;GACZ,SAAS,QAAQ,EAAE,OAAO,GAAG;GAC9B,CAAC;AACF,OAAK,OAAO;;;;;;AAOhB,IAAa,mBAAb,cAAsC,SAAS;CAC7C,AAAS;CAET,YACE,SACA,eACA;AACA,QAAM,SAAS;GACb,MAAM;GACN,YAAY;GACZ,SAAS,gBAAgB,EAAE,eAAe,GAAG;GAC9C,CAAC;AACF,OAAK,OAAO;AACZ,OAAK,gBAAgB;;;;;;AAOzB,IAAa,uBAAb,cAA0C,SAAS;CACjD,YAAY,OAAgB;AAC1B,QAAM,8BAA8B;GAClC,MAAM;GACN,YAAY;GACZ,SAAS,QAAQ,EAAE,gBAAgB,OAAO,GAAG;GAC9C,CAAC;AACF,OAAK,OAAO;;;;;;AAOhB,IAAa,iBAAb,cAAoC,SAAS;CAC3C,AAAS;CAET,YAAY,UAAU,qBAAqB,YAAqB;AAC9D,QAAM,SAAS;GACb,MAAM;GACN,YAAY;GACZ,SAAS,aAAa,EAAE,YAAY,GAAG;GACxC,CAAC;AACF,OAAK,OAAO;AACZ,OAAK,aAAa;;;;;;AAOtB,IAAa,0BAAb,cAA6C,SAAS;CACpD,YAAY,UAAU,mCAAmC;AACvD,QAAM,SAAS;GACb,MAAM;GACN,YAAY;GACb,CAAC;AACF,OAAK,OAAO;;;;;;AAOhB,SAAgB,YACd,YACA,SACA,SACU;AAYV,QAAO,IAAI,SAAS,SAAS;EAC3B,MAZoC;GACpC,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACN,CAGa,eAAe;EAC3B;EACA;EACD,CAAC;;;;;AAMJ,SAAgB,WAAW,OAAmC;AAC5D,QAAO,iBAAiB"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
//#region src/utils/errors.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Error Classes
|
|
4
|
+
*
|
|
5
|
+
* Standard error types for the Arc framework.
|
|
6
|
+
*/
|
|
7
|
+
interface ErrorDetails {
|
|
8
|
+
code?: string;
|
|
9
|
+
statusCode?: number;
|
|
10
|
+
details?: Record<string, unknown>;
|
|
11
|
+
cause?: Error;
|
|
12
|
+
requestId?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Base Arc Error
|
|
16
|
+
*
|
|
17
|
+
* All Arc errors extend this class and produce a consistent error envelope:
|
|
18
|
+
* {
|
|
19
|
+
* success: false,
|
|
20
|
+
* error: "Human-readable message",
|
|
21
|
+
* code: "MACHINE_CODE",
|
|
22
|
+
* requestId: "uuid", // For tracing
|
|
23
|
+
* timestamp: "ISO date", // When error occurred
|
|
24
|
+
* details: { ... } // Additional context
|
|
25
|
+
* }
|
|
26
|
+
*/
|
|
27
|
+
declare class ArcError extends Error {
|
|
28
|
+
name: string;
|
|
29
|
+
readonly code: string;
|
|
30
|
+
readonly statusCode: number;
|
|
31
|
+
readonly details?: Record<string, unknown>;
|
|
32
|
+
readonly cause?: Error;
|
|
33
|
+
readonly timestamp: string;
|
|
34
|
+
requestId?: string;
|
|
35
|
+
constructor(message: string, options?: ErrorDetails);
|
|
36
|
+
/**
|
|
37
|
+
* Set request ID (typically from request context)
|
|
38
|
+
*/
|
|
39
|
+
withRequestId(requestId: string): this;
|
|
40
|
+
/**
|
|
41
|
+
* Convert to JSON response.
|
|
42
|
+
* Includes cause chain when present for debugging visibility.
|
|
43
|
+
*/
|
|
44
|
+
toJSON(): Record<string, unknown>;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Not Found Error - 404
|
|
48
|
+
*/
|
|
49
|
+
declare class NotFoundError extends ArcError {
|
|
50
|
+
constructor(resource: string, identifier?: string);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Validation Error - 400
|
|
54
|
+
*/
|
|
55
|
+
declare class ValidationError extends ArcError {
|
|
56
|
+
readonly errors: Array<{
|
|
57
|
+
field: string;
|
|
58
|
+
message: string;
|
|
59
|
+
}>;
|
|
60
|
+
constructor(message: string, errors?: Array<{
|
|
61
|
+
field: string;
|
|
62
|
+
message: string;
|
|
63
|
+
}>);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Unauthorized Error - 401
|
|
67
|
+
*/
|
|
68
|
+
declare class UnauthorizedError extends ArcError {
|
|
69
|
+
constructor(message?: string);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Forbidden Error - 403
|
|
73
|
+
*/
|
|
74
|
+
declare class ForbiddenError extends ArcError {
|
|
75
|
+
constructor(message?: string);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Conflict Error - 409
|
|
79
|
+
*/
|
|
80
|
+
declare class ConflictError extends ArcError {
|
|
81
|
+
constructor(message: string, field?: string);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Organization Required Error - 403
|
|
85
|
+
*/
|
|
86
|
+
declare class OrgRequiredError extends ArcError {
|
|
87
|
+
readonly organizations?: Array<{
|
|
88
|
+
id: string;
|
|
89
|
+
roles?: string[];
|
|
90
|
+
}>;
|
|
91
|
+
constructor(message: string, organizations?: Array<{
|
|
92
|
+
id: string;
|
|
93
|
+
roles?: string[];
|
|
94
|
+
}>);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Organization Access Denied Error - 403
|
|
98
|
+
*/
|
|
99
|
+
declare class OrgAccessDeniedError extends ArcError {
|
|
100
|
+
constructor(orgId?: string);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Rate Limit Error - 429
|
|
104
|
+
*/
|
|
105
|
+
declare class RateLimitError extends ArcError {
|
|
106
|
+
readonly retryAfter?: number;
|
|
107
|
+
constructor(message?: string, retryAfter?: number);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Service Unavailable Error - 503
|
|
111
|
+
*/
|
|
112
|
+
declare class ServiceUnavailableError extends ArcError {
|
|
113
|
+
constructor(message?: string);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Create error from status code
|
|
117
|
+
*/
|
|
118
|
+
declare function createError(statusCode: number, message: string, details?: Record<string, unknown>): ArcError;
|
|
119
|
+
/**
|
|
120
|
+
* Check if error is an Arc error
|
|
121
|
+
*/
|
|
122
|
+
declare function isArcError(error: unknown): error is ArcError;
|
|
123
|
+
//#endregion
|
|
124
|
+
export { NotFoundError as a, RateLimitError as c, ValidationError as d, createError as f, ForbiddenError as i, ServiceUnavailableError as l, ConflictError as n, OrgAccessDeniedError as o, isArcError as p, ErrorDetails as r, OrgRequiredError as s, ArcError as t, UnauthorizedError as u };
|
|
125
|
+
//# sourceMappingURL=errors-ChKiFz62.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors-ChKiFz62.d.mts","names":[],"sources":["../src/utils/errors.ts"],"mappings":";;AAMA;;;;UAAiB,YAAA;EACf,IAAA;EACA,UAAA;EACA,OAAA,GAAU,MAAA;EACV,KAAA,GAAQ,KAAA;EACR,SAAA;AAAA;;;AAgBF;;;;;;;;;;;cAAa,QAAA,SAAiB,KAAA;EACnB,IAAA;EAAA,SACA,IAAA;EAAA,SACA,UAAA;EAAA,SACA,OAAA,GAAU,MAAA;EAAA,SACD,KAAA,GAAQ,KAAA;EAAA,SACjB,SAAA;EACT,SAAA;cAEY,OAAA,UAAiB,OAAA,GAAS,YAAA;;;;EAqBtC,aAAA,CAAc,SAAA;EAAd;;;;EASA,MAAA,CAAA,GAAU,MAAA;AAAA;AAoBZ;;;AAAA,cAAa,aAAA,SAAsB,QAAA;cACrB,QAAA,UAAkB,UAAA;AAAA;;;;cAiBnB,eAAA,SAAwB,QAAA;EAAA,SAC1B,MAAA,EAAQ,KAAA;IAAQ,KAAA;IAAe,OAAA;EAAA;cAGtC,OAAA,UACA,MAAA,GAAQ,KAAA;IAAQ,KAAA;IAAe,OAAA;EAAA;AAAA;;;;cAetB,iBAAA,SAA0B,QAAA;cACzB,OAAA;AAAA;;;;cAYD,cAAA,SAAuB,QAAA;cACtB,OAAA;AAAA;AAdd;;;AAAA,cA0Ba,aAAA,SAAsB,QAAA;cACrB,OAAA,UAAiB,KAAA;AAAA;;;;cAalB,gBAAA,SAAyB,QAAA;EAAA,SAC3B,aAAA,GAAgB,KAAA;IAAQ,EAAA;IAAY,KAAA;EAAA;cAG3C,OAAA,UACA,aAAA,GAAgB,KAAA;IAAQ,EAAA;IAAY,KAAA;EAAA;AAAA;;;;cAe3B,oBAAA,SAA6B,QAAA;cAC5B,KAAA;AAAA;;;;cAaD,cAAA,SAAuB,QAAA;EAAA,SACzB,UAAA;cAEG,OAAA,WAA+B,UAAA;AAAA;;;;cAchC,uBAAA,SAAgC,QAAA;cAC/B,OAAA;AAAA;;;;iBAYE,WAAA,CACd,UAAA,UACA,OAAA,UACA,OAAA,GAAU,MAAA,oBACT,QAAA;;;;iBAsBa,UAAA,CAAW,KAAA,YAAiB,KAAA,IAAS,QAAA"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { i as EventTransport, n as EventHandler, r as EventLogger, t as DomainEvent } from "./EventTransport-BD2U0BTc.mjs";
|
|
2
|
+
import { FastifyPluginAsync } from "fastify";
|
|
3
|
+
|
|
4
|
+
//#region src/events/retry.d.ts
|
|
5
|
+
interface RetryOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Max retry attempts (not counting the initial attempt).
|
|
8
|
+
* @default 3
|
|
9
|
+
*/
|
|
10
|
+
maxRetries?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Initial backoff delay in ms. Doubles on each retry (exponential backoff).
|
|
13
|
+
* @default 1000
|
|
14
|
+
*/
|
|
15
|
+
backoffMs?: number;
|
|
16
|
+
/**
|
|
17
|
+
* Maximum backoff delay in ms (caps exponential growth).
|
|
18
|
+
* @default 30000
|
|
19
|
+
*/
|
|
20
|
+
maxBackoffMs?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Jitter factor (0-1). Adds randomness to prevent thundering herd.
|
|
23
|
+
* 0 = no jitter, 1 = full jitter (delay ∈ [0, calculated]).
|
|
24
|
+
* @default 0.1
|
|
25
|
+
*/
|
|
26
|
+
jitter?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Callback when all retries are exhausted. The event is "dead".
|
|
29
|
+
* Use this to publish to a `$deadLetter` channel, log, alert, etc.
|
|
30
|
+
*/
|
|
31
|
+
onDead?: (event: DomainEvent, errors: Error[]) => void | Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Optional name for logging/debugging.
|
|
34
|
+
*/
|
|
35
|
+
name?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Logger for retry warnings and error messages (default: console).
|
|
38
|
+
* Pass `fastify.log` to integrate with your application logger.
|
|
39
|
+
*/
|
|
40
|
+
logger?: EventLogger;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Wrap an event handler with retry logic and dead letter support.
|
|
44
|
+
*
|
|
45
|
+
* On failure, retries with exponential backoff (with jitter).
|
|
46
|
+
* After all retries exhausted, calls `onDead` callback if provided.
|
|
47
|
+
*/
|
|
48
|
+
declare function withRetry(handler: EventHandler, options?: RetryOptions): EventHandler;
|
|
49
|
+
/**
|
|
50
|
+
* Create a dead letter publisher that sends failed events to a `$deadLetter` channel.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* import { withRetry, createDeadLetterPublisher } from '@classytic/arc/events';
|
|
55
|
+
*
|
|
56
|
+
* const toDlq = createDeadLetterPublisher(fastify.events);
|
|
57
|
+
*
|
|
58
|
+
* await fastify.events.subscribe('order.created', withRetry(handler, {
|
|
59
|
+
* maxRetries: 3,
|
|
60
|
+
* onDead: toDlq,
|
|
61
|
+
* }));
|
|
62
|
+
*
|
|
63
|
+
* // Monitor dead letters
|
|
64
|
+
* await fastify.events.subscribe('$deadLetter', async (event) => {
|
|
65
|
+
* console.error('Dead letter:', event.payload);
|
|
66
|
+
* await alertOps(event.payload);
|
|
67
|
+
* });
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
declare function createDeadLetterPublisher(events: {
|
|
71
|
+
publish: <T>(type: string, payload: T, meta?: Record<string, unknown>) => Promise<void>;
|
|
72
|
+
}): (event: DomainEvent, errors: Error[]) => Promise<void>;
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/events/eventPlugin.d.ts
|
|
75
|
+
interface EventPluginOptions {
|
|
76
|
+
/** Event transport (default: MemoryEventTransport) */
|
|
77
|
+
transport?: EventTransport;
|
|
78
|
+
/** Enable event logging (default: false) */
|
|
79
|
+
logEvents?: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Fail-open mode for runtime resilience (default: true).
|
|
82
|
+
* - true: publish/subscribe/close errors are logged and suppressed
|
|
83
|
+
* - false: errors are thrown to caller
|
|
84
|
+
*/
|
|
85
|
+
failOpen?: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Write-Ahead Log (WAL) configuration for at-least-once delivery guarantees.
|
|
88
|
+
* If provided, events will be saved to the WAL *before* passing to the transport.
|
|
89
|
+
* After a successful publish, they are acknowledged.
|
|
90
|
+
*/
|
|
91
|
+
wal?: {
|
|
92
|
+
save: (event: DomainEvent) => Promise<void>;
|
|
93
|
+
acknowledge?: (eventId: string) => Promise<void>;
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Auto-wrap all subscribed handlers with retry logic.
|
|
97
|
+
* When enabled, failed handler invocations are retried with exponential backoff.
|
|
98
|
+
*/
|
|
99
|
+
retry?: Pick<RetryOptions, "maxRetries" | "backoffMs" | "maxBackoffMs" | "jitter">;
|
|
100
|
+
/**
|
|
101
|
+
* Dead letter queue for events that exhaust all retries.
|
|
102
|
+
* Requires `retry` to be enabled. If `retry` is set but no custom `store`,
|
|
103
|
+
* failed events are published to the `$deadLetter` event type by default.
|
|
104
|
+
*/
|
|
105
|
+
deadLetterQueue?: {
|
|
106
|
+
/** Custom store function. If omitted, publishes to '$deadLetter' event type. */store?: (event: DomainEvent, errors: Error[]) => void | Promise<void>;
|
|
107
|
+
};
|
|
108
|
+
/** Callback after successful publish (for metrics/tracking) */
|
|
109
|
+
onPublish?: (event: DomainEvent) => void;
|
|
110
|
+
/** Callback on publish failure (for metrics/alerting) */
|
|
111
|
+
onPublishError?: (event: DomainEvent, error: Error) => void;
|
|
112
|
+
}
|
|
113
|
+
declare module "fastify" {
|
|
114
|
+
interface FastifyInstance {
|
|
115
|
+
events: {
|
|
116
|
+
/** Publish an event */publish: <T>(type: string, payload: T, meta?: Partial<DomainEvent["meta"]>) => Promise<void>; /** Subscribe to events */
|
|
117
|
+
subscribe: (pattern: string, handler: EventHandler) => Promise<() => void>; /** Get transport name */
|
|
118
|
+
transportName: string;
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
declare const eventPlugin: FastifyPluginAsync<EventPluginOptions>;
|
|
123
|
+
//#endregion
|
|
124
|
+
export { withRetry as a, createDeadLetterPublisher as i, eventPlugin as n, RetryOptions as r, EventPluginOptions as t };
|
|
125
|
+
//# sourceMappingURL=eventPlugin-CTrLH3mt.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eventPlugin-CTrLH3mt.d.mts","names":[],"sources":["../src/events/retry.ts","../src/events/eventPlugin.ts"],"mappings":";;;;UAiCiB,YAAA;EAoDN;;;;EA/CT,UAAA;EA8CA;;;;EAxCA,SAAA;EA0Ca;AA6Ef;;;EAjHE,YAAA;EAkHwD;;;;;EA3GxD,MAAA;EA4GiD;;;;EAtGjD,MAAA,IAAU,KAAA,EAAO,WAAA,EAAa,MAAA,EAAQ,KAAA,cAAmB,OAAA;EAqGpB;;;EAhGrC,IAAA;EAgGA;;;;EA1FA,MAAA,GAAS,WAAA;AAAA;;;;;;AC1CX;iBDmDgB,SAAA,CACd,OAAA,EAAS,YAAA,EACT,OAAA,GAAS,YAAA,GACR,YAAA;;;;;;;;;;;;;;;;;;;;;;iBA6Ea,yBAAA,CACd,MAAA;EAAU,OAAA,MAAa,IAAA,UAAc,OAAA,EAAS,CAAA,EAAG,IAAA,GAAO,MAAA,sBAA4B,OAAA;AAAA,KAClF,KAAA,EAAO,WAAA,EAAa,MAAA,EAAQ,KAAA,OAAY,OAAA;;;UCrI3B,kBAAA;ED+BL;EC7BV,SAAA,GAAY,cAAA;ED6BkB;EC3B9B,SAAA;EDgCA;;;;;EC1BA,QAAA;EDyCuB;;;;;ECnCvB,GAAA;IACE,IAAA,GAAO,KAAA,EAAO,WAAA,KAAgB,OAAA;IAC9B,WAAA,IAAe,OAAA,aAAoB,OAAA;EAAA;EDmC5B;;;;EC7BT,KAAA,GAAQ,IAAA,CACN,YAAA;ED0GY;;;;;EClGd,eAAA;IDoGS,gFClGP,KAAA,IAAS,KAAA,EAAO,WAAA,EAAa,MAAA,EAAQ,KAAA,cAAmB,OAAA;EAAA;EDkGT;EC/FjD,SAAA,IAAa,KAAA,EAAO,WAAA;ED8FV;EC5FV,cAAA,IAAkB,KAAA,EAAO,WAAA,EAAa,KAAA,EAAO,KAAA;AAAA;AAAA;EAAA,UAInC,eAAA;IACR,MAAA;MDuF+C,uBCrF7C,OAAA,MACE,IAAA,UACA,OAAA,EAAS,CAAA,EACT,IAAA,GAAO,OAAA,CAAQ,WAAA,cACZ,OAAA,QDiFT;MC/EI,SAAA,GACE,OAAA,UACA,OAAA,EAAS,YAAA,KACN,OAAA,cD6EP;MC3EE,aAAA;IAAA;EAAA;AAAA;AAAA,cAKA,WAAA,EAAa,kBAAA,CAAmB,kBAAA"}
|