@classytic/arc 2.41.1 → 2.44.0
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/dist/{EventTransport-CbUKDzZZ.d.mts → EventTransport-CiicKz2Z.d.mts} +1 -1
- package/dist/{EventTransport-DSqD_Xsg.mjs → EventTransport-DZWDsaPa.mjs} +22 -17
- package/dist/{HookSystem-CMF94SEA.mjs → HookSystem-yjEgn7Cm.mjs} +2 -2
- package/dist/{QueryCache-DFA-QrU9.d.mts → QueryCache--5uAuYPW.d.mts} +7 -3
- package/dist/{ResourceRegistry-MGpXoxHZ.mjs → ResourceRegistry-DJxHUpE4.mjs} +44 -13
- package/dist/acquire-BozJ-9yt.mjs +35 -0
- package/dist/actionPermissions-5N04zBL4.mjs +772 -0
- package/dist/audit/index.d.mts +46 -8
- package/dist/audit/index.mjs +48 -26
- package/dist/auth/audit.d.mts +8 -8
- package/dist/auth/audit.mjs +1 -1
- package/dist/auth/index.d.mts +46 -16
- package/dist/auth/index.mjs +134 -156
- package/dist/auth/redis-session.d.mts +4 -5
- package/dist/auth/redis-session.mjs +1 -1
- package/dist/{authorizationDecision-DawKGoXb.mjs → authorizationDecision-wX3SA9w_.mjs} +7 -102
- package/dist/{base-CxrV1LmG.d.mts → base-CZyixEQR.d.mts} +27 -5
- package/dist/boundedMap-DWiKW7lP.mjs +57 -0
- package/dist/{buildHandler-CvxKOc0m.mjs → buildHandler-Bswu_vNb.mjs} +4 -4
- package/dist/cache/index.d.mts +31 -43
- package/dist/cache/index.mjs +4 -4
- package/dist/{caching-DbCBxlgw.mjs → caching-Drp68DIS.mjs} +3 -3
- package/dist/claimed-DYvQoZLv.mjs +8 -0
- package/dist/cleanup/index.d.mts +18 -22
- package/dist/cleanup/index.mjs +27 -73
- package/dist/cli/commands/describe.d.mts +7 -5
- package/dist/cli/commands/describe.mjs +7 -4
- package/dist/cli/commands/docs.d.mts +2 -3
- package/dist/cli/commands/docs.mjs +3 -3
- package/dist/cli/commands/doctor.d.mts +2 -3
- package/dist/cli/commands/doctor.mjs +1 -1
- package/dist/cli/commands/generate.mjs +2 -3
- package/dist/cli/commands/init.mjs +2 -3
- package/dist/cli/commands/introspect.d.mts +2 -3
- package/dist/cli/commands/introspect.mjs +2 -2
- package/dist/cli/index.mjs +3 -3
- package/dist/{constants-D5Ubn1fe.mjs → constants-B2QHb6u6.mjs} +4 -2
- package/dist/context/index.d.mts +11 -14
- package/dist/context/index.mjs +18 -38
- package/dist/core/index.d.mts +3 -3
- package/dist/core/index.mjs +8 -8
- package/dist/{core-5lazhva9.mjs → core-COcqo0Cp.mjs} +15 -5
- package/dist/{createActionRouter-DNqoaK81.mjs → createActionRouter-zG13rpPJ.mjs} +97 -39
- package/dist/{createAggregationRouter-BcbQJf10.mjs → createAggregationRouter-CWRz96Vr.mjs} +11 -8
- package/dist/{preloadResources-f3boenVZ.mjs → createApp-BGLYtErt.mjs} +305 -394
- package/dist/{createMcpServer-CbDWkZ1T.d.mts → createMcpServer-DSztofa9.d.mts} +1 -1
- package/dist/{defineAggregation-D_eJjm5A.mjs → defineAggregation--3xguLkk.mjs} +1 -1
- package/dist/{defineResource-DxkMTjRn.mjs → defineResource-gUp9ug66.mjs} +118 -1024
- package/dist/discovery/index.d.mts +6 -7
- package/dist/discovery/index.mjs +1 -1
- package/dist/docs/index.d.mts +11 -5
- package/dist/docs/index.mjs +4 -4
- package/dist/{elevation-CkvG0LG2.mjs → elevation-BG4gnMsJ.mjs} +41 -12
- package/dist/{elevation-BXCfVcNG.d.mts → elevation-BW2J3tNj.d.mts} +1 -2
- package/dist/encryption/index.d.mts +5 -5
- package/dist/encryption/index.mjs +3 -3
- package/dist/{errorHandler-D1GHKGlV.mjs → errorHandler-COHw3N1b.mjs} +26 -5
- package/dist/{errors-BH7YU_9O.mjs → errors-CW4anJBy.mjs} +58 -23
- package/dist/{errors-BGdVwP25.d.mts → errors-JYc9vwqE.d.mts} +9 -0
- package/dist/{eventPlugin-B52abJ8W.d.mts → eventPlugin-BtmA4-3P.d.mts} +65 -9
- package/dist/{eventPlugin-zZY-unhr.mjs → eventPlugin-BweHAVws.mjs} +82 -21
- package/dist/{subscribe-helpers-DatDkcuG.mjs → eventTypes-N4-omQFR.mjs} +151 -17
- package/dist/events/index.d.mts +43 -18
- package/dist/events/index.mjs +49 -53
- package/dist/events/transports/redis-stream-entry.d.mts +1 -1
- package/dist/events/transports/redis-stream-entry.mjs +139 -157
- package/dist/events/transports/redis.d.mts +5 -6
- package/dist/events/transports/redis.mjs +2 -2
- package/dist/factory/index.d.mts +42 -27
- package/dist/factory/index.mjs +213 -32
- package/dist/{fastify-augmentation-Cq2nHVaW.d.mts → fastify-augmentation-DRlCIWE9.d.mts} +11 -25
- package/dist/{fields-BHrkoF5y.mjs → fields-A5crhsJb.mjs} +1 -1
- package/dist/{fields-I_EeRWND.d.mts → fields-BBSpf8pS.d.mts} +1 -1
- package/dist/filter-merge-DGM-GQ1J.mjs +99 -0
- package/dist/{generate-BLRf2m3y.mjs → generate-BXKo2Gc8.mjs} +2 -2
- package/dist/{headers-BIXWKrzQ.mjs → headers-DKZQKL-Z.mjs} +2 -2
- package/dist/health-BYAwA6YS.mjs +22 -0
- package/dist/{health-ZRHeDHXH.mjs → health-CrqUp3sz.mjs} +115 -55
- package/dist/hooks/index.d.mts +2 -2
- package/dist/hooks/index.mjs +2 -3
- package/dist/idempotency/index.d.mts +36 -10
- package/dist/idempotency/index.mjs +230 -111
- package/dist/idempotency/redis.d.mts +1 -1
- package/dist/idempotency/redis.mjs +77 -12
- package/dist/{index-D4u76eQW.d.mts → index-Beg3aNnK.d.mts} +23 -101
- package/dist/{preloadResources-CjS2OfpU.d.mts → index-BkV55WlV.d.mts} +37 -38
- package/dist/{index-BHdZD8zK.d.mts → index-Bxriq3so.d.mts} +84 -21
- package/dist/index-CUJvoyw3.d.mts +510 -0
- package/dist/{index-CbJiYrfv.d.mts → index-Chgz3d0i.d.mts} +1 -1
- package/dist/{index-DHbyPo5j.d.mts → index-WH7xgvxS.d.mts} +304 -254
- package/dist/index.d.mts +9 -9
- package/dist/index.mjs +11 -11
- package/dist/{init-CpLkjU18.mjs → init-BPzK5Lnr.mjs} +1 -1
- package/dist/integrations/event-gateway.d.mts +11 -7
- package/dist/integrations/event-gateway.mjs +4 -4
- package/dist/integrations/index.d.mts +3 -3
- package/dist/integrations/index.mjs +1 -1
- package/dist/integrations/jobs/index.d.mts +1 -1
- package/dist/integrations/jobs/index.mjs +18 -5
- package/dist/integrations/mcp/index.d.mts +102 -89
- package/dist/integrations/mcp/index.mjs +19 -4
- package/dist/integrations/mcp/testing.d.mts +8 -9
- package/dist/integrations/mcp/testing.mjs +2 -2
- package/dist/integrations/streamline.d.mts +85 -144
- package/dist/integrations/streamline.mjs +131 -55
- package/dist/integrations/webhooks.d.mts +83 -143
- package/dist/integrations/webhooks.mjs +36 -80
- package/dist/integrations/websocket-pushref-redis.d.mts +5 -6
- package/dist/integrations/websocket-pushref-redis.mjs +1 -1
- package/dist/integrations/websocket-redis.d.mts +5 -6
- package/dist/integrations/websocket-redis.mjs +1 -1
- package/dist/integrations/websocket.d.mts +3 -3
- package/dist/integrations/websocket.mjs +2 -2
- package/dist/{interface-DEWNOMza.d.mts → interface-JJzwH4Ro.d.mts} +34 -2
- package/dist/{jsonBody-ELR9lfeU.mjs → jsonBody-YIq-vGLv.mjs} +2 -2
- package/dist/{keys-cpZCtcIE.mjs → keys-CpoiZ8hU.mjs} +7 -18
- package/dist/{loadResources-BPfWiI5s.mjs → loadResources-6jO52-RR.mjs} +3 -3
- package/dist/{loadResourcesFromEntry-ixtfL3J2.mjs → loadResourcesFromEntry-MP8xEppu.mjs} +2 -2
- package/dist/logger/index.d.mts +9 -17
- package/dist/logger/index.mjs +2 -153
- package/dist/logger-D4V1zGLI.mjs +160 -0
- package/dist/{mcpPlugin-BX5PujI0.mjs → mcpPlugin-srPc7ItN.mjs} +446 -170
- package/dist/{memory-Iotz0cCx.mjs → memory-CTa5pOCW.mjs} +36 -34
- package/dist/{metrics-NMsmpRmY.mjs → metrics-DsZrvnpB.mjs} +39 -72
- package/dist/middleware/index.d.mts +5 -5
- package/dist/middleware/index.mjs +3 -3
- package/dist/migrations/index.d.mts +13 -13
- package/dist/migrations/index.mjs +2 -2
- package/dist/{module-DpLJG2_N.mjs → module--L0iBIZz.mjs} +8 -8
- package/dist/mongodb-memory-server-CHhYSq5y.mjs +35539 -0
- package/dist/mongoose-CYJCLyi-.mjs +67451 -0
- package/dist/multiTenant-CAtYlW6H.d.mts +104 -0
- package/dist/{multipartBody-DtRWM6_U.mjs → multipartBody-Cc7eZ9cq.mjs} +46 -7
- package/dist/node-D8UZv_8c.mjs +41236 -0
- package/dist/{openapi-CmFf3yq_.mjs → openapi-CMegfsm8.mjs} +48 -10
- package/dist/outbox-admin/index.d.mts +5 -5
- package/dist/outbox-admin/index.mjs +6 -18
- package/dist/{outbox-module-D2z5WkDY.mjs → outbox-module-Ryk270jd.mjs} +203 -33
- package/dist/{outbox-module-BHdUnuuK.d.mts → outbox-module-gZCHoE4H.d.mts} +79 -6
- package/dist/permissions/index.d.mts +5 -4
- package/dist/permissions/index.mjs +8 -6
- package/dist/{permissions-D8TBH44E.mjs → permissions-C5ijIz5Q.mjs} +149 -33
- package/dist/{pipe-FMWNheSO.mjs → pipe-D81zMtWs.mjs} +2 -2
- package/dist/pipeline/index.d.mts +7 -7
- package/dist/pipeline/index.mjs +2 -2
- package/dist/plan-CJGMKoui.mjs +565 -0
- package/dist/{BaseController-CYEwjyjN.mjs → plugin-DALd9dcF.mjs} +1269 -346
- package/dist/plugins/index.d.mts +17 -14
- package/dist/plugins/index.mjs +44 -22
- package/dist/plugins/response-cache.d.mts +5 -6
- package/dist/plugins/response-cache.mjs +8 -14
- package/dist/plugins/tracing-entry.mjs +2 -2
- package/dist/{pluralize-CXWZIzTv.mjs → pluralize-COUNYo3d.mjs} +1 -1
- package/dist/presets/filesUpload.d.mts +8 -8
- package/dist/presets/filesUpload.mjs +5 -5
- package/dist/presets/index.d.mts +35 -40
- package/dist/presets/index.mjs +4 -4
- package/dist/presets/multiTenant.d.mts +2 -107
- package/dist/presets/multiTenant.mjs +22 -162
- package/dist/presets/search.d.mts +9 -10
- package/dist/presets/search.mjs +2 -2
- package/dist/{presets-ZJSPgmT2.mjs → presets-CONf2Qem.mjs} +99 -107
- package/dist/{projection-BzIgzoKZ.mjs → projection-wFoLqdss.mjs} +2 -2
- package/dist/{pushref-registry-Dov9l4qE.d.mts → pushref-registry-UxCkoA4C.d.mts} +1 -1
- package/dist/{queryCachePlugin-DZHPOm9p.mjs → queryCachePlugin-BATECpyh.mjs} +12 -14
- package/dist/{queryCachePlugin-BzqxconG.d.mts → queryCachePlugin-C2lZjTxk.d.mts} +1 -1
- package/dist/{rateLimitKey-BvOvcBDi.mjs → rateLimitKey-DVEZ_UpV.mjs} +1 -1
- package/dist/{realtime-8tIQWZz4.mjs → realtime-xyubMKSB.mjs} +25 -21
- package/dist/{redis-Bzi1y3F9.d.mts → redis-BDgv9Glw.d.mts} +17 -24
- package/dist/redis-stream-BMk-bpQS.d.mts +219 -0
- package/dist/redisShapes-CQksY67q.d.mts +55 -0
- package/dist/registry/index.d.mts +15 -10
- package/dist/registry/index.mjs +4 -4
- package/dist/{registry-DNkgGQcK.mjs → registry-Bdzg-hdm.mjs} +13 -10
- package/dist/{renewingLease-yF8BdW4b.mjs → renewingLease-BFJxGPuh.mjs} +1 -1
- package/dist/{replyHelpers-CNdvMfM4.mjs → replyHelpers-Bnc6lJyy.mjs} +2 -2
- package/dist/{requestContext-cDkAUr-P.mjs → requestContext-C10UeFe5.mjs} +1 -1
- package/dist/requirement-Bu50QALH.mjs +35 -0
- package/dist/requirement-CbiLdQ1n.d.mts +22 -0
- package/dist/resourceRateLimit-Wf6d6FL9.d.mts +30 -0
- package/dist/resourceRateLimit-urWPJxrt.mjs +180 -0
- package/dist/rolldown-runtime-MYrLNGnq.mjs +45 -0
- package/dist/routeValidator-DHtpzrzk.mjs +70 -0
- package/dist/{runtimeCapabilities-CkhS6jn6.mjs → runtimeCapabilities-DIMKMV2G.mjs} +1 -1
- package/dist/{schedules-j6uXXAeJ.mjs → schedules-CKTs5ys8.mjs} +46 -37
- package/dist/{schemaConverter-BVA7cFRG.mjs → schemaConverter-BVjkQ5DD.mjs} +2 -2
- package/dist/{schemaIR-CTvPDoPB.mjs → schemaIR-BA0Hb21Y.mjs} +2 -2
- package/dist/schemas/index.d.mts +20 -10
- package/dist/schemas/index.mjs +8 -3
- package/dist/scim/index.d.mts +13 -13
- package/dist/scim/index.mjs +2 -2
- package/dist/scope/index.d.mts +4 -4
- package/dist/scope/index.mjs +6 -6
- package/dist/{scope-BUi1xV1I.mjs → scope-DINaj7Ax.mjs} +4 -4
- package/dist/shutdown-LpLMH8T1.mjs +59 -0
- package/dist/{simpleEqualityMatcher-C9bzq2gO.mjs → simpleEqualityMatcher-DbwIM1f1.mjs} +1 -1
- package/dist/{sse-BeqVKQKu.mjs → sse-BzJFPX_1.mjs} +11 -15
- package/dist/{sseStream-Ppzo-WUH.mjs → sseStream-DQChzGTs.mjs} +2 -2
- package/dist/{store-helpers-dW71XVWL.mjs → store-helpers-Coj9RhOZ.mjs} +1 -1
- package/dist/{streaming-IcRFjWQU.mjs → streaming-JzB5CAga.mjs} +1 -1
- package/dist/subscriberIdentity-DeyppIif.mjs +28 -0
- package/dist/tenancy-DxV8OuX2.mjs +43 -0
- package/dist/tenantPreparation-CBvvAcAj.mjs +67 -0
- package/dist/testing/cleanupStoreContract.d.mts +4 -5
- package/dist/testing/cleanupStoreContract.mjs +1 -1
- package/dist/testing/index.d.mts +215 -197
- package/dist/testing/index.mjs +289 -214
- package/dist/testing/outboxStoreContract.d.mts +4 -5
- package/dist/testing/outboxStoreContract.mjs +137 -2
- package/dist/testing/requiredPorts.d.mts +16 -0
- package/dist/testing/requiredPorts.mjs +65 -0
- package/dist/testing/storageContract.d.mts +4 -5
- package/dist/testing/storageContract.mjs +1 -1
- package/dist/timing-CntavTlR.mjs +46 -0
- package/dist/{transactionContext-CPbdlnVw.mjs → transactionContext-orvnGu4F.mjs} +1 -1
- package/dist/{typeGuards-BLjPgVBm.mjs → typeGuards-kEaP_WmO.mjs} +1 -1
- package/dist/types/index.d.mts +4 -4
- package/dist/types/index.mjs +1 -1
- package/dist/types/storage.mjs +1 -1
- package/dist/{types-DfVDvkdP.d.mts → types-BJ-2XqVF.d.mts} +189 -204
- package/dist/{types-CWQn9-IC.d.mts → types-D3Ixsh00.d.mts} +22 -9
- package/dist/{types-CgenB1gv.mjs → types-fvO6Ovzx.mjs} +4 -4
- package/dist/usage/index.d.mts +5 -6
- package/dist/usage/index.mjs +5 -5
- package/dist/{userHelpers-ChRvkuSZ.mjs → userHelpers-C76zD5pa.mjs} +1 -1
- package/dist/utils/index.d.mts +125 -264
- package/dist/utils/index.mjs +13 -12
- package/dist/{utils-CxcctrAh.mjs → utils-BpkVZ8rB.mjs} +315 -404
- package/dist/{validate-DrYWnOzI.mjs → validate-CWp-lsrm.mjs} +6 -14
- package/dist/{versioning-D6JIK8Tk.d.mts → versioning-Bsb51gGT.d.mts} +28 -13
- package/dist/{versioning-DKkT4hNJ.mjs → versioning-CHhL9P3o.mjs} +4 -4
- package/dist/{websocket-BOXVggMf.d.mts → websocket-Cs4awVyD.d.mts} +1 -1
- package/dist/{workScope-CxKqoIFn.mjs → workScope-n9a7d_lZ.mjs} +2 -2
- package/package.json +57 -59
- package/skills/arc/SKILL.md +13 -4
- package/skills/arc/references/auth.md +8 -5
- package/skills/arc/references/integrations.md +1 -1
- package/skills/arc/references/mcp.md +8 -6
- package/skills/arc/references/multi-tenancy.md +19 -14
- package/skills/arc/references/production.md +27 -10
- package/dist/actionPermissions-BoPGQ5-4.mjs +0 -350
- package/dist/index-CFfLKMH4.d.mts +0 -290
- package/dist/interface-YzIbF7Ii.mjs +0 -17
- package/dist/redis-stream-BPKscsTB.d.mts +0 -260
- package/dist/registerRoute-Bsnk6NiZ.mjs +0 -364
- package/dist/rolldown-runtime-eysyzFAF.mjs +0 -15
- package/dist/sync/changelog.d.mts +0 -3
- package/dist/sync/changelog.mjs +0 -3
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
|
|
2
|
-
import { f as WebSocketAdapter } from "../websocket-
|
|
2
|
+
import { f as WebSocketAdapter } from "../websocket-Cs4awVyD.mjs";
|
|
3
3
|
//#region src/integrations/websocket-redis.d.ts
|
|
4
|
-
interface RedisLike {
|
|
4
|
+
export interface RedisLike {
|
|
5
5
|
publish(channel: string, message: string): Promise<number>;
|
|
6
6
|
subscribe(...channels: string[]): Promise<unknown>;
|
|
7
7
|
on(event: string, handler: (...args: unknown[]) => void): unknown;
|
|
8
8
|
duplicate(): RedisLike;
|
|
9
9
|
quit(): Promise<unknown>;
|
|
10
10
|
}
|
|
11
|
-
interface RedisWebSocketAdapterOptions {
|
|
11
|
+
export interface RedisWebSocketAdapterOptions {
|
|
12
12
|
/**
|
|
13
13
|
* Redis channel for WebSocket broadcasts.
|
|
14
14
|
* @default 'arc-ws'
|
|
@@ -31,7 +31,7 @@ interface RedisWebSocketAdapterOptions {
|
|
|
31
31
|
* 5. Each instance checks instanceId — skips if it's own message (prevents double delivery)
|
|
32
32
|
* 6. Other instances call RoomManager.broadcast() to deliver to their local clients
|
|
33
33
|
*/
|
|
34
|
-
declare class RedisWebSocketAdapter implements WebSocketAdapter {
|
|
34
|
+
export declare class RedisWebSocketAdapter implements WebSocketAdapter {
|
|
35
35
|
readonly name = "redis";
|
|
36
36
|
private pub;
|
|
37
37
|
private sub;
|
|
@@ -42,5 +42,4 @@ declare class RedisWebSocketAdapter implements WebSocketAdapter {
|
|
|
42
42
|
subscribe(callback: (room: string, message: string) => void): Promise<void>;
|
|
43
43
|
close(): Promise<void>;
|
|
44
44
|
}
|
|
45
|
-
//#endregion
|
|
46
|
-
export { RedisLike, RedisWebSocketAdapter, RedisWebSocketAdapterOptions };
|
|
45
|
+
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
|
|
2
|
-
import { a as GeoRoomOptions, c as WebSocketClient, d as LocalWebSocketAdapter, f as WebSocketAdapter, i as GeoRoom, l as WebSocketMessage, n as GeoPoint, o as RoomManager, r as GeoPublishOpts, s as AuthResult, t as websocketPlugin, u as WebSocketPluginOptions } from "../websocket-
|
|
3
|
-
import { a as PushRefRegistry, c as SerializedEntry, i as Principal, o as PushRefRegistryOptions, r as MemoryPushRefStore, s as PushRefStore } from "../pushref-registry-
|
|
4
|
-
export { type AuthResult, type GeoPoint, type GeoPublishOpts, GeoRoom, type GeoRoomOptions, LocalWebSocketAdapter, MemoryPushRefStore, type Principal, PushRefRegistry, type PushRefRegistryOptions, type PushRefStore, RoomManager, type SerializedEntry, type WebSocketAdapter, type WebSocketClient, type WebSocketMessage, type WebSocketPluginOptions, websocketPlugin };
|
|
2
|
+
import { a as GeoRoomOptions, c as WebSocketClient, d as LocalWebSocketAdapter, f as WebSocketAdapter, i as GeoRoom, l as WebSocketMessage, n as GeoPoint, o as RoomManager, r as GeoPublishOpts, s as AuthResult, t as websocketPlugin, u as WebSocketPluginOptions } from "../websocket-Cs4awVyD.mjs";
|
|
3
|
+
import { a as PushRefRegistry, c as SerializedEntry, i as Principal, o as PushRefRegistryOptions, r as MemoryPushRefStore, s as PushRefStore, u as DeadQueueEntry } from "../pushref-registry-UxCkoA4C.mjs";
|
|
4
|
+
export { type AuthResult, type DeadQueueEntry, type GeoPoint, type GeoPublishOpts, GeoRoom, type GeoRoomOptions, LocalWebSocketAdapter, MemoryPushRefStore, type Principal, PushRefRegistry, type PushRefRegistryOptions, type PushRefStore, RoomManager, type SerializedEntry, type WebSocketAdapter, type WebSocketClient, type WebSocketMessage, type WebSocketPluginOptions, websocketPlugin };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { n as declareRuntimeCapability } from "../runtimeCapabilities-
|
|
1
|
+
/*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
|
|
2
|
+
import { n as declareRuntimeCapability } from "../runtimeCapabilities-DIMKMV2G.mjs";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
4
|
import sjson from "secure-json-parse";
|
|
5
5
|
import fp from "fastify-plugin";
|
|
@@ -9,12 +9,20 @@
|
|
|
9
9
|
interface IdempotencyResult {
|
|
10
10
|
/** The idempotency key */
|
|
11
11
|
key: string;
|
|
12
|
+
/**
|
|
13
|
+
* `fingerprintRequest` of the body the key was first used with. A retry under the same key
|
|
14
|
+
* with a different body is refused (422), never answered with this response. Absent on
|
|
15
|
+
* entries written before 2.43 — those replay without the check.
|
|
16
|
+
*/
|
|
17
|
+
requestFingerprint?: string;
|
|
12
18
|
/** HTTP status code of the cached response */
|
|
13
19
|
statusCode: number;
|
|
14
20
|
/** Response headers to replay */
|
|
15
21
|
headers: Record<string, string>;
|
|
16
22
|
/** Response body */
|
|
17
23
|
body: unknown;
|
|
24
|
+
/** Binary responses are stored as base64 so JSON-backed stores preserve their bytes. */
|
|
25
|
+
bodyEncoding?: "base64";
|
|
18
26
|
/** When this entry was created */
|
|
19
27
|
createdAt: Date;
|
|
20
28
|
/** When this entry expires */
|
|
@@ -30,9 +38,28 @@ interface IdempotencyLock {
|
|
|
30
38
|
/** When the lock expires (auto-release) */
|
|
31
39
|
expiresAt: Date;
|
|
32
40
|
}
|
|
41
|
+
/** What one atomic {@link IdempotencyStore.acquire} found. */
|
|
42
|
+
type IdempotencyAcquisition = {
|
|
43
|
+
readonly status: "acquired";
|
|
44
|
+
} | {
|
|
45
|
+
readonly status: "completed";
|
|
46
|
+
readonly result: IdempotencyResult;
|
|
47
|
+
} | {
|
|
48
|
+
readonly status: "locked";
|
|
49
|
+
};
|
|
33
50
|
interface IdempotencyStore {
|
|
34
51
|
/** Store name for logging */
|
|
35
52
|
readonly name: string;
|
|
53
|
+
/** false when a conditional completion method cannot be atomic with this backing client. */
|
|
54
|
+
readonly supportsFencedCompletion?: boolean;
|
|
55
|
+
/** true when `setIfLocked` also releases the lock, so a completed request needs no `unlock`. */
|
|
56
|
+
readonly completionReleasesLock?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* ONE atomic step: an unexpired completion → `completed`; an unexpired lock → `locked`;
|
|
59
|
+
* otherwise `requestId` now holds the lock (first use, expired lease, or expired result).
|
|
60
|
+
* Optional — without it callers run `get` → `tryLock` → `get`.
|
|
61
|
+
*/
|
|
62
|
+
acquire?(key: string, requestId: string, lockTtlMs: number): Promise<IdempotencyAcquisition>;
|
|
36
63
|
/**
|
|
37
64
|
* Get a cached result for an idempotency key.
|
|
38
65
|
* Returns undefined if not found or expired.
|
|
@@ -43,6 +70,11 @@ interface IdempotencyStore {
|
|
|
43
70
|
* TTL is handled by the store implementation.
|
|
44
71
|
*/
|
|
45
72
|
set(key: string, result: Omit<IdempotencyResult, "key">): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Atomically record only while requestId owns an unexpired lock. false means ownership lost.
|
|
75
|
+
* A store declaring `completionReleasesLock` clears the lock in the same write.
|
|
76
|
+
*/
|
|
77
|
+
setIfLocked?(key: string, requestId: string, result: Omit<IdempotencyResult, "key">): Promise<boolean>;
|
|
46
78
|
/**
|
|
47
79
|
* Try to acquire a lock for processing a key.
|
|
48
80
|
* Returns true if lock acquired, false if already locked.
|
|
@@ -73,6 +105,6 @@ interface IdempotencyStore {
|
|
|
73
105
|
/**
|
|
74
106
|
* Helper to create a result object
|
|
75
107
|
*/
|
|
76
|
-
declare function createIdempotencyResult(statusCode: number, body: unknown, headers: Record<string, string>, ttlMs: number): Omit<IdempotencyResult, "key">;
|
|
108
|
+
declare function createIdempotencyResult(statusCode: number, body: unknown, headers: Record<string, string>, ttlMs: number, requestFingerprint?: string): Omit<IdempotencyResult, "key">;
|
|
77
109
|
//#endregion
|
|
78
|
-
export { createIdempotencyResult as i,
|
|
110
|
+
export { createIdempotencyResult as a, IdempotencyStore as i, IdempotencyLock as n, IdempotencyResult as r, IdempotencyAcquisition as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { t as ArcError } from "./errors-
|
|
1
|
+
/*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as ArcError } from "./errors-CW4anJBy.mjs";
|
|
3
3
|
import sjson from "secure-json-parse";
|
|
4
4
|
//#region src/utils/jsonBody.ts
|
|
5
5
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
1
|
+
/*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
|
|
2
|
+
import { contentHash } from "@classytic/repo-core/hash";
|
|
2
3
|
//#region src/cache/keys.ts
|
|
3
4
|
/**
|
|
4
5
|
* Cache Key Utilities
|
|
@@ -20,25 +21,13 @@ function tagVersionKey(tag) {
|
|
|
20
21
|
return `arc:tagver:${tag}`;
|
|
21
22
|
}
|
|
22
23
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
24
|
+
* Digest of the query params for a cache key — repo-core's canonical serialiser (escaped,
|
|
25
|
+
* type-preserving, key-order-free) under SHA-256. Two different queries never share a key: a
|
|
26
|
+
* delimiter inside a value, `1` vs `"1"`, two dates or two regexes all stay distinct, and a
|
|
27
|
+
* cryptographic digest leaves no crafted collision onto another caller's cached result.
|
|
26
28
|
*/
|
|
27
29
|
function hashParams(params) {
|
|
28
|
-
return
|
|
29
|
-
}
|
|
30
|
-
function stableStringify(value) {
|
|
31
|
-
if (value === null || value === void 0) return "";
|
|
32
|
-
if (typeof value !== "object") return String(value);
|
|
33
|
-
if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
|
|
34
|
-
if (value instanceof RegExp) return `/${value.source}/${value.flags}`;
|
|
35
|
-
if (value instanceof Date) return `d${value.getTime()}`;
|
|
36
|
-
return "{" + Object.keys(value).sort().map((k) => `${k}:${stableStringify(value[k])}`).join(",") + "}";
|
|
37
|
-
}
|
|
38
|
-
function djb2(str) {
|
|
39
|
-
let hash = 5381;
|
|
40
|
-
for (let i = 0; i < str.length; i++) hash = (hash << 5) + hash + str.charCodeAt(i) >>> 0;
|
|
41
|
-
return hash;
|
|
30
|
+
return contentHash(params, { encoding: "base64url" });
|
|
42
31
|
}
|
|
43
32
|
//#endregion
|
|
44
33
|
export { versionKey as i, hashParams as n, tagVersionKey as r, buildQueryKey as t };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import {
|
|
3
|
-
import { arcLog } from "./logger
|
|
1
|
+
/*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
|
|
2
|
+
import { r as __exportAll } from "./rolldown-runtime-MYrLNGnq.mjs";
|
|
3
|
+
import { t as arcLog } from "./logger-D4V1zGLI.mjs";
|
|
4
4
|
import { readdir } from "node:fs/promises";
|
|
5
5
|
import { dirname, join, resolve } from "node:path";
|
|
6
6
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { t as ResourceRegistry } from "./ResourceRegistry-
|
|
1
|
+
/*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as ResourceRegistry } from "./ResourceRegistry-DJxHUpE4.mjs";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
5
|
//#region src/cli/utils/loadResourcesFromEntry.ts
|
package/dist/logger/index.d.mts
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* log.warn('Something unexpected');
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
|
-
interface ArcLoggerOptions {
|
|
30
|
+
export interface ArcLoggerOptions {
|
|
31
31
|
/**
|
|
32
32
|
* Enable debug output.
|
|
33
33
|
* - `true` or `'*'` — all modules
|
|
@@ -41,13 +41,13 @@ interface ArcLoggerOptions {
|
|
|
41
41
|
*/
|
|
42
42
|
writer?: ArcLogWriter;
|
|
43
43
|
}
|
|
44
|
-
interface ArcLogWriter {
|
|
44
|
+
export interface ArcLogWriter {
|
|
45
45
|
debug: (...args: unknown[]) => void;
|
|
46
46
|
info: (...args: unknown[]) => void;
|
|
47
47
|
warn: (...args: unknown[]) => void;
|
|
48
48
|
error: (...args: unknown[]) => void;
|
|
49
49
|
}
|
|
50
|
-
interface ArcLogger {
|
|
50
|
+
export interface ArcLogger {
|
|
51
51
|
debug: (...args: unknown[]) => void;
|
|
52
52
|
info: (...args: unknown[]) => void;
|
|
53
53
|
warn: (...args: unknown[]) => void;
|
|
@@ -61,14 +61,7 @@ interface ArcLogger {
|
|
|
61
61
|
* constructed. Copying here would freeze the pre-Fastify view and send every
|
|
62
62
|
* post-construction boot warning to the console instead of the app's logger.
|
|
63
63
|
*/
|
|
64
|
-
declare function runWithArcLogger<T>(options: ArcLoggerOptions, fn: () => T): T;
|
|
65
|
-
/**
|
|
66
|
-
* Enter `options` for the remainder of the current async context.
|
|
67
|
-
*
|
|
68
|
-
* For Fastify's `onRequest` hook, where `run(store, done)` wraps the rest of
|
|
69
|
-
* the request lifecycle. Outside a hook, prefer {@link runWithArcLogger}.
|
|
70
|
-
*/
|
|
71
|
-
declare function enterArcLoggerScope(options: ArcLoggerOptions, done: () => void): void;
|
|
64
|
+
export declare function runWithArcLogger<T>(options: ArcLoggerOptions, fn: () => T): T;
|
|
72
65
|
/**
|
|
73
66
|
* Configure the PROCESS-GLOBAL Arc logger — the fallback used outside any app.
|
|
74
67
|
*
|
|
@@ -78,7 +71,7 @@ declare function enterArcLoggerScope(options: ArcLoggerOptions, done: () => void
|
|
|
78
71
|
* standalone use — `defineResource()` at module import, CLI commands, and any
|
|
79
72
|
* code running before or outside a `createApp` boot.
|
|
80
73
|
*/
|
|
81
|
-
declare function configureArcLogger(options: ArcLoggerOptions): void;
|
|
74
|
+
export declare function configureArcLogger(options: ArcLoggerOptions): void;
|
|
82
75
|
/**
|
|
83
76
|
* Create a module-scoped logger.
|
|
84
77
|
*
|
|
@@ -96,13 +89,13 @@ declare function configureArcLogger(options: ArcLoggerOptions): void;
|
|
|
96
89
|
* log.warn('No authenticate decorator found');
|
|
97
90
|
* ```
|
|
98
91
|
*/
|
|
99
|
-
declare function arcLog(module: string): ArcLogger;
|
|
92
|
+
export declare function arcLog(module: string): ArcLogger;
|
|
100
93
|
/**
|
|
101
94
|
* Minimal structural slice of a pino-style logger (`fastify.log`). Each
|
|
102
95
|
* level accepts `(msg)` or `(mergeObject, msg)` — the pino calling
|
|
103
96
|
* convention, which differs from console's variadic `(...args)`.
|
|
104
97
|
*/
|
|
105
|
-
interface PinoLike {
|
|
98
|
+
export interface PinoLike {
|
|
106
99
|
debug: (obj: unknown, msg?: string) => void;
|
|
107
100
|
info: (obj: unknown, msg?: string) => void;
|
|
108
101
|
warn: (obj: unknown, msg?: string) => void;
|
|
@@ -121,6 +114,5 @@ interface PinoLike {
|
|
|
121
114
|
* `createApp` installs this automatically so arc-internal warnings flow
|
|
122
115
|
* through the host's transports, level, and redaction config.
|
|
123
116
|
*/
|
|
124
|
-
declare function createPinoWriter(logger: PinoLike): ArcLogWriter;
|
|
125
|
-
//#endregion
|
|
126
|
-
export { ArcLogWriter, ArcLogger, ArcLoggerOptions, PinoLike, arcLog, configureArcLogger, createPinoWriter, enterArcLoggerScope, runWithArcLogger };
|
|
117
|
+
export declare function createPinoWriter(logger: PinoLike): ArcLogWriter;
|
|
118
|
+
//#endregion
|
package/dist/logger/index.mjs
CHANGED
|
@@ -1,153 +1,2 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
|
|
3
|
-
//#region src/logger/index.ts
|
|
4
|
-
/**
|
|
5
|
-
* Per-app logger options, resolved from the async context.
|
|
6
|
-
*
|
|
7
|
-
* The process-global below is a FALLBACK, not the source of truth. It used to
|
|
8
|
-
* be both, and `configureArcLogger` overwrote it on every boot — so the
|
|
9
|
-
* last-created app owned the writer for every app in the process. One app's
|
|
10
|
-
* framework warnings then surfaced through another app's transports, level,
|
|
11
|
-
* and redaction config. Fine for one-app-per-process; wrong for multi-app test
|
|
12
|
-
* files and for serverless containers that reuse a warm process across apps.
|
|
13
|
-
*
|
|
14
|
-
* Follows the same shape as `requestContext`: the scope is entered once and
|
|
15
|
-
* wraps everything downstream, so the 23 `arcLog()` call sites keep their
|
|
16
|
-
* zero-argument signature and resolve correctly without threading a logger.
|
|
17
|
-
*/
|
|
18
|
-
const scope = new AsyncLocalStorage();
|
|
19
|
-
let globalOptions = {};
|
|
20
|
-
/** Active options: the app's if we're inside one, else the process fallback. */
|
|
21
|
-
function resolveOptions() {
|
|
22
|
-
return scope.getStore() ?? globalOptions;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Run `fn` with `options` as the active logger config.
|
|
26
|
-
*
|
|
27
|
-
* `options` is held BY REFERENCE deliberately: `createApp` enters the scope
|
|
28
|
-
* before Fastify exists, then fills in the pino writer once `fastify.log` is
|
|
29
|
-
* constructed. Copying here would freeze the pre-Fastify view and send every
|
|
30
|
-
* post-construction boot warning to the console instead of the app's logger.
|
|
31
|
-
*/
|
|
32
|
-
function runWithArcLogger(options, fn) {
|
|
33
|
-
return scope.run(options, fn);
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Enter `options` for the remainder of the current async context.
|
|
37
|
-
*
|
|
38
|
-
* For Fastify's `onRequest` hook, where `run(store, done)` wraps the rest of
|
|
39
|
-
* the request lifecycle. Outside a hook, prefer {@link runWithArcLogger}.
|
|
40
|
-
*/
|
|
41
|
-
function enterArcLoggerScope(options, done) {
|
|
42
|
-
scope.run(options, done);
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Configure the PROCESS-GLOBAL Arc logger — the fallback used outside any app.
|
|
46
|
-
*
|
|
47
|
-
* `createApp` no longer routes its writer through here; each app carries its
|
|
48
|
-
* own scoped options (see {@link runWithArcLogger}) so two apps in one process
|
|
49
|
-
* cannot overwrite each other's. This remains the way to configure arcLog for
|
|
50
|
-
* standalone use — `defineResource()` at module import, CLI commands, and any
|
|
51
|
-
* code running before or outside a `createApp` boot.
|
|
52
|
-
*/
|
|
53
|
-
function configureArcLogger(options) {
|
|
54
|
-
globalOptions = { ...options };
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Create a module-scoped logger.
|
|
58
|
-
*
|
|
59
|
-
* Debug and info messages are gated by the `ARC_DEBUG` env var or
|
|
60
|
-
* `createApp({ debug })` option. Warnings always show (unless
|
|
61
|
-
* `ARC_SUPPRESS_WARNINGS=1`). Errors always show.
|
|
62
|
-
*
|
|
63
|
-
* @param module - Module name (e.g., 'scope', 'elevation', 'sse', 'preset')
|
|
64
|
-
* @returns Logger instance for that module
|
|
65
|
-
*
|
|
66
|
-
* @example
|
|
67
|
-
* ```typescript
|
|
68
|
-
* const log = arcLog('elevation');
|
|
69
|
-
* log.debug('Checking elevation header');
|
|
70
|
-
* log.warn('No authenticate decorator found');
|
|
71
|
-
* ```
|
|
72
|
-
*/
|
|
73
|
-
function arcLog(module) {
|
|
74
|
-
const prefix = `[arc:${module}]`;
|
|
75
|
-
return {
|
|
76
|
-
debug(...args) {
|
|
77
|
-
if (isDebugEnabled(module)) getWriter().debug(prefix, ...args);
|
|
78
|
-
},
|
|
79
|
-
info(...args) {
|
|
80
|
-
if (isDebugEnabled(module)) getWriter().info(prefix, ...args);
|
|
81
|
-
},
|
|
82
|
-
warn(...args) {
|
|
83
|
-
if (isSuppressed()) return;
|
|
84
|
-
getWriter().warn(prefix, ...args);
|
|
85
|
-
},
|
|
86
|
-
error(...args) {
|
|
87
|
-
getWriter().error(prefix, ...args);
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Bridge an `ArcLogWriter` onto a pino-style logger (`fastify.log`).
|
|
93
|
-
*
|
|
94
|
-
* arcLog call sites use the console convention — positional args like
|
|
95
|
-
* `log.warn("message", { userId })` — which pino would silently drop
|
|
96
|
-
* (extra args are printf interpolation values there). The bridge folds
|
|
97
|
-
* string args into the message, merges object args into the pino merge
|
|
98
|
-
* object, and maps `Error` instances to `{ err }` so pino's error
|
|
99
|
-
* serializer applies.
|
|
100
|
-
*
|
|
101
|
-
* `createApp` installs this automatically so arc-internal warnings flow
|
|
102
|
-
* through the host's transports, level, and redaction config.
|
|
103
|
-
*/
|
|
104
|
-
function createPinoWriter(logger) {
|
|
105
|
-
const emit = (level) => (...args) => {
|
|
106
|
-
const parts = [];
|
|
107
|
-
let merge;
|
|
108
|
-
for (const arg of args) if (typeof arg === "string") parts.push(arg);
|
|
109
|
-
else if (arg instanceof Error) merge = {
|
|
110
|
-
...merge ?? {},
|
|
111
|
-
err: arg
|
|
112
|
-
};
|
|
113
|
-
else if (arg !== null && typeof arg === "object") merge = {
|
|
114
|
-
...merge ?? {},
|
|
115
|
-
...arg
|
|
116
|
-
};
|
|
117
|
-
else parts.push(String(arg));
|
|
118
|
-
const msg = parts.join(" ");
|
|
119
|
-
if (merge) logger[level](merge, msg);
|
|
120
|
-
else logger[level](msg);
|
|
121
|
-
};
|
|
122
|
-
return {
|
|
123
|
-
debug: emit("debug"),
|
|
124
|
-
info: emit("info"),
|
|
125
|
-
warn: emit("warn"),
|
|
126
|
-
error: emit("error")
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
function getWriter() {
|
|
130
|
-
return resolveOptions().writer ?? console;
|
|
131
|
-
}
|
|
132
|
-
function isDebugEnabled(module) {
|
|
133
|
-
const configDebug = resolveOptions().debug;
|
|
134
|
-
if (configDebug !== void 0 && configDebug !== false) return matchesModule(configDebug, module);
|
|
135
|
-
const envDebug = typeof process !== "undefined" ? process.env?.ARC_DEBUG : void 0;
|
|
136
|
-
if (envDebug) return matchesModule(envDebug, module);
|
|
137
|
-
return false;
|
|
138
|
-
}
|
|
139
|
-
function matchesModule(debug, module) {
|
|
140
|
-
if (debug === true) return true;
|
|
141
|
-
if (typeof debug === "string") {
|
|
142
|
-
const normalized = debug.trim();
|
|
143
|
-
if (normalized === "1" || normalized === "true" || normalized === "*") return true;
|
|
144
|
-
return normalized.split(",").map((s) => s.trim()).includes(module);
|
|
145
|
-
}
|
|
146
|
-
return false;
|
|
147
|
-
}
|
|
148
|
-
function isSuppressed() {
|
|
149
|
-
const env = typeof process !== "undefined" ? process.env?.ARC_SUPPRESS_WARNINGS : void 0;
|
|
150
|
-
return env === "1" || env === "true";
|
|
151
|
-
}
|
|
152
|
-
//#endregion
|
|
153
|
-
export { arcLog, configureArcLogger, createPinoWriter, enterArcLoggerScope, runWithArcLogger };
|
|
1
|
+
/*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
|
|
2
|
+
export { t as arcLog, n as configureArcLogger, r as createPinoWriter, i as runWithArcLogger } from "../logger-D4V1zGLI.mjs";
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
|
|
2
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
|
+
//#region src/logger/scope.ts
|
|
4
|
+
/**
|
|
5
|
+
* Internal — NOT a package entry. The per-app logger scope that
|
|
6
|
+
* `@classytic/arc/logger` resolves against, plus the one hook-shaped entry
|
|
7
|
+
* point `createApp` needs. Kept off the public barrel: hosts use
|
|
8
|
+
* `runWithArcLogger` from `@classytic/arc/logger`.
|
|
9
|
+
*
|
|
10
|
+
* Per-app logger options, resolved from the async context.
|
|
11
|
+
*
|
|
12
|
+
* The process-global in `./index.ts` is a FALLBACK, not the source of truth. It
|
|
13
|
+
* used to be both, and `configureArcLogger` overwrote it on every boot — so the
|
|
14
|
+
* last-created app owned the writer for every app in the process. One app's
|
|
15
|
+
* framework warnings then surfaced through another app's transports, level,
|
|
16
|
+
* and redaction config. Fine for one-app-per-process; wrong for multi-app test
|
|
17
|
+
* files and for serverless containers that reuse a warm process across apps.
|
|
18
|
+
*
|
|
19
|
+
* Follows the same shape as `requestContext`: the scope is entered once and
|
|
20
|
+
* wraps everything downstream, so the `arcLog()` call sites keep their
|
|
21
|
+
* zero-argument signature and resolve correctly without threading a logger.
|
|
22
|
+
*/
|
|
23
|
+
const arcLoggerScope = new AsyncLocalStorage();
|
|
24
|
+
/**
|
|
25
|
+
* Enter `options` for the remainder of the current async context.
|
|
26
|
+
*
|
|
27
|
+
* For Fastify's `onRequest` hook, where `run(store, done)` wraps the rest of
|
|
28
|
+
* the request lifecycle. Outside a hook, use `runWithArcLogger`.
|
|
29
|
+
*/
|
|
30
|
+
function enterArcLoggerScope(options, done) {
|
|
31
|
+
arcLoggerScope.run(options, done);
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/logger/index.ts
|
|
35
|
+
let globalOptions = {};
|
|
36
|
+
/** Active options: the app's if we're inside one, else the process fallback. */
|
|
37
|
+
function resolveOptions() {
|
|
38
|
+
return arcLoggerScope.getStore() ?? globalOptions;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Run `fn` with `options` as the active logger config.
|
|
42
|
+
*
|
|
43
|
+
* `options` is held BY REFERENCE deliberately: `createApp` enters the scope
|
|
44
|
+
* before Fastify exists, then fills in the pino writer once `fastify.log` is
|
|
45
|
+
* constructed. Copying here would freeze the pre-Fastify view and send every
|
|
46
|
+
* post-construction boot warning to the console instead of the app's logger.
|
|
47
|
+
*/
|
|
48
|
+
function runWithArcLogger(options, fn) {
|
|
49
|
+
return arcLoggerScope.run(options, fn);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Configure the PROCESS-GLOBAL Arc logger — the fallback used outside any app.
|
|
53
|
+
*
|
|
54
|
+
* `createApp` no longer routes its writer through here; each app carries its
|
|
55
|
+
* own scoped options (see {@link runWithArcLogger}) so two apps in one process
|
|
56
|
+
* cannot overwrite each other's. This remains the way to configure arcLog for
|
|
57
|
+
* standalone use — `defineResource()` at module import, CLI commands, and any
|
|
58
|
+
* code running before or outside a `createApp` boot.
|
|
59
|
+
*/
|
|
60
|
+
function configureArcLogger(options) {
|
|
61
|
+
globalOptions = { ...options };
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Create a module-scoped logger.
|
|
65
|
+
*
|
|
66
|
+
* Debug and info messages are gated by the `ARC_DEBUG` env var or
|
|
67
|
+
* `createApp({ debug })` option. Warnings always show (unless
|
|
68
|
+
* `ARC_SUPPRESS_WARNINGS=1`). Errors always show.
|
|
69
|
+
*
|
|
70
|
+
* @param module - Module name (e.g., 'scope', 'elevation', 'sse', 'preset')
|
|
71
|
+
* @returns Logger instance for that module
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* const log = arcLog('elevation');
|
|
76
|
+
* log.debug('Checking elevation header');
|
|
77
|
+
* log.warn('No authenticate decorator found');
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
function arcLog(module) {
|
|
81
|
+
const prefix = `[arc:${module}]`;
|
|
82
|
+
return {
|
|
83
|
+
debug(...args) {
|
|
84
|
+
if (isDebugEnabled(module)) getWriter().debug(prefix, ...args);
|
|
85
|
+
},
|
|
86
|
+
info(...args) {
|
|
87
|
+
if (isDebugEnabled(module)) getWriter().info(prefix, ...args);
|
|
88
|
+
},
|
|
89
|
+
warn(...args) {
|
|
90
|
+
if (isSuppressed()) return;
|
|
91
|
+
getWriter().warn(prefix, ...args);
|
|
92
|
+
},
|
|
93
|
+
error(...args) {
|
|
94
|
+
getWriter().error(prefix, ...args);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Bridge an `ArcLogWriter` onto a pino-style logger (`fastify.log`).
|
|
100
|
+
*
|
|
101
|
+
* arcLog call sites use the console convention — positional args like
|
|
102
|
+
* `log.warn("message", { userId })` — which pino would silently drop
|
|
103
|
+
* (extra args are printf interpolation values there). The bridge folds
|
|
104
|
+
* string args into the message, merges object args into the pino merge
|
|
105
|
+
* object, and maps `Error` instances to `{ err }` so pino's error
|
|
106
|
+
* serializer applies.
|
|
107
|
+
*
|
|
108
|
+
* `createApp` installs this automatically so arc-internal warnings flow
|
|
109
|
+
* through the host's transports, level, and redaction config.
|
|
110
|
+
*/
|
|
111
|
+
function createPinoWriter(logger) {
|
|
112
|
+
const emit = (level) => (...args) => {
|
|
113
|
+
const parts = [];
|
|
114
|
+
let merge;
|
|
115
|
+
for (const arg of args) if (typeof arg === "string") parts.push(arg);
|
|
116
|
+
else if (arg instanceof Error) merge = {
|
|
117
|
+
...merge ?? {},
|
|
118
|
+
err: arg
|
|
119
|
+
};
|
|
120
|
+
else if (arg !== null && typeof arg === "object") merge = {
|
|
121
|
+
...merge ?? {},
|
|
122
|
+
...arg
|
|
123
|
+
};
|
|
124
|
+
else parts.push(String(arg));
|
|
125
|
+
const msg = parts.join(" ");
|
|
126
|
+
if (merge) logger[level](merge, msg);
|
|
127
|
+
else logger[level](msg);
|
|
128
|
+
};
|
|
129
|
+
return {
|
|
130
|
+
debug: emit("debug"),
|
|
131
|
+
info: emit("info"),
|
|
132
|
+
warn: emit("warn"),
|
|
133
|
+
error: emit("error")
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function getWriter() {
|
|
137
|
+
return resolveOptions().writer ?? console;
|
|
138
|
+
}
|
|
139
|
+
function isDebugEnabled(module) {
|
|
140
|
+
const configDebug = resolveOptions().debug;
|
|
141
|
+
if (configDebug !== void 0 && configDebug !== false) return matchesModule(configDebug, module);
|
|
142
|
+
const envDebug = typeof process !== "undefined" ? process.env?.ARC_DEBUG : void 0;
|
|
143
|
+
if (envDebug) return matchesModule(envDebug, module);
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
function matchesModule(debug, module) {
|
|
147
|
+
if (debug === true) return true;
|
|
148
|
+
if (typeof debug === "string") {
|
|
149
|
+
const normalized = debug.trim();
|
|
150
|
+
if (normalized === "1" || normalized === "true" || normalized === "*") return true;
|
|
151
|
+
return normalized.split(",").map((s) => s.trim()).includes(module);
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
function isSuppressed() {
|
|
156
|
+
const env = typeof process !== "undefined" ? process.env?.ARC_SUPPRESS_WARNINGS : void 0;
|
|
157
|
+
return env === "1" || env === "true";
|
|
158
|
+
}
|
|
159
|
+
//#endregion
|
|
160
|
+
export { enterArcLoggerScope as a, runWithArcLogger as i, configureArcLogger as n, createPinoWriter as r, arcLog as t };
|