@classytic/arc 2.28.0 → 2.30.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 (83) hide show
  1. package/dist/{BaseController-B65zbz9m.mjs → BaseController-B5DwufbB.mjs} +12 -10
  2. package/dist/EventTransport-C6YA8xY9.mjs +103 -0
  3. package/dist/{HookSystem-C1vB_Gc9.mjs → HookSystem-WkIougo6.mjs} +15 -35
  4. package/dist/applyPermissionResult-Cf6zUCvb.mjs +257 -0
  5. package/dist/audit/index.d.mts +2 -2
  6. package/dist/audit/index.mjs +1 -1
  7. package/dist/auth/index.d.mts +2 -2
  8. package/dist/auth/index.mjs +1 -1
  9. package/dist/{buildHandler-Dtwd8fdz.mjs → buildHandler-BYS3Vkfz.mjs} +32 -6
  10. package/dist/cleanup/index.d.mts +2 -2
  11. package/dist/cleanup/index.mjs +1 -1
  12. package/dist/cli/commands/describe.d.mts +1 -1
  13. package/dist/cli/commands/docs.mjs +1 -1
  14. package/dist/core/index.d.mts +2 -2
  15. package/dist/core/index.mjs +5 -4
  16. package/dist/{core-BGa8TXJR.mjs → core-poalJLvp.mjs} +2 -48
  17. package/dist/{createActionRouter-C-N7z2EL.mjs → createActionRouter-BxuywVRB.mjs} +2 -2
  18. package/dist/{createAggregationRouter-wzwFa_dW.mjs → createAggregationRouter-BiY-lGdY.mjs} +7 -20
  19. package/dist/{createApp-Du5G54TM.mjs → createApp-CXrKFciH.mjs} +24 -3
  20. package/dist/defineAggregation-ufWjUwml.mjs +47 -0
  21. package/dist/{defineResource-2zvVVpxg.mjs → defineResource-CxWqDCAy.mjs} +35 -42
  22. package/dist/docs/index.d.mts +1 -1
  23. package/dist/docs/index.mjs +1 -1
  24. package/dist/{eventPlugin-DrQ_FesK.mjs → eventPlugin-D2NNR4py.mjs} +2 -103
  25. package/dist/events/index.mjs +4 -339
  26. package/dist/factory/index.d.mts +4 -4
  27. package/dist/factory/index.mjs +1 -1
  28. package/dist/{fastify-augmentation-OzYGIiU1.d.mts → fastify-augmentation-0WhPnUH7.d.mts} +3 -3
  29. package/dist/{applyPermissionResult-BnyVE9eD.mjs → fields-CQ_7KQWw.mjs} +1 -107
  30. package/dist/hooks/index.d.mts +1 -1
  31. package/dist/hooks/index.mjs +1 -1
  32. package/dist/idempotency/index.mjs +1 -1
  33. package/dist/{index-CZY4EGga.d.mts → index-CCzVR-N3.d.mts} +1 -1
  34. package/dist/{index-BMnbzvtO.d.mts → index-Ch16aAah.d.mts} +201 -21
  35. package/dist/{index-CjVg-Epg.d.mts → index-Cx7bro4R.d.mts} +4 -4
  36. package/dist/{index-DPRH0Cme.d.mts → index-Q5gzEIWY.d.mts} +97 -66
  37. package/dist/index.d.mts +6 -6
  38. package/dist/index.mjs +8 -7
  39. package/dist/integrations/index.d.mts +1 -1
  40. package/dist/integrations/mcp/index.d.mts +6 -6
  41. package/dist/integrations/mcp/index.mjs +1 -1
  42. package/dist/integrations/mcp/testing.d.mts +1 -1
  43. package/dist/integrations/mcp/testing.mjs +1 -1
  44. package/dist/{mcpPlugin-Cs6nRGCt.mjs → mcpPlugin-nRzm5g2s.mjs} +36 -43
  45. package/dist/middleware/index.d.mts +1 -1
  46. package/dist/migrations/index.d.mts +0 -3
  47. package/dist/migrations/index.mjs +0 -3
  48. package/dist/{openapi-BLV4OMXb.mjs → openapi-B8Vkbxbn.mjs} +1 -1
  49. package/dist/permissions/index.d.mts +3 -3
  50. package/dist/permissions/index.mjs +4 -3
  51. package/dist/{permissions-BrtiBKGs.mjs → permissions-Bfu_8y1U.mjs} +318 -289
  52. package/dist/pipeline/index.d.mts +1 -1
  53. package/dist/{pipeline-BGRnV-To.mjs → pipeline-BJnpkY9i.mjs} +4 -18
  54. package/dist/plugins/index.d.mts +4 -4
  55. package/dist/plugins/index.mjs +2 -2
  56. package/dist/plugins/tracing-entry.mjs +1 -1
  57. package/dist/{preloadResources-CM4uUaFv.d.mts → preloadResources-DCfa2egz.d.mts} +3 -3
  58. package/dist/presets/filesUpload.d.mts +2 -2
  59. package/dist/presets/filesUpload.mjs +1 -1
  60. package/dist/presets/index.d.mts +14 -2
  61. package/dist/presets/index.mjs +1 -1
  62. package/dist/presets/multiTenant.d.mts +1 -1
  63. package/dist/presets/search.d.mts +2 -2
  64. package/dist/presets/search.mjs +1 -1
  65. package/dist/{presets-DwFDVKP0.mjs → presets-CJOEXLuk.mjs} +25 -9
  66. package/dist/projection-UBDgfMwu.mjs +17 -0
  67. package/dist/{realtime-DEuDu9io.mjs → realtime-B9nmIY5V.mjs} +2 -1
  68. package/dist/{registerRoute-DTp18Ah_.mjs → registerRoute-JkxIEBJq.mjs} +3 -1
  69. package/dist/registry/index.d.mts +2 -2
  70. package/dist/registry/index.mjs +1 -1
  71. package/dist/{registry-9km_w1aP.mjs → registry-BYXUUg21.mjs} +1 -1
  72. package/dist/repositoryFilter-Dz8k3S4P.mjs +44 -0
  73. package/dist/subscribe-helpers-DfzsivM6.mjs +339 -0
  74. package/dist/testing/index.d.mts +34 -6
  75. package/dist/testing/index.mjs +314 -211
  76. package/dist/types/index.d.mts +3 -3
  77. package/dist/{types-QFGc3Cjv.d.mts → types-Bmmn-fO0.d.mts} +1 -1
  78. package/dist/{types-Dmw-6Qeo.d.mts → types-ChvvVNP8.d.mts} +93 -88
  79. package/dist/{types-Cu6vVJmh.d.mts → types-D_n8L6VY.d.mts} +32 -1
  80. package/dist/usage/index.d.mts +1 -1
  81. package/dist/usage/index.mjs +0 -0
  82. package/dist/utils/index.d.mts +2 -5
  83. package/package.json +539 -539
@@ -1,5 +1,8 @@
1
1
  import { t as CRUD_OPERATIONS } from "../constants-DNre0wRg.mjs";
2
- import { n as createApp } from "../createApp-Du5G54TM.mjs";
2
+ import { t as BaseController } from "../BaseController-B5DwufbB.mjs";
3
+ import { t as defineResource } from "../defineResource-CxWqDCAy.mjs";
4
+ import { t as defineAggregation } from "../defineAggregation-ufWjUwml.mjs";
5
+ import { n as createApp } from "../createApp-CXrKFciH.mjs";
3
6
  import { n as getModuleExports } from "../module-_-M7C5ES.mjs";
4
7
  import { n as preloadResourcesAsync, t as preloadResources } from "../preloadResources-DSY5HGpS.mjs";
5
8
  import { runStorageContract } from "./storageContract.mjs";
@@ -125,6 +128,314 @@ function expectArc(response) {
125
128
  return assertion;
126
129
  }
127
130
  //#endregion
131
+ //#region src/testing/mocks.ts
132
+ /**
133
+ * Create a mock repository for testing
134
+ *
135
+ * @example
136
+ * const mockRepo = createMockRepository<Product>({
137
+ * getById: vi.fn().mockResolvedValue({ id: '1', name: 'Test' }),
138
+ * create: vi.fn().mockImplementation(data => Promise.resolve({ id: '1', ...data })),
139
+ * });
140
+ *
141
+ * await mockRepo.getById('1'); // Returns mocked product
142
+ */
143
+ function createMockRepository(overrides = {}) {
144
+ return {
145
+ getAll: vi.fn().mockResolvedValue({
146
+ method: "offset",
147
+ data: [],
148
+ total: 0,
149
+ page: 1,
150
+ limit: 20,
151
+ pages: 0,
152
+ hasNext: false,
153
+ hasPrev: false
154
+ }),
155
+ getById: vi.fn().mockResolvedValue(null),
156
+ create: vi.fn().mockImplementation((data) => Promise.resolve({
157
+ _id: "mock-id",
158
+ ...data
159
+ })),
160
+ update: vi.fn().mockImplementation((_id, data) => Promise.resolve({
161
+ _id: "mock-id",
162
+ ...data
163
+ })),
164
+ delete: vi.fn().mockResolvedValue({
165
+ success: true,
166
+ message: "Deleted"
167
+ }),
168
+ updateMany: vi.fn().mockResolvedValue({
169
+ acknowledged: true,
170
+ matchedCount: 0,
171
+ modifiedCount: 0
172
+ }),
173
+ deleteMany: vi.fn().mockResolvedValue({
174
+ acknowledged: true,
175
+ deletedCount: 0
176
+ }),
177
+ claim: vi.fn().mockResolvedValue(null),
178
+ claimVersion: vi.fn().mockResolvedValue(null),
179
+ capabilities: {
180
+ transactions: false,
181
+ nestedTransactions: false,
182
+ upsert: false,
183
+ duplicateKeyError: false,
184
+ distinct: false,
185
+ aggregate: false,
186
+ getOrCreate: false,
187
+ countAndExists: false
188
+ },
189
+ getBySlug: vi.fn().mockResolvedValue(null),
190
+ getDeleted: vi.fn().mockResolvedValue([]),
191
+ restore: vi.fn().mockResolvedValue(null),
192
+ getTree: vi.fn().mockResolvedValue([]),
193
+ getChildren: vi.fn().mockResolvedValue([]),
194
+ ...overrides
195
+ };
196
+ }
197
+ /**
198
+ * Create a mock user for authentication testing
199
+ */
200
+ function createMockUser(overrides = {}) {
201
+ return {
202
+ _id: "mock-user-id",
203
+ id: "mock-user-id",
204
+ email: "test@example.com",
205
+ roles: ["user"],
206
+ organizationId: null,
207
+ ...overrides
208
+ };
209
+ }
210
+ /**
211
+ * Create a mock Fastify request
212
+ */
213
+ function createMockRequest(overrides = {}) {
214
+ return {
215
+ body: {},
216
+ params: {},
217
+ query: {},
218
+ headers: {},
219
+ user: createMockUser(),
220
+ context: {},
221
+ log: {
222
+ info: vi.fn(),
223
+ warn: vi.fn(),
224
+ error: vi.fn(),
225
+ debug: vi.fn()
226
+ },
227
+ ...overrides
228
+ };
229
+ }
230
+ /**
231
+ * Create a mock Fastify reply
232
+ */
233
+ function createMockReply() {
234
+ return {
235
+ code: vi.fn().mockReturnThis(),
236
+ send: vi.fn().mockReturnThis(),
237
+ header: vi.fn().mockReturnThis(),
238
+ headers: vi.fn().mockReturnThis(),
239
+ status: vi.fn().mockReturnThis(),
240
+ type: vi.fn().mockReturnThis(),
241
+ redirect: vi.fn().mockReturnThis(),
242
+ callNotFound: vi.fn().mockReturnThis(),
243
+ sent: false
244
+ };
245
+ }
246
+ /**
247
+ * Create a mock controller for testing
248
+ */
249
+ function createMockController(repository) {
250
+ return {
251
+ repository,
252
+ list: vi.fn(),
253
+ get: vi.fn(),
254
+ create: vi.fn(),
255
+ update: vi.fn(),
256
+ delete: vi.fn()
257
+ };
258
+ }
259
+ /**
260
+ * Create mock data factory
261
+ *
262
+ * @example
263
+ * const productFactory = createDataFactory<Product>({
264
+ * name: () => faker.commerce.productName(),
265
+ * price: () => faker.number.int({ min: 10, max: 1000 }),
266
+ * sku: (i) => `SKU-${i}`,
267
+ * });
268
+ *
269
+ * const product = productFactory.build();
270
+ * const products = productFactory.buildMany(10);
271
+ */
272
+ function createDataFactory(template) {
273
+ let counter = 0;
274
+ return {
275
+ build(overrides = {}) {
276
+ const index = counter++;
277
+ const data = {};
278
+ for (const [key, generator] of Object.entries(template)) data[key] = generator(index);
279
+ return {
280
+ ...data,
281
+ ...overrides
282
+ };
283
+ },
284
+ buildMany(count, overrides = {}) {
285
+ return Array.from({ length: count }, () => this.build(overrides));
286
+ },
287
+ reset() {
288
+ counter = 0;
289
+ }
290
+ };
291
+ }
292
+ /**
293
+ * Create a spy that tracks function calls
294
+ *
295
+ * Useful for testing side effects without full mocking
296
+ */
297
+ function createSpy(_name = "spy") {
298
+ const calls = [];
299
+ const spy = vi.fn((...args) => {
300
+ calls.push(args);
301
+ });
302
+ spy.getCalls = () => calls;
303
+ spy.getLastCall = () => calls[calls.length - 1] || [];
304
+ return spy;
305
+ }
306
+ /**
307
+ * Wait for a condition to be true
308
+ *
309
+ * Useful for async testing
310
+ */
311
+ async function waitFor(condition, options = {}) {
312
+ const { timeout = 5e3, interval = 100 } = options;
313
+ const startTime = Date.now();
314
+ while (Date.now() - startTime < timeout) {
315
+ if (await condition()) return;
316
+ await new Promise((resolve) => setTimeout(resolve, interval));
317
+ }
318
+ throw new Error(`Timeout waiting for condition after ${timeout}ms`);
319
+ }
320
+ /**
321
+ * Create a test timer that can be controlled
322
+ */
323
+ function createTestTimer() {
324
+ let time = Date.now();
325
+ return {
326
+ now: () => time,
327
+ advance: (ms) => {
328
+ time += ms;
329
+ },
330
+ set: (timestamp) => {
331
+ time = timestamp;
332
+ },
333
+ reset: () => {
334
+ time = Date.now();
335
+ }
336
+ };
337
+ }
338
+ //#endregion
339
+ //#region src/testing/authorizationConformance.ts
340
+ /**
341
+ * Cross-surface authorization conformance (arc 2.30).
342
+ *
343
+ * The regression wall that keeps "partial enforcement" from ever coming back:
344
+ * run the SAME permission through more than one arc surface and prove it enforces
345
+ * identically. Reviews kept finding aggregation (and MCP) drifting from CRUD —
346
+ * this makes that a one-call assertion for arc AND for host resources.
347
+ *
348
+ * `runAuthorizationConformance` boots a throwaway Fastify app with one resource
349
+ * whose `list` op AND an `aggregation` share the given permission, backed by a
350
+ * capturing mock repo (no DB). It returns, per surface, the HTTP status and the
351
+ * exact filter arc handed the repository — so the caller asserts:
352
+ * - deny → both surfaces fail closed with the SAME status;
353
+ * - allow + `policy` → the row policy reaches BOTH the list query and the
354
+ * aggregation `$match`, identically.
355
+ *
356
+ * Runner-agnostic: it returns data, it does not assert. Pair with your test
357
+ * framework's expectations (see `tests/core/authorization-conformance.test.ts`).
358
+ */
359
+ /**
360
+ * Boot a one-resource app gated by `permission` on both list + an aggregation,
361
+ * hit both surfaces anonymously, and report what arc enforced on each.
362
+ */
363
+ async function runAuthorizationConformance(opts) {
364
+ const rows = opts.rows ?? [{ _id: "1" }];
365
+ let listFilter;
366
+ let aggFilter;
367
+ const repo = createMockRepository({
368
+ getAll: (async (params = {}) => {
369
+ listFilter = params.filters;
370
+ return {
371
+ method: "offset",
372
+ data: rows,
373
+ total: rows.length,
374
+ page: 1,
375
+ limit: 20,
376
+ pages: 1,
377
+ hasNext: false,
378
+ hasPrev: false
379
+ };
380
+ }),
381
+ aggregate: (async (req = {}) => {
382
+ aggFilter = req.filter;
383
+ return { rows: [{ tally: rows.length }] };
384
+ }),
385
+ capabilities: {
386
+ count: false,
387
+ exists: false,
388
+ distinct: false,
389
+ aggregate: true,
390
+ transactions: false,
391
+ lookup: false,
392
+ softDelete: false
393
+ }
394
+ });
395
+ const resource = defineResource({
396
+ name: "conf",
397
+ prefix: "/confs",
398
+ adapter: { repository: repo },
399
+ controller: new BaseController(repo, {
400
+ resourceName: "conf",
401
+ tenantField: false
402
+ }),
403
+ permissions: {
404
+ list: opts.permission,
405
+ get: opts.permission,
406
+ create: opts.permission,
407
+ update: opts.permission,
408
+ delete: opts.permission
409
+ },
410
+ aggregations: { tally: defineAggregation({
411
+ measures: { tally: { op: "count" } },
412
+ permissions: opts.permission
413
+ }) }
414
+ });
415
+ const app = Fastify({ logger: false });
416
+ await app.register(resource.toPlugin());
417
+ await app.ready();
418
+ const list = await app.inject({
419
+ method: "GET",
420
+ url: "/confs"
421
+ });
422
+ const aggregation = await app.inject({
423
+ method: "GET",
424
+ url: "/confs/aggregations/tally"
425
+ });
426
+ return {
427
+ list: {
428
+ status: list.statusCode,
429
+ filter: listFilter
430
+ },
431
+ aggregation: {
432
+ status: aggregation.statusCode,
433
+ filter: aggFilter
434
+ },
435
+ close: () => app.close()
436
+ };
437
+ }
438
+ //#endregion
128
439
  //#region src/testing/authSession.ts
129
440
  function buildHeaders(token, orgId, extra) {
130
441
  const headers = { authorization: `Bearer ${token}` };
@@ -845,214 +1156,6 @@ function createHttpTestHarness(resource, optionsOrGetter) {
845
1156
  return new HttpTestHarness(resource, optionsOrGetter);
846
1157
  }
847
1158
  //#endregion
848
- //#region src/testing/mocks.ts
849
- /**
850
- * Create a mock repository for testing
851
- *
852
- * @example
853
- * const mockRepo = createMockRepository<Product>({
854
- * getById: vi.fn().mockResolvedValue({ id: '1', name: 'Test' }),
855
- * create: vi.fn().mockImplementation(data => Promise.resolve({ id: '1', ...data })),
856
- * });
857
- *
858
- * await mockRepo.getById('1'); // Returns mocked product
859
- */
860
- function createMockRepository(overrides = {}) {
861
- return {
862
- getAll: vi.fn().mockResolvedValue({
863
- method: "offset",
864
- data: [],
865
- total: 0,
866
- page: 1,
867
- limit: 20,
868
- pages: 0,
869
- hasNext: false,
870
- hasPrev: false
871
- }),
872
- getById: vi.fn().mockResolvedValue(null),
873
- create: vi.fn().mockImplementation((data) => Promise.resolve({
874
- _id: "mock-id",
875
- ...data
876
- })),
877
- update: vi.fn().mockImplementation((_id, data) => Promise.resolve({
878
- _id: "mock-id",
879
- ...data
880
- })),
881
- delete: vi.fn().mockResolvedValue({
882
- success: true,
883
- message: "Deleted"
884
- }),
885
- updateMany: vi.fn().mockResolvedValue({
886
- acknowledged: true,
887
- matchedCount: 0,
888
- modifiedCount: 0
889
- }),
890
- deleteMany: vi.fn().mockResolvedValue({
891
- acknowledged: true,
892
- deletedCount: 0
893
- }),
894
- claim: vi.fn().mockResolvedValue(null),
895
- claimVersion: vi.fn().mockResolvedValue(null),
896
- capabilities: {
897
- transactions: false,
898
- nestedTransactions: false,
899
- upsert: false,
900
- duplicateKeyError: false,
901
- distinct: false,
902
- aggregate: false,
903
- getOrCreate: false,
904
- countAndExists: false
905
- },
906
- getBySlug: vi.fn().mockResolvedValue(null),
907
- getDeleted: vi.fn().mockResolvedValue([]),
908
- restore: vi.fn().mockResolvedValue(null),
909
- getTree: vi.fn().mockResolvedValue([]),
910
- getChildren: vi.fn().mockResolvedValue([]),
911
- ...overrides
912
- };
913
- }
914
- /**
915
- * Create a mock user for authentication testing
916
- */
917
- function createMockUser(overrides = {}) {
918
- return {
919
- _id: "mock-user-id",
920
- id: "mock-user-id",
921
- email: "test@example.com",
922
- roles: ["user"],
923
- organizationId: null,
924
- ...overrides
925
- };
926
- }
927
- /**
928
- * Create a mock Fastify request
929
- */
930
- function createMockRequest(overrides = {}) {
931
- return {
932
- body: {},
933
- params: {},
934
- query: {},
935
- headers: {},
936
- user: createMockUser(),
937
- context: {},
938
- log: {
939
- info: vi.fn(),
940
- warn: vi.fn(),
941
- error: vi.fn(),
942
- debug: vi.fn()
943
- },
944
- ...overrides
945
- };
946
- }
947
- /**
948
- * Create a mock Fastify reply
949
- */
950
- function createMockReply() {
951
- return {
952
- code: vi.fn().mockReturnThis(),
953
- send: vi.fn().mockReturnThis(),
954
- header: vi.fn().mockReturnThis(),
955
- headers: vi.fn().mockReturnThis(),
956
- status: vi.fn().mockReturnThis(),
957
- type: vi.fn().mockReturnThis(),
958
- redirect: vi.fn().mockReturnThis(),
959
- callNotFound: vi.fn().mockReturnThis(),
960
- sent: false
961
- };
962
- }
963
- /**
964
- * Create a mock controller for testing
965
- */
966
- function createMockController(repository) {
967
- return {
968
- repository,
969
- list: vi.fn(),
970
- get: vi.fn(),
971
- create: vi.fn(),
972
- update: vi.fn(),
973
- delete: vi.fn()
974
- };
975
- }
976
- /**
977
- * Create mock data factory
978
- *
979
- * @example
980
- * const productFactory = createDataFactory<Product>({
981
- * name: () => faker.commerce.productName(),
982
- * price: () => faker.number.int({ min: 10, max: 1000 }),
983
- * sku: (i) => `SKU-${i}`,
984
- * });
985
- *
986
- * const product = productFactory.build();
987
- * const products = productFactory.buildMany(10);
988
- */
989
- function createDataFactory(template) {
990
- let counter = 0;
991
- return {
992
- build(overrides = {}) {
993
- const index = counter++;
994
- const data = {};
995
- for (const [key, generator] of Object.entries(template)) data[key] = generator(index);
996
- return {
997
- ...data,
998
- ...overrides
999
- };
1000
- },
1001
- buildMany(count, overrides = {}) {
1002
- return Array.from({ length: count }, () => this.build(overrides));
1003
- },
1004
- reset() {
1005
- counter = 0;
1006
- }
1007
- };
1008
- }
1009
- /**
1010
- * Create a spy that tracks function calls
1011
- *
1012
- * Useful for testing side effects without full mocking
1013
- */
1014
- function createSpy(_name = "spy") {
1015
- const calls = [];
1016
- const spy = vi.fn((...args) => {
1017
- calls.push(args);
1018
- });
1019
- spy.getCalls = () => calls;
1020
- spy.getLastCall = () => calls[calls.length - 1] || [];
1021
- return spy;
1022
- }
1023
- /**
1024
- * Wait for a condition to be true
1025
- *
1026
- * Useful for async testing
1027
- */
1028
- async function waitFor(condition, options = {}) {
1029
- const { timeout = 5e3, interval = 100 } = options;
1030
- const startTime = Date.now();
1031
- while (Date.now() - startTime < timeout) {
1032
- if (await condition()) return;
1033
- await new Promise((resolve) => setTimeout(resolve, interval));
1034
- }
1035
- throw new Error(`Timeout waiting for condition after ${timeout}ms`);
1036
- }
1037
- /**
1038
- * Create a test timer that can be controlled
1039
- */
1040
- function createTestTimer() {
1041
- let time = Date.now();
1042
- return {
1043
- now: () => time,
1044
- advance: (ms) => {
1045
- time += ms;
1046
- },
1047
- set: (timestamp) => {
1048
- time = timestamp;
1049
- },
1050
- reset: () => {
1051
- time = Date.now();
1052
- }
1053
- };
1054
- }
1055
- //#endregion
1056
1159
  //#region src/testing/testApp.ts
1057
1160
  /**
1058
1161
  * createTestApp — test app factory for arc
@@ -1118,7 +1221,7 @@ function pickDefaultAuth(authMode, callerAuth) {
1118
1221
  };
1119
1222
  }
1120
1223
  async function createTestApp(options = {}) {
1121
- const { createApp } = await import("../createApp-Du5G54TM.mjs").then((n) => n.r);
1224
+ const { createApp } = await import("../createApp-CXrKFciH.mjs").then((n) => n.r);
1122
1225
  const { resources = [], db = "in-memory", connectMongoose = false, authMode = "jwt", defaultOrgId, plugins, auth: callerAuth, ...appOptions } = options;
1123
1226
  let dbHandle;
1124
1227
  let dbUri;
@@ -1188,4 +1291,4 @@ function createMinimalTestApp(options = {}) {
1188
1291
  });
1189
1292
  }
1190
1293
  //#endregion
1191
- export { HttpTestHarness, bootModuleApp, createBetterAuthProvider, createBetterAuthTestHelpers, createCustomAuthProvider, createDataFactory, createHttpTestHarness, createJwtAuthProvider, createMinimalTestApp, createMockController, createMockReply, createMockRepository, createMockRequest, createMockUser, createSpy, createTestApp, createTestFixtures, createTestTimer, expectArc, mongoMemoryDatabase, preloadResources, preloadResourcesAsync, runStorageContract, safeParseBody, setupBetterAuthTestApp, waitFor };
1294
+ export { HttpTestHarness, bootModuleApp, createBetterAuthProvider, createBetterAuthTestHelpers, createCustomAuthProvider, createDataFactory, createHttpTestHarness, createJwtAuthProvider, createMinimalTestApp, createMockController, createMockReply, createMockRepository, createMockRequest, createMockUser, createSpy, createTestApp, createTestFixtures, createTestTimer, expectArc, mongoMemoryDatabase, preloadResources, preloadResourcesAsync, runAuthorizationConformance, runStorageContract, safeParseBody, setupBetterAuthTestApp, waitFor };
@@ -1,5 +1,5 @@
1
- import { $ as OpenApiSchemas, A as RequestIdOptions, At as RouteDefinition, Bt as RouteHandler, 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 AuthenticatorContext, H as CrudController, Ht as AuthHelpers, I as MiddlewareHandler, It as FastifyHandler, J as PresetHook, K as ResolvedTenantPurge, Kt as JwtContext, 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 AuthPluginOptions, W as ResourcePermissions, Wt as Authenticator, 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, kn as BaseControllerOptions, 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 TokenPair, 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-DPRH0Cme.mjs";
1
+ import { $ as OpenApiSchemas, A as RequestIdOptions, At as RouteDefinition, Bt as RouteHandler, 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 AuthenticatorContext, H as CrudController, Ht as AuthHelpers, I as MiddlewareHandler, It as FastifyHandler, J as PresetHook, K as ResolvedTenantPurge, Kt as JwtContext, 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 AuthPluginOptions, W as ResourcePermissions, Wt as Authenticator, 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, kn as BaseControllerOptions, 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 TokenPair, 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-Q5gzEIWY.mjs";
2
2
  import { i as RequestScope } from "../types-DjC-KUCz.mjs";
3
- import { c as AnyRecord, d as ObjectId, f as UserLike, i as UserBase, l as ArcRequest, n as PermissionContext, p as UserOrganization, r as PermissionResult, t as PermissionCheck, u as JWTPayload } from "../types-Dmw-6Qeo.mjs";
3
+ 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-ChvvVNP8.mjs";
4
4
  import { n as ElevationOptions, t as ElevationEvent } from "../elevation-C9s5hFP_.mjs";
5
- export type { ActionDefinition, ActionEntry, ActionHandlerFn, ActionsMap, AnyRecord, ArcDecorator, ArcFieldRule, ArcInternalMetadata, ArcRequest, AuthHelpers, AuthPluginOptions, Authenticator, AuthenticatorContext, BaseControllerOptions, ConfigError, ControllerHandler, ControllerLike, ControllerQueryOptions, CrudController, CrudRouteKey, CrudRouterOptions, CrudSchemas, 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, PermissionResult, PopulateOption, PresetFunction, PresetHook, PresetResult, QueryParserInterface, RateLimitConfig, 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 };
5
+ 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, 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 };
@@ -1,4 +1,4 @@
1
- import { V as ResourceDefinition } from "./index-DPRH0Cme.mjs";
1
+ import { V as ResourceDefinition } from "./index-Q5gzEIWY.mjs";
2
2
  import { z } from "zod";
3
3
  //#region src/integrations/mcp/types.d.ts
4
4
  /** Behavioral hints for MCP clients (tool annotations per MCP spec) */