@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
package/dist/plugins/index.js
DELETED
|
@@ -1,1069 +0,0 @@
|
|
|
1
|
-
import fp from 'fastify-plugin';
|
|
2
|
-
import { randomUUID } from 'crypto';
|
|
3
|
-
import { createRequire } from 'module';
|
|
4
|
-
|
|
5
|
-
// src/plugins/requestId.ts
|
|
6
|
-
var requestIdPlugin = async (fastify, opts = {}) => {
|
|
7
|
-
const {
|
|
8
|
-
header = "x-request-id",
|
|
9
|
-
generator = randomUUID,
|
|
10
|
-
setResponseHeader = true
|
|
11
|
-
} = opts;
|
|
12
|
-
if (!fastify.hasRequestDecorator("requestId")) {
|
|
13
|
-
fastify.decorateRequest("requestId", "");
|
|
14
|
-
}
|
|
15
|
-
fastify.addHook("onRequest", async (request) => {
|
|
16
|
-
const incomingId = request.headers[header];
|
|
17
|
-
const requestId = typeof incomingId === "string" && incomingId.trim() ? incomingId.trim() : generator();
|
|
18
|
-
request.id = requestId;
|
|
19
|
-
request.requestId = requestId;
|
|
20
|
-
});
|
|
21
|
-
if (setResponseHeader) {
|
|
22
|
-
fastify.addHook("onSend", async (request, reply) => {
|
|
23
|
-
reply.header(header, request.requestId);
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
fastify.log?.debug?.("Request ID plugin registered");
|
|
27
|
-
};
|
|
28
|
-
var requestId_default = fp(requestIdPlugin, {
|
|
29
|
-
name: "arc-request-id",
|
|
30
|
-
fastify: "5.x"
|
|
31
|
-
});
|
|
32
|
-
var httpMetrics = {
|
|
33
|
-
requestsTotal: {},
|
|
34
|
-
requestDurations: []};
|
|
35
|
-
var healthPlugin = async (fastify, opts = {}) => {
|
|
36
|
-
const {
|
|
37
|
-
prefix = "/_health",
|
|
38
|
-
checks = [],
|
|
39
|
-
metrics = false,
|
|
40
|
-
metricsCollector,
|
|
41
|
-
version,
|
|
42
|
-
collectHttpMetrics = metrics
|
|
43
|
-
} = opts;
|
|
44
|
-
fastify.get(`${prefix}/live`, {
|
|
45
|
-
schema: {
|
|
46
|
-
tags: ["Health"],
|
|
47
|
-
summary: "Liveness probe",
|
|
48
|
-
description: "Returns 200 if the process is alive",
|
|
49
|
-
response: {
|
|
50
|
-
200: {
|
|
51
|
-
type: "object",
|
|
52
|
-
properties: {
|
|
53
|
-
status: { type: "string", enum: ["ok"] },
|
|
54
|
-
timestamp: { type: "string" },
|
|
55
|
-
version: { type: "string" }
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}, async () => {
|
|
61
|
-
return {
|
|
62
|
-
status: "ok",
|
|
63
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
64
|
-
...version ? { version } : {}
|
|
65
|
-
};
|
|
66
|
-
});
|
|
67
|
-
fastify.get(`${prefix}/ready`, {
|
|
68
|
-
schema: {
|
|
69
|
-
tags: ["Health"],
|
|
70
|
-
summary: "Readiness probe",
|
|
71
|
-
description: "Returns 200 if all dependencies are healthy",
|
|
72
|
-
response: {
|
|
73
|
-
200: {
|
|
74
|
-
type: "object",
|
|
75
|
-
properties: {
|
|
76
|
-
status: { type: "string", enum: ["ready", "not_ready"] },
|
|
77
|
-
timestamp: { type: "string" },
|
|
78
|
-
checks: {
|
|
79
|
-
type: "array",
|
|
80
|
-
items: {
|
|
81
|
-
type: "object",
|
|
82
|
-
properties: {
|
|
83
|
-
name: { type: "string" },
|
|
84
|
-
healthy: { type: "boolean" },
|
|
85
|
-
duration: { type: "number" },
|
|
86
|
-
error: { type: "string" }
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
503: {
|
|
93
|
-
type: "object",
|
|
94
|
-
properties: {
|
|
95
|
-
status: { type: "string", enum: ["not_ready"] },
|
|
96
|
-
timestamp: { type: "string" },
|
|
97
|
-
checks: { type: "array" }
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}, async (_, reply) => {
|
|
103
|
-
const results = await runChecks(checks);
|
|
104
|
-
const criticalFailed = results.some(
|
|
105
|
-
(r) => !r.healthy && (checks.find((c) => c.name === r.name)?.critical ?? true)
|
|
106
|
-
);
|
|
107
|
-
const response = {
|
|
108
|
-
status: criticalFailed ? "not_ready" : "ready",
|
|
109
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
110
|
-
checks: results
|
|
111
|
-
};
|
|
112
|
-
if (criticalFailed) {
|
|
113
|
-
reply.code(503);
|
|
114
|
-
}
|
|
115
|
-
return response;
|
|
116
|
-
});
|
|
117
|
-
if (metrics) {
|
|
118
|
-
fastify.get(`${prefix}/metrics`, async (_, reply) => {
|
|
119
|
-
reply.type("text/plain; charset=utf-8");
|
|
120
|
-
if (metricsCollector) {
|
|
121
|
-
return await metricsCollector();
|
|
122
|
-
}
|
|
123
|
-
const uptime = process.uptime();
|
|
124
|
-
const memory = process.memoryUsage();
|
|
125
|
-
const cpu = process.cpuUsage();
|
|
126
|
-
const lines = [
|
|
127
|
-
"# HELP process_uptime_seconds Process uptime in seconds",
|
|
128
|
-
"# TYPE process_uptime_seconds gauge",
|
|
129
|
-
`process_uptime_seconds ${uptime.toFixed(2)}`,
|
|
130
|
-
"",
|
|
131
|
-
"# HELP process_memory_heap_bytes Heap memory usage in bytes",
|
|
132
|
-
"# TYPE process_memory_heap_bytes gauge",
|
|
133
|
-
`process_memory_heap_bytes{type="used"} ${memory.heapUsed}`,
|
|
134
|
-
`process_memory_heap_bytes{type="total"} ${memory.heapTotal}`,
|
|
135
|
-
"",
|
|
136
|
-
"# HELP process_memory_rss_bytes RSS memory in bytes",
|
|
137
|
-
"# TYPE process_memory_rss_bytes gauge",
|
|
138
|
-
`process_memory_rss_bytes ${memory.rss}`,
|
|
139
|
-
"",
|
|
140
|
-
"# HELP process_memory_external_bytes External memory in bytes",
|
|
141
|
-
"# TYPE process_memory_external_bytes gauge",
|
|
142
|
-
`process_memory_external_bytes ${memory.external}`,
|
|
143
|
-
"",
|
|
144
|
-
"# HELP process_cpu_user_microseconds User CPU time in microseconds",
|
|
145
|
-
"# TYPE process_cpu_user_microseconds counter",
|
|
146
|
-
`process_cpu_user_microseconds ${cpu.user}`,
|
|
147
|
-
"",
|
|
148
|
-
"# HELP process_cpu_system_microseconds System CPU time in microseconds",
|
|
149
|
-
"# TYPE process_cpu_system_microseconds counter",
|
|
150
|
-
`process_cpu_system_microseconds ${cpu.system}`,
|
|
151
|
-
""
|
|
152
|
-
];
|
|
153
|
-
if (collectHttpMetrics && Object.keys(httpMetrics.requestsTotal).length > 0) {
|
|
154
|
-
lines.push(
|
|
155
|
-
"# HELP http_requests_total Total HTTP requests by status code",
|
|
156
|
-
"# TYPE http_requests_total counter"
|
|
157
|
-
);
|
|
158
|
-
for (const [status, count] of Object.entries(httpMetrics.requestsTotal)) {
|
|
159
|
-
lines.push(`http_requests_total{status="${status}"} ${count}`);
|
|
160
|
-
}
|
|
161
|
-
lines.push("");
|
|
162
|
-
if (httpMetrics.requestDurations.length > 0) {
|
|
163
|
-
const sorted = [...httpMetrics.requestDurations].sort((a, b) => a - b);
|
|
164
|
-
const p50 = sorted[Math.floor(sorted.length * 0.5)] || 0;
|
|
165
|
-
const p95 = sorted[Math.floor(sorted.length * 0.95)] || 0;
|
|
166
|
-
const p99 = sorted[Math.floor(sorted.length * 0.99)] || 0;
|
|
167
|
-
const sum = sorted.reduce((a, b) => a + b, 0);
|
|
168
|
-
lines.push(
|
|
169
|
-
"# HELP http_request_duration_milliseconds HTTP request duration",
|
|
170
|
-
"# TYPE http_request_duration_milliseconds summary",
|
|
171
|
-
`http_request_duration_milliseconds{quantile="0.5"} ${p50.toFixed(2)}`,
|
|
172
|
-
`http_request_duration_milliseconds{quantile="0.95"} ${p95.toFixed(2)}`,
|
|
173
|
-
`http_request_duration_milliseconds{quantile="0.99"} ${p99.toFixed(2)}`,
|
|
174
|
-
`http_request_duration_milliseconds_sum ${sum.toFixed(2)}`,
|
|
175
|
-
`http_request_duration_milliseconds_count ${sorted.length}`,
|
|
176
|
-
""
|
|
177
|
-
);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
return lines.join("\n");
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
if (collectHttpMetrics) {
|
|
184
|
-
fastify.addHook("onRequest", async (request) => {
|
|
185
|
-
request._startTime = Date.now();
|
|
186
|
-
});
|
|
187
|
-
fastify.addHook("onResponse", async (request, reply) => {
|
|
188
|
-
const duration = Date.now() - (request._startTime || Date.now());
|
|
189
|
-
const statusBucket = `${Math.floor(reply.statusCode / 100)}xx`;
|
|
190
|
-
httpMetrics.requestsTotal[statusBucket] = (httpMetrics.requestsTotal[statusBucket] || 0) + 1;
|
|
191
|
-
httpMetrics.requestDurations.push(duration);
|
|
192
|
-
if (httpMetrics.requestDurations.length > 1e4) {
|
|
193
|
-
httpMetrics.requestDurations.shift();
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
fastify.log?.info?.(`Health plugin registered at ${prefix}`);
|
|
198
|
-
};
|
|
199
|
-
async function runChecks(checks) {
|
|
200
|
-
const results = [];
|
|
201
|
-
for (const check of checks) {
|
|
202
|
-
const start = Date.now();
|
|
203
|
-
const timeout = check.timeout ?? 5e3;
|
|
204
|
-
try {
|
|
205
|
-
const checkPromise = Promise.resolve(check.check());
|
|
206
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
207
|
-
setTimeout(() => reject(new Error("Health check timeout")), timeout);
|
|
208
|
-
});
|
|
209
|
-
const healthy = await Promise.race([checkPromise, timeoutPromise]);
|
|
210
|
-
results.push({
|
|
211
|
-
name: check.name,
|
|
212
|
-
healthy: Boolean(healthy),
|
|
213
|
-
duration: Date.now() - start
|
|
214
|
-
});
|
|
215
|
-
} catch (err) {
|
|
216
|
-
results.push({
|
|
217
|
-
name: check.name,
|
|
218
|
-
healthy: false,
|
|
219
|
-
duration: Date.now() - start,
|
|
220
|
-
error: err.message
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
return results;
|
|
225
|
-
}
|
|
226
|
-
var health_default = fp(healthPlugin, {
|
|
227
|
-
name: "arc-health",
|
|
228
|
-
fastify: "5.x"
|
|
229
|
-
});
|
|
230
|
-
var require2 = createRequire(import.meta.url);
|
|
231
|
-
var trace;
|
|
232
|
-
var context;
|
|
233
|
-
var SpanStatusCode;
|
|
234
|
-
var NodeTracerProvider;
|
|
235
|
-
var BatchSpanProcessor;
|
|
236
|
-
var OTLPTraceExporter;
|
|
237
|
-
var HttpInstrumentation;
|
|
238
|
-
var MongoDBInstrumentation;
|
|
239
|
-
var getNodeAutoInstrumentations;
|
|
240
|
-
var isAvailable = false;
|
|
241
|
-
try {
|
|
242
|
-
const api = require2("@opentelemetry/api");
|
|
243
|
-
trace = api.trace;
|
|
244
|
-
context = api.context;
|
|
245
|
-
SpanStatusCode = api.SpanStatusCode;
|
|
246
|
-
const sdkNode = require2("@opentelemetry/sdk-node");
|
|
247
|
-
NodeTracerProvider = sdkNode.NodeTracerProvider;
|
|
248
|
-
BatchSpanProcessor = sdkNode.BatchSpanProcessor;
|
|
249
|
-
const exporterTraceOtlp = require2("@opentelemetry/exporter-trace-otlp-http");
|
|
250
|
-
OTLPTraceExporter = exporterTraceOtlp.OTLPTraceExporter;
|
|
251
|
-
const instrHttp = require2("@opentelemetry/instrumentation-http");
|
|
252
|
-
HttpInstrumentation = instrHttp.HttpInstrumentation;
|
|
253
|
-
const instrMongo = require2("@opentelemetry/instrumentation-mongodb");
|
|
254
|
-
MongoDBInstrumentation = instrMongo.MongoDBInstrumentation;
|
|
255
|
-
const autoInstr = require2("@opentelemetry/auto-instrumentations-node");
|
|
256
|
-
getNodeAutoInstrumentations = autoInstr.getNodeAutoInstrumentations;
|
|
257
|
-
isAvailable = true;
|
|
258
|
-
} catch (e) {
|
|
259
|
-
}
|
|
260
|
-
function createTracerProvider(options) {
|
|
261
|
-
if (!isAvailable) {
|
|
262
|
-
return null;
|
|
263
|
-
}
|
|
264
|
-
const { serviceName = "@classytic/arc", exporterUrl = "http://localhost:4318/v1/traces" } = options;
|
|
265
|
-
const exporter = new OTLPTraceExporter({
|
|
266
|
-
url: exporterUrl
|
|
267
|
-
});
|
|
268
|
-
const provider = new NodeTracerProvider({
|
|
269
|
-
resource: {
|
|
270
|
-
attributes: {
|
|
271
|
-
"service.name": serviceName,
|
|
272
|
-
"service.version": "1.0.0"
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
});
|
|
276
|
-
provider.addSpanProcessor(new BatchSpanProcessor(exporter));
|
|
277
|
-
provider.register();
|
|
278
|
-
return provider;
|
|
279
|
-
}
|
|
280
|
-
async function tracingPlugin(fastify, options = {}) {
|
|
281
|
-
const {
|
|
282
|
-
serviceName = "@classytic/arc",
|
|
283
|
-
autoInstrumentation = true,
|
|
284
|
-
traceRepository = true,
|
|
285
|
-
traceController = true,
|
|
286
|
-
sampleRate = 1
|
|
287
|
-
} = options;
|
|
288
|
-
if (!isAvailable) {
|
|
289
|
-
fastify.log.warn("OpenTelemetry not installed. Tracing disabled.");
|
|
290
|
-
fastify.log.warn("Install: npm install @opentelemetry/api @opentelemetry/sdk-node");
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
const provider = createTracerProvider(options);
|
|
294
|
-
if (!provider) {
|
|
295
|
-
return;
|
|
296
|
-
}
|
|
297
|
-
if (autoInstrumentation && getNodeAutoInstrumentations) {
|
|
298
|
-
getNodeAutoInstrumentations({
|
|
299
|
-
"@opentelemetry/instrumentation-http": {
|
|
300
|
-
enabled: true
|
|
301
|
-
},
|
|
302
|
-
"@opentelemetry/instrumentation-mongodb": {
|
|
303
|
-
enabled: true
|
|
304
|
-
}
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
const tracer = trace.getTracer(serviceName);
|
|
308
|
-
fastify.decorateRequest("tracer", void 0);
|
|
309
|
-
fastify.addHook("onRequest", async (request, reply) => {
|
|
310
|
-
if (Math.random() > sampleRate) {
|
|
311
|
-
return;
|
|
312
|
-
}
|
|
313
|
-
const span = tracer.startSpan(`HTTP ${request.method} ${request.url}`, {
|
|
314
|
-
kind: 1,
|
|
315
|
-
// SpanKind.SERVER
|
|
316
|
-
attributes: {
|
|
317
|
-
"http.method": request.method,
|
|
318
|
-
"http.url": request.url,
|
|
319
|
-
"http.target": request.routeOptions?.url ?? request.url,
|
|
320
|
-
"http.host": request.hostname,
|
|
321
|
-
"http.scheme": request.protocol,
|
|
322
|
-
"http.user_agent": request.headers["user-agent"]
|
|
323
|
-
}
|
|
324
|
-
});
|
|
325
|
-
request.tracer = {
|
|
326
|
-
tracer,
|
|
327
|
-
currentSpan: span
|
|
328
|
-
};
|
|
329
|
-
context.with(trace.setSpan(context.active(), span), () => {
|
|
330
|
-
});
|
|
331
|
-
});
|
|
332
|
-
fastify.addHook("onResponse", async (request, reply) => {
|
|
333
|
-
if (!request.tracer?.currentSpan) {
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
|
-
const span = request.tracer.currentSpan;
|
|
337
|
-
span.setAttributes({
|
|
338
|
-
"http.status_code": reply.statusCode,
|
|
339
|
-
"http.response_content_length": reply.getHeader("content-length")
|
|
340
|
-
});
|
|
341
|
-
if (reply.statusCode >= 500) {
|
|
342
|
-
span.setStatus({
|
|
343
|
-
code: SpanStatusCode.ERROR,
|
|
344
|
-
message: `HTTP ${reply.statusCode}`
|
|
345
|
-
});
|
|
346
|
-
} else {
|
|
347
|
-
span.setStatus({ code: SpanStatusCode.OK });
|
|
348
|
-
}
|
|
349
|
-
span.end();
|
|
350
|
-
});
|
|
351
|
-
fastify.addHook("onError", async (request, reply, error) => {
|
|
352
|
-
if (!request.tracer?.currentSpan) {
|
|
353
|
-
return;
|
|
354
|
-
}
|
|
355
|
-
const span = request.tracer.currentSpan;
|
|
356
|
-
span.recordException(error);
|
|
357
|
-
span.setStatus({
|
|
358
|
-
code: SpanStatusCode.ERROR,
|
|
359
|
-
message: error.message
|
|
360
|
-
});
|
|
361
|
-
});
|
|
362
|
-
fastify.log.info({ serviceName }, "OpenTelemetry tracing enabled");
|
|
363
|
-
}
|
|
364
|
-
function createSpan(request, name, fn, attributes) {
|
|
365
|
-
if (!isAvailable || !request.tracer) {
|
|
366
|
-
return fn(null);
|
|
367
|
-
}
|
|
368
|
-
const { tracer, currentSpan } = request.tracer;
|
|
369
|
-
const span = tracer.startSpan(
|
|
370
|
-
name,
|
|
371
|
-
{
|
|
372
|
-
parent: currentSpan,
|
|
373
|
-
attributes: attributes || {}
|
|
374
|
-
},
|
|
375
|
-
trace.setSpan(context.active(), currentSpan)
|
|
376
|
-
);
|
|
377
|
-
return context.with(trace.setSpan(context.active(), span), async () => {
|
|
378
|
-
try {
|
|
379
|
-
const result = await fn(span);
|
|
380
|
-
span.setStatus({ code: SpanStatusCode.OK });
|
|
381
|
-
return result;
|
|
382
|
-
} catch (error) {
|
|
383
|
-
span.recordException(error);
|
|
384
|
-
span.setStatus({
|
|
385
|
-
code: SpanStatusCode.ERROR,
|
|
386
|
-
message: error.message
|
|
387
|
-
});
|
|
388
|
-
throw error;
|
|
389
|
-
} finally {
|
|
390
|
-
span.end();
|
|
391
|
-
}
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
function traced(spanName) {
|
|
395
|
-
return function(target, propertyKey, descriptor) {
|
|
396
|
-
const originalMethod = descriptor.value;
|
|
397
|
-
descriptor.value = async function(...args) {
|
|
398
|
-
const request = args.find((arg) => arg && arg.tracer);
|
|
399
|
-
if (!request?.tracer) {
|
|
400
|
-
return originalMethod.apply(this, args);
|
|
401
|
-
}
|
|
402
|
-
const name = spanName || `${target.constructor.name}.${propertyKey}`;
|
|
403
|
-
return createSpan(request, name, async (span) => {
|
|
404
|
-
if (span) {
|
|
405
|
-
span.setAttribute("db.operation", propertyKey);
|
|
406
|
-
span.setAttribute("db.system", "mongodb");
|
|
407
|
-
}
|
|
408
|
-
return originalMethod.apply(this, args);
|
|
409
|
-
});
|
|
410
|
-
};
|
|
411
|
-
return descriptor;
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
function isTracingAvailable() {
|
|
415
|
-
return isAvailable;
|
|
416
|
-
}
|
|
417
|
-
var tracing_default = fp(tracingPlugin, {
|
|
418
|
-
name: "arc-tracing",
|
|
419
|
-
fastify: "5.x"
|
|
420
|
-
});
|
|
421
|
-
var gracefulShutdownPlugin = async (fastify, opts = {}) => {
|
|
422
|
-
const {
|
|
423
|
-
timeout = 3e4,
|
|
424
|
-
onShutdown,
|
|
425
|
-
signals = ["SIGTERM", "SIGINT"],
|
|
426
|
-
logEvents = true
|
|
427
|
-
} = opts;
|
|
428
|
-
let isShuttingDown = false;
|
|
429
|
-
const shutdown = async (signal) => {
|
|
430
|
-
if (isShuttingDown) {
|
|
431
|
-
if (logEvents) {
|
|
432
|
-
fastify.log?.warn?.({ signal }, "Shutdown already in progress, ignoring signal");
|
|
433
|
-
}
|
|
434
|
-
return;
|
|
435
|
-
}
|
|
436
|
-
isShuttingDown = true;
|
|
437
|
-
if (logEvents) {
|
|
438
|
-
fastify.log?.info?.({ signal, timeout }, "Shutdown signal received, starting graceful shutdown");
|
|
439
|
-
}
|
|
440
|
-
const forceExitTimer = setTimeout(() => {
|
|
441
|
-
if (logEvents) {
|
|
442
|
-
fastify.log?.error?.("Graceful shutdown timeout exceeded, forcing exit");
|
|
443
|
-
}
|
|
444
|
-
process.exit(1);
|
|
445
|
-
}, timeout);
|
|
446
|
-
forceExitTimer.unref();
|
|
447
|
-
try {
|
|
448
|
-
if (logEvents) {
|
|
449
|
-
fastify.log?.info?.("Closing server to new connections");
|
|
450
|
-
}
|
|
451
|
-
await fastify.close();
|
|
452
|
-
if (onShutdown) {
|
|
453
|
-
if (logEvents) {
|
|
454
|
-
fastify.log?.info?.("Running custom shutdown handler");
|
|
455
|
-
}
|
|
456
|
-
await onShutdown();
|
|
457
|
-
}
|
|
458
|
-
if (logEvents) {
|
|
459
|
-
fastify.log?.info?.("Graceful shutdown complete");
|
|
460
|
-
}
|
|
461
|
-
clearTimeout(forceExitTimer);
|
|
462
|
-
process.exit(0);
|
|
463
|
-
} catch (err) {
|
|
464
|
-
if (logEvents) {
|
|
465
|
-
fastify.log?.error?.({ error: err.message }, "Error during shutdown");
|
|
466
|
-
}
|
|
467
|
-
clearTimeout(forceExitTimer);
|
|
468
|
-
process.exit(1);
|
|
469
|
-
}
|
|
470
|
-
};
|
|
471
|
-
for (const signal of signals) {
|
|
472
|
-
process.on(signal, () => {
|
|
473
|
-
void shutdown(signal);
|
|
474
|
-
});
|
|
475
|
-
}
|
|
476
|
-
fastify.decorate("shutdown", async () => {
|
|
477
|
-
await shutdown("MANUAL");
|
|
478
|
-
});
|
|
479
|
-
if (logEvents) {
|
|
480
|
-
fastify.log?.debug?.({ signals }, "Graceful shutdown plugin registered");
|
|
481
|
-
}
|
|
482
|
-
};
|
|
483
|
-
var gracefulShutdown_default = fp(gracefulShutdownPlugin, {
|
|
484
|
-
name: "arc-graceful-shutdown",
|
|
485
|
-
fastify: "5.x"
|
|
486
|
-
});
|
|
487
|
-
|
|
488
|
-
// src/utils/errors.ts
|
|
489
|
-
var ArcError = class extends Error {
|
|
490
|
-
name;
|
|
491
|
-
code;
|
|
492
|
-
statusCode;
|
|
493
|
-
details;
|
|
494
|
-
cause;
|
|
495
|
-
timestamp;
|
|
496
|
-
requestId;
|
|
497
|
-
constructor(message, options = {}) {
|
|
498
|
-
super(message);
|
|
499
|
-
this.name = "ArcError";
|
|
500
|
-
this.code = options.code ?? "ARC_ERROR";
|
|
501
|
-
this.statusCode = options.statusCode ?? 500;
|
|
502
|
-
this.details = options.details;
|
|
503
|
-
this.cause = options.cause;
|
|
504
|
-
this.timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
505
|
-
this.requestId = options.requestId;
|
|
506
|
-
if (Error.captureStackTrace) {
|
|
507
|
-
Error.captureStackTrace(this, this.constructor);
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
/**
|
|
511
|
-
* Set request ID (typically from request context)
|
|
512
|
-
*/
|
|
513
|
-
withRequestId(requestId) {
|
|
514
|
-
this.requestId = requestId;
|
|
515
|
-
return this;
|
|
516
|
-
}
|
|
517
|
-
/**
|
|
518
|
-
* Convert to JSON response
|
|
519
|
-
*/
|
|
520
|
-
toJSON() {
|
|
521
|
-
return {
|
|
522
|
-
success: false,
|
|
523
|
-
error: this.message,
|
|
524
|
-
code: this.code,
|
|
525
|
-
timestamp: this.timestamp,
|
|
526
|
-
...this.requestId && { requestId: this.requestId },
|
|
527
|
-
...this.details && { details: this.details }
|
|
528
|
-
};
|
|
529
|
-
}
|
|
530
|
-
};
|
|
531
|
-
function isArcError(error) {
|
|
532
|
-
return error instanceof ArcError;
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
// src/plugins/errorHandler.ts
|
|
536
|
-
async function errorHandlerPluginFn(fastify, options = {}) {
|
|
537
|
-
const {
|
|
538
|
-
includeStack = process.env.NODE_ENV !== "production",
|
|
539
|
-
onError,
|
|
540
|
-
errorMap = {}
|
|
541
|
-
} = options;
|
|
542
|
-
fastify.setErrorHandler(async (error, request, reply) => {
|
|
543
|
-
if (onError) {
|
|
544
|
-
try {
|
|
545
|
-
await onError(error, request);
|
|
546
|
-
} catch (callbackError) {
|
|
547
|
-
request.log.error({ err: callbackError }, "Error in onError callback");
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
const requestId = request.id;
|
|
551
|
-
const response = {
|
|
552
|
-
success: false,
|
|
553
|
-
error: error.message || "Internal Server Error",
|
|
554
|
-
code: "INTERNAL_ERROR",
|
|
555
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
556
|
-
...requestId && { requestId }
|
|
557
|
-
};
|
|
558
|
-
let statusCode = 500;
|
|
559
|
-
if (isArcError(error)) {
|
|
560
|
-
statusCode = error.statusCode;
|
|
561
|
-
response.code = error.code;
|
|
562
|
-
if (error.details) {
|
|
563
|
-
response.details = error.details;
|
|
564
|
-
}
|
|
565
|
-
if (error.requestId) {
|
|
566
|
-
response.requestId = error.requestId;
|
|
567
|
-
}
|
|
568
|
-
} else if ("validation" in error && Array.isArray(error.validation)) {
|
|
569
|
-
statusCode = 400;
|
|
570
|
-
response.code = "VALIDATION_ERROR";
|
|
571
|
-
response.error = "Validation failed";
|
|
572
|
-
response.details = {
|
|
573
|
-
errors: error.validation?.map((v) => ({
|
|
574
|
-
field: v.instancePath?.replace(/^\//, "") || v.params?.missingProperty || "unknown",
|
|
575
|
-
message: v.message || "Invalid value",
|
|
576
|
-
keyword: v.keyword
|
|
577
|
-
}))
|
|
578
|
-
};
|
|
579
|
-
} else if ("statusCode" in error && typeof error.statusCode === "number") {
|
|
580
|
-
statusCode = error.statusCode;
|
|
581
|
-
response.code = statusCodeToCode(statusCode);
|
|
582
|
-
} else if (error.name && errorMap[error.name]) {
|
|
583
|
-
const mapping = errorMap[error.name];
|
|
584
|
-
statusCode = mapping.statusCode;
|
|
585
|
-
response.code = mapping.code;
|
|
586
|
-
if (mapping.message) {
|
|
587
|
-
response.error = mapping.message;
|
|
588
|
-
}
|
|
589
|
-
} else if (error.name === "ValidationError" && "errors" in error) {
|
|
590
|
-
statusCode = 400;
|
|
591
|
-
response.code = "VALIDATION_ERROR";
|
|
592
|
-
const mongooseErrors = error.errors;
|
|
593
|
-
if (process.env.NODE_ENV === "production") {
|
|
594
|
-
response.details = { errorCount: Object.keys(mongooseErrors).length };
|
|
595
|
-
} else {
|
|
596
|
-
response.details = {
|
|
597
|
-
errors: Object.entries(mongooseErrors).map(([field, err]) => ({
|
|
598
|
-
field: err.path || field,
|
|
599
|
-
message: err.message
|
|
600
|
-
}))
|
|
601
|
-
};
|
|
602
|
-
}
|
|
603
|
-
} else if (error.name === "CastError") {
|
|
604
|
-
statusCode = 400;
|
|
605
|
-
response.code = "INVALID_ID";
|
|
606
|
-
response.error = "Invalid identifier format";
|
|
607
|
-
} else if (error.name === "MongoServerError" && error.code === 11e3) {
|
|
608
|
-
statusCode = 409;
|
|
609
|
-
response.code = "DUPLICATE_KEY";
|
|
610
|
-
response.error = "Resource already exists";
|
|
611
|
-
const keyValue = error.keyValue;
|
|
612
|
-
if (keyValue && process.env.NODE_ENV !== "production") {
|
|
613
|
-
response.details = { duplicateFields: Object.keys(keyValue) };
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
if (includeStack && error.stack) {
|
|
617
|
-
response.stack = error.stack;
|
|
618
|
-
}
|
|
619
|
-
if (statusCode >= 500) {
|
|
620
|
-
request.log.error({ err: error, statusCode }, "Server error");
|
|
621
|
-
} else if (statusCode >= 400) {
|
|
622
|
-
request.log.warn({ err: error, statusCode }, "Client error");
|
|
623
|
-
}
|
|
624
|
-
return reply.status(statusCode).send(response);
|
|
625
|
-
});
|
|
626
|
-
}
|
|
627
|
-
function statusCodeToCode(statusCode) {
|
|
628
|
-
const codes = {
|
|
629
|
-
400: "BAD_REQUEST",
|
|
630
|
-
401: "UNAUTHORIZED",
|
|
631
|
-
403: "FORBIDDEN",
|
|
632
|
-
404: "NOT_FOUND",
|
|
633
|
-
405: "METHOD_NOT_ALLOWED",
|
|
634
|
-
409: "CONFLICT",
|
|
635
|
-
422: "UNPROCESSABLE_ENTITY",
|
|
636
|
-
429: "RATE_LIMITED",
|
|
637
|
-
500: "INTERNAL_ERROR",
|
|
638
|
-
502: "BAD_GATEWAY",
|
|
639
|
-
503: "SERVICE_UNAVAILABLE",
|
|
640
|
-
504: "GATEWAY_TIMEOUT"
|
|
641
|
-
};
|
|
642
|
-
return codes[statusCode] ?? "ERROR";
|
|
643
|
-
}
|
|
644
|
-
var errorHandlerPlugin = fp(errorHandlerPluginFn, {
|
|
645
|
-
name: "arc-error-handler",
|
|
646
|
-
fastify: "5.x"
|
|
647
|
-
});
|
|
648
|
-
var errorHandler_default = errorHandlerPlugin;
|
|
649
|
-
|
|
650
|
-
// src/hooks/HookSystem.ts
|
|
651
|
-
var HookSystem = class {
|
|
652
|
-
hooks;
|
|
653
|
-
logger;
|
|
654
|
-
constructor(options) {
|
|
655
|
-
this.hooks = /* @__PURE__ */ new Map();
|
|
656
|
-
this.logger = options?.logger ?? { error: (...args) => console.error(...args) };
|
|
657
|
-
}
|
|
658
|
-
/**
|
|
659
|
-
* Generate hook key
|
|
660
|
-
*/
|
|
661
|
-
getKey(resource, operation, phase) {
|
|
662
|
-
return `${resource}:${operation}:${phase}`;
|
|
663
|
-
}
|
|
664
|
-
/**
|
|
665
|
-
* Register a hook
|
|
666
|
-
* Supports both object parameter and positional arguments
|
|
667
|
-
*/
|
|
668
|
-
register(resourceOrOptions, operation, phase, handler, priority = 10) {
|
|
669
|
-
let resource;
|
|
670
|
-
let finalOperation;
|
|
671
|
-
let finalPhase;
|
|
672
|
-
let finalHandler;
|
|
673
|
-
let finalPriority;
|
|
674
|
-
if (typeof resourceOrOptions === "object") {
|
|
675
|
-
resource = resourceOrOptions.resource;
|
|
676
|
-
finalOperation = resourceOrOptions.operation;
|
|
677
|
-
finalPhase = resourceOrOptions.phase;
|
|
678
|
-
finalHandler = resourceOrOptions.handler;
|
|
679
|
-
finalPriority = resourceOrOptions.priority ?? 10;
|
|
680
|
-
} else {
|
|
681
|
-
resource = resourceOrOptions;
|
|
682
|
-
finalOperation = operation;
|
|
683
|
-
finalPhase = phase;
|
|
684
|
-
finalHandler = handler;
|
|
685
|
-
finalPriority = priority;
|
|
686
|
-
}
|
|
687
|
-
const key = this.getKey(resource, finalOperation, finalPhase);
|
|
688
|
-
if (!this.hooks.has(key)) {
|
|
689
|
-
this.hooks.set(key, []);
|
|
690
|
-
}
|
|
691
|
-
const registration = {
|
|
692
|
-
resource,
|
|
693
|
-
operation: finalOperation,
|
|
694
|
-
phase: finalPhase,
|
|
695
|
-
handler: finalHandler,
|
|
696
|
-
priority: finalPriority
|
|
697
|
-
};
|
|
698
|
-
const hooks = this.hooks.get(key);
|
|
699
|
-
hooks.push(registration);
|
|
700
|
-
hooks.sort((a, b) => a.priority - b.priority);
|
|
701
|
-
return () => {
|
|
702
|
-
const idx = hooks.indexOf(registration);
|
|
703
|
-
if (idx !== -1) {
|
|
704
|
-
hooks.splice(idx, 1);
|
|
705
|
-
}
|
|
706
|
-
};
|
|
707
|
-
}
|
|
708
|
-
/**
|
|
709
|
-
* Register before hook
|
|
710
|
-
*/
|
|
711
|
-
before(resource, operation, handler, priority = 10) {
|
|
712
|
-
return this.register(resource, operation, "before", handler, priority);
|
|
713
|
-
}
|
|
714
|
-
/**
|
|
715
|
-
* Register after hook
|
|
716
|
-
*/
|
|
717
|
-
after(resource, operation, handler, priority = 10) {
|
|
718
|
-
return this.register(resource, operation, "after", handler, priority);
|
|
719
|
-
}
|
|
720
|
-
/**
|
|
721
|
-
* Execute hooks for a given context
|
|
722
|
-
*/
|
|
723
|
-
async execute(ctx) {
|
|
724
|
-
const key = this.getKey(ctx.resource, ctx.operation, ctx.phase);
|
|
725
|
-
const hooks = this.hooks.get(key) ?? [];
|
|
726
|
-
const wildcardKey = this.getKey("*", ctx.operation, ctx.phase);
|
|
727
|
-
const wildcardHooks = this.hooks.get(wildcardKey) ?? [];
|
|
728
|
-
const allHooks = [...wildcardHooks, ...hooks];
|
|
729
|
-
allHooks.sort((a, b) => a.priority - b.priority);
|
|
730
|
-
let result = ctx.data;
|
|
731
|
-
for (const hook of allHooks) {
|
|
732
|
-
const handlerContext = {
|
|
733
|
-
resource: ctx.resource,
|
|
734
|
-
operation: ctx.operation,
|
|
735
|
-
phase: ctx.phase,
|
|
736
|
-
data: result,
|
|
737
|
-
result: ctx.result,
|
|
738
|
-
user: ctx.user,
|
|
739
|
-
context: ctx.context,
|
|
740
|
-
meta: ctx.meta
|
|
741
|
-
};
|
|
742
|
-
const hookResult = await hook.handler(handlerContext);
|
|
743
|
-
if (hookResult !== void 0 && hookResult !== null) {
|
|
744
|
-
result = hookResult;
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
return result;
|
|
748
|
-
}
|
|
749
|
-
/**
|
|
750
|
-
* Execute before hooks
|
|
751
|
-
*/
|
|
752
|
-
async executeBefore(resource, operation, data, options) {
|
|
753
|
-
const result = await this.execute({
|
|
754
|
-
resource,
|
|
755
|
-
operation,
|
|
756
|
-
phase: "before",
|
|
757
|
-
data,
|
|
758
|
-
user: options?.user,
|
|
759
|
-
context: options?.context,
|
|
760
|
-
meta: options?.meta
|
|
761
|
-
});
|
|
762
|
-
return result ?? data;
|
|
763
|
-
}
|
|
764
|
-
/**
|
|
765
|
-
* Execute after hooks
|
|
766
|
-
* Errors in after hooks are logged but don't fail the request
|
|
767
|
-
*/
|
|
768
|
-
async executeAfter(resource, operation, result, options) {
|
|
769
|
-
try {
|
|
770
|
-
await this.execute({
|
|
771
|
-
resource,
|
|
772
|
-
operation,
|
|
773
|
-
phase: "after",
|
|
774
|
-
result,
|
|
775
|
-
user: options?.user,
|
|
776
|
-
context: options?.context,
|
|
777
|
-
meta: options?.meta
|
|
778
|
-
});
|
|
779
|
-
} catch (error) {
|
|
780
|
-
this.logger.error(
|
|
781
|
-
`[HookSystem] Error in after hook for ${resource}:${operation}:`,
|
|
782
|
-
error
|
|
783
|
-
);
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
/**
|
|
787
|
-
* Get all registered hooks
|
|
788
|
-
*/
|
|
789
|
-
getAll() {
|
|
790
|
-
const all = [];
|
|
791
|
-
for (const hooks of this.hooks.values()) {
|
|
792
|
-
all.push(...hooks);
|
|
793
|
-
}
|
|
794
|
-
return all;
|
|
795
|
-
}
|
|
796
|
-
/**
|
|
797
|
-
* Get hooks for a specific resource
|
|
798
|
-
*/
|
|
799
|
-
getForResource(resource) {
|
|
800
|
-
const all = [];
|
|
801
|
-
for (const [key, hooks] of this.hooks.entries()) {
|
|
802
|
-
if (key.startsWith(`${resource}:`)) {
|
|
803
|
-
all.push(...hooks);
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
return all;
|
|
807
|
-
}
|
|
808
|
-
/**
|
|
809
|
-
* Clear all hooks
|
|
810
|
-
*/
|
|
811
|
-
clear() {
|
|
812
|
-
this.hooks.clear();
|
|
813
|
-
}
|
|
814
|
-
/**
|
|
815
|
-
* Clear hooks for a specific resource
|
|
816
|
-
*/
|
|
817
|
-
clearResource(resource) {
|
|
818
|
-
for (const key of this.hooks.keys()) {
|
|
819
|
-
if (key.startsWith(`${resource}:`)) {
|
|
820
|
-
this.hooks.delete(key);
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
};
|
|
825
|
-
var hookSystem = new HookSystem();
|
|
826
|
-
|
|
827
|
-
// src/registry/ResourceRegistry.ts
|
|
828
|
-
var ResourceRegistry = class {
|
|
829
|
-
_resources;
|
|
830
|
-
_frozen;
|
|
831
|
-
constructor() {
|
|
832
|
-
this._resources = /* @__PURE__ */ new Map();
|
|
833
|
-
this._frozen = false;
|
|
834
|
-
}
|
|
835
|
-
/**
|
|
836
|
-
* Register a resource
|
|
837
|
-
*/
|
|
838
|
-
register(resource, options = {}) {
|
|
839
|
-
if (this._frozen) {
|
|
840
|
-
throw new Error(
|
|
841
|
-
`Registry frozen. Cannot register '${resource.name}' after startup.`
|
|
842
|
-
);
|
|
843
|
-
}
|
|
844
|
-
if (this._resources.has(resource.name)) {
|
|
845
|
-
throw new Error(`Resource '${resource.name}' already registered.`);
|
|
846
|
-
}
|
|
847
|
-
const entry = {
|
|
848
|
-
name: resource.name,
|
|
849
|
-
displayName: resource.displayName,
|
|
850
|
-
tag: resource.tag,
|
|
851
|
-
prefix: resource.prefix,
|
|
852
|
-
module: options.module ?? void 0,
|
|
853
|
-
adapter: resource.adapter ? {
|
|
854
|
-
type: resource.adapter.type,
|
|
855
|
-
name: resource.adapter.name
|
|
856
|
-
} : null,
|
|
857
|
-
permissions: resource.permissions,
|
|
858
|
-
presets: resource._appliedPresets ?? [],
|
|
859
|
-
routes: [],
|
|
860
|
-
// Populated later by getIntrospection()
|
|
861
|
-
additionalRoutes: resource.additionalRoutes.map((r) => ({
|
|
862
|
-
method: r.method,
|
|
863
|
-
path: r.path,
|
|
864
|
-
handler: typeof r.handler === "string" ? r.handler : r.handler.name || "anonymous",
|
|
865
|
-
summary: r.summary,
|
|
866
|
-
description: r.description,
|
|
867
|
-
permissions: r.permissions,
|
|
868
|
-
wrapHandler: r.wrapHandler,
|
|
869
|
-
schema: r.schema
|
|
870
|
-
// Include schema for OpenAPI docs
|
|
871
|
-
})),
|
|
872
|
-
events: Object.keys(resource.events ?? {}),
|
|
873
|
-
registeredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
874
|
-
disableDefaultRoutes: resource.disableDefaultRoutes,
|
|
875
|
-
openApiSchemas: options.openApiSchemas,
|
|
876
|
-
plugin: resource.toPlugin()
|
|
877
|
-
// Store plugin factory
|
|
878
|
-
};
|
|
879
|
-
this._resources.set(resource.name, entry);
|
|
880
|
-
return this;
|
|
881
|
-
}
|
|
882
|
-
/**
|
|
883
|
-
* Get resource by name
|
|
884
|
-
*/
|
|
885
|
-
get(name) {
|
|
886
|
-
return this._resources.get(name);
|
|
887
|
-
}
|
|
888
|
-
/**
|
|
889
|
-
* Get all resources
|
|
890
|
-
*/
|
|
891
|
-
getAll() {
|
|
892
|
-
return Array.from(this._resources.values());
|
|
893
|
-
}
|
|
894
|
-
/**
|
|
895
|
-
* Get resources by module
|
|
896
|
-
*/
|
|
897
|
-
getByModule(moduleName) {
|
|
898
|
-
return this.getAll().filter((r) => r.module === moduleName);
|
|
899
|
-
}
|
|
900
|
-
/**
|
|
901
|
-
* Get resources by preset
|
|
902
|
-
*/
|
|
903
|
-
getByPreset(presetName) {
|
|
904
|
-
return this.getAll().filter((r) => r.presets.includes(presetName));
|
|
905
|
-
}
|
|
906
|
-
/**
|
|
907
|
-
* Check if resource exists
|
|
908
|
-
*/
|
|
909
|
-
has(name) {
|
|
910
|
-
return this._resources.has(name);
|
|
911
|
-
}
|
|
912
|
-
/**
|
|
913
|
-
* Get registry statistics
|
|
914
|
-
*/
|
|
915
|
-
getStats() {
|
|
916
|
-
const resources = this.getAll();
|
|
917
|
-
const presetCounts = {};
|
|
918
|
-
for (const r of resources) {
|
|
919
|
-
for (const preset of r.presets) {
|
|
920
|
-
presetCounts[preset] = (presetCounts[preset] ?? 0) + 1;
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
return {
|
|
924
|
-
totalResources: resources.length,
|
|
925
|
-
byModule: this._groupBy(resources, "module"),
|
|
926
|
-
presetUsage: presetCounts,
|
|
927
|
-
totalRoutes: resources.reduce((sum, r) => {
|
|
928
|
-
const defaultRouteCount = r.disableDefaultRoutes ? 0 : 5;
|
|
929
|
-
return sum + (r.additionalRoutes?.length ?? 0) + defaultRouteCount;
|
|
930
|
-
}, 0),
|
|
931
|
-
totalEvents: resources.reduce((sum, r) => sum + (r.events?.length ?? 0), 0)
|
|
932
|
-
};
|
|
933
|
-
}
|
|
934
|
-
/**
|
|
935
|
-
* Get full introspection data
|
|
936
|
-
*/
|
|
937
|
-
getIntrospection() {
|
|
938
|
-
return {
|
|
939
|
-
resources: this.getAll().map((r) => {
|
|
940
|
-
const defaultRoutes = r.disableDefaultRoutes ? [] : [
|
|
941
|
-
{ method: "GET", path: r.prefix, operation: "list" },
|
|
942
|
-
{ method: "GET", path: `${r.prefix}/:id`, operation: "get" },
|
|
943
|
-
{ method: "POST", path: r.prefix, operation: "create" },
|
|
944
|
-
{ method: "PATCH", path: `${r.prefix}/:id`, operation: "update" },
|
|
945
|
-
{ method: "DELETE", path: `${r.prefix}/:id`, operation: "delete" }
|
|
946
|
-
];
|
|
947
|
-
return {
|
|
948
|
-
name: r.name,
|
|
949
|
-
displayName: r.displayName,
|
|
950
|
-
prefix: r.prefix,
|
|
951
|
-
module: r.module,
|
|
952
|
-
presets: r.presets,
|
|
953
|
-
permissions: r.permissions,
|
|
954
|
-
routes: [
|
|
955
|
-
...defaultRoutes,
|
|
956
|
-
...r.additionalRoutes?.map((ar) => ({
|
|
957
|
-
method: ar.method,
|
|
958
|
-
path: `${r.prefix}${ar.path}`,
|
|
959
|
-
operation: typeof ar.handler === "string" ? ar.handler : "custom",
|
|
960
|
-
handler: typeof ar.handler === "string" ? ar.handler : void 0,
|
|
961
|
-
summary: ar.summary
|
|
962
|
-
})) ?? []
|
|
963
|
-
],
|
|
964
|
-
events: r.events
|
|
965
|
-
};
|
|
966
|
-
}),
|
|
967
|
-
stats: this.getStats(),
|
|
968
|
-
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
969
|
-
};
|
|
970
|
-
}
|
|
971
|
-
/**
|
|
972
|
-
* Freeze registry (prevent further registrations)
|
|
973
|
-
*/
|
|
974
|
-
freeze() {
|
|
975
|
-
this._frozen = true;
|
|
976
|
-
}
|
|
977
|
-
/**
|
|
978
|
-
* Check if frozen
|
|
979
|
-
*/
|
|
980
|
-
isFrozen() {
|
|
981
|
-
return this._frozen;
|
|
982
|
-
}
|
|
983
|
-
/**
|
|
984
|
-
* Unfreeze registry (for testing)
|
|
985
|
-
*/
|
|
986
|
-
_unfreeze() {
|
|
987
|
-
this._frozen = false;
|
|
988
|
-
}
|
|
989
|
-
/**
|
|
990
|
-
* Clear all resources (for testing)
|
|
991
|
-
*/
|
|
992
|
-
_clear() {
|
|
993
|
-
this._resources.clear();
|
|
994
|
-
this._frozen = false;
|
|
995
|
-
}
|
|
996
|
-
/**
|
|
997
|
-
* Group by key
|
|
998
|
-
*/
|
|
999
|
-
_groupBy(arr, key) {
|
|
1000
|
-
const result = {};
|
|
1001
|
-
for (const item of arr) {
|
|
1002
|
-
const k = String(item[key] ?? "uncategorized");
|
|
1003
|
-
result[k] = (result[k] ?? 0) + 1;
|
|
1004
|
-
}
|
|
1005
|
-
return result;
|
|
1006
|
-
}
|
|
1007
|
-
};
|
|
1008
|
-
var registryKey = /* @__PURE__ */ Symbol.for("arc.resourceRegistry");
|
|
1009
|
-
var globalScope = globalThis;
|
|
1010
|
-
var resourceRegistry = globalScope[registryKey] ?? new ResourceRegistry();
|
|
1011
|
-
if (!globalScope[registryKey]) {
|
|
1012
|
-
globalScope[registryKey] = resourceRegistry;
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
// src/core/arcCorePlugin.ts
|
|
1016
|
-
function hasEvents(instance) {
|
|
1017
|
-
return "events" in instance && instance.events != null && typeof instance.events.publish === "function";
|
|
1018
|
-
}
|
|
1019
|
-
var arcCorePlugin = async (fastify, opts = {}) => {
|
|
1020
|
-
const {
|
|
1021
|
-
emitEvents = true,
|
|
1022
|
-
hookSystem: hookSystem2,
|
|
1023
|
-
registry,
|
|
1024
|
-
useGlobalSingletons = false
|
|
1025
|
-
} = opts;
|
|
1026
|
-
const actualHookSystem = useGlobalSingletons ? hookSystem : hookSystem2 ?? new HookSystem();
|
|
1027
|
-
const actualRegistry = useGlobalSingletons ? resourceRegistry : registry ?? new ResourceRegistry();
|
|
1028
|
-
fastify.decorate("arc", {
|
|
1029
|
-
hooks: actualHookSystem,
|
|
1030
|
-
registry: actualRegistry,
|
|
1031
|
-
emitEvents
|
|
1032
|
-
});
|
|
1033
|
-
if (emitEvents) {
|
|
1034
|
-
const eventOperations = ["create", "update", "delete"];
|
|
1035
|
-
for (const operation of eventOperations) {
|
|
1036
|
-
actualHookSystem.after("*", operation, async (ctx) => {
|
|
1037
|
-
if (!hasEvents(fastify)) return;
|
|
1038
|
-
const eventType = `${ctx.resource}.${operation}d`;
|
|
1039
|
-
const payload = {
|
|
1040
|
-
resource: ctx.resource,
|
|
1041
|
-
operation: ctx.operation,
|
|
1042
|
-
data: ctx.result,
|
|
1043
|
-
userId: ctx.user?.id ?? ctx.user?._id,
|
|
1044
|
-
organizationId: ctx.context?.organizationId,
|
|
1045
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1046
|
-
};
|
|
1047
|
-
try {
|
|
1048
|
-
await fastify.events.publish(eventType, payload);
|
|
1049
|
-
} catch (error) {
|
|
1050
|
-
fastify.log?.warn?.(
|
|
1051
|
-
{ eventType, error },
|
|
1052
|
-
"Failed to emit event"
|
|
1053
|
-
);
|
|
1054
|
-
}
|
|
1055
|
-
});
|
|
1056
|
-
}
|
|
1057
|
-
}
|
|
1058
|
-
fastify.addHook("onClose", async () => {
|
|
1059
|
-
actualHookSystem.clear();
|
|
1060
|
-
actualRegistry._clear();
|
|
1061
|
-
});
|
|
1062
|
-
fastify.log?.info?.("✅ Arc core plugin enabled (instance-scoped hooks & registry)");
|
|
1063
|
-
};
|
|
1064
|
-
var arcCorePlugin_default = fp(arcCorePlugin, {
|
|
1065
|
-
name: "arc-core",
|
|
1066
|
-
fastify: "5.x"
|
|
1067
|
-
});
|
|
1068
|
-
|
|
1069
|
-
export { arcCorePlugin_default as arcCorePlugin, arcCorePlugin as arcCorePluginFn, createSpan, errorHandler_default as errorHandlerPlugin, errorHandlerPlugin as errorHandlerPluginFn, gracefulShutdown_default as gracefulShutdownPlugin, gracefulShutdownPlugin as gracefulShutdownPluginFn, health_default as healthPlugin, healthPlugin as healthPluginFn, isTracingAvailable, requestId_default as requestIdPlugin, requestIdPlugin as requestIdPluginFn, traced, tracing_default as tracingPlugin };
|