@classytic/arc 1.1.0 → 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/README.md +247 -794
  2. package/bin/arc.js +91 -52
  3. package/dist/EventTransport-BkUDYZEb.d.mts +99 -0
  4. package/dist/HookSystem-BsGV-j2l.mjs +404 -0
  5. package/dist/ResourceRegistry-7Ic20ZMw.mjs +249 -0
  6. package/dist/adapters/index.d.mts +5 -0
  7. package/dist/adapters/index.mjs +3 -0
  8. package/dist/audit/index.d.mts +81 -0
  9. package/dist/audit/index.mjs +275 -0
  10. package/dist/audit/mongodb.d.mts +5 -0
  11. package/dist/audit/mongodb.mjs +3 -0
  12. package/dist/audited-CGdLiSlE.mjs +140 -0
  13. package/dist/auth/index.d.mts +188 -0
  14. package/dist/auth/index.mjs +1096 -0
  15. package/dist/auth/redis-session.d.mts +43 -0
  16. package/dist/auth/redis-session.mjs +75 -0
  17. package/dist/betterAuthOpenApi-DjWDddNc.mjs +249 -0
  18. package/dist/cache/index.d.mts +145 -0
  19. package/dist/cache/index.mjs +91 -0
  20. package/dist/caching-GSDJcA6-.mjs +93 -0
  21. package/dist/chunk-C7Uep-_p.mjs +20 -0
  22. package/dist/circuitBreaker-DYhWBW_D.mjs +1096 -0
  23. package/dist/cli/commands/describe.d.mts +18 -0
  24. package/dist/cli/commands/describe.mjs +238 -0
  25. package/dist/cli/commands/docs.d.mts +13 -0
  26. package/dist/cli/commands/docs.mjs +52 -0
  27. package/dist/cli/commands/{generate.d.ts → generate.d.mts} +3 -2
  28. package/dist/cli/commands/generate.mjs +357 -0
  29. package/dist/cli/commands/{init.d.ts → init.d.mts} +11 -8
  30. package/dist/cli/commands/{init.js → init.mjs} +807 -617
  31. package/dist/cli/commands/introspect.d.mts +10 -0
  32. package/dist/cli/commands/introspect.mjs +75 -0
  33. package/dist/cli/index.d.mts +16 -0
  34. package/dist/cli/index.mjs +156 -0
  35. package/dist/constants-DdXFXQtN.mjs +84 -0
  36. package/dist/core/index.d.mts +5 -0
  37. package/dist/core/index.mjs +4 -0
  38. package/dist/createApp-D2D5XXaV.mjs +559 -0
  39. package/dist/defineResource-PXzSJ15_.mjs +2197 -0
  40. package/dist/discovery/index.d.mts +46 -0
  41. package/dist/discovery/index.mjs +109 -0
  42. package/dist/docs/index.d.mts +162 -0
  43. package/dist/docs/index.mjs +74 -0
  44. package/dist/elevation-DGo5shaX.d.mts +87 -0
  45. package/dist/elevation-DSTbVvYj.mjs +113 -0
  46. package/dist/errorHandler-C3GY3_ow.mjs +108 -0
  47. package/dist/errorHandler-CW3OOeYq.d.mts +72 -0
  48. package/dist/errors-DAWRdiYP.d.mts +124 -0
  49. package/dist/errors-DBANPbGr.mjs +211 -0
  50. package/dist/eventPlugin-BEOvaDqo.mjs +229 -0
  51. package/dist/eventPlugin-H6wDDjGO.d.mts +124 -0
  52. package/dist/events/index.d.mts +53 -0
  53. package/dist/events/index.mjs +51 -0
  54. package/dist/events/transports/redis-stream-entry.d.mts +2 -0
  55. package/dist/events/transports/redis-stream-entry.mjs +177 -0
  56. package/dist/events/transports/redis.d.mts +76 -0
  57. package/dist/events/transports/redis.mjs +124 -0
  58. package/dist/externalPaths-SyPF2tgK.d.mts +50 -0
  59. package/dist/factory/index.d.mts +63 -0
  60. package/dist/factory/index.mjs +3 -0
  61. package/dist/fastifyAdapter-C8DlE0YH.d.mts +216 -0
  62. package/dist/fields-Bi_AVKSo.d.mts +109 -0
  63. package/dist/fields-CTd_CrKr.mjs +114 -0
  64. package/dist/hooks/index.d.mts +4 -0
  65. package/dist/hooks/index.mjs +3 -0
  66. package/dist/idempotency/index.d.mts +96 -0
  67. package/dist/idempotency/index.mjs +319 -0
  68. package/dist/idempotency/mongodb.d.mts +2 -0
  69. package/dist/idempotency/mongodb.mjs +114 -0
  70. package/dist/idempotency/redis.d.mts +2 -0
  71. package/dist/idempotency/redis.mjs +103 -0
  72. package/dist/index.d.mts +260 -0
  73. package/dist/index.mjs +104 -0
  74. package/dist/integrations/event-gateway.d.mts +46 -0
  75. package/dist/integrations/event-gateway.mjs +43 -0
  76. package/dist/integrations/index.d.mts +5 -0
  77. package/dist/integrations/index.mjs +1 -0
  78. package/dist/integrations/jobs.d.mts +103 -0
  79. package/dist/integrations/jobs.mjs +123 -0
  80. package/dist/integrations/streamline.d.mts +60 -0
  81. package/dist/integrations/streamline.mjs +125 -0
  82. package/dist/integrations/websocket.d.mts +82 -0
  83. package/dist/integrations/websocket.mjs +288 -0
  84. package/dist/interface-CSNjltAc.d.mts +77 -0
  85. package/dist/interface-DTbsvIWe.d.mts +54 -0
  86. package/dist/interface-e9XfSsUV.d.mts +1097 -0
  87. package/dist/introspectionPlugin-B3JkrjwU.mjs +53 -0
  88. package/dist/keys-DhqDRxv3.mjs +42 -0
  89. package/dist/logger-ByrvQWZO.mjs +78 -0
  90. package/dist/memory-B2v7KrCB.mjs +143 -0
  91. package/dist/migrations/index.d.mts +156 -0
  92. package/dist/migrations/index.mjs +260 -0
  93. package/dist/mongodb-ClykrfGo.d.mts +118 -0
  94. package/dist/mongodb-DNKEExbf.mjs +93 -0
  95. package/dist/mongodb-Dg8O_gvd.d.mts +71 -0
  96. package/dist/openapi-9nB_kiuR.mjs +525 -0
  97. package/dist/org/index.d.mts +68 -0
  98. package/dist/org/index.mjs +513 -0
  99. package/dist/org/types.d.mts +82 -0
  100. package/dist/org/types.mjs +1 -0
  101. package/dist/permissions/index.d.mts +278 -0
  102. package/dist/permissions/index.mjs +579 -0
  103. package/dist/plugins/index.d.mts +172 -0
  104. package/dist/plugins/index.mjs +522 -0
  105. package/dist/plugins/response-cache.d.mts +87 -0
  106. package/dist/plugins/response-cache.mjs +283 -0
  107. package/dist/plugins/tracing-entry.d.mts +2 -0
  108. package/dist/plugins/tracing-entry.mjs +185 -0
  109. package/dist/pluralize-CM-jZg7p.mjs +86 -0
  110. package/dist/policies/{index.d.ts → index.d.mts} +204 -170
  111. package/dist/policies/index.mjs +321 -0
  112. package/dist/presets/{index.d.ts → index.d.mts} +62 -131
  113. package/dist/presets/index.mjs +143 -0
  114. package/dist/presets/multiTenant.d.mts +24 -0
  115. package/dist/presets/multiTenant.mjs +113 -0
  116. package/dist/presets-BTeYbw7h.d.mts +57 -0
  117. package/dist/presets-CeFtfDR8.mjs +119 -0
  118. package/dist/prisma-C3iornoK.d.mts +274 -0
  119. package/dist/prisma-DJbMt3yf.mjs +627 -0
  120. package/dist/queryCachePlugin-B6R0d4av.mjs +138 -0
  121. package/dist/queryCachePlugin-Q6SYuHZ6.d.mts +71 -0
  122. package/dist/redis-UwjEp8Ea.d.mts +49 -0
  123. package/dist/redis-stream-CBg0upHI.d.mts +103 -0
  124. package/dist/registry/index.d.mts +11 -0
  125. package/dist/registry/index.mjs +4 -0
  126. package/dist/requestContext-xi6OKBL-.mjs +55 -0
  127. package/dist/schemaConverter-Dtg0Kt9T.mjs +98 -0
  128. package/dist/schemas/index.d.mts +63 -0
  129. package/dist/schemas/index.mjs +82 -0
  130. package/dist/scope/index.d.mts +21 -0
  131. package/dist/scope/index.mjs +65 -0
  132. package/dist/sessionManager-D_iEHjQl.d.mts +186 -0
  133. package/dist/sse-DkqQ1uxb.mjs +123 -0
  134. package/dist/testing/index.d.mts +907 -0
  135. package/dist/testing/index.mjs +1976 -0
  136. package/dist/tracing-8CEbhF0w.d.mts +70 -0
  137. package/dist/typeGuards-DwxA1t_L.mjs +9 -0
  138. package/dist/types/index.d.mts +946 -0
  139. package/dist/types/index.mjs +14 -0
  140. package/dist/types-B0dhNrnd.d.mts +445 -0
  141. package/dist/types-Beqn1Un7.mjs +38 -0
  142. package/dist/types-DelU6kln.mjs +25 -0
  143. package/dist/types-RLkFVgaw.d.mts +101 -0
  144. package/dist/utils/index.d.mts +747 -0
  145. package/dist/utils/index.mjs +6 -0
  146. package/package.json +194 -68
  147. package/dist/BaseController-DVAiHxEQ.d.ts +0 -233
  148. package/dist/adapters/index.d.ts +0 -237
  149. package/dist/adapters/index.js +0 -668
  150. package/dist/arcCorePlugin-CsShQdyP.d.ts +0 -273
  151. package/dist/audit/index.d.ts +0 -195
  152. package/dist/audit/index.js +0 -319
  153. package/dist/auth/index.d.ts +0 -47
  154. package/dist/auth/index.js +0 -174
  155. package/dist/cli/commands/docs.d.ts +0 -11
  156. package/dist/cli/commands/docs.js +0 -474
  157. package/dist/cli/commands/generate.js +0 -334
  158. package/dist/cli/commands/introspect.d.ts +0 -8
  159. package/dist/cli/commands/introspect.js +0 -338
  160. package/dist/cli/index.d.ts +0 -4
  161. package/dist/cli/index.js +0 -3269
  162. package/dist/core/index.d.ts +0 -220
  163. package/dist/core/index.js +0 -2786
  164. package/dist/createApp-Ce9wl8W9.d.ts +0 -77
  165. package/dist/docs/index.d.ts +0 -166
  166. package/dist/docs/index.js +0 -658
  167. package/dist/errors-8WIxGS_6.d.ts +0 -122
  168. package/dist/events/index.d.ts +0 -117
  169. package/dist/events/index.js +0 -89
  170. package/dist/factory/index.d.ts +0 -38
  171. package/dist/factory/index.js +0 -1652
  172. package/dist/hooks/index.d.ts +0 -4
  173. package/dist/hooks/index.js +0 -199
  174. package/dist/idempotency/index.d.ts +0 -323
  175. package/dist/idempotency/index.js +0 -500
  176. package/dist/index-B4t03KQ0.d.ts +0 -1366
  177. package/dist/index.d.ts +0 -135
  178. package/dist/index.js +0 -4756
  179. package/dist/migrations/index.d.ts +0 -185
  180. package/dist/migrations/index.js +0 -274
  181. package/dist/org/index.d.ts +0 -129
  182. package/dist/org/index.js +0 -220
  183. package/dist/permissions/index.d.ts +0 -144
  184. package/dist/permissions/index.js +0 -103
  185. package/dist/plugins/index.d.ts +0 -46
  186. package/dist/plugins/index.js +0 -1069
  187. package/dist/policies/index.js +0 -196
  188. package/dist/presets/index.js +0 -384
  189. package/dist/presets/multiTenant.d.ts +0 -39
  190. package/dist/presets/multiTenant.js +0 -112
  191. package/dist/registry/index.d.ts +0 -16
  192. package/dist/registry/index.js +0 -253
  193. package/dist/testing/index.d.ts +0 -618
  194. package/dist/testing/index.js +0 -48020
  195. package/dist/types/index.d.ts +0 -4
  196. package/dist/types/index.js +0 -8
  197. package/dist/types-B99TBmFV.d.ts +0 -76
  198. package/dist/types-BvckRbs2.d.ts +0 -143
  199. package/dist/utils/index.d.ts +0 -679
  200. package/dist/utils/index.js +0 -931
@@ -0,0 +1,138 @@
1
+ import { t as __exportAll } from "./chunk-C7Uep-_p.mjs";
2
+ import { i as versionKey, r as tagVersionKey } from "./keys-DhqDRxv3.mjs";
3
+ import { t as hasEvents } from "./typeGuards-DwxA1t_L.mjs";
4
+ import { t as MemoryCacheStore } from "./memory-B2v7KrCB.mjs";
5
+ import fp from "fastify-plugin";
6
+
7
+ //#region src/cache/QueryCache.ts
8
+ var QueryCache = class {
9
+ store;
10
+ constructor(store) {
11
+ this.store = store;
12
+ }
13
+ async get(key) {
14
+ const envelope = await this.store.get(key);
15
+ if (!envelope || !envelope.createdAt) return {
16
+ data: void 0,
17
+ status: "miss"
18
+ };
19
+ const now = Date.now();
20
+ if (now >= envelope.expiresAt) {
21
+ await this.store.delete(key);
22
+ return {
23
+ data: void 0,
24
+ status: "miss"
25
+ };
26
+ }
27
+ if (now < envelope.staleAfter) return {
28
+ data: envelope.data,
29
+ status: "fresh"
30
+ };
31
+ return {
32
+ data: envelope.data,
33
+ status: "stale"
34
+ };
35
+ }
36
+ async set(key, data, config) {
37
+ const staleTimeMs = (config.staleTime ?? 0) * 1e3;
38
+ const totalTtl = staleTimeMs + (config.gcTime ?? 60) * 1e3;
39
+ const now = Date.now();
40
+ const envelope = {
41
+ data,
42
+ createdAt: now,
43
+ staleAfter: now + staleTimeMs,
44
+ expiresAt: now + totalTtl,
45
+ tags: config.tags ?? []
46
+ };
47
+ await this.store.set(key, envelope, { ttlMs: totalTtl });
48
+ }
49
+ async invalidate(key) {
50
+ await this.store.delete(key);
51
+ }
52
+ /** Get current version for a resource (defaults to 0 if not set) */
53
+ async getResourceVersion(resource) {
54
+ return await this.store.get(versionKey(resource)) ?? 0;
55
+ }
56
+ /** Bump resource version — orphans all cached queries for this resource */
57
+ async bumpResourceVersion(resource) {
58
+ const key = versionKey(resource);
59
+ const newVersion = Date.now();
60
+ await this.store.set(key, newVersion, { ttlMs: 1440 * 60 * 1e3 });
61
+ }
62
+ /** Get current version for a tag */
63
+ async getTagVersion(tag) {
64
+ return await this.store.get(tagVersionKey(tag)) ?? 0;
65
+ }
66
+ /** Bump tag version — orphans all cached queries tagged with this tag */
67
+ async bumpTagVersion(tag) {
68
+ const key = tagVersionKey(tag);
69
+ const newVersion = Date.now();
70
+ await this.store.set(key, newVersion, { ttlMs: 1440 * 60 * 1e3 });
71
+ }
72
+ };
73
+
74
+ //#endregion
75
+ //#region src/cache/queryCachePlugin.ts
76
+ /**
77
+ * QueryCache Fastify Plugin
78
+ *
79
+ * Registers QueryCache on `fastify.queryCache` and wires automatic
80
+ * cache invalidation via CRUD events. Zero config for memory mode.
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * // Memory mode (default)
85
+ * await fastify.register(queryCachePlugin);
86
+ *
87
+ * // With Redis store
88
+ * await fastify.register(queryCachePlugin, {
89
+ * store: new RedisCacheStore({ client: redis, prefix: 'arc:qc:' }),
90
+ * defaults: { staleTime: 30, gcTime: 300 },
91
+ * });
92
+ * ```
93
+ */
94
+ var queryCachePlugin_exports = /* @__PURE__ */ __exportAll({ queryCachePlugin: () => queryCachePlugin });
95
+ const CRUD_SUFFIXES = new Set([
96
+ "created",
97
+ "updated",
98
+ "deleted"
99
+ ]);
100
+ const queryCachePluginImpl = async (fastify, opts = {}) => {
101
+ const store = opts.store ?? new MemoryCacheStore();
102
+ const queryCache = new QueryCache(store);
103
+ const defaults = {
104
+ staleTime: opts.defaults?.staleTime ?? 0,
105
+ gcTime: opts.defaults?.gcTime ?? 60
106
+ };
107
+ fastify.decorate("queryCache", queryCache);
108
+ fastify.decorate("queryCacheConfig", defaults);
109
+ const crossResourceRules = [];
110
+ fastify.decorate("registerCacheInvalidationRule", (rule) => {
111
+ crossResourceRules.push(rule);
112
+ });
113
+ fastify.addHook("onReady", async () => {
114
+ if (!hasEvents(fastify)) return;
115
+ await fastify.events.subscribe("*", async (event) => {
116
+ const type = event.type;
117
+ const dotIdx = type.lastIndexOf(".");
118
+ if (dotIdx === -1) return;
119
+ const suffix = type.slice(dotIdx + 1);
120
+ if (!CRUD_SUFFIXES.has(suffix)) return;
121
+ const resource = type.slice(0, dotIdx);
122
+ await queryCache.bumpResourceVersion(resource);
123
+ });
124
+ for (const rule of crossResourceRules) await fastify.events.subscribe(rule.pattern, async () => {
125
+ for (const tag of rule.tags) await queryCache.bumpTagVersion(tag);
126
+ });
127
+ });
128
+ fastify.addHook("onClose", async () => {
129
+ if ("close" in store && typeof store.close === "function") await store.close();
130
+ });
131
+ };
132
+ const queryCachePlugin = fp(queryCachePluginImpl, {
133
+ name: "arc-query-cache",
134
+ fastify: "5.x"
135
+ });
136
+
137
+ //#endregion
138
+ export { queryCachePlugin_exports as n, QueryCache as r, queryCachePlugin as t };
@@ -0,0 +1,71 @@
1
+ import { i as CacheStore } from "./interface-DTbsvIWe.mjs";
2
+ import { FastifyPluginAsync } from "fastify";
3
+
4
+ //#region src/cache/QueryCache.d.ts
5
+ /** Metadata wrapper stored in CacheStore */
6
+ interface CacheEnvelope<T = unknown> {
7
+ data: T;
8
+ createdAt: number;
9
+ staleAfter: number;
10
+ expiresAt: number;
11
+ tags: string[];
12
+ }
13
+ interface QueryCacheConfig {
14
+ /** Seconds data is "fresh" (no revalidation). Default: 0 */
15
+ staleTime?: number;
16
+ /** Seconds stale data stays cached (SWR window). Default: 60 */
17
+ gcTime?: number;
18
+ /** Tags for group invalidation */
19
+ tags?: string[];
20
+ }
21
+ type CacheStatus = 'fresh' | 'stale' | 'miss';
22
+ interface CacheResult<T> {
23
+ data: T;
24
+ status: CacheStatus;
25
+ }
26
+ declare class QueryCache {
27
+ private readonly store;
28
+ constructor(store: CacheStore);
29
+ get<T>(key: string): Promise<CacheResult<T>>;
30
+ set<T>(key: string, data: T, config: QueryCacheConfig): Promise<void>;
31
+ invalidate(key: string): Promise<void>;
32
+ /** Get current version for a resource (defaults to 0 if not set) */
33
+ getResourceVersion(resource: string): Promise<number>;
34
+ /** Bump resource version — orphans all cached queries for this resource */
35
+ bumpResourceVersion(resource: string): Promise<void>;
36
+ /** Get current version for a tag */
37
+ getTagVersion(tag: string): Promise<number>;
38
+ /** Bump tag version — orphans all cached queries tagged with this tag */
39
+ bumpTagVersion(tag: string): Promise<void>;
40
+ }
41
+ //#endregion
42
+ //#region src/cache/queryCachePlugin.d.ts
43
+ interface QueryCachePluginOptions {
44
+ /** CacheStore instance. Default: MemoryCacheStore with default options. */
45
+ store?: CacheStore;
46
+ /** Global defaults for staleTime/gcTime (seconds) */
47
+ defaults?: {
48
+ staleTime?: number;
49
+ gcTime?: number;
50
+ };
51
+ }
52
+ interface QueryCacheDefaults {
53
+ staleTime: number;
54
+ gcTime: number;
55
+ }
56
+ /** Cross-resource invalidation rules collected from resource configs */
57
+ interface CrossResourceRule {
58
+ pattern: string;
59
+ tags: string[];
60
+ }
61
+ declare module 'fastify' {
62
+ interface FastifyInstance {
63
+ queryCache: QueryCache;
64
+ queryCacheConfig: QueryCacheDefaults;
65
+ /** Register cross-resource invalidation rules (called by defineResource) */
66
+ registerCacheInvalidationRule?(rule: CrossResourceRule): void;
67
+ }
68
+ }
69
+ declare const queryCachePlugin: FastifyPluginAsync<QueryCachePluginOptions>;
70
+ //#endregion
71
+ export { CacheEnvelope as a, QueryCache as c, queryCachePlugin as i, QueryCacheConfig as l, QueryCacheDefaults as n, CacheResult as o, QueryCachePluginOptions as r, CacheStatus as s, CrossResourceRule as t };
@@ -0,0 +1,49 @@
1
+ import { n as IdempotencyResult, r as IdempotencyStore } from "./interface-CSNjltAc.mjs";
2
+
3
+ //#region src/idempotency/stores/redis.d.ts
4
+ interface RedisClient {
5
+ get(key: string): Promise<string | null>;
6
+ set(key: string, value: string, options?: {
7
+ EX?: number;
8
+ NX?: boolean;
9
+ }): Promise<string | null>;
10
+ del(key: string | string[]): Promise<number>;
11
+ exists(key: string | string[]): Promise<number>;
12
+ /** SCAN command — compatible with node-redis and ioredis varargs signatures. */
13
+ scan?(cursor: string | number, ...args: (string | number)[]): Promise<[string | number, string[]]>;
14
+ quit?(): Promise<string>;
15
+ disconnect?(): Promise<void>;
16
+ }
17
+ interface RedisIdempotencyStoreOptions {
18
+ /** Redis client instance */
19
+ client: RedisClient;
20
+ /** Key prefix (default: 'idem:') */
21
+ prefix?: string;
22
+ /** Lock key prefix (default: 'idem:lock:') */
23
+ lockPrefix?: string;
24
+ /** Default TTL in ms (default: 86400000 = 24 hours) */
25
+ ttlMs?: number;
26
+ }
27
+ declare class RedisIdempotencyStore implements IdempotencyStore {
28
+ readonly name = "redis";
29
+ private client;
30
+ private prefix;
31
+ private lockPrefix;
32
+ private ttlMs;
33
+ constructor(options: RedisIdempotencyStoreOptions);
34
+ private resultKey;
35
+ private lockKey;
36
+ get(key: string): Promise<IdempotencyResult | undefined>;
37
+ set(key: string, result: Omit<IdempotencyResult, 'key'>): Promise<void>;
38
+ tryLock(key: string, requestId: string, ttlMs: number): Promise<boolean>;
39
+ unlock(key: string, requestId: string): Promise<void>;
40
+ isLocked(key: string): Promise<boolean>;
41
+ delete(key: string): Promise<void>;
42
+ deleteByPrefix(prefix: string): Promise<number>;
43
+ findByPrefix(prefix: string): Promise<IdempotencyResult | undefined>;
44
+ /** Scan Redis keys matching a prefix pattern. Falls back to empty if SCAN unavailable. */
45
+ private scanByPrefix;
46
+ close(): Promise<void>;
47
+ }
48
+ //#endregion
49
+ export { RedisIdempotencyStore as n, RedisIdempotencyStoreOptions as r, RedisClient as t };
@@ -0,0 +1,103 @@
1
+ import { i as EventTransport, n as EventHandler, r as EventLogger, t as DomainEvent } from "./EventTransport-BkUDYZEb.mjs";
2
+
3
+ //#region src/events/transports/redis-stream.d.ts
4
+ interface RedisStreamLike {
5
+ xadd(key: string, id: string, ...fieldValues: string[]): Promise<string | null>;
6
+ xreadgroup(command: 'GROUP', group: string, consumer: string, ...args: (string | number)[]): Promise<Array<[string, Array<[string, string[]]>]> | null>;
7
+ xack(key: string, group: string, ...ids: string[]): Promise<number>;
8
+ xgroup(command: string, key: string, group: string, ...args: string[]): Promise<unknown>;
9
+ xpending(key: string, group: string, ...args: (string | number)[]): Promise<Array<[string, string, number, number]>>;
10
+ xclaim(key: string, group: string, consumer: string, minIdleTime: number, ...ids: string[]): Promise<Array<[string, string[]]>>;
11
+ xlen(key: string): Promise<number>;
12
+ quit(): Promise<unknown>;
13
+ }
14
+ interface RedisStreamTransportOptions {
15
+ /**
16
+ * Redis stream key name.
17
+ * @default 'arc:events'
18
+ */
19
+ stream?: string;
20
+ /**
21
+ * Consumer group name. Each group receives every event independently.
22
+ * Multiple instances of the same service should share a group name.
23
+ * @default 'default'
24
+ */
25
+ group?: string;
26
+ /**
27
+ * Consumer name within the group. Must be unique per instance.
28
+ * @default 'consumer-<random>'
29
+ */
30
+ consumer?: string;
31
+ /**
32
+ * Block time in ms when waiting for new events.
33
+ * @default 5000
34
+ */
35
+ blockTimeMs?: number;
36
+ /**
37
+ * Max events to read per batch.
38
+ * @default 10
39
+ */
40
+ batchSize?: number;
41
+ /**
42
+ * Max delivery attempts before moving to dead letter stream.
43
+ * @default 5
44
+ */
45
+ maxRetries?: number;
46
+ /**
47
+ * Idle time in ms before pending entries are claimed by this consumer.
48
+ * Handles crash recovery — if a consumer dies mid-processing, another
49
+ * consumer will claim its pending entries after this timeout.
50
+ * @default 30000
51
+ */
52
+ claimTimeoutMs?: number;
53
+ /**
54
+ * Dead letter stream name. Failed events are moved here after maxRetries.
55
+ * Set to `false` to disable DLQ (failed events are acked and dropped).
56
+ * @default 'arc:events:dlq'
57
+ */
58
+ deadLetterStream?: string | false;
59
+ /**
60
+ * Max stream length (approximate). Uses XADD MAXLEN ~ to trim old entries.
61
+ * Set to 0 to disable trimming.
62
+ * @default 10000
63
+ */
64
+ maxLen?: number;
65
+ /**
66
+ * Logger for error messages (default: console).
67
+ * Pass `fastify.log` to integrate with your application logger.
68
+ */
69
+ logger?: EventLogger;
70
+ }
71
+ declare class RedisStreamTransport implements EventTransport {
72
+ readonly name = "redis-stream";
73
+ private redis;
74
+ private stream;
75
+ private group;
76
+ private consumer;
77
+ private blockTimeMs;
78
+ private batchSize;
79
+ private maxRetries;
80
+ private claimTimeoutMs;
81
+ private deadLetterStream;
82
+ private maxLen;
83
+ private logger;
84
+ private handlers;
85
+ private running;
86
+ private pollPromise;
87
+ private groupCreated;
88
+ constructor(redis: RedisStreamLike, options?: RedisStreamTransportOptions);
89
+ publish(event: DomainEvent): Promise<void>;
90
+ subscribe(pattern: string, handler: EventHandler): Promise<() => void>;
91
+ close(): Promise<void>;
92
+ private ensureGroup;
93
+ private pollLoop;
94
+ private readNewMessages;
95
+ private claimPending;
96
+ private processEntry;
97
+ private getMatchingHandlers;
98
+ private matchesPattern;
99
+ private moveToDlq;
100
+ private sleep;
101
+ }
102
+ //#endregion
103
+ export { RedisStreamTransport as n, RedisStreamTransportOptions as r, RedisStreamLike as t };
@@ -0,0 +1,11 @@
1
+ import "../elevation-DGo5shaX.mjs";
2
+ import { C as RegisterOptions, w as ResourceRegistry } from "../interface-e9XfSsUV.mjs";
3
+ import "../types-RLkFVgaw.mjs";
4
+ import { IntrospectionPluginOptions } from "../types/index.mjs";
5
+ import { FastifyPluginAsync } from "fastify";
6
+
7
+ //#region src/registry/introspectionPlugin.d.ts
8
+ declare const introspectionPlugin: FastifyPluginAsync<IntrospectionPluginOptions>;
9
+ declare const _default: FastifyPluginAsync<IntrospectionPluginOptions>;
10
+ //#endregion
11
+ export { type IntrospectionPluginOptions, type RegisterOptions, ResourceRegistry, _default as introspectionPlugin, introspectionPlugin as introspectionPluginFn };
@@ -0,0 +1,4 @@
1
+ import { t as ResourceRegistry } from "../ResourceRegistry-7Ic20ZMw.mjs";
2
+ import { n as introspectionPlugin_default, t as introspectionPlugin } from "../introspectionPlugin-B3JkrjwU.mjs";
3
+
4
+ export { ResourceRegistry, introspectionPlugin_default as introspectionPlugin, introspectionPlugin as introspectionPluginFn };
@@ -0,0 +1,55 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+
3
+ //#region src/context/requestContext.ts
4
+ /**
5
+ * Request Context via AsyncLocalStorage
6
+ *
7
+ * Provides request-scoped context accessible anywhere in the call stack
8
+ * without threading parameters through every function call.
9
+ *
10
+ * Uses Node.js native AsyncLocalStorage — zero-cost per request, no allocation
11
+ * beyond the store object, and fully supported since Node 16.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * import { requestContext } from '@classytic/arc';
16
+ *
17
+ * // Anywhere in the call stack — no parameter passing needed
18
+ * async function auditAction(action: string) {
19
+ * const ctx = requestContext.get();
20
+ * await auditLog.write({
21
+ * action,
22
+ * userId: ctx?.user?.id,
23
+ * orgId: ctx?.organizationId,
24
+ * requestId: ctx?.requestId,
25
+ * });
26
+ * }
27
+ *
28
+ * // Type-safe access to specific fields
29
+ * const userId = requestContext.get()?.user?.id;
30
+ * const orgId = requestContext.get()?.organizationId;
31
+ * ```
32
+ */
33
+ const storage = new AsyncLocalStorage();
34
+ /**
35
+ * Request context API.
36
+ *
37
+ * - `get()` — returns current store or undefined if outside request scope
38
+ * - `run(store, fn)` — run a function with a specific store (used by Arc internals)
39
+ * - `getStore()` — alias for get() (matches Node.js API naming)
40
+ */
41
+ const requestContext = {
42
+ get() {
43
+ return storage.getStore();
44
+ },
45
+ getStore() {
46
+ return storage.getStore();
47
+ },
48
+ run(store, fn) {
49
+ return storage.run(store, fn);
50
+ },
51
+ storage
52
+ };
53
+
54
+ //#endregion
55
+ export { requestContext as t };
@@ -0,0 +1,98 @@
1
+ //#region src/utils/schemaConverter.ts
2
+ let _toJSONSchema = null;
3
+ import("zod").then(({ z }) => {
4
+ if (typeof z?.toJSONSchema === "function") _toJSONSchema = (schema, opts) => z.toJSONSchema(schema, opts);
5
+ }).catch(() => {});
6
+ /**
7
+ * Check if an object is already a plain JSON Schema.
8
+ * Returns true if it has JSON Schema markers (`type`, `properties`, `$ref`,
9
+ * `allOf`, `anyOf`, `oneOf`, `items`, `enum`) and does NOT have Zod markers.
10
+ */
11
+ function isJsonSchema(input) {
12
+ if (input === null || typeof input !== "object") return false;
13
+ const obj = input;
14
+ if ("_def" in obj || "_zod" in obj) return false;
15
+ return "type" in obj || "properties" in obj || "$ref" in obj || "allOf" in obj || "anyOf" in obj || "oneOf" in obj || "items" in obj || "enum" in obj;
16
+ }
17
+ /**
18
+ * Check if an object is a Zod schema (has `_zod` marker from Zod v4).
19
+ */
20
+ function isZodSchema(input) {
21
+ return input !== null && typeof input === "object" && "_zod" in input;
22
+ }
23
+ /**
24
+ * Convert any schema input to JSON Schema.
25
+ *
26
+ * Detection order:
27
+ * 1. `null`/`undefined` → `undefined`
28
+ * 2. Already JSON Schema → pass through as-is (zero overhead)
29
+ * 3. Zod v4 schema → `z.toJSONSchema(schema, { target: 'openapi-3.0' })`
30
+ * 4. Unrecognized object → return as-is (treat as opaque schema)
31
+ */
32
+ function toJsonSchema(input) {
33
+ if (input == null) return void 0;
34
+ if (typeof input !== "object") return void 0;
35
+ if (isJsonSchema(input)) return input;
36
+ if (isZodSchema(input)) {
37
+ if (!_toJSONSchema) {
38
+ console.warn("[Arc] Zod schema detected but zod is not installed. Install zod v4: npm install zod");
39
+ return input;
40
+ }
41
+ try {
42
+ return _toJSONSchema(input, { target: "openapi-3.0" });
43
+ } catch {
44
+ return { type: "object" };
45
+ }
46
+ }
47
+ return input;
48
+ }
49
+ /**
50
+ * Convert all schema fields in an OpenApiSchemas object.
51
+ * JSON Schema values pass through unchanged. Only Zod schemas are converted.
52
+ */
53
+ function convertOpenApiSchemas(schemas) {
54
+ const result = {};
55
+ const schemaFields = [
56
+ "entity",
57
+ "createBody",
58
+ "updateBody",
59
+ "params",
60
+ "listQuery",
61
+ "response"
62
+ ];
63
+ for (const field of schemaFields) {
64
+ const value = schemas[field];
65
+ if (value !== void 0) result[field] = toJsonSchema(value) ?? value;
66
+ }
67
+ for (const [key, value] of Object.entries(schemas)) if (!schemaFields.includes(key)) result[key] = value;
68
+ return result;
69
+ }
70
+ /**
71
+ * Convert schema values in a Fastify route schema record.
72
+ *
73
+ * Handles `body`, `querystring`, `params`, `headers` (top-level conversion)
74
+ * and `response` (iterates by status code — each value converted individually).
75
+ *
76
+ * JSON Schema values pass through unchanged. Only Zod schemas are converted.
77
+ *
78
+ * Used for both additionalRoutes and customSchemas (CRUD overrides).
79
+ */
80
+ function convertRouteSchema(schema) {
81
+ const result = { ...schema };
82
+ for (const field of [
83
+ "body",
84
+ "querystring",
85
+ "params",
86
+ "headers"
87
+ ]) if (result[field] !== void 0) result[field] = toJsonSchema(result[field]) ?? result[field];
88
+ if (result.response !== void 0 && typeof result.response === "object" && result.response !== null) {
89
+ const responseObj = result.response;
90
+ const convertedResponse = {};
91
+ for (const [statusCode, responseSchema] of Object.entries(responseObj)) convertedResponse[statusCode] = toJsonSchema(responseSchema) ?? responseSchema;
92
+ result.response = convertedResponse;
93
+ }
94
+ return result;
95
+ }
96
+
97
+ //#endregion
98
+ export { toJsonSchema as a, isZodSchema as i, convertRouteSchema as n, isJsonSchema as r, convertOpenApiSchemas as t };
@@ -0,0 +1,63 @@
1
+ import * as _sinclair_typebox0 from "@sinclair/typebox";
2
+ import { Static, TObject, TSchema, TSchema as TSchema$1, Type } from "@sinclair/typebox";
3
+ import { FastifyPluginAsyncTypebox, FastifyPluginCallbackTypebox, TypeBoxTypeProvider, TypeBoxValidatorCompiler } from "@fastify/type-provider-typebox";
4
+
5
+ //#region src/schemas/index.d.ts
6
+ /**
7
+ * Paginated list response — matches Arc's runtime format:
8
+ * `{ success, docs: [...], page, limit, total, pages, hasNext, hasPrev }`
9
+ */
10
+ declare function ArcListResponse<T extends TSchema$1>(itemSchema: T): _sinclair_typebox0.TObject<{
11
+ success: _sinclair_typebox0.TBoolean;
12
+ docs: _sinclair_typebox0.TArray<T>;
13
+ page: _sinclair_typebox0.TInteger;
14
+ limit: _sinclair_typebox0.TInteger;
15
+ total: _sinclair_typebox0.TInteger;
16
+ pages: _sinclair_typebox0.TInteger;
17
+ hasNext: _sinclair_typebox0.TBoolean;
18
+ hasPrev: _sinclair_typebox0.TBoolean;
19
+ }>;
20
+ /**
21
+ * Single item response — `{ success, data: {...} }`
22
+ */
23
+ declare function ArcItemResponse<T extends TSchema$1>(itemSchema: T): _sinclair_typebox0.TObject<{
24
+ success: _sinclair_typebox0.TBoolean;
25
+ data: T;
26
+ }>;
27
+ /**
28
+ * Mutation (create/update) response — `{ success, data: {...}, message? }`
29
+ */
30
+ declare function ArcMutationResponse<T extends TSchema$1>(itemSchema: T): _sinclair_typebox0.TObject<{
31
+ success: _sinclair_typebox0.TBoolean;
32
+ data: T;
33
+ message: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
34
+ }>;
35
+ /**
36
+ * Delete response — `{ success, message }`
37
+ */
38
+ declare function ArcDeleteResponse(): _sinclair_typebox0.TObject<{
39
+ success: _sinclair_typebox0.TBoolean;
40
+ message: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
41
+ }>;
42
+ /**
43
+ * Error response schema
44
+ */
45
+ declare function ArcErrorResponse(): _sinclair_typebox0.TObject<{
46
+ success: _sinclair_typebox0.TLiteral<false>;
47
+ error: _sinclair_typebox0.TString;
48
+ code: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
49
+ message: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
50
+ }>;
51
+ /**
52
+ * Standard pagination + sorting + filtering query parameters.
53
+ * Matches Arc's list endpoint conventions.
54
+ */
55
+ declare function ArcPaginationQuery(): _sinclair_typebox0.TObject<{
56
+ page: _sinclair_typebox0.TOptional<_sinclair_typebox0.TInteger>;
57
+ limit: _sinclair_typebox0.TOptional<_sinclair_typebox0.TInteger>;
58
+ sort: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
59
+ select: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
60
+ populate: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
61
+ }>;
62
+ //#endregion
63
+ export { ArcDeleteResponse, ArcErrorResponse, ArcItemResponse, ArcListResponse, ArcMutationResponse, ArcPaginationQuery, type FastifyPluginAsyncTypebox, type FastifyPluginCallbackTypebox, type Static, type TObject, type TSchema, Type, type TypeBoxTypeProvider, TypeBoxValidatorCompiler };
@@ -0,0 +1,82 @@
1
+ import { Type, Type as Type$1 } from "@sinclair/typebox";
2
+ import { TypeBoxValidatorCompiler } from "@fastify/type-provider-typebox";
3
+
4
+ //#region src/schemas/index.ts
5
+ /**
6
+ * Paginated list response — matches Arc's runtime format:
7
+ * `{ success, docs: [...], page, limit, total, pages, hasNext, hasPrev }`
8
+ */
9
+ function ArcListResponse(itemSchema) {
10
+ return Type$1.Object({
11
+ success: Type$1.Boolean(),
12
+ docs: Type$1.Array(itemSchema),
13
+ page: Type$1.Integer(),
14
+ limit: Type$1.Integer(),
15
+ total: Type$1.Integer(),
16
+ pages: Type$1.Integer(),
17
+ hasNext: Type$1.Boolean(),
18
+ hasPrev: Type$1.Boolean()
19
+ });
20
+ }
21
+ /**
22
+ * Single item response — `{ success, data: {...} }`
23
+ */
24
+ function ArcItemResponse(itemSchema) {
25
+ return Type$1.Object({
26
+ success: Type$1.Boolean(),
27
+ data: itemSchema
28
+ });
29
+ }
30
+ /**
31
+ * Mutation (create/update) response — `{ success, data: {...}, message? }`
32
+ */
33
+ function ArcMutationResponse(itemSchema) {
34
+ return Type$1.Object({
35
+ success: Type$1.Boolean(),
36
+ data: itemSchema,
37
+ message: Type$1.Optional(Type$1.String())
38
+ });
39
+ }
40
+ /**
41
+ * Delete response — `{ success, message }`
42
+ */
43
+ function ArcDeleteResponse() {
44
+ return Type$1.Object({
45
+ success: Type$1.Boolean(),
46
+ message: Type$1.Optional(Type$1.String())
47
+ });
48
+ }
49
+ /**
50
+ * Error response schema
51
+ */
52
+ function ArcErrorResponse() {
53
+ return Type$1.Object({
54
+ success: Type$1.Literal(false),
55
+ error: Type$1.String(),
56
+ code: Type$1.Optional(Type$1.String()),
57
+ message: Type$1.Optional(Type$1.String())
58
+ });
59
+ }
60
+ /**
61
+ * Standard pagination + sorting + filtering query parameters.
62
+ * Matches Arc's list endpoint conventions.
63
+ */
64
+ function ArcPaginationQuery() {
65
+ return Type$1.Object({
66
+ page: Type$1.Optional(Type$1.Integer({
67
+ minimum: 1,
68
+ default: 1
69
+ })),
70
+ limit: Type$1.Optional(Type$1.Integer({
71
+ minimum: 1,
72
+ maximum: 100,
73
+ default: 20
74
+ })),
75
+ sort: Type$1.Optional(Type$1.String()),
76
+ select: Type$1.Optional(Type$1.String()),
77
+ populate: Type$1.Optional(Type$1.String())
78
+ });
79
+ }
80
+
81
+ //#endregion
82
+ export { ArcDeleteResponse, ArcErrorResponse, ArcItemResponse, ArcListResponse, ArcMutationResponse, ArcPaginationQuery, Type, TypeBoxValidatorCompiler };