@classytic/arc 2.31.0 → 2.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/README.md +1 -1
  2. package/bin/arc.js +58 -17
  3. package/dist/{BaseController-De7GqHck.mjs → BaseController-CaQC5EXX.mjs} +298 -35
  4. package/dist/{EventTransport-2uVV34WU.d.mts → EventTransport-BEVP50ka.d.mts} +16 -0
  5. package/dist/{EventTransport-9mlTgqzE.mjs → EventTransport-tq4CEB-q.mjs} +39 -2
  6. package/dist/{HookSystem-BcmPyq5I.mjs → HookSystem-DqXkMXkB.mjs} +2 -2
  7. package/dist/{ResourceRegistry-qq0mn2s9.mjs → ResourceRegistry-DoALUlOO.mjs} +18 -15
  8. package/dist/{actionPermissions-BE5NwaQk.mjs → actionPermissions-CUeCmpUd.mjs} +1 -1
  9. package/dist/audit/index.d.mts +2 -2
  10. package/dist/audit/index.mjs +2 -2
  11. package/dist/auth/audit.mjs +1 -1
  12. package/dist/auth/index.d.mts +2 -2
  13. package/dist/auth/index.mjs +44 -11
  14. package/dist/auth/redis-session.mjs +1 -1
  15. package/dist/{authorizationDecision-ChvUQGG1.mjs → authorizationDecision-B3mP_QTy.mjs} +2 -2
  16. package/dist/{types-B7XeLEgK.d.mts → base-Csjc2oF-.d.mts} +74 -74
  17. package/dist/{buildHandler-CDrCJzmB.mjs → buildHandler-DLE9xX-V.mjs} +6 -5
  18. package/dist/cache/index.mjs +4 -4
  19. package/dist/{caching-BFHA6Scf.mjs → caching-BcGmvnHh.mjs} +2 -2
  20. package/dist/cleanup/index.d.mts +52 -18
  21. package/dist/cleanup/index.mjs +281 -32
  22. package/dist/cli/commands/describe.d.mts +1 -1
  23. package/dist/cli/commands/describe.mjs +4 -6
  24. package/dist/cli/commands/docs.mjs +3 -3
  25. package/dist/cli/commands/doctor.mjs +1 -1
  26. package/dist/cli/commands/generate.mjs +2 -2
  27. package/dist/cli/commands/init.mjs +2 -2
  28. package/dist/cli/commands/introspect.mjs +2 -2
  29. package/dist/cli/index.mjs +3 -3
  30. package/dist/{constants-D3Dv4LAV.mjs → constants-BxCoxmiN.mjs} +1 -1
  31. package/dist/context/index.mjs +3 -3
  32. package/dist/core/index.d.mts +2 -2
  33. package/dist/core/index.mjs +7 -7
  34. package/dist/{core-BGpIxINN.mjs → core-dxhcHhUD.mjs} +3 -3
  35. package/dist/{createActionRouter-CDXEdasl.mjs → createActionRouter-DVpoA0do.mjs} +14 -11
  36. package/dist/{createAggregationRouter-KrQDzx-k.mjs → createAggregationRouter-B_B48JZ-.mjs} +10 -8
  37. package/dist/{createApp-Df89BEni.mjs → createApp-CLGegqiG.mjs} +287 -62
  38. package/dist/{defineAggregation-DbPPS8RI.mjs → defineAggregation-Nv-DwfOf.mjs} +1 -1
  39. package/dist/{defineResource-Bv6EtN1x.mjs → defineResource-DR9vsUYy.mjs} +318 -35
  40. package/dist/discovery/index.mjs +1 -1
  41. package/dist/docs/index.d.mts +1 -1
  42. package/dist/docs/index.mjs +3 -3
  43. package/dist/{elevation-D2l1mh4g.mjs → elevation-B0tlY8y1.mjs} +4 -4
  44. package/dist/encryption/index.mjs +5 -4
  45. package/dist/{errorHandler-C5NeD6bT.mjs → errorHandler-C7xBqHsI.mjs} +42 -5
  46. package/dist/{errorHandler-CpYUJmPA.d.mts → errorHandler-DI5AN2b5.d.mts} +14 -3
  47. package/dist/{errors-Cj42AntO.mjs → errors-Cd_yy7aW.mjs} +1 -1
  48. package/dist/{eventPlugin-GF5nnBIq.d.mts → eventPlugin-DSNEZWfV.d.mts} +29 -1
  49. package/dist/{eventPlugin-CkffEihm.mjs → eventPlugin-Dar8qRaj.mjs} +68 -11
  50. package/dist/events/index.d.mts +18 -297
  51. package/dist/events/index.mjs +7 -758
  52. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  53. package/dist/events/transports/redis-stream-entry.mjs +14 -10
  54. package/dist/events/transports/redis.d.mts +1 -1
  55. package/dist/events/transports/redis.mjs +1 -1
  56. package/dist/factory/index.d.mts +20 -5
  57. package/dist/factory/index.mjs +131 -8
  58. package/dist/fastify-augmentation-DVsTAy6X.d.mts +179 -0
  59. package/dist/{fields-CB5Cuzk9.mjs → fields-CojeUkS4.mjs} +6 -11
  60. package/dist/{generate-EcA6ui4i.mjs → generate-DiB0nHPR.mjs} +2 -2
  61. package/dist/{headers-3zvE0rM3.mjs → headers-CveNO9gR.mjs} +2 -2
  62. package/dist/{health-DjZYjM7H.mjs → health-CasG2A28.mjs} +1 -1
  63. package/dist/hooks/index.d.mts +1 -1
  64. package/dist/hooks/index.mjs +2 -2
  65. package/dist/idempotency/index.d.mts +45 -1
  66. package/dist/idempotency/index.mjs +95 -11
  67. package/dist/idempotency/redis.mjs +1 -1
  68. package/dist/{index-CEJNZFtX.d.mts → index-B-DvUzsr.d.mts} +82 -3
  69. package/dist/{index-CpzxqePp.d.mts → index-BcR2bFZQ.d.mts} +707 -373
  70. package/dist/{index-Bc2ox8_U.d.mts → index-Brin0ODU.d.mts} +4 -4
  71. package/dist/{index-CFThn1K9.d.mts → index-C5NnMEKF.d.mts} +70 -4
  72. package/dist/{index-C-481Zf2.d.mts → index-ugr1tQlW.d.mts} +17 -1
  73. package/dist/index.d.mts +6 -6
  74. package/dist/index.mjs +11 -11
  75. package/dist/{init-BEiNZBsJ.mjs → init-mdJ-v4Xp.mjs} +24 -16
  76. package/dist/integrations/event-gateway.d.mts +1 -1
  77. package/dist/integrations/event-gateway.mjs +2 -2
  78. package/dist/integrations/index.d.mts +2 -2
  79. package/dist/integrations/index.mjs +1 -1
  80. package/dist/integrations/jobs/index.d.mts +1 -1
  81. package/dist/integrations/jobs/index.mjs +100 -98
  82. package/dist/integrations/mcp/index.d.mts +12 -3
  83. package/dist/integrations/mcp/index.mjs +2 -2
  84. package/dist/integrations/mcp/testing.d.mts +1 -1
  85. package/dist/integrations/mcp/testing.mjs +2 -2
  86. package/dist/integrations/streamline.mjs +3 -3
  87. package/dist/integrations/webhooks.d.mts +124 -1
  88. package/dist/integrations/webhooks.mjs +180 -2
  89. package/dist/integrations/websocket-pushref-redis.mjs +1 -1
  90. package/dist/integrations/websocket-redis.mjs +1 -1
  91. package/dist/integrations/websocket.mjs +38 -35
  92. package/dist/{interface-DYzM0q-u.mjs → interface-DznJrm9R.mjs} +1 -1
  93. package/dist/{jsonBody-BYbLDi5D.mjs → jsonBody-CfGH-GxO.mjs} +2 -2
  94. package/dist/{keys-C0_pa1tY.mjs → keys-WeKvY1dE.mjs} +1 -1
  95. package/dist/{loadResources-yawi9tAE.mjs → loadResources-Bj-aSsXi.mjs} +4 -3
  96. package/dist/{loadResourcesFromEntry-BAjYZonx.mjs → loadResourcesFromEntry-DwaxNcE2.mjs} +2 -2
  97. package/dist/logger/index.mjs +1 -1
  98. package/dist/{mcpPlugin-B_es0hiF.mjs → mcpPlugin-aJg5TqHi.mjs} +76 -36
  99. package/dist/{memory-DR6wpa9F.mjs → memory-qYSB7rMQ.mjs} +5 -5
  100. package/dist/{metrics-CUdw_wLB.mjs → metrics-D7uchLjN.mjs} +2 -2
  101. package/dist/middleware/index.d.mts +1 -1
  102. package/dist/middleware/index.mjs +3 -3
  103. package/dist/migrations/index.mjs +3 -3
  104. package/dist/{module-0pFJA6YW.mjs → module-CwKsgZXp.mjs} +1 -1
  105. package/dist/{multipartBody-wOgj_fnj.mjs → multipartBody-4w-S3-PU.mjs} +3 -3
  106. package/dist/{openapi-B2L4js1v.mjs → openapi-BN5cQaO2.mjs} +6 -6
  107. package/dist/outbox-admin/index.d.mts +85 -0
  108. package/dist/outbox-admin/index.mjs +115 -0
  109. package/dist/outbox-module-CXB79bvt.mjs +839 -0
  110. package/dist/outbox-module-D-VFq37T.d.mts +368 -0
  111. package/dist/permissions/index.d.mts +3 -3
  112. package/dist/permissions/index.mjs +6 -6
  113. package/dist/{permissions-L--QDAir.mjs → permissions-BAfwgBxc.mjs} +120 -8
  114. package/dist/{pipe-DRDNsI2T.mjs → pipe-BzzoEhHj.mjs} +3 -5
  115. package/dist/pipeline/index.d.mts +1 -1
  116. package/dist/pipeline/index.mjs +2 -2
  117. package/dist/{pipeline-UPQFatit.mjs → pipeline-q69DZzgG.mjs} +17 -15
  118. package/dist/plugins/index.d.mts +6 -6
  119. package/dist/plugins/index.mjs +16 -16
  120. package/dist/plugins/response-cache.mjs +2 -2
  121. package/dist/plugins/tracing-entry.mjs +2 -2
  122. package/dist/{pluralize-O0FZgESl.mjs → pluralize-B7xf8qZF.mjs} +1 -1
  123. package/dist/{preloadResources-Dz6BjzM6.mjs → preloadResources-BkyqeTDz.mjs} +1 -1
  124. package/dist/{preloadResources-CyoJMSiO.d.mts → preloadResources-g07ldtzh.d.mts} +30 -7
  125. package/dist/presets/filesUpload.d.mts +2 -2
  126. package/dist/presets/filesUpload.mjs +6 -6
  127. package/dist/presets/index.d.mts +2 -2
  128. package/dist/presets/index.mjs +2 -2
  129. package/dist/presets/multiTenant.d.mts +1 -1
  130. package/dist/presets/multiTenant.mjs +3 -3
  131. package/dist/presets/search.d.mts +2 -2
  132. package/dist/presets/search.mjs +2 -2
  133. package/dist/{presets-C4-g4_4P.mjs → presets-D-h0uWtP.mjs} +6 -5
  134. package/dist/projection-BKM0Ui-s.mjs +42 -0
  135. package/dist/{queryCachePlugin-BZr8v46E.mjs → queryCachePlugin-DhsZ0ZIc.mjs} +50 -8
  136. package/dist/{rateLimit-CMPY5Qms.mjs → rateLimit-D4-ASwsI.mjs} +2 -2
  137. package/dist/{rateLimitKey-Dn5JNmkj.mjs → rateLimitKey-XngqVNEV.mjs} +1 -1
  138. package/dist/{realtime-C5NoxWFY.mjs → realtime-CTkv3O59.mjs} +10 -10
  139. package/dist/{redis-stream-qN6A-RFv.d.mts → redis-stream-mwLWlfHG.d.mts} +1 -1
  140. package/dist/{registerRoute-CBN84fc7.mjs → registerRoute-DNnd3vkz.mjs} +10 -8
  141. package/dist/registry/index.d.mts +3 -3
  142. package/dist/registry/index.mjs +3 -3
  143. package/dist/{registry-4213U4zb.mjs → registry-CLxCR5LF.mjs} +2 -2
  144. package/dist/{renewingLease-Dll8mGgc.mjs → renewingLease-BnWtbA2U.mjs} +1 -1
  145. package/dist/{replyHelpers-DIiZKGUt.mjs → replyHelpers-BSBVCwL3.mjs} +2 -2
  146. package/dist/{repositoryFilter-f9eAfq_l.mjs → repositoryFilter-DKny7PDn.mjs} +1 -1
  147. package/dist/{requestContext-2TxXOJ7T.mjs → requestContext-uYE35JxI.mjs} +1 -1
  148. package/dist/{rolldown-runtime-CUsjNX9R.mjs → rolldown-runtime-DNg-KNCk.mjs} +1 -1
  149. package/dist/runtimeCapabilities-Dm88DaTW.mjs +49 -0
  150. package/dist/{schedules-DdtlICTf.mjs → schedules-CAcZgia0.mjs} +3 -3
  151. package/dist/{schemaConverter-D--wdJM-.mjs → schemaConverter-XH1RZRyu.mjs} +1 -1
  152. package/dist/{schemaIR-Bm2enbnh.mjs → schemaIR-CDvclAew.mjs} +2 -2
  153. package/dist/schemas/index.mjs +1 -1
  154. package/dist/scim/index.mjs +2 -2
  155. package/dist/scope/index.mjs +5 -5
  156. package/dist/{scope-DHx5Fous.mjs → scope-BaWcqBvr.mjs} +4 -4
  157. package/dist/{simpleEqualityMatcher-DjQJ7FKA.mjs → simpleEqualityMatcher-Se8VrsaP.mjs} +1 -1
  158. package/dist/{sse-CUTo9y0X.mjs → sse-Cf0jUHsh.mjs} +7 -6
  159. package/dist/{sseStream-B_5XcVVd.mjs → sseStream-Bvpi-UXQ.mjs} +2 -2
  160. package/dist/{store-helpers-D1MP_gRG.mjs → store-helpers-B88p99Z2.mjs} +1 -1
  161. package/dist/{streaming-PSZwi8JV.mjs → streaming-DsT1B5zJ.mjs} +1 -1
  162. package/dist/{subscribe-helpers-C0Tb2aUp.mjs → subscribe-helpers-CLIOHsOK.mjs} +2 -2
  163. package/dist/sync/changelog.mjs +1 -1
  164. package/dist/testing/cleanupStoreContract.d.mts +1 -1
  165. package/dist/testing/cleanupStoreContract.mjs +12 -6
  166. package/dist/testing/index.d.mts +52 -13
  167. package/dist/testing/index.mjs +110 -40
  168. package/dist/testing/outboxStoreContract.d.mts +11 -2
  169. package/dist/testing/outboxStoreContract.mjs +110 -21
  170. package/dist/testing/storageContract.mjs +11 -6
  171. package/dist/{transactionContext-dAfBVUrk.mjs → transactionContext-BYtWnwAS.mjs} +1 -1
  172. package/dist/{typeGuards-B0ryPo3I.mjs → typeGuards-jjKJDN13.mjs} +1 -1
  173. package/dist/types/index.d.mts +3 -3
  174. package/dist/types/index.mjs +1 -1
  175. package/dist/types/storage.mjs +1 -1
  176. package/dist/{types-CBgvkp8O.d.mts → types-BcTumAz_.d.mts} +128 -18
  177. package/dist/{types-CwcUQ610.d.mts → types-BfC83KsP.d.mts} +15 -1
  178. package/dist/{types-Cys0ko9Z.mjs → types-CoqIRrkY.mjs} +4 -4
  179. package/dist/{types-C4QE8qnm.d.mts → types-DVLddu2q.d.mts} +144 -1
  180. package/dist/usage/index.d.mts +1 -1
  181. package/dist/usage/index.mjs +0 -0
  182. package/dist/{userHelpers-ChYJ6CdK.mjs → userHelpers-CWF5pbZD.mjs} +1 -1
  183. package/dist/utils/index.d.mts +57 -5
  184. package/dist/utils/index.mjs +12 -11
  185. package/dist/{utils-vL8BrDE2.mjs → utils-h1V_sT-t.mjs} +38 -7
  186. package/dist/{validate-_KbifpHF.mjs → validate-CdQlz52F.mjs} +2 -2
  187. package/dist/{versioning-D_rhHfZm.d.mts → versioning-DEs-_hFi.d.mts} +1 -1
  188. package/dist/{versioning-CHDTor3P.mjs → versioning-rZbyLVD-.mjs} +4 -4
  189. package/package.json +31 -20
  190. package/skills/arc/SKILL.md +96 -4
  191. package/skills/arc/references/api-reference.md +19 -0
  192. package/skills/arc/references/production.md +2 -2
  193. package/dist/fastify-augmentation-zh0_AYHa.d.mts +0 -85
  194. package/dist/projection-BHw6xlOQ.mjs +0 -18
@@ -1,13 +1,13 @@
1
- /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
- import { t as CRUD_OPERATIONS } from "../constants-D3Dv4LAV.mjs";
3
- import { g as getUserId } from "../types-Cys0ko9Z.mjs";
4
- import { t as BaseController } from "../BaseController-De7GqHck.mjs";
5
- import { t as defineResource } from "../defineResource-Bv6EtN1x.mjs";
6
- import { t as defineAggregation } from "../defineAggregation-DbPPS8RI.mjs";
7
- import { S as requireOrgRole } from "../permissions-L--QDAir.mjs";
8
- import { n as createApp } from "../createApp-Df89BEni.mjs";
9
- import { n as getModuleExports } from "../module-0pFJA6YW.mjs";
10
- import { n as preloadResourcesAsync, t as preloadResources } from "../preloadResources-Dz6BjzM6.mjs";
1
+ /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
+ import { t as CRUD_OPERATIONS } from "../constants-BxCoxmiN.mjs";
3
+ import { g as getUserId } from "../types-CoqIRrkY.mjs";
4
+ import { t as BaseController } from "../BaseController-CaQC5EXX.mjs";
5
+ import { t as defineResource } from "../defineResource-DR9vsUYy.mjs";
6
+ import { t as defineAggregation } from "../defineAggregation-Nv-DwfOf.mjs";
7
+ import { E as requireOrgRole } from "../permissions-BAfwgBxc.mjs";
8
+ import { r as createApp } from "../createApp-CLGegqiG.mjs";
9
+ import { n as getModuleExports } from "../module-CwKsgZXp.mjs";
10
+ import { n as preloadResourcesAsync, t as preloadResources } from "../preloadResources-BkyqeTDz.mjs";
11
11
  import { runStorageContract } from "./storageContract.mjs";
12
12
  import Fastify from "fastify";
13
13
  import { afterAll, describe, expect, it, vi } from "vitest";
@@ -64,7 +64,8 @@ function expectArc(response) {
64
64
  failed(status) {
65
65
  if (status !== void 0) expect(response.statusCode).toBe(status);
66
66
  else expect(response.statusCode).toBeGreaterThanOrEqual(400);
67
- expect(getBody().code, "expected ErrorContract.code on failed response").toBeDefined();
67
+ const body = getBody();
68
+ expect(body.code, "expected ErrorContract.code on failed response").toBeDefined();
68
69
  return assertion;
69
70
  },
70
71
  unauthorized() {
@@ -84,7 +85,8 @@ function expectArc(response) {
84
85
  },
85
86
  hasData() {
86
87
  const body = getBody();
87
- expect(Object.keys(body).length > 0, "expected response body to be defined").toBe(true);
88
+ const hasContent = Object.keys(body).length > 0;
89
+ expect(hasContent, "expected response body to be defined").toBe(true);
88
90
  return assertion;
89
91
  },
90
92
  hasStatus(status) {
@@ -92,11 +94,13 @@ function expectArc(response) {
92
94
  return assertion;
93
95
  },
94
96
  hidesField(field) {
95
- expect(getBody(), `expected field '${field}' to be hidden from response`).not.toHaveProperty(field);
97
+ const body = getBody();
98
+ expect(body, `expected field '${field}' to be hidden from response`).not.toHaveProperty(field);
96
99
  return assertion;
97
100
  },
98
101
  showsField(field) {
99
- expect(getBody(), `expected field '${field}' on response`).toHaveProperty(field);
102
+ const body = getBody();
103
+ expect(body, `expected field '${field}' on response`).toHaveProperty(field);
100
104
  return assertion;
101
105
  },
102
106
  paginated(expected) {
@@ -247,7 +251,19 @@ function createMockReply() {
247
251
  };
248
252
  }
249
253
  /**
250
- * Create a mock controller for testing
254
+ * Create a mock controller for testing.
255
+ *
256
+ * The return type is ANNOTATED rather than inferred, and writing it out IS the
257
+ * fix: inference expands `Mock`'s default type argument to `Procedure`, which
258
+ * vitest declares in an internal sub-package arc does not depend on. The
259
+ * emitted declaration then referenced that package by name — resolvable under
260
+ * npm's hoisting because `vitest` (a real peer) drags it in, and broken under
261
+ * pnpm's strict layout, where a transitive dep is not reachable from a
262
+ * consumer's root.
263
+ *
264
+ * Bare `Mock` keeps the permissive ergonomics (`.mockResolvedValue(...)`, any
265
+ * arguments) while naming only `vitest`, which arc does declare. Same shape
266
+ * `MockRepository` above uses.
251
267
  */
252
268
  function createMockController(repository) {
253
269
  return {
@@ -398,6 +414,21 @@ async function runAuthorizationConformance(opts) {
398
414
  getFilter = filter;
399
415
  return rows[0] ?? null;
400
416
  }),
417
+ /**
418
+ * The single-record read has TWO paths, and the harness must be able to observe both.
419
+ *
420
+ * `fetchDetailed` only builds a compound filter and calls `getOne` when there is something to
421
+ * compound — a row policy, a tenant field, or a non-default id field. A permission that simply
422
+ * ALLOWS (no policy) leaves `{ _id }` alone and takes the plain `getById` path instead. The base
423
+ * mock stubs that as `null`, so before this stub the `get` surface reported **404 on every
424
+ * policy-free allow** while `list` and `aggregation` reported 200.
425
+ *
426
+ * That reads as partial enforcement and it is not: it is the harness failing to answer. A host
427
+ * asserting `get.status === 200` for its own allow-gate — the obvious falsification case to pair
428
+ * with a deny-parity suite — was told its gate broke the single-record surface. Found from
429
+ * be-prod, whose conformance suite does exactly that.
430
+ */
431
+ getById: (async () => rows[0] ?? null),
401
432
  aggregate: (async (req = {}) => {
402
433
  aggFilter = req.filter;
403
434
  return { rows: [{ tally: rows.length }] };
@@ -1166,12 +1197,13 @@ var HttpTestHarness = class {
1166
1197
  it(`${verb} /:id with non-existent ID should return 404`, async () => {
1167
1198
  const { app, fixtures } = this.getOptions();
1168
1199
  const payload = fixtures.update ?? fixtures.valid;
1169
- expect((await app.inject({
1200
+ const res = await app.inject({
1170
1201
  method: verb,
1171
1202
  url: `${this.getBaseUrl()}/000000000000000000000000`,
1172
1203
  headers: this.adminHeaders(),
1173
1204
  payload
1174
- })).statusCode).toBe(404);
1205
+ });
1206
+ expect(res.statusCode).toBe(404);
1175
1207
  });
1176
1208
  }
1177
1209
  if (enabledRoutes.has("delete")) {
@@ -1188,24 +1220,29 @@ var HttpTestHarness = class {
1188
1220
  deleteId = JSON.parse(createRes.body)._id;
1189
1221
  }
1190
1222
  if (!deleteId) return;
1191
- expect((await app.inject({
1223
+ const res = await app.inject({
1192
1224
  method: "DELETE",
1193
1225
  url: `${this.getBaseUrl()}/${deleteId}`,
1194
1226
  headers: this.adminHeaders()
1195
- })).statusCode).toBe(200);
1196
- if (enabledRoutes.has("get")) expect((await app.inject({
1197
- method: "GET",
1198
- url: `${this.getBaseUrl()}/${deleteId}`,
1199
- headers: this.adminHeaders()
1200
- })).statusCode).toBe(404);
1227
+ });
1228
+ expect(res.statusCode).toBe(200);
1229
+ if (enabledRoutes.has("get")) {
1230
+ const getRes = await app.inject({
1231
+ method: "GET",
1232
+ url: `${this.getBaseUrl()}/${deleteId}`,
1233
+ headers: this.adminHeaders()
1234
+ });
1235
+ expect(getRes.statusCode).toBe(404);
1236
+ }
1201
1237
  });
1202
1238
  it("DELETE /:id with non-existent ID should return 404", async () => {
1203
1239
  const { app } = this.getOptions();
1204
- expect((await app.inject({
1240
+ const res = await app.inject({
1205
1241
  method: "DELETE",
1206
1242
  url: `${this.getBaseUrl()}/000000000000000000000000`,
1207
1243
  headers: this.adminHeaders()
1208
- })).statusCode).toBe(404);
1244
+ });
1245
+ expect(res.statusCode).toBe(404);
1209
1246
  });
1210
1247
  }
1211
1248
  });
@@ -1224,49 +1261,55 @@ var HttpTestHarness = class {
1224
1261
  describe(`${resource.displayName} HTTP Permissions`, () => {
1225
1262
  if (enabledRoutes.has("list") && protectedOps.list) it("GET list without auth should return 401", async () => {
1226
1263
  const { app } = this.getOptions();
1227
- expect((await app.inject({
1264
+ const res = await app.inject({
1228
1265
  method: "GET",
1229
1266
  url: this.getBaseUrl()
1230
- })).statusCode).toBe(401);
1267
+ });
1268
+ expect(res.statusCode).toBe(401);
1231
1269
  });
1232
1270
  if (enabledRoutes.has("get") && protectedOps.get) it("GET /:id without auth should return 401", async () => {
1233
1271
  const { app } = this.getOptions();
1234
- expect((await app.inject({
1272
+ const res = await app.inject({
1235
1273
  method: "GET",
1236
1274
  url: `${this.getBaseUrl()}/000000000000000000000000`
1237
- })).statusCode).toBe(401);
1275
+ });
1276
+ expect(res.statusCode).toBe(401);
1238
1277
  });
1239
1278
  if (enabledRoutes.has("create") && protectedOps.create) it("POST without auth should return 401", async () => {
1240
1279
  const { app, fixtures } = this.getOptions();
1241
- expect((await app.inject({
1280
+ const res = await app.inject({
1242
1281
  method: "POST",
1243
1282
  url: this.getBaseUrl(),
1244
1283
  payload: fixtures.valid
1245
- })).statusCode).toBe(401);
1284
+ });
1285
+ expect(res.statusCode).toBe(401);
1246
1286
  });
1247
1287
  if (enabledRoutes.has("update") && protectedOps.update) for (const verb of updateMethods) it(`${verb} without auth should return 401`, async () => {
1248
1288
  const { app, fixtures } = this.getOptions();
1249
1289
  const payload = fixtures.update ?? fixtures.valid;
1250
- expect((await app.inject({
1290
+ const res = await app.inject({
1251
1291
  method: verb,
1252
1292
  url: `${this.getBaseUrl()}/000000000000000000000000`,
1253
1293
  payload
1254
- })).statusCode).toBe(401);
1294
+ });
1295
+ expect(res.statusCode).toBe(401);
1255
1296
  });
1256
1297
  if (enabledRoutes.has("delete") && protectedOps.delete) it("DELETE without auth should return 401", async () => {
1257
1298
  const { app } = this.getOptions();
1258
- expect((await app.inject({
1299
+ const res = await app.inject({
1259
1300
  method: "DELETE",
1260
1301
  url: `${this.getBaseUrl()}/000000000000000000000000`
1261
- })).statusCode).toBe(401);
1302
+ });
1303
+ expect(res.statusCode).toBe(401);
1262
1304
  });
1263
1305
  if (enabledRoutes.has("list")) it("admin should access list endpoint", async () => {
1264
1306
  const { app } = this.getOptions();
1265
- expect((await app.inject({
1307
+ const res = await app.inject({
1266
1308
  method: "GET",
1267
1309
  url: this.getBaseUrl(),
1268
1310
  headers: this.adminHeaders()
1269
- })).statusCode).toBeLessThan(400);
1311
+ });
1312
+ expect(res.statusCode).toBeLessThan(400);
1270
1313
  });
1271
1314
  if (enabledRoutes.has("create")) it("admin should access create endpoint", async () => {
1272
1315
  const { app, fixtures } = this.getOptions();
@@ -1313,6 +1356,33 @@ function createHttpTestHarness(resource, optionsOrGetter) {
1313
1356
  return new HttpTestHarness(resource, optionsOrGetter);
1314
1357
  }
1315
1358
  //#endregion
1359
+ //#region src/testing/moduleSetup.ts
1360
+ function createTestModuleSetup() {
1361
+ const deferred = [];
1362
+ return {
1363
+ context: { defer(disposer) {
1364
+ if (typeof disposer !== "function") throw new TypeError(`[arc/testing] defer() expected a function, received ${typeof disposer}.`);
1365
+ deferred.push(disposer);
1366
+ } },
1367
+ deferred,
1368
+ async dispose() {
1369
+ const errors = [];
1370
+ for (let i = deferred.length - 1; i >= 0; i--) {
1371
+ const dispose = deferred[i];
1372
+ if (!dispose) continue;
1373
+ try {
1374
+ await dispose();
1375
+ } catch (err) {
1376
+ errors.push(err);
1377
+ }
1378
+ }
1379
+ deferred.length = 0;
1380
+ if (errors.length === 1) throw errors[0];
1381
+ if (errors.length > 1) throw new AggregateError(errors, `[arc/testing] ${errors.length} disposers threw`);
1382
+ }
1383
+ };
1384
+ }
1385
+ //#endregion
1316
1386
  //#region src/testing/scopeRoleGate.ts
1317
1387
  /**
1318
1388
  * `scopeRoleGate` — the ONE role gate for package tests.
@@ -1435,7 +1505,7 @@ function pickDefaultAuth(authMode, callerAuth) {
1435
1505
  };
1436
1506
  }
1437
1507
  async function createTestApp(options = {}) {
1438
- const { createApp } = await import("../createApp-Df89BEni.mjs").then((n) => n.r);
1508
+ const { createApp } = await import("../createApp-CLGegqiG.mjs").then((n) => n.i);
1439
1509
  const { resources = [], db = "in-memory", connectMongoose = false, authMode = "jwt", defaultOrgId, plugins, auth: callerAuth, ...appOptions } = options;
1440
1510
  let dbHandle;
1441
1511
  let dbUri;
@@ -1505,4 +1575,4 @@ function createMinimalTestApp(options = {}) {
1505
1575
  });
1506
1576
  }
1507
1577
  //#endregion
1508
- export { HttpTestHarness, TEST_ACTOR_HEADER, bootModuleApp, createBetterAuthProvider, createBetterAuthTestHelpers, createCustomAuthProvider, createDataFactory, createHttpTestHarness, createJwtAuthProvider, createMinimalTestApp, createMockController, createMockReply, createMockRepository, createMockRequest, createMockUser, createSpy, createTestApp, createTestFixtures, createTestTimer, expectArc, mongoMemoryDatabase, preloadResources, preloadResourcesAsync, runAuthorizationConformance, runStorageContract, safeParseBody, scopeFromTestActor, scopeRoleGate, setupBetterAuthTestApp, testActorAuth, testActorHeaders, waitFor };
1578
+ export { HttpTestHarness, TEST_ACTOR_HEADER, bootModuleApp, createBetterAuthProvider, createBetterAuthTestHelpers, createCustomAuthProvider, createDataFactory, createHttpTestHarness, createJwtAuthProvider, createMinimalTestApp, createMockController, createMockReply, createMockRepository, createMockRequest, createMockUser, createSpy, createTestApp, createTestFixtures, createTestModuleSetup, createTestTimer, expectArc, mongoMemoryDatabase, preloadResources, preloadResourcesAsync, runAuthorizationConformance, runStorageContract, safeParseBody, scopeFromTestActor, scopeRoleGate, setupBetterAuthTestApp, testActorAuth, testActorHeaders, waitFor };
@@ -5,8 +5,17 @@ interface OutboxStoreContractSetupResult {
5
5
  store: OutboxStore;
6
6
  /** Called once after the suite. */
7
7
  teardown?: () => Promise<void>;
8
- /** Empty the store between tests. Strongly recommended for isolation. */
9
- reset?: () => Promise<void>;
8
+ /**
9
+ * Empty the store. REQUIRED, and run before every test.
10
+ *
11
+ * Not a recommendation: several assertions are absolute rather than relative —
12
+ * "exactly zero pending", "exactly two", "`oldestPendingAgeMs()` is null on an
13
+ * empty queue". Without a reset those read whatever the previous test left, so the
14
+ * suite passes on ORDER rather than on behaviour, and inserting one unrelated case
15
+ * turns a conforming store red. A store that cannot empty itself cannot be
16
+ * conformance-tested.
17
+ */
18
+ reset: () => Promise<void>;
10
19
  }
11
20
  type OutboxStoreContractSetup = () => Promise<OutboxStoreContractSetupResult>;
12
21
  declare function runOutboxStoreContract(name: string, setup: OutboxStoreContractSetup): void;
@@ -1,6 +1,6 @@
1
- /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
2
  import { OutboxOwnershipError } from "@classytic/primitives/outbox";
3
- import { afterAll, beforeAll, describe, expect, it } from "vitest";
3
+ import { afterAll, beforeAll, beforeEach, describe, expect, it } from "vitest";
4
4
  //#region src/testing/outboxStoreContract.ts
5
5
  let seq = 0;
6
6
  /** A minimal well-formed event. Ids are unique per call. */
@@ -30,9 +30,16 @@ function runOutboxStoreContract(name, setup) {
30
30
  afterAll(async () => {
31
31
  if (teardown) await teardown();
32
32
  });
33
+ /**
34
+ * Isolation for EVERY test, not just the ones that call `seed()`. Resetting inside
35
+ * `seed()` left any test that asserts on an empty store — or that only reads —
36
+ * running against its predecessor's rows.
37
+ */
38
+ beforeEach(async () => {
39
+ await reset();
40
+ });
33
41
  /** Save n events, oldest first. */
34
42
  async function seed(n, type) {
35
- if (reset) await reset();
36
43
  const events = [];
37
44
  for (let i = 0; i < n; i++) {
38
45
  const e = event(type);
@@ -44,10 +51,10 @@ function runOutboxStoreContract(name, setup) {
44
51
  describe("save — rejects malformed events (invariant 1)", () => {
45
52
  it("persists a well-formed event", async () => {
46
53
  const [e] = await seed(1);
47
- expect((await store.getPending(10)).map(idOf)).toContain(idOf(e));
54
+ const pending = await store.getPending(10);
55
+ expect(pending.map(idOf)).toContain(idOf(e));
48
56
  });
49
57
  it("THROWS rather than persisting an event with no `type`", async () => {
50
- if (reset) await reset();
51
58
  await expect(store.save({
52
59
  payload: {},
53
60
  meta: { id: "no-type" }
@@ -55,7 +62,6 @@ function runOutboxStoreContract(name, setup) {
55
62
  expect((await store.getPending(10)).length).toBe(0);
56
63
  });
57
64
  it("THROWS rather than persisting an event with no `meta.id`", async () => {
58
- if (reset) await reset();
59
65
  await expect(store.save({
60
66
  type: "x",
61
67
  payload: {},
@@ -67,7 +73,8 @@ function runOutboxStoreContract(name, setup) {
67
73
  describe("getPending", () => {
68
74
  it("returns events FIFO (oldest first)", async () => {
69
75
  const saved = await seed(3);
70
- expect((await store.getPending(10)).slice(0, 3).map(idOf)).toEqual(saved.map(idOf));
76
+ const pending = await store.getPending(10);
77
+ expect(pending.slice(0, 3).map(idOf)).toEqual(saved.map(idOf));
71
78
  });
72
79
  it("honours the limit", async () => {
73
80
  await seed(3);
@@ -86,10 +93,11 @@ function runOutboxStoreContract(name, setup) {
86
93
  it("claims pending events", async ({ skip }) => {
87
94
  if (!store.claimPending) return skip();
88
95
  await seed(2);
89
- expect((await store.claimPending({
96
+ const claimed = await store.claimPending({
90
97
  consumerId: "c1",
91
98
  limit: 10
92
- })).length).toBe(2);
99
+ });
100
+ expect(claimed.length).toBe(2);
93
101
  });
94
102
  it("two concurrent claimers NEVER receive the same event", async ({ skip }) => {
95
103
  if (!store.claimPending) return skip();
@@ -103,7 +111,8 @@ function runOutboxStoreContract(name, setup) {
103
111
  })]);
104
112
  const idsA = a.map(idOf);
105
113
  const idsB = b.map(idOf);
106
- expect(idsA.filter((id) => idsB.includes(id))).toEqual([]);
114
+ const overlap = idsA.filter((id) => idsB.includes(id));
115
+ expect(overlap).toEqual([]);
107
116
  expect(idsA.length + idsB.length).toBeLessThanOrEqual(6);
108
117
  });
109
118
  it("does not re-claim an event whose lease is still live", async ({ skip }) => {
@@ -114,10 +123,11 @@ function runOutboxStoreContract(name, setup) {
114
123
  limit: 10,
115
124
  leaseMs: 6e4
116
125
  });
117
- expect(await store.claimPending({
126
+ const second = await store.claimPending({
118
127
  consumerId: "c2",
119
128
  limit: 10
120
- })).toEqual([]);
129
+ });
130
+ expect(second).toEqual([]);
121
131
  });
122
132
  it("RECLAIMS an event whose lease expired (crashed worker)", async ({ skip }) => {
123
133
  if (!store.claimPending) return skip();
@@ -127,18 +137,20 @@ function runOutboxStoreContract(name, setup) {
127
137
  limit: 10,
128
138
  leaseMs: 0
129
139
  });
130
- expect((await store.claimPending({
140
+ const reclaimed = await store.claimPending({
131
141
  consumerId: "c2",
132
142
  limit: 10
133
- })).length).toBe(1);
143
+ });
144
+ expect(reclaimed.length).toBe(1);
134
145
  });
135
146
  it("claims FIFO", async ({ skip }) => {
136
147
  if (!store.claimPending) return skip();
137
148
  const saved = await seed(3);
138
- expect((await store.claimPending({
149
+ const claimed = await store.claimPending({
139
150
  consumerId: "c1",
140
151
  limit: 2
141
- })).map(idOf)).toEqual(saved.slice(0, 2).map(idOf));
152
+ });
153
+ expect(claimed.map(idOf)).toEqual(saved.slice(0, 2).map(idOf));
142
154
  });
143
155
  });
144
156
  describe("acknowledge", () => {
@@ -148,7 +160,6 @@ function runOutboxStoreContract(name, setup) {
148
160
  expect((await store.getPending(10)).map(idOf)).not.toContain(idOf(e));
149
161
  });
150
162
  it("is a NO-OP for an unknown id — never an ownership error (invariant 4)", async () => {
151
- if (reset) await reset();
152
163
  await expect(store.acknowledge("does-not-exist")).resolves.not.toThrow();
153
164
  });
154
165
  it("THROWS OutboxOwnershipError when consumerId is not the lease owner (invariant 3)", async ({ skip }) => {
@@ -185,10 +196,11 @@ function runOutboxStoreContract(name, setup) {
185
196
  });
186
197
  if (!claimed) return skip();
187
198
  await store.fail(idOf(claimed), { message: "boom" });
188
- expect((await store.claimPending({
199
+ const again = await store.claimPending({
189
200
  consumerId: "c2",
190
201
  limit: 10
191
- })).map(idOf)).toContain(idOf(claimed));
202
+ });
203
+ expect(again.map(idOf)).toContain(idOf(claimed));
192
204
  });
193
205
  it("THROWS OutboxOwnershipError on a consumerId mismatch (invariant 3)", async ({ skip }) => {
194
206
  if (!store.fail || !store.claimPending) return skip();
@@ -211,10 +223,11 @@ function runOutboxStoreContract(name, setup) {
211
223
  });
212
224
  if (!claimed) return skip();
213
225
  await store.fail(idOf(claimed), { message: "boom" }, { retryAt: new Date(Date.now() + 6e4) });
214
- expect((await store.claimPending({
226
+ const again = await store.claimPending({
215
227
  consumerId: "c2",
216
228
  limit: 10
217
- })).map(idOf)).not.toContain(idOf(claimed));
229
+ });
230
+ expect(again.map(idOf)).not.toContain(idOf(claimed));
218
231
  });
219
232
  it("`deadLetter: true` removes it from the pending stream", async ({ skip }) => {
220
233
  if (!store.fail) return skip();
@@ -242,6 +255,82 @@ function runOutboxStoreContract(name, setup) {
242
255
  expect((await store.getPending(10)).length).toBe(2);
243
256
  });
244
257
  });
258
+ /**
259
+ * `requeue`, `countByStatus` and `oldestPendingAgeMs` were a HOST's three extra
260
+ * methods before they were contract members — which is why they are pinned here.
261
+ * A dead-letter row an operator cannot re-drive, or a health number that lies, fails
262
+ * silently: the operator concludes the queue is fine, and the whole point of the
263
+ * table is that somebody eventually looks.
264
+ */
265
+ describe("requeue", () => {
266
+ it("returns a dead-lettered event to pending and clears the attempt count", async ({ skip }) => {
267
+ if (!store.fail || !store.requeue) return skip();
268
+ const [e] = await seed(1);
269
+ const id = idOf(e);
270
+ await store.fail(id, { message: "fatal" }, { deadLetter: true });
271
+ expect((await store.getPending(10)).length).toBe(0);
272
+ expect(await store.requeue(id)).toBe(true);
273
+ const pending = await store.getPending(10);
274
+ expect(pending.length).toBe(1);
275
+ if (store.countByStatus) expect(await store.countByStatus("dead_letter")).toBe(0);
276
+ });
277
+ it("REFUSES a pending event — requeue is dead-letter-scoped", async ({ skip }) => {
278
+ if (!store.requeue) return skip();
279
+ const [e] = await seed(1);
280
+ expect(await store.requeue(idOf(e))).toBe(false);
281
+ });
282
+ it("is FALSE, not an error, for an unknown id", async ({ skip }) => {
283
+ if (!store.requeue) return skip();
284
+ expect(await store.requeue("no-such-event")).toBe(false);
285
+ });
286
+ });
287
+ describe("countByStatus", () => {
288
+ it("counts pending, and moves the count as events are delivered", async ({ skip }) => {
289
+ if (!store.countByStatus) return skip();
290
+ await seed(3);
291
+ expect(await store.countByStatus("pending")).toBe(3);
292
+ if (!store.claimPending) return skip();
293
+ const [claimed] = await store.claimPending({
294
+ consumerId: "c",
295
+ limit: 1,
296
+ leaseMs: 6e4
297
+ });
298
+ if (!claimed) return skip();
299
+ await store.acknowledge(idOf(claimed), { consumerId: "c" });
300
+ expect(await store.countByStatus("pending")).toBe(2);
301
+ expect(await store.countByStatus("delivered")).toBe(1);
302
+ });
303
+ it("counts dead-lettered rows — the number an alert fires on", async ({ skip }) => {
304
+ if (!store.countByStatus || !store.fail) return skip();
305
+ expect(await store.countByStatus("dead_letter")).toBe(0);
306
+ const [e] = await seed(1);
307
+ await store.fail(idOf(e), { message: "fatal" }, { deadLetter: true });
308
+ expect(await store.countByStatus("dead_letter")).toBe(1);
309
+ });
310
+ });
311
+ describe("oldestPendingAgeMs", () => {
312
+ it("is null on an empty queue, and a non-negative age once something pends", async ({ skip }) => {
313
+ if (!store.oldestPendingAgeMs) return skip();
314
+ expect(await store.oldestPendingAgeMs()).toBeNull();
315
+ await seed(1);
316
+ const age = await store.oldestPendingAgeMs();
317
+ expect(age).not.toBeNull();
318
+ expect(age ?? -1).toBeGreaterThanOrEqual(0);
319
+ });
320
+ it("ignores DELIVERED rows — it answers 'how long undelivered', not 'how old'", async ({ skip }) => {
321
+ if (!store.oldestPendingAgeMs) return skip();
322
+ if (!store.claimPending) return skip();
323
+ await seed(1);
324
+ const [claimed] = await store.claimPending({
325
+ consumerId: "c",
326
+ limit: 1,
327
+ leaseMs: 6e4
328
+ });
329
+ if (!claimed) return skip();
330
+ await store.acknowledge(idOf(claimed), { consumerId: "c" });
331
+ expect(await store.oldestPendingAgeMs()).toBeNull();
332
+ });
333
+ });
245
334
  });
246
335
  }
247
336
  //#endregion
@@ -1,4 +1,4 @@
1
- /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
2
  import { afterAll, beforeAll, describe, expect, it } from "vitest";
3
3
  //#region src/testing/storageContract.ts
4
4
  /**
@@ -89,7 +89,8 @@ function runStorageContract(name, setup) {
89
89
  size: bytes.length
90
90
  }, EMPTY_CTX);
91
91
  const read = await storage.read(file.id, EMPTY_CTX);
92
- expect((await readAll(read)).equals(bytes)).toBe(true);
92
+ const actual = await readAll(read);
93
+ expect(actual.equals(bytes)).toBe(true);
93
94
  expect(read.contentType).toBe("application/octet-stream");
94
95
  await storage.delete(file.id, EMPTY_CTX);
95
96
  });
@@ -101,7 +102,8 @@ function runStorageContract(name, setup) {
101
102
  mimeType: "application/octet-stream",
102
103
  size: bytes.length
103
104
  }, EMPTY_CTX);
104
- expect(await storage.delete(file.id, EMPTY_CTX)).toBe(true);
105
+ const first = await storage.delete(file.id, EMPTY_CTX);
106
+ expect(first).toBe(true);
105
107
  let second = "threw";
106
108
  try {
107
109
  second = await storage.delete(file.id, EMPTY_CTX);
@@ -169,8 +171,10 @@ function runStorageContract(name, setup) {
169
171
  mimeType: "application/octet-stream",
170
172
  size: bytes.length
171
173
  }, EMPTY_CTX);
172
- expect((await readAll(await storage.read(file.id, EMPTY_CTX))).equals(bytes)).toBe(true);
173
- expect(await storage.delete(file.id, EMPTY_CTX)).toBe(true);
174
+ const before = await readAll(await storage.read(file.id, EMPTY_CTX));
175
+ expect(before.equals(bytes)).toBe(true);
176
+ const removed = await storage.delete(file.id, EMPTY_CTX);
177
+ expect(removed).toBe(true);
174
178
  let rejected = false;
175
179
  try {
176
180
  if (!(await readAll(await storage.read(file.id, EMPTY_CTX))).equals(bytes)) rejected = true;
@@ -189,7 +193,8 @@ function runStorageContract(name, setup) {
189
193
  }, EMPTY_CTX);
190
194
  const result = await storage.read(file.id, EMPTY_CTX);
191
195
  expect(result.kind === "stream" || result.kind === "buffer").toBe(true);
192
- expect((await readAll(result)).equals(bytes)).toBe(true);
196
+ const actual = await readAll(result);
197
+ expect(actual.equals(bytes)).toBe(true);
193
198
  await storage.delete(file.id, EMPTY_CTX);
194
199
  });
195
200
  it("read() with a mid-object range slices correctly (when adapter supports ranges)", async () => {
@@ -1,4 +1,4 @@
1
- /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
2
  import { AsyncLocalStorage } from "node:async_hooks";
3
3
  //#region src/context/transactionContext.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
2
  //#region src/utils/typeGuards.ts
3
3
  /** Check if fastify has the events plugin registered */
4
4
  function hasEvents(instance) {
@@ -1,6 +1,6 @@
1
1
 
2
- import { $ as OpenApiSchemas, A as RequestIdOptions, An as BaseControllerOptions, At as RouteDefinition, Bt as RawRouteHandler, C as RequestContext, D as HealthCheck, Dt as ActionEntry, E as GracefulShutdownOptions, Et as ActionDefinition, F as FastifyWithDecorators, Ft as ControllerLike, G as OnTenantDeleteConfig, Gt as Authenticator, H as CrudController, I as MiddlewareHandler, It as FastifyHandler, J as PresetHook, Jt as TokenPair, K as ResolvedTenantPurge, Kt as AuthenticatorContext, L as RequestWithExtras, Lt as IController, M as EventsDecorator, Mt as RouteMethod, N as FastifyRequestExtras, Nt as RateLimitConfig, O as HealthOptions, Ot as ActionHandlerFn, P as FastifyWithAuth, Pt as ControllerHandler, Q as MiddlewareConfig, Rt as IControllerResponse, S as QueryParserInterface, T as CrudRouterOptions, Tt as ResourceCacheConfig, U as ResourceConfig, Ut as AuthHelpers, Vt as RouteHandler, W as ResourcePermissions, Wt as AuthPluginOptions, X as CrudRouteKey, Y as PresetResult, Z as CrudSchemas, _ as ControllerQueryOptions, a as InferAdapterDoc, at as ResourceExtensions, b as ParsedQuery, c as TypedController, d as PaginationResult, et as RouteSchemaOptions, f as IntrospectionData, g as ArcInternalMetadata, h as ResourceMetadata, i as ValidationResult, it as ResourceHooks, j as ArcDecorator, jt as RouteMcpConfig, k as IntrospectionPluginOptions, kt as ActionsMap, l as TypedRepository, m as RegistryStats, n as ConfigError, nt as FieldRule, o as InferDocType, ot as EventDefinition, p as RegistryEntry, q as PresetFunction, qt as JwtContext, r as ValidateOptions, rt as ResourceHookContext, s as InferResourceDoc, t as RouteHandlerMethod, tt as ArcFieldRule, u as TypedResourceConfig, v as LookupOption, w as ServiceContext, x as PopulateOption, y as OwnershipCheck, zt as IRequestContext } from "../index-CpzxqePp.mjs";
3
2
  import { i as RequestScope } from "../types-ChuShpCP.mjs";
4
- import { a as UserBase, d as JWTPayload, f as ObjectId, i as PermissionContext, l as AnyRecord, m as UserOrganization, n as DataPolicy, p as UserLike, r as PermissionCheck, t as AuthorizationDecision, u as ArcRequest } from "../types-B7XeLEgK.mjs";
3
+ import { a as UserLike, c as DataPolicy, d as UserBase, i as ObjectId, l as PermissionCheck, n as ArcRequest, o as UserOrganization, r as JWTPayload, s as AuthorizationDecision, t as AnyRecord, u as PermissionContext } from "../base-Csjc2oF-.mjs";
4
+ import { $ as OpenApiSchemas, A as RequestIdOptions, An as WriteVerbKey, At as RouteDefinition, C as RequestContext, D as HealthCheck, Dn as MutationWriteContext, Dt as ActionEntry, E as GracefulShutdownOptions, Et as ActionDefinition, F as FastifyWithDecorators, Fn as IControllerResponse, Ft as AuthPluginOptions, G as OnTenantDeleteConfig, H as CrudController, I as MiddlewareHandler, In as IRequestContext, It as Authenticator, J as PresetHook, K as ResolvedTenantPurge, L as RequestWithExtras, Ln as RawRouteHandler, Lt as AuthenticatorContext, M as EventsDecorator, Mn as ControllerLike, Mt as RouteMethod, N as FastifyRequestExtras, Nn as FastifyHandler, Nt as RateLimitConfig, O as HealthOptions, On as ResourceWrites, Ot as ActionHandlerFn, P as FastifyWithAuth, Pn as IController, Pt as AuthHelpers, Q as MiddlewareConfig, Rn as RouteHandler, Rt as JwtContext, S as QueryParserInterface, T as CrudRouterOptions, Tt as ResourceCacheConfig, U as ResourceConfig, W as ResourcePermissions, X as CrudRouteKey, Y as PresetResult, Z as CrudSchemas, _ as ControllerQueryOptions, a as InferAdapterDoc, at as ResourceExtensions, b as ParsedQuery, c as TypedController, d as PaginationResult, et as RouteSchemaOptions, f as IntrospectionData, g as ArcInternalMetadata, h as ResourceMetadata, i as ValidationResult, it as ResourceHooks, j as ArcDecorator, jn as ControllerHandler, jt as RouteMcpConfig, k as IntrospectionPluginOptions, kn as WriteContext, kt as ActionsMap, l as TypedRepository, m as RegistryStats, n as ConfigError, nt as FieldRule, o as InferDocType, ot as EventDefinition, p as RegistryEntry, q as PresetFunction, r as ValidateOptions, rt as ResourceHookContext, s as InferResourceDoc, t as RouteHandlerMethod, tt as ArcFieldRule, u as TypedResourceConfig, v as LookupOption, w as ServiceContext, x as PopulateOption, xn as BaseControllerOptions, y as OwnershipCheck, zt as TokenPair } from "../index-BcR2bFZQ.mjs";
5
5
  import { n as ElevationOptions, t as ElevationEvent } from "../elevation-BXCfVcNG.mjs";
6
- export type { ActionDefinition, ActionEntry, ActionHandlerFn, ActionsMap, AnyRecord, ArcDecorator, ArcFieldRule, ArcInternalMetadata, ArcRequest, AuthHelpers, AuthPluginOptions, Authenticator, AuthenticatorContext, AuthorizationDecision, BaseControllerOptions, ConfigError, ControllerHandler, ControllerLike, ControllerQueryOptions, CrudController, CrudRouteKey, CrudRouterOptions, CrudSchemas, DataPolicy, ElevationEvent, ElevationOptions, EventDefinition, EventsDecorator, FastifyHandler, FastifyRequestExtras, FastifyWithAuth, FastifyWithDecorators, FieldRule, GracefulShutdownOptions, HealthCheck, HealthOptions, IController, IControllerResponse, IRequestContext, InferAdapterDoc, InferDocType, InferResourceDoc, IntrospectionData, IntrospectionPluginOptions, JWTPayload, JwtContext, LookupOption, MiddlewareConfig, MiddlewareHandler, ObjectId, OnTenantDeleteConfig, OpenApiSchemas, OwnershipCheck, PaginationResult, ParsedQuery, PermissionCheck, PermissionContext, PopulateOption, PresetFunction, PresetHook, PresetResult, QueryParserInterface, RateLimitConfig, RawRouteHandler, RegistryEntry, RegistryStats, RequestContext, RequestIdOptions, RequestScope, RequestWithExtras, ResolvedTenantPurge, ResourceCacheConfig, ResourceConfig, ResourceExtensions, ResourceHookContext, ResourceHooks, ResourceMetadata, ResourcePermissions, RouteDefinition, RouteHandler, RouteHandlerMethod, RouteMcpConfig, RouteMethod, RouteSchemaOptions, ServiceContext, TokenPair, TypedController, TypedRepository, TypedResourceConfig, UserBase, UserLike, UserOrganization, ValidateOptions, ValidationResult };
6
+ export type { ActionDefinition, ActionEntry, ActionHandlerFn, ActionsMap, AnyRecord, ArcDecorator, ArcFieldRule, ArcInternalMetadata, ArcRequest, AuthHelpers, AuthPluginOptions, Authenticator, AuthenticatorContext, AuthorizationDecision, BaseControllerOptions, ConfigError, ControllerHandler, ControllerLike, ControllerQueryOptions, CrudController, CrudRouteKey, CrudRouterOptions, CrudSchemas, DataPolicy, ElevationEvent, ElevationOptions, EventDefinition, EventsDecorator, FastifyHandler, FastifyRequestExtras, FastifyWithAuth, FastifyWithDecorators, FieldRule, GracefulShutdownOptions, HealthCheck, HealthOptions, IController, IControllerResponse, IRequestContext, InferAdapterDoc, InferDocType, InferResourceDoc, IntrospectionData, IntrospectionPluginOptions, JWTPayload, JwtContext, LookupOption, MiddlewareConfig, MiddlewareHandler, MutationWriteContext, ObjectId, OnTenantDeleteConfig, OpenApiSchemas, OwnershipCheck, PaginationResult, ParsedQuery, PermissionCheck, PermissionContext, PopulateOption, PresetFunction, PresetHook, PresetResult, QueryParserInterface, RateLimitConfig, RawRouteHandler, RegistryEntry, RegistryStats, RequestContext, RequestIdOptions, RequestScope, RequestWithExtras, ResolvedTenantPurge, ResourceCacheConfig, ResourceConfig, ResourceExtensions, ResourceHookContext, ResourceHooks, ResourceMetadata, ResourcePermissions, ResourceWrites, RouteDefinition, RouteHandler, RouteHandlerMethod, RouteMcpConfig, RouteMethod, RouteSchemaOptions, ServiceContext, TokenPair, TypedController, TypedRepository, TypedResourceConfig, UserBase, UserLike, UserOrganization, ValidateOptions, ValidationResult, WriteContext, WriteVerbKey };
@@ -1,2 +1,2 @@
1
- /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
2
  export {};
@@ -1,2 +1,2 @@
1
- /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
2
  export {};