@classytic/arc 2.3.0 → 2.4.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.
Files changed (175) hide show
  1. package/README.md +187 -18
  2. package/bin/arc.js +11 -3
  3. package/dist/BaseController-CkM5dUh_.mjs +1031 -0
  4. package/dist/{EventTransport-BkUDYZEb.d.mts → EventTransport-wc5hSLik.d.mts} +1 -1
  5. package/dist/{HookSystem-BsGV-j2l.mjs → HookSystem-COkyWztM.mjs} +2 -3
  6. package/dist/{ResourceRegistry-7Ic20ZMw.mjs → ResourceRegistry-DeCIFlix.mjs} +8 -5
  7. package/dist/adapters/index.d.mts +3 -5
  8. package/dist/adapters/index.mjs +2 -3
  9. package/dist/{prisma-DJbMt3yf.mjs → adapters-DTC4Ug66.mjs} +45 -12
  10. package/dist/audit/index.d.mts +4 -7
  11. package/dist/audit/index.mjs +2 -29
  12. package/dist/audit/mongodb.d.mts +1 -4
  13. package/dist/audit/mongodb.mjs +2 -3
  14. package/dist/auth/index.d.mts +7 -9
  15. package/dist/auth/index.mjs +65 -63
  16. package/dist/auth/redis-session.d.mts +1 -1
  17. package/dist/auth/redis-session.mjs +1 -2
  18. package/dist/{betterAuthOpenApi-DjWDddNc.mjs → betterAuthOpenApi-lz0IRbXJ.mjs} +4 -6
  19. package/dist/cache/index.d.mts +23 -23
  20. package/dist/cache/index.mjs +4 -6
  21. package/dist/{caching-GSDJcA6-.mjs → caching-BSXB-Xr7.mjs} +2 -24
  22. package/dist/chunk-BpYLSNr0.mjs +14 -0
  23. package/dist/circuitBreaker-BOBOpN2w.mjs +284 -0
  24. package/dist/circuitBreaker-JP2GdJ4b.d.mts +206 -0
  25. package/dist/cli/commands/describe.mjs +24 -7
  26. package/dist/cli/commands/docs.mjs +6 -7
  27. package/dist/cli/commands/doctor.d.mts +10 -0
  28. package/dist/cli/commands/doctor.mjs +156 -0
  29. package/dist/cli/commands/generate.mjs +66 -17
  30. package/dist/cli/commands/init.mjs +315 -45
  31. package/dist/cli/commands/introspect.mjs +2 -4
  32. package/dist/cli/index.d.mts +1 -10
  33. package/dist/cli/index.mjs +4 -153
  34. package/dist/{constants-DdXFXQtN.mjs → constants-Cxde4rpC.mjs} +1 -2
  35. package/dist/core/index.d.mts +3 -5
  36. package/dist/core/index.mjs +5 -4
  37. package/dist/core-C1XCMtqM.mjs +185 -0
  38. package/dist/{createApp-CgKOPhA4.mjs → createApp-ByWNRsZj.mjs} +64 -35
  39. package/dist/{defineResource-DWbpJYtm.mjs → defineResource-D9aY5Cy6.mjs} +108 -1157
  40. package/dist/discovery/index.mjs +37 -5
  41. package/dist/docs/index.d.mts +6 -9
  42. package/dist/docs/index.mjs +3 -21
  43. package/dist/dynamic/index.d.mts +93 -0
  44. package/dist/dynamic/index.mjs +122 -0
  45. package/dist/{elevation-DSTbVvYj.mjs → elevation-BEdACOLB.mjs} +5 -36
  46. package/dist/{elevation-DGo5shaX.d.mts → elevation-Ca_yveIO.d.mts} +41 -7
  47. package/dist/{errorHandler-C3GY3_ow.mjs → errorHandler--zp54tGc.mjs} +3 -5
  48. package/dist/errorHandler-Do4vVQ1f.d.mts +139 -0
  49. package/dist/{errors-DBANPbGr.mjs → errors-rxhfP7Hf.mjs} +1 -2
  50. package/dist/{eventPlugin-BEOvaDqo.mjs → eventPlugin-Ba00swHF.mjs} +25 -27
  51. package/dist/{eventPlugin-H6wDDjGO.d.mts → eventPlugin-iGrSEmwJ.d.mts} +105 -5
  52. package/dist/events/index.d.mts +72 -7
  53. package/dist/events/index.mjs +216 -4
  54. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  55. package/dist/events/transports/redis-stream-entry.mjs +19 -7
  56. package/dist/events/transports/redis.d.mts +1 -1
  57. package/dist/events/transports/redis.mjs +3 -4
  58. package/dist/factory/index.d.mts +23 -9
  59. package/dist/factory/index.mjs +48 -3
  60. package/dist/{fields-Bi_AVKSo.d.mts → fields-DFwdaWCq.d.mts} +1 -1
  61. package/dist/{fields-CTd_CrKr.mjs → fields-ipsbIRPK.mjs} +1 -2
  62. package/dist/hooks/index.d.mts +1 -3
  63. package/dist/hooks/index.mjs +2 -3
  64. package/dist/idempotency/index.d.mts +5 -5
  65. package/dist/idempotency/index.mjs +3 -7
  66. package/dist/idempotency/mongodb.d.mts +1 -1
  67. package/dist/idempotency/mongodb.mjs +4 -5
  68. package/dist/idempotency/redis.d.mts +1 -1
  69. package/dist/idempotency/redis.mjs +2 -5
  70. package/dist/{fastifyAdapter-6b_eRDBw.d.mts → index-BL8CaQih.d.mts} +56 -57
  71. package/dist/index-Diqcm14c.d.mts +369 -0
  72. package/dist/{prisma-Dy5S5F5i.d.mts → index-yhxyjqNb.d.mts} +4 -5
  73. package/dist/index.d.mts +100 -105
  74. package/dist/index.mjs +85 -58
  75. package/dist/integrations/event-gateway.d.mts +1 -1
  76. package/dist/integrations/event-gateway.mjs +8 -4
  77. package/dist/integrations/index.d.mts +4 -2
  78. package/dist/integrations/index.mjs +1 -1
  79. package/dist/integrations/jobs.d.mts +2 -2
  80. package/dist/integrations/jobs.mjs +63 -14
  81. package/dist/integrations/mcp/index.d.mts +219 -0
  82. package/dist/integrations/mcp/index.mjs +572 -0
  83. package/dist/integrations/mcp/testing.d.mts +53 -0
  84. package/dist/integrations/mcp/testing.mjs +104 -0
  85. package/dist/integrations/streamline.mjs +39 -19
  86. package/dist/integrations/webhooks.d.mts +56 -0
  87. package/dist/integrations/webhooks.mjs +139 -0
  88. package/dist/integrations/websocket-redis.d.mts +46 -0
  89. package/dist/integrations/websocket-redis.mjs +50 -0
  90. package/dist/integrations/websocket.d.mts +68 -2
  91. package/dist/integrations/websocket.mjs +96 -13
  92. package/dist/{interface-CSNjltAc.d.mts → interface-B4awm1RJ.d.mts} +2 -2
  93. package/dist/interface-DGmPxakH.d.mts +2213 -0
  94. package/dist/{keys-DhqDRxv3.mjs → keys-qcD-TVJl.mjs} +3 -4
  95. package/dist/{logger-ByrvQWZO.mjs → logger-Dz3j1ItV.mjs} +2 -4
  96. package/dist/{memory-B2v7KrCB.mjs → memory-Cb_7iy9e.mjs} +2 -4
  97. package/dist/metrics-Csh4nsvv.mjs +224 -0
  98. package/dist/migrations/index.d.mts +113 -44
  99. package/dist/migrations/index.mjs +84 -102
  100. package/dist/{mongodb-DNKEExbf.mjs → mongodb-BuQ7fNTg.mjs} +1 -4
  101. package/dist/{mongodb-ClykrfGo.d.mts → mongodb-CUpYfxfD.d.mts} +2 -3
  102. package/dist/{mongodb-Dg8O_gvd.d.mts → mongodb-bga9AbkD.d.mts} +2 -2
  103. package/dist/{openapi-9nB_kiuR.mjs → openapi-CBmZ6EQN.mjs} +4 -21
  104. package/dist/org/index.d.mts +12 -14
  105. package/dist/org/index.mjs +92 -119
  106. package/dist/org/types.d.mts +2 -2
  107. package/dist/org/types.mjs +1 -1
  108. package/dist/permissions/index.d.mts +4 -278
  109. package/dist/permissions/index.mjs +4 -579
  110. package/dist/permissions-CA5zg0yK.mjs +751 -0
  111. package/dist/plugins/index.d.mts +104 -107
  112. package/dist/plugins/index.mjs +203 -313
  113. package/dist/plugins/response-cache.mjs +4 -69
  114. package/dist/plugins/tracing-entry.d.mts +1 -1
  115. package/dist/plugins/tracing-entry.mjs +24 -11
  116. package/dist/{pluralize-CM-jZg7p.mjs → pluralize-CcT6qF0a.mjs} +12 -13
  117. package/dist/policies/index.d.mts +2 -2
  118. package/dist/policies/index.mjs +80 -83
  119. package/dist/presets/index.d.mts +26 -19
  120. package/dist/presets/index.mjs +2 -142
  121. package/dist/presets/multiTenant.d.mts +1 -4
  122. package/dist/presets/multiTenant.mjs +4 -6
  123. package/dist/presets-C9QXJV1u.mjs +422 -0
  124. package/dist/{queryCachePlugin-B6R0d4av.mjs → queryCachePlugin-ClosZdNS.mjs} +6 -27
  125. package/dist/{queryCachePlugin-Q6SYuHZ6.d.mts → queryCachePlugin-DcmETvcB.d.mts} +3 -3
  126. package/dist/queryParser-CgCtsjti.mjs +352 -0
  127. package/dist/{redis-UwjEp8Ea.d.mts → redis-CQ5YxMC5.d.mts} +2 -2
  128. package/dist/{redis-stream-CBg0upHI.d.mts → redis-stream-BW9UKLZM.d.mts} +9 -2
  129. package/dist/registry/index.d.mts +1 -4
  130. package/dist/registry/index.mjs +3 -4
  131. package/dist/{introspectionPlugin-B3JkrjwU.mjs → registry-I-ogLgL9.mjs} +1 -8
  132. package/dist/{requestContext-xi6OKBL-.mjs → requestContext-DYtmNpm5.mjs} +1 -3
  133. package/dist/resourceToTools-PMFE8HIv.mjs +533 -0
  134. package/dist/rpc/index.d.mts +90 -0
  135. package/dist/rpc/index.mjs +248 -0
  136. package/dist/{schemaConverter-Dtg0Kt9T.mjs → schemaConverter-DjzHpFam.mjs} +1 -2
  137. package/dist/schemas/index.d.mts +30 -30
  138. package/dist/schemas/index.mjs +2 -4
  139. package/dist/scope/index.d.mts +13 -2
  140. package/dist/scope/index.mjs +18 -5
  141. package/dist/{sessionManager-D_iEHjQl.d.mts → sessionManager-wbkYj2HL.d.mts} +2 -2
  142. package/dist/{sse-DkqQ1uxb.mjs → sse-BkViJPlT.mjs} +4 -25
  143. package/dist/testing/index.d.mts +551 -567
  144. package/dist/testing/index.mjs +1744 -1799
  145. package/dist/{tracing-8CEbhF0w.d.mts → tracing-bz_U4EM1.d.mts} +6 -1
  146. package/dist/{typeGuards-DwxA1t_L.mjs → typeGuards-Cj5Rgvlg.mjs} +1 -2
  147. package/dist/types/index.d.mts +4 -946
  148. package/dist/types/index.mjs +2 -4
  149. package/dist/types-BJmgxNbF.d.mts +275 -0
  150. package/dist/{types-RLkFVgaw.d.mts → types-BNUccdcf.d.mts} +2 -2
  151. package/dist/{types-Beqn1Un7.mjs → types-C6TQjtdi.mjs} +30 -2
  152. package/dist/{types-tKwaViYB.d.mts → types-Dt0-AI6E.d.mts} +68 -27
  153. package/dist/{types-DelU6kln.mjs → types-ZUu_h0jp.mjs} +1 -2
  154. package/dist/utils/index.d.mts +254 -351
  155. package/dist/utils/index.mjs +7 -6
  156. package/dist/utils-Dc0WhlIl.mjs +594 -0
  157. package/dist/versioning-BzfeHmhj.mjs +37 -0
  158. package/package.json +44 -10
  159. package/skills/arc/SKILL.md +518 -0
  160. package/skills/arc/references/auth.md +250 -0
  161. package/skills/arc/references/events.md +272 -0
  162. package/skills/arc/references/integrations.md +385 -0
  163. package/skills/arc/references/mcp.md +431 -0
  164. package/skills/arc/references/production.md +610 -0
  165. package/skills/arc/references/testing.md +183 -0
  166. package/dist/audited-CGdLiSlE.mjs +0 -140
  167. package/dist/chunk-C7Uep-_p.mjs +0 -20
  168. package/dist/circuitBreaker-CSS2VvL6.mjs +0 -1109
  169. package/dist/errorHandler-CW3OOeYq.d.mts +0 -72
  170. package/dist/interface-BtdYtQUA.d.mts +0 -1114
  171. package/dist/presets-BTeYbw7h.d.mts +0 -57
  172. package/dist/presets-CeFtfDR8.mjs +0 -119
  173. /package/dist/{errors-DAWRdiYP.d.mts → errors-CPpvPHT0.d.mts} +0 -0
  174. /package/dist/{externalPaths-SyPF2tgK.d.mts → externalPaths-DpO-s7r8.d.mts} +0 -0
  175. /package/dist/{interface-DTbsvIWe.d.mts → interface-D_BWALyZ.d.mts} +0 -0
@@ -1,10 +1,201 @@
1
- import "../elevation-DGo5shaX.mjs";
2
- import "../interface-BtdYtQUA.mjs";
3
- import "../types-RLkFVgaw.mjs";
4
- import { AnyRecord, OpenApiSchemas, ParsedQuery, QueryParserInterface } from "../types/index.mjs";
5
- import { a as NotFoundError, c as RateLimitError, d as ValidationError, f as createError, i as ForbiddenError, l as ServiceUnavailableError, n as ConflictError, o as OrgAccessDeniedError, p as isArcError, r as ErrorDetails, s as OrgRequiredError, t as ArcError, u as UnauthorizedError } from "../errors-DAWRdiYP.mjs";
1
+ import { G as ParsedQuery, U as OpenApiSchemas, X as QueryParserInterface, l as AnyRecord } from "../interface-DGmPxakH.mjs";
2
+ import { a as NotFoundError, c as RateLimitError, d as ValidationError, f as createError, i as ForbiddenError, l as ServiceUnavailableError, n as ConflictError, o as OrgAccessDeniedError, p as isArcError, r as ErrorDetails, s as OrgRequiredError, t as ArcError, u as UnauthorizedError } from "../errors-CPpvPHT0.mjs";
3
+ import { a as CircuitBreakerStats, c as createCircuitBreakerRegistry, i as CircuitBreakerRegistry, n as CircuitBreakerError, o as CircuitState, r as CircuitBreakerOptions, s as createCircuitBreaker, t as CircuitBreaker } from "../circuitBreaker-JP2GdJ4b.mjs";
6
4
  import { FastifyInstance } from "fastify";
7
5
 
6
+ //#region src/utils/compensation.d.ts
7
+ /**
8
+ * Compensating Transaction — In-Process Rollback Primitive
9
+ *
10
+ * Runs steps in order. If any step fails, runs compensating actions
11
+ * for already-completed steps in reverse. Zero dependencies.
12
+ *
13
+ * Type-safe: generic context type gives autocomplete across steps.
14
+ * Discriminated union result: compiler enforces checking success before
15
+ * accessing failedStep/error.
16
+ *
17
+ * For distributed sagas across services, use Temporal, Inngest, or Streamline.
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * interface CheckoutCtx {
22
+ * orderId: string;
23
+ * reservationId?: string;
24
+ * }
25
+ *
26
+ * const result = await withCompensation<CheckoutCtx>('checkout', [
27
+ * {
28
+ * name: 'reserve',
29
+ * execute: async (ctx) => {
30
+ * const res = await inventoryService.reserve(ctx.orderId);
31
+ * ctx.reservationId = res.id;
32
+ * return res;
33
+ * },
34
+ * compensate: async (ctx) => {
35
+ * await inventoryService.release(ctx.reservationId!);
36
+ * },
37
+ * },
38
+ * { name: 'notify', execute: sendEmail, fireAndForget: true },
39
+ * ], { orderId: 'ord-123' });
40
+ *
41
+ * if (result.success) {
42
+ * // result.results available, no failedStep
43
+ * } else {
44
+ * // result.failedStep and result.error guaranteed
45
+ * }
46
+ * ```
47
+ */
48
+ /** Step definition with typed context and typed result */
49
+ interface CompensationStep<TCtx = Record<string, unknown>, TResult = unknown> {
50
+ /** Step name — used in results, logs, and hooks */
51
+ readonly name: string;
52
+ /** Execute the step — return value stored in results[name] */
53
+ readonly execute: (ctx: TCtx) => Promise<TResult>;
54
+ /** Rollback on failure — receives context and this step's own result */
55
+ readonly compensate?: (ctx: TCtx, stepResult: TResult) => Promise<void>;
56
+ /** Fire-and-forget — don't await, don't block, swallow errors, skip in rollback */
57
+ readonly fireAndForget?: boolean;
58
+ }
59
+ /** Lifecycle hooks for observability — wire to Arc events, metrics, or logging */
60
+ interface CompensationHooks {
61
+ readonly onStepComplete?: (stepName: string, result: unknown) => void;
62
+ readonly onStepFailed?: (stepName: string, error: Error) => void;
63
+ readonly onCompensate?: (stepName: string) => void;
64
+ }
65
+ /** Error from a compensation action that failed during rollback */
66
+ interface CompensationError {
67
+ readonly step: string;
68
+ readonly error: string;
69
+ }
70
+ /** Discriminated union — success and failure are mutually exclusive */
71
+ type CompensationResult = {
72
+ readonly success: true;
73
+ readonly completedSteps: readonly string[];
74
+ readonly results: Readonly<Record<string, unknown>>;
75
+ } | {
76
+ readonly success: false;
77
+ readonly completedSteps: readonly string[];
78
+ readonly results: Readonly<Record<string, unknown>>;
79
+ readonly failedStep: string;
80
+ readonly error: string;
81
+ readonly compensationErrors?: readonly CompensationError[];
82
+ };
83
+ /**
84
+ * Run steps in order with automatic compensation on failure.
85
+ *
86
+ * @typeParam TCtx - Context type shared across steps (defaults to Record<string, unknown>)
87
+ */
88
+ declare function withCompensation<TCtx extends Record<string, unknown> = Record<string, unknown>>(_name: string, steps: readonly CompensationStep<TCtx>[], initialContext?: TCtx, hooks?: CompensationHooks): Promise<CompensationResult>;
89
+ interface CompensationDefinition<TCtx extends Record<string, unknown> = Record<string, unknown>> {
90
+ readonly name: string;
91
+ readonly execute: (initialContext?: TCtx, hooks?: CompensationHooks) => Promise<CompensationResult>;
92
+ }
93
+ declare function defineCompensation<TCtx extends Record<string, unknown> = Record<string, unknown>>(name: string, steps: readonly CompensationStep<TCtx>[]): CompensationDefinition<TCtx>;
94
+ //#endregion
95
+ //#region src/utils/queryParser.d.ts
96
+ interface ArcQueryParserOptions {
97
+ /** Maximum allowed limit value (default: 1000) */
98
+ maxLimit?: number;
99
+ /** Default limit for pagination (default: 20) */
100
+ defaultLimit?: number;
101
+ /** Maximum regex pattern length (default: 500) */
102
+ maxRegexLength?: number;
103
+ /** Maximum search query length (default: 200) */
104
+ maxSearchLength?: number;
105
+ /** Maximum filter nesting depth (default: 10) */
106
+ maxFilterDepth?: number;
107
+ /**
108
+ * Whitelist of fields that can be filtered on.
109
+ * When set, only these fields are accepted as filters — all others are silently dropped.
110
+ * Also used by MCP to auto-derive filterable fields in tool schemas.
111
+ */
112
+ allowedFilterFields?: string[];
113
+ /**
114
+ * Whitelist of fields that can be sorted on.
115
+ * When set, sort fields not in this list are silently dropped.
116
+ * Also used by MCP to describe available sort options.
117
+ */
118
+ allowedSortFields?: string[];
119
+ /**
120
+ * Whitelist of filter operators (e.g. ['eq', 'ne', 'gt', 'lt', 'in']).
121
+ * When set, only these operators are accepted — all others are dropped.
122
+ * Also used by MCP to enrich list tool descriptions.
123
+ */
124
+ allowedOperators?: string[];
125
+ }
126
+ /**
127
+ * Arc's default query parser
128
+ *
129
+ * Converts URL query parameters to a structured query format:
130
+ * - Pagination: ?page=1&limit=20
131
+ * - Sorting: ?sort=-createdAt,name (- prefix = descending)
132
+ * - Filtering: ?status=active&price[gte]=100&price[lte]=500
133
+ * - Search: ?search=keyword
134
+ * - Populate: ?populate=author,category
135
+ * - Field selection: ?select=name,price,status
136
+ * - Keyset pagination: ?after=cursor_value
137
+ *
138
+ * For advanced MongoDB features ($lookup, aggregations), use MongoKit's QueryParser.
139
+ */
140
+ declare class ArcQueryParser implements QueryParserInterface {
141
+ private readonly maxLimit;
142
+ private readonly defaultLimit;
143
+ private readonly maxRegexLength;
144
+ private readonly maxSearchLength;
145
+ private readonly maxFilterDepth;
146
+ private readonly _allowedFilterFields?;
147
+ private readonly _allowedSortFields?;
148
+ private readonly _allowedOperators?;
149
+ /** Allowed filter fields (used by MCP for auto-derive) */
150
+ readonly allowedFilterFields?: readonly string[];
151
+ /** Allowed sort fields (used by MCP for sort descriptions) */
152
+ readonly allowedSortFields?: readonly string[];
153
+ /** Allowed operators (used by MCP for operator descriptions) */
154
+ readonly allowedOperators?: readonly string[];
155
+ /** Supported filter operators */
156
+ private readonly operators;
157
+ constructor(options?: ArcQueryParserOptions);
158
+ /**
159
+ * Parse URL query parameters into structured query options
160
+ */
161
+ parse(query: Record<string, unknown> | null | undefined): ParsedQuery;
162
+ private parseNumber;
163
+ private parseString;
164
+ /**
165
+ * Parse populate parameter — handles both simple string and bracket notation.
166
+ *
167
+ * Simple: ?populate=author,category → { populate: 'author,category' }
168
+ * Bracket: ?populate[author][select]=name,email → { populateOptions: [{ path: 'author', select: 'name email' }] }
169
+ */
170
+ private parsePopulate;
171
+ private parseSort;
172
+ private parseSearch;
173
+ private parseSelect;
174
+ /**
175
+ * Check if a value exceeds the maximum nesting depth.
176
+ * Prevents filter bombs where deeply nested objects consume excessive memory/CPU.
177
+ */
178
+ private exceedsDepth;
179
+ private parseFilters;
180
+ private parseFilterValue;
181
+ private coerceValue;
182
+ /**
183
+ * Generate OpenAPI-compatible JSON Schema for query parameters.
184
+ * Arc's defineResource() auto-detects this method and uses it
185
+ * to document list endpoint query parameters in OpenAPI/Swagger.
186
+ */
187
+ getQuerySchema(): {
188
+ type: "object";
189
+ properties: Record<string, unknown>;
190
+ required?: string[];
191
+ };
192
+ private sanitizeRegex;
193
+ }
194
+ /**
195
+ * Create a new ArcQueryParser instance
196
+ */
197
+ declare function createQueryParser(options?: ArcQueryParserOptions): ArcQueryParser;
198
+ //#endregion
8
199
  //#region src/utils/responseSchemas.d.ts
9
200
  interface JsonSchema {
10
201
  type: string;
@@ -76,7 +267,7 @@ declare const responses: {
76
267
  200: (schema: JsonSchema) => {
77
268
  description: string;
78
269
  content: {
79
- 'application/json': {
270
+ "application/json": {
80
271
  schema: JsonSchema;
81
272
  };
82
273
  };
@@ -84,7 +275,7 @@ declare const responses: {
84
275
  201: (schema: JsonSchema) => {
85
276
  description: string;
86
277
  content: {
87
- 'application/json': {
278
+ "application/json": {
88
279
  schema: JsonSchema;
89
280
  };
90
281
  };
@@ -92,7 +283,7 @@ declare const responses: {
92
283
  400: {
93
284
  description: string;
94
285
  content: {
95
- 'application/json': {
286
+ "application/json": {
96
287
  schema: {
97
288
  properties: {
98
289
  code: {
@@ -132,7 +323,7 @@ declare const responses: {
132
323
  401: {
133
324
  description: string;
134
325
  content: {
135
- 'application/json': {
326
+ "application/json": {
136
327
  schema: {
137
328
  properties: {
138
329
  code: {
@@ -153,7 +344,7 @@ declare const responses: {
153
344
  403: {
154
345
  description: string;
155
346
  content: {
156
- 'application/json': {
347
+ "application/json": {
157
348
  schema: {
158
349
  properties: {
159
350
  code: {
@@ -174,7 +365,7 @@ declare const responses: {
174
365
  404: {
175
366
  description: string;
176
367
  content: {
177
- 'application/json': {
368
+ "application/json": {
178
369
  schema: {
179
370
  properties: {
180
371
  code: {
@@ -195,7 +386,7 @@ declare const responses: {
195
386
  409: {
196
387
  description: string;
197
388
  content: {
198
- 'application/json': {
389
+ "application/json": {
199
390
  schema: {
200
391
  properties: {
201
392
  code: {
@@ -216,7 +407,7 @@ declare const responses: {
216
407
  500: {
217
408
  description: string;
218
409
  content: {
219
- 'application/json': {
410
+ "application/json": {
220
411
  schema: {
221
412
  properties: {
222
413
  code: {
@@ -288,6 +479,44 @@ declare function getListQueryParams(): AnyRecord;
288
479
  */
289
480
  declare function getDefaultCrudSchemas(): Record<string, Record<string, unknown>>;
290
481
  //#endregion
482
+ //#region src/utils/schemaConverter.d.ts
483
+ /**
484
+ * Check if an object is already a plain JSON Schema.
485
+ * Returns true if it has JSON Schema markers (`type`, `properties`, `$ref`,
486
+ * `allOf`, `anyOf`, `oneOf`, `items`, `enum`) and does NOT have Zod markers.
487
+ */
488
+ declare function isJsonSchema(input: unknown): input is Record<string, unknown>;
489
+ /**
490
+ * Check if an object is a Zod schema (has `_zod` marker from Zod v4).
491
+ */
492
+ declare function isZodSchema(input: unknown): boolean;
493
+ /**
494
+ * Convert any schema input to JSON Schema.
495
+ *
496
+ * Detection order:
497
+ * 1. `null`/`undefined` → `undefined`
498
+ * 2. Already JSON Schema → pass through as-is (zero overhead)
499
+ * 3. Zod v4 schema → `z.toJSONSchema(schema, { target: 'openapi-3.0' })`
500
+ * 4. Unrecognized object → return as-is (treat as opaque schema)
501
+ */
502
+ declare function toJsonSchema(input: unknown): Record<string, unknown> | undefined;
503
+ /**
504
+ * Convert all schema fields in an OpenApiSchemas object.
505
+ * JSON Schema values pass through unchanged. Only Zod schemas are converted.
506
+ */
507
+ declare function convertOpenApiSchemas(schemas: OpenApiSchemas): OpenApiSchemas;
508
+ /**
509
+ * Convert schema values in a Fastify route schema record.
510
+ *
511
+ * Handles `body`, `querystring`, `params`, `headers` (top-level conversion)
512
+ * and `response` (iterates by status code — each value converted individually).
513
+ *
514
+ * JSON Schema values pass through unchanged. Only Zod schemas are converted.
515
+ *
516
+ * Used for both additionalRoutes and customSchemas (CRUD overrides).
517
+ */
518
+ declare function convertRouteSchema(schema: Record<string, unknown>): Record<string, unknown>;
519
+ //#endregion
291
520
  //#region src/utils/stateMachine.d.ts
292
521
  /**
293
522
  * State Machine Utility
@@ -321,7 +550,7 @@ interface StateMachine {
321
550
  * Asynchronously check if action can be performed, including guard evaluation.
322
551
  * Falls back to simple transition check when no guard is defined.
323
552
  */
324
- canAsync(action: string, status: string | null | undefined, context?: any): Promise<boolean>;
553
+ canAsync(action: string, status: string | null | undefined, context?: Record<string, unknown>): Promise<boolean>;
325
554
  /**
326
555
  * Assert action can be performed, throw error if invalid
327
556
  * @param action - Action to perform
@@ -337,7 +566,7 @@ interface StateMachine {
337
566
  /**
338
567
  * Record a transition
339
568
  */
340
- recordTransition?(from: string, to: string, action: string, metadata?: any): void;
569
+ recordTransition?(from: string, to: string, action: string, metadata?: Record<string, unknown>): void;
341
570
  /**
342
571
  * Clear history
343
572
  */
@@ -352,24 +581,17 @@ interface TransitionHistoryEntry {
352
581
  to: string;
353
582
  action: string;
354
583
  timestamp: Date;
355
- metadata?: any;
584
+ metadata?: Record<string, unknown>;
356
585
  }
357
- interface TransitionGuard {
358
- (context: {
359
- from: string;
360
- to: string;
361
- action: string;
362
- data?: any;
363
- }): boolean | Promise<boolean>;
364
- }
365
- interface TransitionAction {
366
- (context: {
367
- from: string;
368
- to: string;
369
- action: string;
370
- data?: any;
371
- }): void | Promise<void>;
586
+ /** Context passed to transition guards and actions */
587
+ interface TransitionContext {
588
+ from: string;
589
+ to: string;
590
+ action: string;
591
+ data?: Record<string, unknown>;
372
592
  }
593
+ type TransitionGuard = (context: TransitionContext) => boolean | Promise<boolean>;
594
+ type TransitionAction = (context: TransitionContext) => void | Promise<void>;
373
595
  type TransitionConfig = Record<string, string[] | {
374
596
  from: string[];
375
597
  to?: string;
@@ -410,287 +632,6 @@ declare function createStateMachine(name: string, transitions?: TransitionConfig
410
632
  trackHistory?: boolean;
411
633
  }): StateMachine;
412
634
  //#endregion
413
- //#region src/utils/circuitBreaker.d.ts
414
- /**
415
- * Circuit Breaker Pattern
416
- *
417
- * Wraps external service calls with failure protection.
418
- * Prevents cascading failures by "opening" the circuit when
419
- * a service is failing, allowing it time to recover.
420
- *
421
- * States:
422
- * - CLOSED: Normal operation, requests pass through
423
- * - OPEN: Too many failures, all requests fail fast
424
- * - HALF_OPEN: Testing if service recovered, limited requests
425
- *
426
- * @example
427
- * import { CircuitBreaker } from '@classytic/arc/utils';
428
- *
429
- * const paymentBreaker = new CircuitBreaker(async (amount) => {
430
- * return await stripe.charges.create({ amount });
431
- * }, {
432
- * failureThreshold: 5,
433
- * resetTimeout: 30000,
434
- * timeout: 5000,
435
- * });
436
- *
437
- * try {
438
- * const result = await paymentBreaker.call(100);
439
- * } catch (error) {
440
- * // Handle failure or circuit open
441
- * }
442
- */
443
- declare const CircuitState: {
444
- readonly CLOSED: "CLOSED";
445
- readonly OPEN: "OPEN";
446
- readonly HALF_OPEN: "HALF_OPEN";
447
- };
448
- type CircuitState = (typeof CircuitState)[keyof typeof CircuitState];
449
- interface CircuitBreakerOptions {
450
- /**
451
- * Number of failures before opening circuit
452
- * @default 5
453
- */
454
- failureThreshold?: number;
455
- /**
456
- * Time in ms before attempting to close circuit
457
- * @default 60000 (60 seconds)
458
- */
459
- resetTimeout?: number;
460
- /**
461
- * Request timeout in ms
462
- * @default 10000 (10 seconds)
463
- */
464
- timeout?: number;
465
- /**
466
- * Number of successful requests in HALF_OPEN before closing
467
- * @default 1
468
- */
469
- successThreshold?: number;
470
- /**
471
- * Fallback function when circuit is open
472
- */
473
- fallback?: (...args: any[]) => Promise<any>;
474
- /**
475
- * Callback when state changes
476
- */
477
- onStateChange?: (from: CircuitState, to: CircuitState) => void;
478
- /**
479
- * Callback on error
480
- */
481
- onError?: (error: Error) => void;
482
- /**
483
- * Name for logging/monitoring
484
- */
485
- name?: string;
486
- }
487
- interface CircuitBreakerStats {
488
- name?: string;
489
- state: CircuitState;
490
- failures: number;
491
- successes: number;
492
- totalCalls: number;
493
- openedAt: number | null;
494
- lastCallAt: number | null;
495
- }
496
- declare class CircuitBreakerError extends Error {
497
- state: CircuitState;
498
- constructor(message: string, state: CircuitState);
499
- }
500
- declare class CircuitBreaker<T extends (...args: any[]) => Promise<any>> {
501
- private state;
502
- private failures;
503
- private successes;
504
- private totalCalls;
505
- private nextAttempt;
506
- private lastCallAt;
507
- private openedAt;
508
- private readonly failureThreshold;
509
- private readonly resetTimeout;
510
- private readonly timeout;
511
- private readonly successThreshold;
512
- private readonly fallback?;
513
- private readonly onStateChange?;
514
- private readonly onError?;
515
- private readonly name;
516
- private readonly fn;
517
- constructor(fn: T, options?: CircuitBreakerOptions);
518
- /**
519
- * Call the wrapped function with circuit breaker protection
520
- */
521
- call(...args: Parameters<T>): Promise<ReturnType<T>>;
522
- /**
523
- * Execute function with timeout
524
- */
525
- private executeWithTimeout;
526
- /**
527
- * Handle successful call
528
- */
529
- private onSuccess;
530
- /**
531
- * Handle failed call
532
- */
533
- private onFailure;
534
- /**
535
- * Change circuit state
536
- */
537
- private setState;
538
- /**
539
- * Manually open the circuit
540
- */
541
- open(): void;
542
- /**
543
- * Manually close the circuit
544
- */
545
- close(): void;
546
- /**
547
- * Get current statistics
548
- */
549
- getStats(): CircuitBreakerStats;
550
- /**
551
- * Get current state
552
- */
553
- getState(): CircuitState;
554
- /**
555
- * Check if circuit is open
556
- */
557
- isOpen(): boolean;
558
- /**
559
- * Check if circuit is closed
560
- */
561
- isClosed(): boolean;
562
- /**
563
- * Reset statistics
564
- */
565
- reset(): void;
566
- }
567
- /**
568
- * Create a circuit breaker with sensible defaults
569
- *
570
- * @example
571
- * const emailBreaker = createCircuitBreaker(
572
- * async (to, subject, body) => sendEmail(to, subject, body),
573
- * { name: 'email-service' }
574
- * );
575
- */
576
- declare function createCircuitBreaker<T extends (...args: any[]) => Promise<any>>(fn: T, options?: CircuitBreakerOptions): CircuitBreaker<T>;
577
- /**
578
- * Circuit breaker registry for managing multiple breakers
579
- */
580
- declare class CircuitBreakerRegistry {
581
- private breakers;
582
- /**
583
- * Register a circuit breaker
584
- */
585
- register<T extends (...args: any[]) => Promise<any>>(name: string, fn: T, options?: Omit<CircuitBreakerOptions, 'name'>): CircuitBreaker<T>;
586
- /**
587
- * Get a circuit breaker by name
588
- */
589
- get(name: string): CircuitBreaker<any> | undefined;
590
- /**
591
- * Get all breakers
592
- */
593
- getAll(): Map<string, CircuitBreaker<any>>;
594
- /**
595
- * Get statistics for all breakers
596
- */
597
- getAllStats(): Record<string, CircuitBreakerStats>;
598
- /**
599
- * Reset all breakers
600
- */
601
- resetAll(): void;
602
- /**
603
- * Open all breakers
604
- */
605
- openAll(): void;
606
- /**
607
- * Close all breakers
608
- */
609
- closeAll(): void;
610
- }
611
- /**
612
- * Create a new CircuitBreakerRegistry instance.
613
- * Use this instead of a global singleton — attach to fastify.arc or pass explicitly.
614
- */
615
- declare function createCircuitBreakerRegistry(): CircuitBreakerRegistry;
616
- //#endregion
617
- //#region src/utils/queryParser.d.ts
618
- interface ArcQueryParserOptions {
619
- /** Maximum allowed limit value (default: 1000) */
620
- maxLimit?: number;
621
- /** Default limit for pagination (default: 20) */
622
- defaultLimit?: number;
623
- /** Maximum regex pattern length (default: 500) */
624
- maxRegexLength?: number;
625
- /** Maximum search query length (default: 200) */
626
- maxSearchLength?: number;
627
- /** Maximum filter nesting depth (default: 10) */
628
- maxFilterDepth?: number;
629
- }
630
- /**
631
- * Arc's default query parser
632
- *
633
- * Converts URL query parameters to a structured query format:
634
- * - Pagination: ?page=1&limit=20
635
- * - Sorting: ?sort=-createdAt,name (- prefix = descending)
636
- * - Filtering: ?status=active&price[gte]=100&price[lte]=500
637
- * - Search: ?search=keyword
638
- * - Populate: ?populate=author,category
639
- * - Field selection: ?select=name,price,status
640
- * - Keyset pagination: ?after=cursor_value
641
- *
642
- * For advanced MongoDB features ($lookup, aggregations), use MongoKit's QueryParser.
643
- */
644
- declare class ArcQueryParser implements QueryParserInterface {
645
- private readonly maxLimit;
646
- private readonly defaultLimit;
647
- private readonly maxRegexLength;
648
- private readonly maxSearchLength;
649
- private readonly maxFilterDepth;
650
- /** Supported filter operators */
651
- private readonly operators;
652
- constructor(options?: ArcQueryParserOptions);
653
- /**
654
- * Parse URL query parameters into structured query options
655
- */
656
- parse(query: Record<string, unknown> | null | undefined): ParsedQuery;
657
- private parseNumber;
658
- private parseString;
659
- /**
660
- * Parse populate parameter — handles both simple string and bracket notation.
661
- *
662
- * Simple: ?populate=author,category → { populate: 'author,category' }
663
- * Bracket: ?populate[author][select]=name,email → { populateOptions: [{ path: 'author', select: 'name email' }] }
664
- */
665
- private parsePopulate;
666
- private parseSort;
667
- private parseSearch;
668
- private parseSelect;
669
- /**
670
- * Check if a value exceeds the maximum nesting depth.
671
- * Prevents filter bombs where deeply nested objects consume excessive memory/CPU.
672
- */
673
- private exceedsDepth;
674
- private parseFilters;
675
- private parseFilterValue;
676
- private coerceValue;
677
- /**
678
- * Generate OpenAPI-compatible JSON Schema for query parameters.
679
- * Arc's defineResource() auto-detects this method and uses it
680
- * to document list endpoint query parameters in OpenAPI/Swagger.
681
- */
682
- getQuerySchema(): {
683
- type: 'object';
684
- properties: Record<string, unknown>;
685
- required?: string[];
686
- };
687
- private sanitizeRegex;
688
- }
689
- /**
690
- * Create a new ArcQueryParser instance
691
- */
692
- declare function createQueryParser(options?: ArcQueryParserOptions): ArcQueryParser;
693
- //#endregion
694
635
  //#region src/utils/typeGuards.d.ts
695
636
  interface EventsDecorator {
696
637
  publish: <T>(type: string, payload: T, meta?: Record<string, unknown>) => Promise<void>;
@@ -706,42 +647,4 @@ declare function hasEvents(instance: FastifyInstance): instance is FastifyInstan
706
647
  events: EventsDecorator;
707
648
  };
708
649
  //#endregion
709
- //#region src/utils/schemaConverter.d.ts
710
- /**
711
- * Check if an object is already a plain JSON Schema.
712
- * Returns true if it has JSON Schema markers (`type`, `properties`, `$ref`,
713
- * `allOf`, `anyOf`, `oneOf`, `items`, `enum`) and does NOT have Zod markers.
714
- */
715
- declare function isJsonSchema(input: unknown): input is Record<string, unknown>;
716
- /**
717
- * Check if an object is a Zod schema (has `_zod` marker from Zod v4).
718
- */
719
- declare function isZodSchema(input: unknown): boolean;
720
- /**
721
- * Convert any schema input to JSON Schema.
722
- *
723
- * Detection order:
724
- * 1. `null`/`undefined` → `undefined`
725
- * 2. Already JSON Schema → pass through as-is (zero overhead)
726
- * 3. Zod v4 schema → `z.toJSONSchema(schema, { target: 'openapi-3.0' })`
727
- * 4. Unrecognized object → return as-is (treat as opaque schema)
728
- */
729
- declare function toJsonSchema(input: unknown): Record<string, unknown> | undefined;
730
- /**
731
- * Convert all schema fields in an OpenApiSchemas object.
732
- * JSON Schema values pass through unchanged. Only Zod schemas are converted.
733
- */
734
- declare function convertOpenApiSchemas(schemas: OpenApiSchemas): OpenApiSchemas;
735
- /**
736
- * Convert schema values in a Fastify route schema record.
737
- *
738
- * Handles `body`, `querystring`, `params`, `headers` (top-level conversion)
739
- * and `response` (iterates by status code — each value converted individually).
740
- *
741
- * JSON Schema values pass through unchanged. Only Zod schemas are converted.
742
- *
743
- * Used for both additionalRoutes and customSchemas (CRUD overrides).
744
- */
745
- declare function convertRouteSchema(schema: Record<string, unknown>): Record<string, unknown>;
746
- //#endregion
747
- export { ArcError, ArcQueryParser, type ArcQueryParserOptions, CircuitBreaker, CircuitBreakerError, type CircuitBreakerOptions, CircuitBreakerRegistry, type CircuitBreakerStats, CircuitState, ConflictError, type ErrorDetails, type EventsDecorator, ForbiddenError, type JsonSchema, NotFoundError, OrgAccessDeniedError, OrgRequiredError, RateLimitError, ServiceUnavailableError, type StateMachine, type TransitionConfig, UnauthorizedError, ValidationError, convertOpenApiSchemas, convertRouteSchema, createCircuitBreaker, createCircuitBreakerRegistry, createError, createQueryParser, createStateMachine, deleteResponse, errorResponseSchema, getDefaultCrudSchemas, getListQueryParams, hasEvents, isArcError, isJsonSchema, isZodSchema, itemResponse, itemWrapper, listResponse, messageWrapper, mutationResponse, paginateWrapper, paginationSchema, queryParams, responses, successResponseSchema, toJsonSchema, wrapResponse };
650
+ export { ArcError, ArcQueryParser, type ArcQueryParserOptions, CircuitBreaker, CircuitBreakerError, type CircuitBreakerOptions, CircuitBreakerRegistry, type CircuitBreakerStats, CircuitState, type CompensationDefinition, type CompensationError, type CompensationHooks, type CompensationResult, type CompensationStep, ConflictError, type ErrorDetails, type EventsDecorator, ForbiddenError, type JsonSchema, NotFoundError, OrgAccessDeniedError, OrgRequiredError, RateLimitError, ServiceUnavailableError, type StateMachine, type TransitionConfig, UnauthorizedError, ValidationError, convertOpenApiSchemas, convertRouteSchema, createCircuitBreaker, createCircuitBreakerRegistry, createError, createQueryParser, createStateMachine, defineCompensation, deleteResponse, errorResponseSchema, getDefaultCrudSchemas, getListQueryParams, hasEvents, isArcError, isJsonSchema, isZodSchema, itemResponse, itemWrapper, listResponse, messageWrapper, mutationResponse, paginateWrapper, paginationSchema, queryParams, responses, successResponseSchema, toJsonSchema, withCompensation, wrapResponse };