@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,1109 +0,0 @@
1
- import { d as MAX_REGEX_LENGTH, f as MAX_SEARCH_LENGTH, i as DEFAULT_MAX_LIMIT, m as RESERVED_QUERY_PARAMS, r as DEFAULT_LIMIT, u as MAX_FILTER_DEPTH } from "./constants-DdXFXQtN.mjs";
2
-
3
- //#region src/utils/queryParser.ts
4
- /**
5
- * Regex patterns that can cause catastrophic backtracking (ReDoS attacks)
6
- * Detects:
7
- * - Quantifiers: {n,m}
8
- * - Possessive quantifiers: *+, ++, ?+
9
- * - Nested quantifiers: (a+)+, (a*)*
10
- * - Backreferences: \1, \2, etc.
11
- */
12
- const DANGEROUS_REGEX_PATTERNS = /(\{[0-9,]+\}|\*\+|\+\+|\?\+|(\(.+\))\+|\(\?\:|\\[0-9]|(\[.+\]).+(\[.+\]))/;
13
- /**
14
- * Arc's default query parser
15
- *
16
- * Converts URL query parameters to a structured query format:
17
- * - Pagination: ?page=1&limit=20
18
- * - Sorting: ?sort=-createdAt,name (- prefix = descending)
19
- * - Filtering: ?status=active&price[gte]=100&price[lte]=500
20
- * - Search: ?search=keyword
21
- * - Populate: ?populate=author,category
22
- * - Field selection: ?select=name,price,status
23
- * - Keyset pagination: ?after=cursor_value
24
- *
25
- * For advanced MongoDB features ($lookup, aggregations), use MongoKit's QueryParser.
26
- */
27
- var ArcQueryParser = class {
28
- maxLimit;
29
- defaultLimit;
30
- maxRegexLength;
31
- maxSearchLength;
32
- maxFilterDepth;
33
- /** Supported filter operators */
34
- operators = {
35
- eq: "$eq",
36
- ne: "$ne",
37
- gt: "$gt",
38
- gte: "$gte",
39
- lt: "$lt",
40
- lte: "$lte",
41
- in: "$in",
42
- nin: "$nin",
43
- like: "$regex",
44
- contains: "$regex",
45
- regex: "$regex",
46
- exists: "$exists"
47
- };
48
- constructor(options = {}) {
49
- this.maxLimit = options.maxLimit ?? DEFAULT_MAX_LIMIT;
50
- this.defaultLimit = options.defaultLimit ?? DEFAULT_LIMIT;
51
- this.maxRegexLength = options.maxRegexLength ?? MAX_REGEX_LENGTH;
52
- this.maxSearchLength = options.maxSearchLength ?? MAX_SEARCH_LENGTH;
53
- this.maxFilterDepth = options.maxFilterDepth ?? MAX_FILTER_DEPTH;
54
- }
55
- /**
56
- * Parse URL query parameters into structured query options
57
- */
58
- parse(query) {
59
- const q = query ?? {};
60
- const page = this.parseNumber(q.page, 1);
61
- const limit = Math.min(this.parseNumber(q.limit, this.defaultLimit), this.maxLimit);
62
- const after = this.parseString(q.after ?? q.cursor);
63
- const sort = this.parseSort(q.sort);
64
- const { populate, populateOptions } = this.parsePopulate(q.populate);
65
- const search = this.parseSearch(q.search);
66
- const select = this.parseSelect(q.select);
67
- return {
68
- filters: this.parseFilters(q),
69
- limit,
70
- sort,
71
- populate,
72
- populateOptions,
73
- search,
74
- page: after ? void 0 : page,
75
- after,
76
- select
77
- };
78
- }
79
- parseNumber(value, defaultValue) {
80
- if (value === void 0 || value === null) return defaultValue;
81
- const num = parseInt(String(value), 10);
82
- return Number.isNaN(num) ? defaultValue : Math.max(1, num);
83
- }
84
- parseString(value) {
85
- if (value === void 0 || value === null) return void 0;
86
- const str = String(value).trim();
87
- return str.length > 0 ? str : void 0;
88
- }
89
- /**
90
- * Parse populate parameter — handles both simple string and bracket notation.
91
- *
92
- * Simple: ?populate=author,category → { populate: 'author,category' }
93
- * Bracket: ?populate[author][select]=name,email → { populateOptions: [{ path: 'author', select: 'name email' }] }
94
- */
95
- parsePopulate(value) {
96
- if (value === void 0 || value === null) return {};
97
- if (typeof value === "string") {
98
- const trimmed = value.trim();
99
- return trimmed.length > 0 ? { populate: trimmed } : {};
100
- }
101
- if (typeof value === "object" && !Array.isArray(value)) {
102
- const obj = value;
103
- const keys = Object.keys(obj);
104
- if (keys.length === 0) return {};
105
- const options = [];
106
- for (const path of keys) {
107
- if (!/^[a-zA-Z_][a-zA-Z0-9_.]*$/.test(path)) continue;
108
- const config = obj[path];
109
- if (typeof config === "object" && config !== null && !Array.isArray(config)) {
110
- const cfg = config;
111
- const option = { path };
112
- if (typeof cfg.select === "string") option.select = cfg.select.split(",").map((s) => s.trim()).filter(Boolean).join(" ");
113
- if (typeof cfg.match === "object" && cfg.match !== null) option.match = cfg.match;
114
- options.push(option);
115
- } else options.push({ path });
116
- }
117
- return options.length > 0 ? { populateOptions: options } : {};
118
- }
119
- return {};
120
- }
121
- parseSort(value) {
122
- if (!value) return void 0;
123
- const sortStr = String(value);
124
- const result = {};
125
- for (const field of sortStr.split(",")) {
126
- const trimmed = field.trim();
127
- if (!trimmed) continue;
128
- if (!/^-?[a-zA-Z_][a-zA-Z0-9_.]*$/.test(trimmed)) continue;
129
- if (trimmed.startsWith("-")) result[trimmed.slice(1)] = -1;
130
- else result[trimmed] = 1;
131
- }
132
- return Object.keys(result).length > 0 ? result : void 0;
133
- }
134
- parseSearch(value) {
135
- if (!value) return void 0;
136
- const search = String(value).trim();
137
- if (search.length === 0) return void 0;
138
- if (search.length > this.maxSearchLength) return search.slice(0, this.maxSearchLength);
139
- return search;
140
- }
141
- parseSelect(value) {
142
- if (!value) return void 0;
143
- const selectStr = String(value);
144
- const result = {};
145
- for (const field of selectStr.split(",")) {
146
- const trimmed = field.trim();
147
- if (!trimmed) continue;
148
- if (!/^-?[a-zA-Z_][a-zA-Z0-9_.]*$/.test(trimmed)) continue;
149
- if (trimmed.startsWith("-")) result[trimmed.slice(1)] = 0;
150
- else result[trimmed] = 1;
151
- }
152
- return Object.keys(result).length > 0 ? result : void 0;
153
- }
154
- /**
155
- * Check if a value exceeds the maximum nesting depth.
156
- * Prevents filter bombs where deeply nested objects consume excessive memory/CPU.
157
- */
158
- exceedsDepth(obj, currentDepth = 0) {
159
- if (currentDepth > this.maxFilterDepth) return true;
160
- if (obj === null || obj === void 0) return false;
161
- if (Array.isArray(obj)) return obj.some((v) => this.exceedsDepth(v, currentDepth));
162
- if (typeof obj !== "object") return false;
163
- return Object.values(obj).some((v) => this.exceedsDepth(v, currentDepth + 1));
164
- }
165
- parseFilters(query) {
166
- const filters = {};
167
- for (const [key, value] of Object.entries(query)) {
168
- if (RESERVED_QUERY_PARAMS.has(key)) continue;
169
- if (value === void 0 || value === null) continue;
170
- if (!/^[a-zA-Z_][a-zA-Z0-9_.]*$/.test(key)) continue;
171
- if (this.exceedsDepth(value)) continue;
172
- if (typeof value === "object" && value !== null && !Array.isArray(value)) {
173
- const operatorObj = value;
174
- const operatorKeys = Object.keys(operatorObj);
175
- if (operatorKeys.every((op) => this.operators[op]) && operatorKeys.length > 0) {
176
- const mongoFilters = {};
177
- for (const [op, opValue] of Object.entries(operatorObj)) {
178
- const mongoOp = this.operators[op];
179
- if (mongoOp) mongoFilters[mongoOp] = this.parseFilterValue(opValue, op);
180
- }
181
- filters[key] = mongoFilters;
182
- continue;
183
- }
184
- }
185
- const match = key.match(/^([a-zA-Z_][a-zA-Z0-9_.]*)(?:\[([a-z]+)\])?$/);
186
- if (!match) continue;
187
- const [, fieldName, operator] = match;
188
- if (!fieldName) continue;
189
- if (operator && this.operators[operator]) {
190
- const mongoOp = this.operators[operator];
191
- const parsedValue = this.parseFilterValue(value, operator);
192
- if (!filters[fieldName]) filters[fieldName] = {};
193
- filters[fieldName][mongoOp] = parsedValue;
194
- } else if (!operator) filters[fieldName] = this.parseFilterValue(value);
195
- }
196
- return filters;
197
- }
198
- parseFilterValue(value, operator) {
199
- if (operator === "in" || operator === "nin") {
200
- if (Array.isArray(value)) return value.map((v) => this.coerceValue(v));
201
- if (typeof value === "string" && value.includes(",")) return value.split(",").map((v) => this.coerceValue(v.trim()));
202
- return [this.coerceValue(value)];
203
- }
204
- if (operator === "like" || operator === "contains" || operator === "regex") return this.sanitizeRegex(String(value));
205
- if (operator === "exists") {
206
- const str = String(value).toLowerCase();
207
- return str === "true" || str === "1";
208
- }
209
- return this.coerceValue(value);
210
- }
211
- coerceValue(value) {
212
- if (value === "true") return true;
213
- if (value === "false") return false;
214
- if (value === "null") return null;
215
- if (typeof value === "string") {
216
- const num = Number(value);
217
- if (!Number.isNaN(num) && value.trim() !== "") return num;
218
- }
219
- return value;
220
- }
221
- /**
222
- * Generate OpenAPI-compatible JSON Schema for query parameters.
223
- * Arc's defineResource() auto-detects this method and uses it
224
- * to document list endpoint query parameters in OpenAPI/Swagger.
225
- */
226
- getQuerySchema() {
227
- const operatorLines = Object.entries(this.operators).map(([op, mongoOp]) => {
228
- return ` ${op} → ${mongoOp}: ${{
229
- eq: "Equal (default when no operator specified)",
230
- ne: "Not equal",
231
- gt: "Greater than",
232
- gte: "Greater than or equal",
233
- lt: "Less than",
234
- lte: "Less than or equal",
235
- in: "In list (comma-separated values)",
236
- nin: "Not in list",
237
- like: "Pattern match (case-insensitive)",
238
- contains: "Contains substring (case-insensitive)",
239
- regex: "Regex pattern",
240
- exists: "Field exists (true/false)"
241
- }[op] || op}`;
242
- });
243
- return {
244
- type: "object",
245
- properties: {
246
- page: {
247
- type: "integer",
248
- description: "Page number for offset pagination",
249
- default: 1,
250
- minimum: 1
251
- },
252
- limit: {
253
- type: "integer",
254
- description: "Number of items per page",
255
- default: this.defaultLimit,
256
- minimum: 1,
257
- maximum: this.maxLimit
258
- },
259
- sort: {
260
- type: "string",
261
- description: "Sort fields (comma-separated). Prefix with - for descending. Example: -createdAt,name"
262
- },
263
- search: {
264
- type: "string",
265
- description: "Full-text search query",
266
- maxLength: this.maxSearchLength
267
- },
268
- select: {
269
- type: "string",
270
- description: "Fields to include/exclude (comma-separated). Prefix with - to exclude. Example: name,email,-password"
271
- },
272
- populate: {
273
- type: "string",
274
- description: "Fields to populate/join (comma-separated). Example: author,category"
275
- },
276
- after: {
277
- type: "string",
278
- description: "Cursor value for keyset pagination"
279
- },
280
- _filterOperators: {
281
- type: "string",
282
- description: ["Available filter operators (use as field[operator]=value):", ...operatorLines].join("\n")
283
- }
284
- }
285
- };
286
- }
287
- sanitizeRegex(pattern) {
288
- let sanitized = pattern.slice(0, this.maxRegexLength);
289
- if (DANGEROUS_REGEX_PATTERNS.test(sanitized)) sanitized = sanitized.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
290
- return sanitized;
291
- }
292
- };
293
- /**
294
- * Create a new ArcQueryParser instance
295
- */
296
- function createQueryParser(options) {
297
- return new ArcQueryParser(options);
298
- }
299
-
300
- //#endregion
301
- //#region src/utils/responseSchemas.ts
302
- /**
303
- * Base success response schema
304
- */
305
- const successResponseSchema = {
306
- type: "object",
307
- properties: { success: {
308
- type: "boolean",
309
- example: true
310
- } },
311
- required: ["success"]
312
- };
313
- /**
314
- * Error response schema
315
- */
316
- const errorResponseSchema = {
317
- type: "object",
318
- properties: {
319
- success: {
320
- type: "boolean",
321
- example: false
322
- },
323
- error: {
324
- type: "string",
325
- description: "Error message"
326
- },
327
- code: {
328
- type: "string",
329
- description: "Error code"
330
- },
331
- message: {
332
- type: "string",
333
- description: "Detailed message"
334
- }
335
- },
336
- required: ["success", "error"]
337
- };
338
- /**
339
- * Pagination schema - matches MongoKit/Arc runtime format
340
- *
341
- * Runtime format (flat fields):
342
- * { page, limit, total, pages, hasNext, hasPrev }
343
- */
344
- const paginationSchema = {
345
- type: "object",
346
- properties: {
347
- page: {
348
- type: "integer",
349
- example: 1
350
- },
351
- limit: {
352
- type: "integer",
353
- example: 20
354
- },
355
- total: {
356
- type: "integer",
357
- example: 100
358
- },
359
- pages: {
360
- type: "integer",
361
- example: 5
362
- },
363
- hasNext: {
364
- type: "boolean",
365
- example: true
366
- },
367
- hasPrev: {
368
- type: "boolean",
369
- example: false
370
- }
371
- },
372
- required: [
373
- "page",
374
- "limit",
375
- "total",
376
- "pages",
377
- "hasNext",
378
- "hasPrev"
379
- ]
380
- };
381
- /**
382
- * Wrap a data schema in a success response
383
- */
384
- function wrapResponse(dataSchema) {
385
- return {
386
- type: "object",
387
- properties: {
388
- success: {
389
- type: "boolean",
390
- example: true
391
- },
392
- data: dataSchema
393
- },
394
- required: ["success", "data"],
395
- additionalProperties: true
396
- };
397
- }
398
- /**
399
- * Create a list response schema with pagination - matches MongoKit/Arc runtime format
400
- *
401
- * Runtime format:
402
- * { success, docs: [...], page, limit, total, pages, hasNext, hasPrev }
403
- *
404
- * Note: Uses 'docs' array (not 'data') with flat pagination fields
405
- */
406
- function listResponse(itemSchema) {
407
- return {
408
- type: "object",
409
- properties: {
410
- success: {
411
- type: "boolean",
412
- example: true
413
- },
414
- docs: {
415
- type: "array",
416
- items: itemSchema
417
- },
418
- page: {
419
- type: "integer",
420
- example: 1
421
- },
422
- limit: {
423
- type: "integer",
424
- example: 20
425
- },
426
- total: {
427
- type: "integer",
428
- example: 100
429
- },
430
- pages: {
431
- type: "integer",
432
- example: 5
433
- },
434
- hasNext: {
435
- type: "boolean",
436
- example: false
437
- },
438
- hasPrev: {
439
- type: "boolean",
440
- example: false
441
- }
442
- },
443
- required: ["success", "docs"],
444
- additionalProperties: true
445
- };
446
- }
447
- /**
448
- * Alias for listResponse - matches local responseSchemas.js naming
449
- */
450
- const paginateWrapper = listResponse;
451
- /**
452
- * Create a single item response schema
453
- *
454
- * Runtime format: { success, data: {...} }
455
- */
456
- function itemResponse(itemSchema) {
457
- return wrapResponse(itemSchema);
458
- }
459
- /**
460
- * Alias for itemResponse - matches local responseSchemas.js naming
461
- */
462
- const itemWrapper = itemResponse;
463
- /**
464
- * Create a create/update response schema
465
- */
466
- function mutationResponse(itemSchema) {
467
- return {
468
- type: "object",
469
- properties: {
470
- success: {
471
- type: "boolean",
472
- example: true
473
- },
474
- data: itemSchema,
475
- message: {
476
- type: "string",
477
- example: "Created successfully"
478
- }
479
- },
480
- required: ["success", "data"],
481
- additionalProperties: true
482
- };
483
- }
484
- /**
485
- * Create a delete response schema
486
- *
487
- * Runtime format: { success, data: { message, id?, soft? } }
488
- */
489
- function deleteResponse() {
490
- return {
491
- type: "object",
492
- properties: {
493
- success: {
494
- type: "boolean",
495
- example: true
496
- },
497
- data: {
498
- type: "object",
499
- properties: {
500
- message: {
501
- type: "string",
502
- example: "Deleted successfully"
503
- },
504
- id: {
505
- type: "string",
506
- example: "507f1f77bcf86cd799439011"
507
- },
508
- soft: {
509
- type: "boolean",
510
- example: false
511
- }
512
- },
513
- required: ["message"]
514
- }
515
- },
516
- required: ["success"],
517
- additionalProperties: true
518
- };
519
- }
520
- /**
521
- * Alias for deleteResponse - matches local responseSchemas.js naming
522
- */
523
- const messageWrapper = deleteResponse;
524
- const responses = {
525
- 200: (schema) => ({
526
- description: "Successful response",
527
- content: { "application/json": { schema } }
528
- }),
529
- 201: (schema) => ({
530
- description: "Created successfully",
531
- content: { "application/json": { schema: mutationResponse(schema) } }
532
- }),
533
- 400: {
534
- description: "Bad Request",
535
- content: { "application/json": { schema: {
536
- ...errorResponseSchema,
537
- properties: {
538
- ...errorResponseSchema.properties,
539
- code: {
540
- type: "string",
541
- example: "VALIDATION_ERROR"
542
- },
543
- details: {
544
- type: "object",
545
- properties: { errors: {
546
- type: "array",
547
- items: {
548
- type: "object",
549
- properties: {
550
- field: { type: "string" },
551
- message: { type: "string" }
552
- }
553
- }
554
- } }
555
- }
556
- }
557
- } } }
558
- },
559
- 401: {
560
- description: "Unauthorized",
561
- content: { "application/json": { schema: {
562
- ...errorResponseSchema,
563
- properties: {
564
- ...errorResponseSchema.properties,
565
- code: {
566
- type: "string",
567
- example: "UNAUTHORIZED"
568
- }
569
- }
570
- } } }
571
- },
572
- 403: {
573
- description: "Forbidden",
574
- content: { "application/json": { schema: {
575
- ...errorResponseSchema,
576
- properties: {
577
- ...errorResponseSchema.properties,
578
- code: {
579
- type: "string",
580
- example: "FORBIDDEN"
581
- }
582
- }
583
- } } }
584
- },
585
- 404: {
586
- description: "Not Found",
587
- content: { "application/json": { schema: {
588
- ...errorResponseSchema,
589
- properties: {
590
- ...errorResponseSchema.properties,
591
- code: {
592
- type: "string",
593
- example: "NOT_FOUND"
594
- }
595
- }
596
- } } }
597
- },
598
- 409: {
599
- description: "Conflict",
600
- content: { "application/json": { schema: {
601
- ...errorResponseSchema,
602
- properties: {
603
- ...errorResponseSchema.properties,
604
- code: {
605
- type: "string",
606
- example: "CONFLICT"
607
- }
608
- }
609
- } } }
610
- },
611
- 500: {
612
- description: "Internal Server Error",
613
- content: { "application/json": { schema: {
614
- ...errorResponseSchema,
615
- properties: {
616
- ...errorResponseSchema.properties,
617
- code: {
618
- type: "string",
619
- example: "INTERNAL_ERROR"
620
- }
621
- }
622
- } } }
623
- }
624
- };
625
- const queryParams = {
626
- pagination: {
627
- page: {
628
- type: "integer",
629
- minimum: 1,
630
- default: 1,
631
- description: "Page number"
632
- },
633
- limit: {
634
- type: "integer",
635
- minimum: 1,
636
- maximum: 100,
637
- default: 20,
638
- description: "Items per page"
639
- }
640
- },
641
- sorting: { sort: {
642
- type: "string",
643
- description: "Sort field (prefix with - for descending)",
644
- example: "-createdAt"
645
- } },
646
- filtering: {
647
- select: {
648
- description: "Fields to include (space-separated or object)",
649
- example: "name email createdAt"
650
- },
651
- populate: {
652
- description: "Relations to populate (comma-separated string or bracket-notation object)",
653
- example: "author,category"
654
- }
655
- }
656
- };
657
- /**
658
- * Get standard list query parameters schema
659
- */
660
- function getListQueryParams() {
661
- return {
662
- type: "object",
663
- properties: {
664
- ...queryParams.pagination,
665
- ...queryParams.sorting,
666
- ...queryParams.filtering
667
- },
668
- additionalProperties: true
669
- };
670
- }
671
- /**
672
- * Generic item schema that allows any properties.
673
- * Used as default when no user schema is provided.
674
- * Enables fast-json-stringify while still passing through all fields.
675
- */
676
- const genericItemSchema = {
677
- type: "object",
678
- additionalProperties: true
679
- };
680
- /**
681
- * Recursively strip `example` keys from a schema object.
682
- * The `example` keyword is OpenAPI metadata — not standard JSON Schema —
683
- * and triggers Ajv strict mode errors when used on routes without the
684
- * `keywords: ['example']` AJV config (e.g., raw Fastify without createApp).
685
- */
686
- function stripExamples(schema) {
687
- if (schema === null || typeof schema !== "object") return schema;
688
- if (Array.isArray(schema)) return schema.map(stripExamples);
689
- const result = {};
690
- for (const [key, value] of Object.entries(schema)) {
691
- if (key === "example") continue;
692
- result[key] = stripExamples(value);
693
- }
694
- return result;
695
- }
696
- /**
697
- * Get default response schemas for all CRUD operations.
698
- *
699
- * When routes have response schemas, Fastify compiles them with
700
- * fast-json-stringify for 2-3x faster serialization and prevents
701
- * accidental field disclosure.
702
- *
703
- * These defaults use `additionalProperties: true` so all fields pass through.
704
- * Override with specific schemas for full serialization performance + safety.
705
- *
706
- * Note: `example` properties are stripped from defaults so they work with
707
- * any Fastify instance (not just createApp which adds `keywords: ['example']`).
708
- */
709
- function getDefaultCrudSchemas() {
710
- return stripExamples({
711
- list: {
712
- querystring: getListQueryParams(),
713
- response: { 200: listResponse(genericItemSchema) }
714
- },
715
- get: { response: { 200: itemResponse(genericItemSchema) } },
716
- create: { response: { 201: mutationResponse(genericItemSchema) } },
717
- update: { response: { 200: itemResponse(genericItemSchema) } },
718
- delete: { response: { 200: deleteResponse() } }
719
- });
720
- }
721
-
722
- //#endregion
723
- //#region src/utils/stateMachine.ts
724
- /**
725
- * Create a state machine for validating transitions
726
- *
727
- * @param name - Name of the state machine (used in error messages)
728
- * @param transitions - Map of actions to allowed source statuses
729
- * @param options - Additional options (history, guards, actions)
730
- * @returns State machine with can() and assert() methods
731
- *
732
- * @example
733
- * // Basic usage
734
- * const transferState = createStateMachine('Transfer', {
735
- * approve: ['draft'],
736
- * dispatch: ['approved'],
737
- * receive: ['dispatched', 'in_transit'],
738
- * cancel: ['draft', 'approved'],
739
- * });
740
- *
741
- * @example
742
- * // With guards and actions
743
- * const orderState = createStateMachine('Order', {
744
- * approve: {
745
- * from: ['pending'],
746
- * to: 'approved',
747
- * guard: ({ data }) => data.paymentConfirmed,
748
- * before: ({ from, to }) => console.log(`Approving order from ${from} to ${to}`),
749
- * after: ({ data }) => sendApprovalEmail(data.customerId),
750
- * },
751
- * }, { trackHistory: true });
752
- */
753
- function createStateMachine(name, transitions = {}, options = {}) {
754
- const normalized = /* @__PURE__ */ new Map();
755
- const history = options.trackHistory ? [] : void 0;
756
- Object.entries(transitions).forEach(([action, allowed]) => {
757
- if (Array.isArray(allowed)) normalized.set(action, { from: new Set(allowed) });
758
- else if (typeof allowed === "object" && "from" in allowed) normalized.set(action, {
759
- from: new Set(Array.isArray(allowed.from) ? allowed.from : [allowed.from]),
760
- to: allowed.to,
761
- guard: allowed.guard,
762
- before: allowed.before,
763
- after: allowed.after
764
- });
765
- });
766
- const can = (action, status) => {
767
- const transition = normalized.get(action);
768
- if (!transition || !status) return false;
769
- return transition.from.has(status);
770
- };
771
- const canAsync = async (action, status, context) => {
772
- const transition = normalized.get(action);
773
- if (!transition || !status) return false;
774
- if (!transition.from.has(status)) return false;
775
- if (transition.guard) try {
776
- return await transition.guard({
777
- from: status,
778
- to: transition.to || "",
779
- action,
780
- data: context
781
- });
782
- } catch {
783
- return false;
784
- }
785
- return true;
786
- };
787
- const assert = (action, status, errorFactory, message) => {
788
- if (can(action, status)) return;
789
- const errorMessage = message || `${name} cannot '${action}' when status is '${status || "unknown"}'`;
790
- if (typeof errorFactory === "function") throw errorFactory(errorMessage);
791
- throw new Error(errorMessage);
792
- };
793
- const recordTransition = (from, to, action, metadata) => {
794
- if (history) history.push({
795
- from,
796
- to,
797
- action,
798
- timestamp: /* @__PURE__ */ new Date(),
799
- metadata
800
- });
801
- };
802
- const getHistory = () => {
803
- return history ? [...history] : [];
804
- };
805
- const clearHistory = () => {
806
- if (history) history.length = 0;
807
- };
808
- const getAvailableActions = (status) => {
809
- const actions = [];
810
- for (const [action, transition] of normalized.entries()) if (transition.from.has(status)) actions.push(action);
811
- return actions;
812
- };
813
- return {
814
- can,
815
- canAsync,
816
- assert,
817
- recordTransition,
818
- getHistory,
819
- clearHistory,
820
- getAvailableActions
821
- };
822
- }
823
-
824
- //#endregion
825
- //#region src/utils/circuitBreaker.ts
826
- /**
827
- * Circuit Breaker Pattern
828
- *
829
- * Wraps external service calls with failure protection.
830
- * Prevents cascading failures by "opening" the circuit when
831
- * a service is failing, allowing it time to recover.
832
- *
833
- * States:
834
- * - CLOSED: Normal operation, requests pass through
835
- * - OPEN: Too many failures, all requests fail fast
836
- * - HALF_OPEN: Testing if service recovered, limited requests
837
- *
838
- * @example
839
- * import { CircuitBreaker } from '@classytic/arc/utils';
840
- *
841
- * const paymentBreaker = new CircuitBreaker(async (amount) => {
842
- * return await stripe.charges.create({ amount });
843
- * }, {
844
- * failureThreshold: 5,
845
- * resetTimeout: 30000,
846
- * timeout: 5000,
847
- * });
848
- *
849
- * try {
850
- * const result = await paymentBreaker.call(100);
851
- * } catch (error) {
852
- * // Handle failure or circuit open
853
- * }
854
- */
855
- const CircuitState = {
856
- CLOSED: "CLOSED",
857
- OPEN: "OPEN",
858
- HALF_OPEN: "HALF_OPEN"
859
- };
860
- var CircuitBreakerError = class extends Error {
861
- state;
862
- constructor(message, state) {
863
- super(message);
864
- this.name = "CircuitBreakerError";
865
- this.state = state;
866
- }
867
- };
868
- var CircuitBreaker = class {
869
- state = CircuitState.CLOSED;
870
- failures = 0;
871
- successes = 0;
872
- totalCalls = 0;
873
- nextAttempt = 0;
874
- lastCallAt = null;
875
- openedAt = null;
876
- failureThreshold;
877
- resetTimeout;
878
- timeout;
879
- successThreshold;
880
- fallback;
881
- onStateChange;
882
- onError;
883
- name;
884
- fn;
885
- constructor(fn, options = {}) {
886
- this.fn = fn;
887
- this.failureThreshold = options.failureThreshold ?? 5;
888
- this.resetTimeout = options.resetTimeout ?? 6e4;
889
- this.timeout = options.timeout ?? 1e4;
890
- this.successThreshold = options.successThreshold ?? 1;
891
- this.fallback = options.fallback;
892
- this.onStateChange = options.onStateChange;
893
- this.onError = options.onError;
894
- this.name = options.name ?? "CircuitBreaker";
895
- }
896
- /**
897
- * Call the wrapped function with circuit breaker protection
898
- */
899
- async call(...args) {
900
- this.totalCalls++;
901
- this.lastCallAt = Date.now();
902
- if (this.state === CircuitState.OPEN) {
903
- if (Date.now() < this.nextAttempt) {
904
- const error = new CircuitBreakerError(`Circuit breaker is OPEN for ${this.name}`, CircuitState.OPEN);
905
- if (this.fallback) return this.fallback(...args);
906
- throw error;
907
- }
908
- this.setState(CircuitState.HALF_OPEN);
909
- }
910
- try {
911
- const result = await this.executeWithTimeout(args);
912
- this.onSuccess();
913
- return result;
914
- } catch (error) {
915
- this.onFailure(error);
916
- throw error;
917
- }
918
- }
919
- /**
920
- * Execute function with timeout
921
- */
922
- async executeWithTimeout(args) {
923
- return new Promise((resolve, reject) => {
924
- const timeoutId = setTimeout(() => {
925
- reject(/* @__PURE__ */ new Error(`Request timeout after ${this.timeout}ms`));
926
- }, this.timeout);
927
- this.fn(...args).then((result) => {
928
- clearTimeout(timeoutId);
929
- resolve(result);
930
- }).catch((error) => {
931
- clearTimeout(timeoutId);
932
- reject(error);
933
- });
934
- });
935
- }
936
- /**
937
- * Handle successful call
938
- */
939
- onSuccess() {
940
- this.failures = 0;
941
- this.successes++;
942
- if (this.state === CircuitState.HALF_OPEN) {
943
- if (this.successes >= this.successThreshold) {
944
- this.setState(CircuitState.CLOSED);
945
- this.successes = 0;
946
- }
947
- }
948
- }
949
- /**
950
- * Handle failed call
951
- */
952
- onFailure(error) {
953
- this.failures++;
954
- this.successes = 0;
955
- if (this.onError) this.onError(error);
956
- if (this.state === CircuitState.HALF_OPEN || this.failures >= this.failureThreshold) {
957
- this.setState(CircuitState.OPEN);
958
- this.nextAttempt = Date.now() + this.resetTimeout;
959
- this.openedAt = Date.now();
960
- }
961
- }
962
- /**
963
- * Change circuit state
964
- */
965
- setState(newState) {
966
- const oldState = this.state;
967
- if (oldState !== newState) {
968
- this.state = newState;
969
- if (this.onStateChange) this.onStateChange(oldState, newState);
970
- }
971
- }
972
- /**
973
- * Manually open the circuit
974
- */
975
- open() {
976
- this.setState(CircuitState.OPEN);
977
- this.nextAttempt = Date.now() + this.resetTimeout;
978
- this.openedAt = Date.now();
979
- }
980
- /**
981
- * Manually close the circuit
982
- */
983
- close() {
984
- this.failures = 0;
985
- this.successes = 0;
986
- this.setState(CircuitState.CLOSED);
987
- this.openedAt = null;
988
- }
989
- /**
990
- * Get current statistics
991
- */
992
- getStats() {
993
- return {
994
- name: this.name,
995
- state: this.state,
996
- failures: this.failures,
997
- successes: this.successes,
998
- totalCalls: this.totalCalls,
999
- openedAt: this.openedAt,
1000
- lastCallAt: this.lastCallAt
1001
- };
1002
- }
1003
- /**
1004
- * Get current state
1005
- */
1006
- getState() {
1007
- return this.state;
1008
- }
1009
- /**
1010
- * Check if circuit is open
1011
- */
1012
- isOpen() {
1013
- return this.state === CircuitState.OPEN;
1014
- }
1015
- /**
1016
- * Check if circuit is closed
1017
- */
1018
- isClosed() {
1019
- return this.state === CircuitState.CLOSED;
1020
- }
1021
- /**
1022
- * Reset statistics
1023
- */
1024
- reset() {
1025
- this.failures = 0;
1026
- this.successes = 0;
1027
- this.totalCalls = 0;
1028
- this.lastCallAt = null;
1029
- this.openedAt = null;
1030
- this.setState(CircuitState.CLOSED);
1031
- }
1032
- };
1033
- /**
1034
- * Create a circuit breaker with sensible defaults
1035
- *
1036
- * @example
1037
- * const emailBreaker = createCircuitBreaker(
1038
- * async (to, subject, body) => sendEmail(to, subject, body),
1039
- * { name: 'email-service' }
1040
- * );
1041
- */
1042
- function createCircuitBreaker(fn, options) {
1043
- return new CircuitBreaker(fn, options);
1044
- }
1045
- /**
1046
- * Circuit breaker registry for managing multiple breakers
1047
- */
1048
- var CircuitBreakerRegistry = class {
1049
- breakers = /* @__PURE__ */ new Map();
1050
- /**
1051
- * Register a circuit breaker
1052
- */
1053
- register(name, fn, options) {
1054
- const breaker = new CircuitBreaker(fn, {
1055
- ...options,
1056
- name
1057
- });
1058
- this.breakers.set(name, breaker);
1059
- return breaker;
1060
- }
1061
- /**
1062
- * Get a circuit breaker by name
1063
- */
1064
- get(name) {
1065
- return this.breakers.get(name);
1066
- }
1067
- /**
1068
- * Get all breakers
1069
- */
1070
- getAll() {
1071
- return this.breakers;
1072
- }
1073
- /**
1074
- * Get statistics for all breakers
1075
- */
1076
- getAllStats() {
1077
- const stats = {};
1078
- for (const [name, breaker] of this.breakers.entries()) stats[name] = breaker.getStats();
1079
- return stats;
1080
- }
1081
- /**
1082
- * Reset all breakers
1083
- */
1084
- resetAll() {
1085
- for (const breaker of this.breakers.values()) breaker.reset();
1086
- }
1087
- /**
1088
- * Open all breakers
1089
- */
1090
- openAll() {
1091
- for (const breaker of this.breakers.values()) breaker.open();
1092
- }
1093
- /**
1094
- * Close all breakers
1095
- */
1096
- closeAll() {
1097
- for (const breaker of this.breakers.values()) breaker.close();
1098
- }
1099
- };
1100
- /**
1101
- * Create a new CircuitBreakerRegistry instance.
1102
- * Use this instead of a global singleton — attach to fastify.arc or pass explicitly.
1103
- */
1104
- function createCircuitBreakerRegistry() {
1105
- return new CircuitBreakerRegistry();
1106
- }
1107
-
1108
- //#endregion
1109
- export { ArcQueryParser as C, wrapResponse as S, paginateWrapper as _, createCircuitBreaker as a, responses as b, deleteResponse as c, getListQueryParams as d, itemResponse as f, mutationResponse as g, messageWrapper as h, CircuitState as i, errorResponseSchema as l, listResponse as m, CircuitBreakerError as n, createCircuitBreakerRegistry as o, itemWrapper as p, CircuitBreakerRegistry as r, createStateMachine as s, CircuitBreaker as t, getDefaultCrudSchemas as u, paginationSchema as v, createQueryParser as w, successResponseSchema as x, queryParams as y };