@classytic/arc 2.8.5 → 2.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/README.md +50 -38
  2. package/dist/{BaseController-DAGGc5Xn.mjs → BaseController-CbKKIflT.mjs} +193 -143
  3. package/dist/EventTransport-CUw5NNWe.d.mts +293 -0
  4. package/dist/{ResourceRegistry-C6uXlWe3.mjs → ResourceRegistry-BPd6NQDm.mjs} +1 -1
  5. package/dist/adapters/index.d.mts +3 -3
  6. package/dist/adapters/index.mjs +2 -2
  7. package/dist/{adapters-BBqAVvPK.mjs → adapters-BXY4i-hw.mjs} +210 -41
  8. package/dist/audit/index.d.mts +135 -11
  9. package/dist/audit/index.mjs +107 -20
  10. package/dist/auth/index.d.mts +17 -9
  11. package/dist/auth/index.mjs +14 -7
  12. package/dist/auth/redis-session.d.mts +1 -1
  13. package/dist/{betterAuthOpenApi-BuUcUEJq.mjs → betterAuthOpenApi-BBRVhjQN.mjs} +1 -1
  14. package/dist/cache/index.d.mts +17 -15
  15. package/dist/cache/index.mjs +15 -14
  16. package/dist/{caching-IMuYVjTL.mjs → caching-CBpK_SCM.mjs} +8 -3
  17. package/dist/cli/commands/describe.mjs +1 -1
  18. package/dist/cli/commands/docs.mjs +2 -2
  19. package/dist/cli/commands/generate.mjs +1 -1
  20. package/dist/cli/commands/init.mjs +1 -1
  21. package/dist/cli/commands/introspect.mjs +1 -1
  22. package/dist/core/index.d.mts +3 -3
  23. package/dist/core/index.mjs +4 -6
  24. package/dist/{defineResource-tcgySDo1.mjs → core-CcR01lup.mjs} +58 -61
  25. package/dist/{createActionRouter-BORM8f17.mjs → createActionRouter-Bp_5c_2b.mjs} +3 -3
  26. package/dist/{createApp-B1EY8zxa.mjs → createApp-BuvPma24.mjs} +15 -14
  27. package/dist/docs/index.d.mts +2 -2
  28. package/dist/docs/index.mjs +2 -2
  29. package/dist/{elevation-DtFxrG0s.mjs → elevation-C7hgL_aI.mjs} +22 -8
  30. package/dist/{errorHandler-f869_8PQ.mjs → errorHandler-Bb49BvPD.mjs} +59 -7
  31. package/dist/{errorHandler-Bah5JhBd.d.mts → errorHandler-DRQ3EqfL.d.mts} +37 -2
  32. package/dist/{eventPlugin-D9DKB2zM.d.mts → eventPlugin-CxWgpd6K.d.mts} +14 -2
  33. package/dist/{eventPlugin-CDjVTM82.mjs → eventPlugin-DCUjuiQT.mjs} +83 -5
  34. package/dist/events/index.d.mts +150 -36
  35. package/dist/events/index.mjs +355 -101
  36. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  37. package/dist/events/transports/redis.d.mts +1 -1
  38. package/dist/factory/index.d.mts +1 -1
  39. package/dist/factory/index.mjs +2 -2
  40. package/dist/{types-DZi1aYhm.d.mts → fields-Lo1VUDpt.d.mts} +121 -1
  41. package/dist/{fields-ipsbIRPK.mjs → fields-bxkeltzz.mjs} +18 -5
  42. package/dist/{filesUpload-C7r7HIeA.mjs → filesUpload-t21LS-py.mjs} +65 -7
  43. package/dist/hooks/index.d.mts +1 -1
  44. package/dist/hooks/index.mjs +1 -1
  45. package/dist/idempotency/index.d.mts +32 -5
  46. package/dist/idempotency/index.mjs +119 -12
  47. package/dist/idempotency/redis.d.mts +1 -1
  48. package/dist/{index-DtDzOBn8.d.mts → index-8qw4y6ff.d.mts} +4 -135
  49. package/dist/{index-BLXBmWud.d.mts → index-ChIw3776.d.mts} +283 -408
  50. package/dist/{interface-CMRutPfe.d.mts → index-Cl0uoKd5.d.mts} +1758 -2506
  51. package/dist/{index-C1meYuDn.d.mts → index-DStwgFUK.d.mts} +81 -7
  52. package/dist/index.d.mts +7 -8
  53. package/dist/index.mjs +11 -12
  54. package/dist/integrations/event-gateway.d.mts +1 -1
  55. package/dist/integrations/event-gateway.mjs +1 -1
  56. package/dist/integrations/index.d.mts +1 -1
  57. package/dist/integrations/mcp/index.d.mts +26 -8
  58. package/dist/integrations/mcp/index.mjs +96 -17
  59. package/dist/integrations/mcp/testing.d.mts +1 -1
  60. package/dist/integrations/mcp/testing.mjs +1 -1
  61. package/dist/integrations/webhooks.d.mts +5 -0
  62. package/dist/integrations/webhooks.mjs +6 -0
  63. package/dist/interface-D218ikEo.d.mts +77 -0
  64. package/dist/{memory-Cp7_cAko.mjs → memory-B5Amv9A1.mjs} +23 -8
  65. package/dist/{openapi-CbKUJY_m.mjs → openapi-B5F8AddX.mjs} +3 -3
  66. package/dist/org/index.d.mts +2 -2
  67. package/dist/permissions/index.d.mts +3 -4
  68. package/dist/permissions/index.mjs +5 -5
  69. package/dist/{permissions-CH4cNwJi.mjs → permissions-Dk6mshja.mjs} +315 -397
  70. package/dist/plugins/index.d.mts +7 -7
  71. package/dist/plugins/index.mjs +14 -16
  72. package/dist/plugins/response-cache.mjs +2 -2
  73. package/dist/plugins/tracing-entry.d.mts +1 -1
  74. package/dist/plugins/tracing-entry.mjs +1 -1
  75. package/dist/presets/filesUpload.d.mts +27 -5
  76. package/dist/presets/filesUpload.mjs +1 -1
  77. package/dist/presets/index.d.mts +3 -2
  78. package/dist/presets/index.mjs +4 -3
  79. package/dist/presets/multiTenant.d.mts +1 -1
  80. package/dist/presets/multiTenant.mjs +2 -2
  81. package/dist/presets/search.d.mts +178 -0
  82. package/dist/presets/search.mjs +150 -0
  83. package/dist/{presets-C2xgzW6x.mjs → presets-fLJVXdVn.mjs} +1 -1
  84. package/dist/{queryCachePlugin-BJJGBTlu.d.mts → queryCachePlugin-BKbWjgDG.d.mts} +1 -1
  85. package/dist/{queryCachePlugin-BH-fidlv.mjs → queryCachePlugin-DQCEfJis.mjs} +9 -9
  86. package/dist/{queryParser-CgCtsjti.mjs → queryParser-DBqBB6AC.mjs} +1 -1
  87. package/dist/{redis-BM00zaPB.d.mts → redis-DqyeggCa.d.mts} +1 -1
  88. package/dist/{redis-stream-CrsfUmPt.d.mts → redis-stream-CakIQmwR.d.mts} +1 -1
  89. package/dist/registry/index.d.mts +1 -1
  90. package/dist/registry/index.mjs +2 -2
  91. package/dist/{resourceToTools-8s-EsCCe.mjs → resourceToTools-BElv3xPT.mjs} +65 -48
  92. package/dist/{schemaConverter-Y7nCYaLJ.mjs → schemaConverter-BxFDdtXu.mjs} +1 -1
  93. package/dist/scope/index.d.mts +1 -1
  94. package/dist/scope/index.mjs +2 -2
  95. package/dist/{sse-Ad7ypl9e.mjs → sse-yBCgOLGu.mjs} +1 -1
  96. package/dist/store-helpers-ZCSMJJAX.mjs +57 -0
  97. package/dist/testing/index.d.mts +9 -17
  98. package/dist/testing/index.mjs +27 -83
  99. package/dist/testing/storageContract.d.mts +1 -1
  100. package/dist/types/index.d.mts +4 -4
  101. package/dist/types/index.mjs +1 -31
  102. package/dist/types/storage.d.mts +1 -1
  103. package/dist/{types-BsbNMEDR.d.mts → types-Btdda02s.d.mts} +1 -1
  104. package/dist/{types-Ch9pTQbf.d.mts → types-Co8k3NyS.d.mts} +11 -9
  105. package/dist/types-Csi3FLfq.mjs +27 -0
  106. package/dist/utils/index.d.mts +208 -4
  107. package/dist/utils/index.mjs +5 -6
  108. package/dist/{utils-yYT3HDXt.mjs → utils-B2fNOD_i.mjs} +285 -2
  109. package/dist/{versioning-CDugduqI.mjs → versioning-C2U_bLY0.mjs} +3 -5
  110. package/package.json +20 -26
  111. package/skills/arc/SKILL.md +97 -23
  112. package/skills/arc/references/auth.md +94 -0
  113. package/skills/arc/references/events.md +200 -12
  114. package/skills/arc/references/mcp.md +4 -17
  115. package/skills/arc/references/multi-tenancy.md +43 -0
  116. package/skills/arc/references/production.md +34 -60
  117. package/dist/EventTransport-BXja8NOc.d.mts +0 -135
  118. package/dist/audit/mongodb.d.mts +0 -2
  119. package/dist/audit/mongodb.mjs +0 -2
  120. package/dist/circuitBreaker-cmi5XDv5.mjs +0 -284
  121. package/dist/circuitBreaker-dTtG-UyS.d.mts +0 -206
  122. package/dist/core-F0QoWBt2.mjs +0 -34
  123. package/dist/dynamic/index.d.mts +0 -93
  124. package/dist/dynamic/index.mjs +0 -122
  125. package/dist/fields-DpZQa_Q3.d.mts +0 -109
  126. package/dist/idempotency/mongodb.d.mts +0 -2
  127. package/dist/idempotency/mongodb.mjs +0 -123
  128. package/dist/interface-4y979v99.d.mts +0 -54
  129. package/dist/mongodb-BsP-WbhN.d.mts +0 -127
  130. package/dist/mongodb-CTcp0hQZ.d.mts +0 -80
  131. package/dist/mongodb-Utc5k_-0.mjs +0 -90
  132. package/dist/policies/index.d.mts +0 -432
  133. package/dist/policies/index.mjs +0 -318
  134. package/dist/rpc/index.d.mts +0 -90
  135. package/dist/rpc/index.mjs +0 -248
  136. /package/dist/{HookSystem-HprTmvVY.mjs → HookSystem-BNYKnrXF.mjs} +0 -0
  137. /package/dist/{applyPermissionResult-D6GPMsvh.mjs → applyPermissionResult-QhV1Pa-g.mjs} +0 -0
  138. /package/dist/{constants-Cxde4rpC.mjs → constants-BhY1OHoH.mjs} +0 -0
  139. /package/dist/{elevation-B6S5csVA.d.mts → elevation-C5SwtkAn.d.mts} +0 -0
  140. /package/dist/{errors-Ck2h67pm.d.mts → errors-CCSsMpXE.d.mts} +0 -0
  141. /package/dist/{errors-BF2bIOIS.mjs → errors-D5c-5BJL.mjs} +0 -0
  142. /package/dist/{externalPaths-BnkYrNzp.d.mts → externalPaths-BQ8QijNH.d.mts} +0 -0
  143. /package/dist/{interface-DfLGcus7.d.mts → interface-CSbZdv_3.d.mts} +0 -0
  144. /package/dist/{loadResources-PWd0OCpV.mjs → loadResources-BAzJItAJ.mjs} +0 -0
  145. /package/dist/{logger-D1YrIImS.mjs → logger-DLg8-Ueg.mjs} +0 -0
  146. /package/dist/{metrics-B-PU4-Yu.mjs → metrics-DuhiSEZI.mjs} +0 -0
  147. /package/dist/{pluralize-CWP6MB39.mjs → pluralize-A0tWEl1K.mjs} +0 -0
  148. /package/dist/{registry-BiTKT1Dg.mjs → registry-B3lRFBWo.mjs} +0 -0
  149. /package/dist/{replyHelpers-CxkYGT81.mjs → replyHelpers-CXtJDAZ0.mjs} +0 -0
  150. /package/dist/{requestContext-DYvHl113.mjs → requestContext-xHIKedG6.mjs} +0 -0
  151. /package/dist/{sessionManager-DDCmiNIo.d.mts → sessionManager-BkzVU8h2.d.mts} +0 -0
  152. /package/dist/{storage-Dfzt4VTl.d.mts → storage-CVk_SEn2.d.mts} +0 -0
  153. /package/dist/{tracing-DdN2-wHJ.d.mts → tracing-65B51Dw3.d.mts} +0 -0
  154. /package/dist/{typeGuards-CcFZXgU7.mjs → typeGuards-Cj5Rgvlg.mjs} +0 -0
  155. /package/dist/{types-ZUu_h0jp.mjs → types-DV9WDfeg.mjs} +0 -0
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Database-agnostic resource framework for Fastify. Define resources, get CRUD routes, permissions, presets, caching, events, OpenAPI, and MCP tools — without boilerplate.
4
4
 
5
- **v2.8.4** | Fastify 5+ | Node.js 22+ | ESM only | 279+ test files, 3867+ tests
5
+ **v2.10** | Fastify 5+ | Node.js 22+ | ESM only
6
6
 
7
7
  ## Install
8
8
 
@@ -65,8 +65,15 @@ const app = await createApp({
65
65
  Clean DX without growing exclude lists:
66
66
 
67
67
  ```typescript
68
- // app.ts register once with perResource mode
69
- await fastify.register(auditPlugin, { autoAudit: { perResource: true } });
68
+ import { Repository, methodRegistryPlugin, batchOperationsPlugin } from '@classytic/mongokit';
69
+
70
+ // app.ts — pass any RepositoryLike (mongokit / prismakit / custom)
71
+ await fastify.register(auditPlugin, {
72
+ autoAudit: { perResource: true },
73
+ // batchOperationsPlugin enables deleteMany, required for purgeOlderThan()
74
+ repository: new Repository(AuditModel, [methodRegistryPlugin(), batchOperationsPlugin()]),
75
+ // or omit `repository` for in-memory dev
76
+ });
70
77
 
71
78
  // order.resource.ts — opt in
72
79
  defineResource({ name: 'order', audit: true });
@@ -99,8 +106,8 @@ const productResource = defineResource({
99
106
  delete: roles('admin'),
100
107
  },
101
108
  cache: { staleTime: 30, gcTime: 300, tags: ['catalog'] }, // QueryCache (opt-in)
102
- additionalRoutes: [
103
- { method: 'GET', path: '/featured', handler: 'getFeatured', permissions: allowPublic(), wrapHandler: true },
109
+ routes: [
110
+ { method: 'GET', path: '/featured', handler: 'getFeatured', permissions: allowPublic() },
104
111
  ],
105
112
  });
106
113
 
@@ -383,6 +390,29 @@ await app.events.subscribe('order.*', async (event) => { ... });
383
390
 
384
391
  CRUD events (`product.created`, `product.updated`, `product.deleted`) emit automatically.
385
392
 
393
+ ### Causation Chains & DLQ (v2.9)
394
+
395
+ ```typescript
396
+ import { createEvent, createChildEvent, type DeadLetteredEvent } from '@classytic/arc/events';
397
+
398
+ const placed = createEvent('order.placed', { orderId: 'o1' }, {
399
+ correlationId: req.id, userId: user.id,
400
+ });
401
+ await app.events.publish(placed.type, placed.payload, placed.meta);
402
+
403
+ // Downstream handler emits a child — correlation inherited, causation linked:
404
+ const reserved = createChildEvent(placed, 'inventory.reserved', { sku: 'a' });
405
+ // reserved.meta.correlationId === placed.meta.correlationId (stays stable across chain)
406
+ // reserved.meta.causationId === placed.meta.id (direct parent)
407
+
408
+ // Transports with native DLQ (Kafka, SQS) implement optional deadLetter():
409
+ class KafkaTransport implements EventTransport {
410
+ async deadLetter(dlq: DeadLetteredEvent) { /* route to .DLQ topic */ }
411
+ }
412
+ ```
413
+
414
+ `EventMeta` also accepts `schemaVersion` (evolve event payloads) and `partitionKey` (ordered delivery hint for Kafka/Kinesis).
415
+
386
416
  ### defineEvent — Typed Events with Schema Validation
387
417
 
388
418
  Declare events with schemas for runtime validation and introspection:
@@ -709,7 +739,6 @@ Arc sets `"sideEffects": false` in [package.json](package.json), so modern bundl
709
739
  | `@classytic/arc/presets` | Preset functions + interfaces |
710
740
  | `@classytic/arc/audit` | Audit trail |
711
741
  | `@classytic/arc/idempotency` | Idempotency |
712
- | `@classytic/arc/policies` | Policy engine |
713
742
  | `@classytic/arc/schemas` | TypeBox helpers |
714
743
  | `@classytic/arc/utils` | Errors, circuit breaker, state machine, query parser |
715
744
  | `@classytic/arc/testing` | Test utilities, mocks, in-memory DB |
@@ -722,46 +751,29 @@ Arc sets `"sideEffects": false` in [package.json](package.json), so modern bundl
722
751
  | `@classytic/arc/docs` | OpenAPI generation |
723
752
  | `@classytic/arc/cli` | CLI commands (programmatic) |
724
753
 
725
- ## v2.8.4 Highlights
754
+ ## Type imports
726
755
 
727
- - **MCP AI SDK bridge** — expose AI SDK `tool()` definitions over MCP without duplicating code. `bridgeToMcp(bridge)` adapts any AI SDK tool into an MCP tool with automatic auth, guard delegation, and `{ error } → isError` envelope translation. `buildMcpToolsFromBridges(bridges, { include, exclude })` registers a whole catalog at once with per-environment filtering.
756
+ Arc owns framework types (`IController`, `IRequestContext`, `ResourceConfig`, `RepositoryLike`, `PaginationResult`). The repository contract lives in `@classytic/repo-core` import those types directly:
728
757
 
729
758
  ```typescript
730
- import { bridgeToMcp, buildMcpToolsFromBridges, type McpBridge } from '@classytic/arc/mcp';
731
-
732
- export const triggerJobBridge: McpBridge = {
733
- name: 'trigger_job',
734
- description: 'Start a job.',
735
- inputSchema: { phase: z.enum(['investigate', 'fix']) },
736
- annotations: { destructiveHint: true },
737
- buildTool: (ctx) => buildTriggerJobTool(getUserId(ctx) ?? ''),
738
- };
739
-
740
- await app.register(mcpPlugin, {
741
- resources,
742
- extraTools: buildMcpToolsFromBridges([triggerJobBridge]),
743
- });
759
+ // Arc framework types
760
+ import type { IRequestContext, RepositoryLike, PaginationResult } from '@classytic/arc';
761
+
762
+ // Repository contract (repo-core is the single source of truth)
763
+ import type { StandardRepo, WriteOptions, QueryOptions } from '@classytic/repo-core/repository';
764
+ import type { OffsetPaginationResult } from '@classytic/repo-core/pagination';
744
765
  ```
745
766
 
746
- ## v2.8.1 Highlights
767
+ > Arc 2.10 dropped the legacy `CrudRepository`, `PaginatedResult`, and pass-through `WriteOptions`/`QueryOptions` re-exports. See [CHANGELOG.md](CHANGELOG.md#210) for the migration table.
747
768
 
748
- - **Per-action discriminated validation** — `actions` schemas now enforce required fields via a `oneOf` body schema; missing inputs are rejected at the HTTP layer by AJV (no more silent bypass)
749
- - **Actions in OpenAPI** — `POST /:id/action` endpoint auto-generated from `ResourceDefinition.actions`, with per-action descriptions and the same discriminated body schema as the runtime router
750
- - **Route/action metadata preserved** — `mcp: false`, `description`, `annotations` no longer dropped during `routes → additionalRoutes` normalization
751
- - **Canonical source retained** — `ResourceDefinition.routes` and `ResourceDefinition.actions` now kept as declared, so OpenAPI/MCP/registry can read the original shape
752
- - **Outbox hardening** — expanded `OutboxStore` contract (`claimPending`, `fail`, write options, dedupe, visibleAt), ownership-mismatch throws, onError reporting, safe multi-worker relay
753
- - **`slugLookup` fallback** — works with MongoKit's default Repository (no custom `getBySlug` needed)
769
+ ## v2.10 Highlights
754
770
 
755
- ## v2.8.0 Highlights
771
+ - **Clean-break on repo-core types** — `CrudRepository` / `PaginatedResult` / pass-through repo options removed from arc's public surface. Import `StandardRepo`, `OffsetPaginationResult`, etc. directly from `@classytic/repo-core`. See [CHANGELOG.md](CHANGELOG.md) for the rewrite table.
772
+ - **Outbox bugfix** — `repositoryAsOutboxStore.fail()` now passes `updatePipeline: true` to `findOneAndUpdate`, so retry / DLQ transitions work on mongokit ≥3.10.
773
+ - **Plugin requirements documented** — audit / outbox / idempotency require mongokit's `methodRegistryPlugin` + `batchOperationsPlugin` for `deleteMany`; README snippets + production-ops docs now show the correct chain.
774
+ - **Removed** — `@classytic/arc/policies` (use `permissions/`), `@classytic/arc/rpc`, `@classytic/arc/dynamic` (use `factory/loadResources`).
756
775
 
757
- - **MCP Integration** expose resources as AI agent tools (stateless by default, service scope, multi-tenancy)
758
- - **Reply Helpers** — `reply.ok()`, `reply.fail()`, `reply.paginated()`, `reply.stream()` (opt-in)
759
- - **Error Mappers** — class-based `instanceof` domain error → HTTP response mapping
760
- - **Multipart Body** — `multipartBody()` middleware for file upload in CRUD routes
761
- - **Service Scope** — `kind: "service"` RequestScope for machine-to-machine auth (MCP + WebSocket)
762
- - **BigInt Serialization** — `serializeBigInt: true` auto-converts BigInt → Number
763
- - **Event WAL** — skips internal `arc.*` events to prevent startup timeout with durable stores
764
- - **Security** — `auth: false` produces null `ctx.user` (prevents anonymous bypass of `!!ctx.user` guards)
776
+ See [CHANGELOG.md](CHANGELOG.md) for the full v2.9 / v2.8 / v2.7 history.
765
777
 
766
778
  ## License
767
779