@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.
- package/README.md +50 -38
- package/dist/{BaseController-DAGGc5Xn.mjs → BaseController-CbKKIflT.mjs} +193 -143
- package/dist/EventTransport-CUw5NNWe.d.mts +293 -0
- package/dist/{ResourceRegistry-C6uXlWe3.mjs → ResourceRegistry-BPd6NQDm.mjs} +1 -1
- package/dist/adapters/index.d.mts +3 -3
- package/dist/adapters/index.mjs +2 -2
- package/dist/{adapters-BBqAVvPK.mjs → adapters-BXY4i-hw.mjs} +210 -41
- package/dist/audit/index.d.mts +135 -11
- package/dist/audit/index.mjs +107 -20
- package/dist/auth/index.d.mts +17 -9
- package/dist/auth/index.mjs +14 -7
- package/dist/auth/redis-session.d.mts +1 -1
- package/dist/{betterAuthOpenApi-BuUcUEJq.mjs → betterAuthOpenApi-BBRVhjQN.mjs} +1 -1
- package/dist/cache/index.d.mts +17 -15
- package/dist/cache/index.mjs +15 -14
- package/dist/{caching-IMuYVjTL.mjs → caching-CBpK_SCM.mjs} +8 -3
- package/dist/cli/commands/describe.mjs +1 -1
- package/dist/cli/commands/docs.mjs +2 -2
- package/dist/cli/commands/generate.mjs +1 -1
- package/dist/cli/commands/init.mjs +1 -1
- package/dist/cli/commands/introspect.mjs +1 -1
- package/dist/core/index.d.mts +3 -3
- package/dist/core/index.mjs +4 -6
- package/dist/{defineResource-tcgySDo1.mjs → core-CcR01lup.mjs} +58 -61
- package/dist/{createActionRouter-BORM8f17.mjs → createActionRouter-Bp_5c_2b.mjs} +3 -3
- package/dist/{createApp-B1EY8zxa.mjs → createApp-BuvPma24.mjs} +15 -14
- package/dist/docs/index.d.mts +2 -2
- package/dist/docs/index.mjs +2 -2
- package/dist/{elevation-DtFxrG0s.mjs → elevation-C7hgL_aI.mjs} +22 -8
- package/dist/{errorHandler-f869_8PQ.mjs → errorHandler-Bb49BvPD.mjs} +59 -7
- package/dist/{errorHandler-Bah5JhBd.d.mts → errorHandler-DRQ3EqfL.d.mts} +37 -2
- package/dist/{eventPlugin-D9DKB2zM.d.mts → eventPlugin-CxWgpd6K.d.mts} +14 -2
- package/dist/{eventPlugin-CDjVTM82.mjs → eventPlugin-DCUjuiQT.mjs} +83 -5
- package/dist/events/index.d.mts +150 -36
- package/dist/events/index.mjs +355 -101
- package/dist/events/transports/redis-stream-entry.d.mts +1 -1
- package/dist/events/transports/redis.d.mts +1 -1
- package/dist/factory/index.d.mts +1 -1
- package/dist/factory/index.mjs +2 -2
- package/dist/{types-DZi1aYhm.d.mts → fields-Lo1VUDpt.d.mts} +121 -1
- package/dist/{fields-ipsbIRPK.mjs → fields-bxkeltzz.mjs} +18 -5
- package/dist/{filesUpload-C7r7HIeA.mjs → filesUpload-t21LS-py.mjs} +65 -7
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.mjs +1 -1
- package/dist/idempotency/index.d.mts +32 -5
- package/dist/idempotency/index.mjs +119 -12
- package/dist/idempotency/redis.d.mts +1 -1
- package/dist/{index-DtDzOBn8.d.mts → index-8qw4y6ff.d.mts} +4 -135
- package/dist/{index-BLXBmWud.d.mts → index-ChIw3776.d.mts} +283 -408
- package/dist/{interface-CMRutPfe.d.mts → index-Cl0uoKd5.d.mts} +1758 -2506
- package/dist/{index-C1meYuDn.d.mts → index-DStwgFUK.d.mts} +81 -7
- package/dist/index.d.mts +7 -8
- package/dist/index.mjs +11 -12
- package/dist/integrations/event-gateway.d.mts +1 -1
- package/dist/integrations/event-gateway.mjs +1 -1
- package/dist/integrations/index.d.mts +1 -1
- package/dist/integrations/mcp/index.d.mts +26 -8
- package/dist/integrations/mcp/index.mjs +96 -17
- package/dist/integrations/mcp/testing.d.mts +1 -1
- package/dist/integrations/mcp/testing.mjs +1 -1
- package/dist/integrations/webhooks.d.mts +5 -0
- package/dist/integrations/webhooks.mjs +6 -0
- package/dist/interface-D218ikEo.d.mts +77 -0
- package/dist/{memory-Cp7_cAko.mjs → memory-B5Amv9A1.mjs} +23 -8
- package/dist/{openapi-CbKUJY_m.mjs → openapi-B5F8AddX.mjs} +3 -3
- package/dist/org/index.d.mts +2 -2
- package/dist/permissions/index.d.mts +3 -4
- package/dist/permissions/index.mjs +5 -5
- package/dist/{permissions-CH4cNwJi.mjs → permissions-Dk6mshja.mjs} +315 -397
- package/dist/plugins/index.d.mts +7 -7
- package/dist/plugins/index.mjs +14 -16
- package/dist/plugins/response-cache.mjs +2 -2
- package/dist/plugins/tracing-entry.d.mts +1 -1
- package/dist/plugins/tracing-entry.mjs +1 -1
- package/dist/presets/filesUpload.d.mts +27 -5
- package/dist/presets/filesUpload.mjs +1 -1
- package/dist/presets/index.d.mts +3 -2
- package/dist/presets/index.mjs +4 -3
- package/dist/presets/multiTenant.d.mts +1 -1
- package/dist/presets/multiTenant.mjs +2 -2
- package/dist/presets/search.d.mts +178 -0
- package/dist/presets/search.mjs +150 -0
- package/dist/{presets-C2xgzW6x.mjs → presets-fLJVXdVn.mjs} +1 -1
- package/dist/{queryCachePlugin-BJJGBTlu.d.mts → queryCachePlugin-BKbWjgDG.d.mts} +1 -1
- package/dist/{queryCachePlugin-BH-fidlv.mjs → queryCachePlugin-DQCEfJis.mjs} +9 -9
- package/dist/{queryParser-CgCtsjti.mjs → queryParser-DBqBB6AC.mjs} +1 -1
- package/dist/{redis-BM00zaPB.d.mts → redis-DqyeggCa.d.mts} +1 -1
- package/dist/{redis-stream-CrsfUmPt.d.mts → redis-stream-CakIQmwR.d.mts} +1 -1
- package/dist/registry/index.d.mts +1 -1
- package/dist/registry/index.mjs +2 -2
- package/dist/{resourceToTools-8s-EsCCe.mjs → resourceToTools-BElv3xPT.mjs} +65 -48
- package/dist/{schemaConverter-Y7nCYaLJ.mjs → schemaConverter-BxFDdtXu.mjs} +1 -1
- package/dist/scope/index.d.mts +1 -1
- package/dist/scope/index.mjs +2 -2
- package/dist/{sse-Ad7ypl9e.mjs → sse-yBCgOLGu.mjs} +1 -1
- package/dist/store-helpers-ZCSMJJAX.mjs +57 -0
- package/dist/testing/index.d.mts +9 -17
- package/dist/testing/index.mjs +27 -83
- package/dist/testing/storageContract.d.mts +1 -1
- package/dist/types/index.d.mts +4 -4
- package/dist/types/index.mjs +1 -31
- package/dist/types/storage.d.mts +1 -1
- package/dist/{types-BsbNMEDR.d.mts → types-Btdda02s.d.mts} +1 -1
- package/dist/{types-Ch9pTQbf.d.mts → types-Co8k3NyS.d.mts} +11 -9
- package/dist/types-Csi3FLfq.mjs +27 -0
- package/dist/utils/index.d.mts +208 -4
- package/dist/utils/index.mjs +5 -6
- package/dist/{utils-yYT3HDXt.mjs → utils-B2fNOD_i.mjs} +285 -2
- package/dist/{versioning-CDugduqI.mjs → versioning-C2U_bLY0.mjs} +3 -5
- package/package.json +20 -26
- package/skills/arc/SKILL.md +97 -23
- package/skills/arc/references/auth.md +94 -0
- package/skills/arc/references/events.md +200 -12
- package/skills/arc/references/mcp.md +4 -17
- package/skills/arc/references/multi-tenancy.md +43 -0
- package/skills/arc/references/production.md +34 -60
- package/dist/EventTransport-BXja8NOc.d.mts +0 -135
- package/dist/audit/mongodb.d.mts +0 -2
- package/dist/audit/mongodb.mjs +0 -2
- package/dist/circuitBreaker-cmi5XDv5.mjs +0 -284
- package/dist/circuitBreaker-dTtG-UyS.d.mts +0 -206
- package/dist/core-F0QoWBt2.mjs +0 -34
- package/dist/dynamic/index.d.mts +0 -93
- package/dist/dynamic/index.mjs +0 -122
- package/dist/fields-DpZQa_Q3.d.mts +0 -109
- package/dist/idempotency/mongodb.d.mts +0 -2
- package/dist/idempotency/mongodb.mjs +0 -123
- package/dist/interface-4y979v99.d.mts +0 -54
- package/dist/mongodb-BsP-WbhN.d.mts +0 -127
- package/dist/mongodb-CTcp0hQZ.d.mts +0 -80
- package/dist/mongodb-Utc5k_-0.mjs +0 -90
- package/dist/policies/index.d.mts +0 -432
- package/dist/policies/index.mjs +0 -318
- package/dist/rpc/index.d.mts +0 -90
- package/dist/rpc/index.mjs +0 -248
- /package/dist/{HookSystem-HprTmvVY.mjs → HookSystem-BNYKnrXF.mjs} +0 -0
- /package/dist/{applyPermissionResult-D6GPMsvh.mjs → applyPermissionResult-QhV1Pa-g.mjs} +0 -0
- /package/dist/{constants-Cxde4rpC.mjs → constants-BhY1OHoH.mjs} +0 -0
- /package/dist/{elevation-B6S5csVA.d.mts → elevation-C5SwtkAn.d.mts} +0 -0
- /package/dist/{errors-Ck2h67pm.d.mts → errors-CCSsMpXE.d.mts} +0 -0
- /package/dist/{errors-BF2bIOIS.mjs → errors-D5c-5BJL.mjs} +0 -0
- /package/dist/{externalPaths-BnkYrNzp.d.mts → externalPaths-BQ8QijNH.d.mts} +0 -0
- /package/dist/{interface-DfLGcus7.d.mts → interface-CSbZdv_3.d.mts} +0 -0
- /package/dist/{loadResources-PWd0OCpV.mjs → loadResources-BAzJItAJ.mjs} +0 -0
- /package/dist/{logger-D1YrIImS.mjs → logger-DLg8-Ueg.mjs} +0 -0
- /package/dist/{metrics-B-PU4-Yu.mjs → metrics-DuhiSEZI.mjs} +0 -0
- /package/dist/{pluralize-CWP6MB39.mjs → pluralize-A0tWEl1K.mjs} +0 -0
- /package/dist/{registry-BiTKT1Dg.mjs → registry-B3lRFBWo.mjs} +0 -0
- /package/dist/{replyHelpers-CxkYGT81.mjs → replyHelpers-CXtJDAZ0.mjs} +0 -0
- /package/dist/{requestContext-DYvHl113.mjs → requestContext-xHIKedG6.mjs} +0 -0
- /package/dist/{sessionManager-DDCmiNIo.d.mts → sessionManager-BkzVU8h2.d.mts} +0 -0
- /package/dist/{storage-Dfzt4VTl.d.mts → storage-CVk_SEn2.d.mts} +0 -0
- /package/dist/{tracing-DdN2-wHJ.d.mts → tracing-65B51Dw3.d.mts} +0 -0
- /package/dist/{typeGuards-CcFZXgU7.mjs → typeGuards-Cj5Rgvlg.mjs} +0 -0
- /package/dist/{types-ZUu_h0jp.mjs → types-DV9WDfeg.mjs} +0 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
//#region src/events/EventTransport.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Event Transport Interface
|
|
4
|
+
*
|
|
5
|
+
* Defines contract for event delivery backends.
|
|
6
|
+
* Implement for durable transports (Redis, RabbitMQ, Kafka, etc.)
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* // Redis Pub/Sub implementation
|
|
10
|
+
* class RedisEventTransport implements EventTransport {
|
|
11
|
+
* async publish(event) {
|
|
12
|
+
* await redis.publish(event.type, JSON.stringify(event));
|
|
13
|
+
* }
|
|
14
|
+
* async subscribe(pattern, handler) {
|
|
15
|
+
* redis.psubscribe(pattern);
|
|
16
|
+
* redis.on('pmessage', (p, channel, msg) => handler(JSON.parse(msg)));
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Event metadata.
|
|
22
|
+
*
|
|
23
|
+
* Split out as a standalone interface so primitives / downstream packages can
|
|
24
|
+
* mirror it without re-declaring the DomainEvent wrapper. See events.ts in
|
|
25
|
+
* @classytic/primitives for the sibling shape.
|
|
26
|
+
*/
|
|
27
|
+
interface EventMeta {
|
|
28
|
+
/** Unique event ID (UUID v4 recommended) */
|
|
29
|
+
id: string;
|
|
30
|
+
/** Event timestamp */
|
|
31
|
+
timestamp: Date;
|
|
32
|
+
/**
|
|
33
|
+
* Schema version for this event type. Default: `1`.
|
|
34
|
+
*
|
|
35
|
+
* Use when the payload shape evolves so handlers can branch on version
|
|
36
|
+
* during migration windows (`if (event.meta.schemaVersion === 2) ...`).
|
|
37
|
+
* Bump ONLY when the payload contract changes in a breaking way.
|
|
38
|
+
*/
|
|
39
|
+
schemaVersion?: number;
|
|
40
|
+
/**
|
|
41
|
+
* Correlation ID — stays stable across an entire causal chain so a single
|
|
42
|
+
* user action can be traced through every downstream event. Spans service
|
|
43
|
+
* boundaries. Generated at the edge (HTTP request, CLI invocation) and
|
|
44
|
+
* inherited by every child event.
|
|
45
|
+
*/
|
|
46
|
+
correlationId?: string;
|
|
47
|
+
/**
|
|
48
|
+
* Causation ID — the `meta.id` of the direct parent event that caused
|
|
49
|
+
* this one. Forms a linked-list of cause-and-effect within a correlation.
|
|
50
|
+
*
|
|
51
|
+
* Distinct from correlationId: correlation groups, causation chains.
|
|
52
|
+
* Use {@link createChildEvent} to populate this automatically.
|
|
53
|
+
*/
|
|
54
|
+
causationId?: string;
|
|
55
|
+
/**
|
|
56
|
+
* Partition key hint for ordered transports (Kafka, Kinesis, Redis Streams
|
|
57
|
+
* consumer groups). Events with the same partitionKey are guaranteed to be
|
|
58
|
+
* delivered in publish order by transports that honour it.
|
|
59
|
+
*
|
|
60
|
+
* Defaults to `resourceId` if unset. Transports that don't support ordering
|
|
61
|
+
* (in-memory, simple pub/sub) ignore this field.
|
|
62
|
+
*/
|
|
63
|
+
partitionKey?: string;
|
|
64
|
+
/** Source resource (e.g. 'order', 'transaction') */
|
|
65
|
+
resource?: string;
|
|
66
|
+
/** Resource identifier */
|
|
67
|
+
resourceId?: string;
|
|
68
|
+
/** User who triggered the event */
|
|
69
|
+
userId?: string;
|
|
70
|
+
/** Organization context */
|
|
71
|
+
organizationId?: string;
|
|
72
|
+
/**
|
|
73
|
+
* Originating service or package (e.g. `'commerce'`, `'billing'`, `'arc-core'`).
|
|
74
|
+
*
|
|
75
|
+
* In a multi-service deployment, consumers route / log / alert by `source`
|
|
76
|
+
* without parsing `type` prefixes. Arc itself never populates this — hosts
|
|
77
|
+
* set it once per emitter (`app.events.publish('order.placed', p, { source: 'commerce' })`).
|
|
78
|
+
* Inherited by {@link createChildEvent} so downstream events carry the same
|
|
79
|
+
* source unless overridden.
|
|
80
|
+
*/
|
|
81
|
+
source?: string;
|
|
82
|
+
/**
|
|
83
|
+
* Idempotency key — stable hint that this event represents a specific
|
|
84
|
+
* operation exactly once. Consumers dedupe with `if (processed.has(meta.idempotencyKey)) return`.
|
|
85
|
+
*
|
|
86
|
+
* Survives every transport (Memory / Pub-Sub / Streams / Kafka) because it's
|
|
87
|
+
* part of the event, not a transport-side option. Distinct from `meta.id`
|
|
88
|
+
* (which is fresh per emit — a retry would produce a new id).
|
|
89
|
+
*
|
|
90
|
+
* Typical sources: HTTP `Idempotency-Key` header, outbox `dedupeKey`, or
|
|
91
|
+
* `{aggregate.type}:{aggregate.id}:{action}`. Inherited by child events.
|
|
92
|
+
*/
|
|
93
|
+
idempotencyKey?: string;
|
|
94
|
+
/**
|
|
95
|
+
* DDD aggregate marker — the aggregate that owns this event's invariant.
|
|
96
|
+
*
|
|
97
|
+
* Use when routing events by aggregate, doing event-sourcing replay, or
|
|
98
|
+
* enforcing consistency boundaries. Distinct from `resource` / `resourceId`
|
|
99
|
+
* (HTTP-origin entity) because an event emitted *by* one REST resource can
|
|
100
|
+
* *belong to* a different aggregate (e.g. `POST /orders/:id/ship` emits
|
|
101
|
+
* `shipment.dispatched` owned by a shipment aggregate).
|
|
102
|
+
*
|
|
103
|
+
* Downstream packages narrow `aggregate.type` to their own string union via
|
|
104
|
+
* interface extension:
|
|
105
|
+
*
|
|
106
|
+
* ```ts
|
|
107
|
+
* type CartAggregateType = 'cart' | 'cart-item';
|
|
108
|
+
* interface CartEventMeta extends EventMeta {
|
|
109
|
+
* aggregate?: { type: CartAggregateType; id: string };
|
|
110
|
+
* }
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* Not inherited by {@link createChildEvent} — child events typically belong
|
|
114
|
+
* to a different aggregate than their parent.
|
|
115
|
+
*/
|
|
116
|
+
aggregate?: {
|
|
117
|
+
type: string;
|
|
118
|
+
id: string;
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
interface DomainEvent<T = unknown> {
|
|
122
|
+
/** Event type (e.g., 'product.created', 'order.shipped') */
|
|
123
|
+
type: string;
|
|
124
|
+
/** Event payload */
|
|
125
|
+
payload: T;
|
|
126
|
+
/** Event metadata */
|
|
127
|
+
meta: EventMeta;
|
|
128
|
+
}
|
|
129
|
+
type EventHandler<T = unknown> = (event: DomainEvent<T>) => void | Promise<void>;
|
|
130
|
+
/**
|
|
131
|
+
* A permanently-failed event routed to a dead-letter sink after retries
|
|
132
|
+
* have been exhausted. Mirrors the shape a caller would log, alert on, or
|
|
133
|
+
* replay from once the upstream issue is fixed.
|
|
134
|
+
*/
|
|
135
|
+
interface DeadLetteredEvent<T = unknown> {
|
|
136
|
+
/** The original event */
|
|
137
|
+
event: DomainEvent<T>;
|
|
138
|
+
/** Serialised failure reason (message + optional machine code + stack) */
|
|
139
|
+
error: {
|
|
140
|
+
message: string;
|
|
141
|
+
code?: string;
|
|
142
|
+
stack?: string;
|
|
143
|
+
};
|
|
144
|
+
/** How many delivery attempts were made before giving up */
|
|
145
|
+
attempts: number;
|
|
146
|
+
/** First failure timestamp */
|
|
147
|
+
firstFailedAt: Date;
|
|
148
|
+
/** Last failure timestamp (immediately before dead-lettering) */
|
|
149
|
+
lastFailedAt: Date;
|
|
150
|
+
/** Optional handler / subscriber name that last failed (for debug) */
|
|
151
|
+
handlerName?: string;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Minimal logger interface for event transports.
|
|
155
|
+
* Compatible with `console`, `pino`, `fastify.log`, and any custom logger.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```typescript
|
|
159
|
+
* // Use Fastify's logger
|
|
160
|
+
* new MemoryEventTransport({ logger: fastify.log });
|
|
161
|
+
*
|
|
162
|
+
* // Use a custom logger
|
|
163
|
+
* new MemoryEventTransport({ logger: { warn: myWarn, error: myError } });
|
|
164
|
+
*
|
|
165
|
+
* // Default: console (no logger option needed)
|
|
166
|
+
* new MemoryEventTransport();
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
interface EventLogger {
|
|
170
|
+
warn(message: string, ...args: unknown[]): void;
|
|
171
|
+
error(message: string, ...args: unknown[]): void;
|
|
172
|
+
}
|
|
173
|
+
interface EventTransport {
|
|
174
|
+
/** Transport name for logging */
|
|
175
|
+
readonly name: string;
|
|
176
|
+
/**
|
|
177
|
+
* Publish an event to the transport
|
|
178
|
+
*/
|
|
179
|
+
publish(event: DomainEvent): Promise<void>;
|
|
180
|
+
/**
|
|
181
|
+
* Publish a batch of events to the transport (optional, v2.8.1+).
|
|
182
|
+
*
|
|
183
|
+
* Transports that can efficiently batch (Kafka producer, Redis pipeline,
|
|
184
|
+
* RabbitMQ publisher confirms, SQS send-message-batch) should implement
|
|
185
|
+
* this. {@link import('./outbox.js').EventOutbox.relay} auto-detects and
|
|
186
|
+
* uses it for much higher throughput than per-event publishing.
|
|
187
|
+
*
|
|
188
|
+
* **Contract**: the returned `PublishManyResult` must describe the
|
|
189
|
+
* per-event outcome so the caller can acknowledge successes and fail the
|
|
190
|
+
* rest. Partial success is allowed — the transport reports it per event.
|
|
191
|
+
*
|
|
192
|
+
* If not implemented, `EventOutbox.relay` falls back to calling
|
|
193
|
+
* {@link publish} once per event.
|
|
194
|
+
*
|
|
195
|
+
* @param events - Events to publish (in order)
|
|
196
|
+
* @returns Per-event outcome map keyed by `event.meta.id`
|
|
197
|
+
*/
|
|
198
|
+
publishMany?(events: readonly DomainEvent[]): Promise<PublishManyResult>;
|
|
199
|
+
/**
|
|
200
|
+
* Subscribe to events matching a pattern
|
|
201
|
+
* @param pattern - Event type pattern (e.g., 'product.*', '*')
|
|
202
|
+
* @param handler - Handler function
|
|
203
|
+
* @returns Unsubscribe function
|
|
204
|
+
*/
|
|
205
|
+
subscribe(pattern: string, handler: EventHandler): Promise<() => void>;
|
|
206
|
+
/**
|
|
207
|
+
* Route a permanently-failed event to the transport's dead-letter sink
|
|
208
|
+
* (Kafka DLQ topic, SQS DLQ, Redis Stream `PEL` timeout handler, etc.).
|
|
209
|
+
*
|
|
210
|
+
* Called by {@link import('./outbox.js').EventOutbox} after exhausting
|
|
211
|
+
* retries. Transports that don't have a native DLQ can omit this —
|
|
212
|
+
* callers treat an absent `deadLetter` as "log and drop".
|
|
213
|
+
*/
|
|
214
|
+
deadLetter?(dlq: DeadLetteredEvent): Promise<void>;
|
|
215
|
+
/**
|
|
216
|
+
* Close transport connections
|
|
217
|
+
*/
|
|
218
|
+
close?(): Promise<void>;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Per-event outcome returned by {@link EventTransport.publishMany}.
|
|
222
|
+
*
|
|
223
|
+
* The key is `event.meta.id`; the value is `null` for success or an `Error`
|
|
224
|
+
* for per-event failure. Transports MUST include an entry for every event
|
|
225
|
+
* in the input batch.
|
|
226
|
+
*/
|
|
227
|
+
type PublishManyResult = ReadonlyMap<string, Error | null>;
|
|
228
|
+
interface MemoryEventTransportOptions {
|
|
229
|
+
/** Logger for error/warning messages (default: console) */
|
|
230
|
+
logger?: EventLogger;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* In-memory event transport (default)
|
|
234
|
+
* Events are delivered synchronously within the process.
|
|
235
|
+
* Not suitable for multi-instance deployments.
|
|
236
|
+
*/
|
|
237
|
+
declare class MemoryEventTransport implements EventTransport {
|
|
238
|
+
readonly name = "memory";
|
|
239
|
+
private handlers;
|
|
240
|
+
private logger;
|
|
241
|
+
constructor(options?: MemoryEventTransportOptions);
|
|
242
|
+
publish(event: DomainEvent): Promise<void>;
|
|
243
|
+
/**
|
|
244
|
+
* Reference `publishMany` implementation — delegates to `publish()` in order.
|
|
245
|
+
*
|
|
246
|
+
* Production transports (Kafka, Redis pipeline, SQS batch) should override
|
|
247
|
+
* this with a single batched network call. Memory transport has nothing to
|
|
248
|
+
* batch, so we just loop — the loop still returns a proper result map so
|
|
249
|
+
* `EventOutbox.relay` can exercise the batched code path in tests.
|
|
250
|
+
*/
|
|
251
|
+
publishMany(events: readonly DomainEvent[]): Promise<PublishManyResult>;
|
|
252
|
+
subscribe(pattern: string, handler: EventHandler): Promise<() => void>;
|
|
253
|
+
close(): Promise<void>;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Create a domain event with auto-generated metadata.
|
|
257
|
+
*
|
|
258
|
+
* `id` and `timestamp` are filled in; everything else is caller-controlled.
|
|
259
|
+
* Set `schemaVersion` explicitly for any event type you plan to evolve.
|
|
260
|
+
*/
|
|
261
|
+
declare function createEvent<T>(type: string, payload: T, meta?: Partial<EventMeta>): DomainEvent<T>;
|
|
262
|
+
/**
|
|
263
|
+
* Create a child event that chains causation from a parent event.
|
|
264
|
+
*
|
|
265
|
+
* Rules:
|
|
266
|
+
* - `causationId` is set to the parent's `id` (direct cause)
|
|
267
|
+
* - `correlationId` is inherited from the parent if set, else falls back
|
|
268
|
+
* to the parent's `id` (root correlation)
|
|
269
|
+
* - `userId` / `organizationId` are inherited when not overridden so the
|
|
270
|
+
* whole chain stays scoped to the originating principal/tenant
|
|
271
|
+
*
|
|
272
|
+
* Caller-supplied `meta` wins over inherited fields — pass `{ userId: newActor }`
|
|
273
|
+
* to override when a subsystem acts on behalf of a different principal.
|
|
274
|
+
*
|
|
275
|
+
* @example
|
|
276
|
+
* ```typescript
|
|
277
|
+
* const orderPlaced = createEvent('order.placed', { orderId: 'o1' }, {
|
|
278
|
+
* correlationId: req.id, userId: user.id,
|
|
279
|
+
* });
|
|
280
|
+
* await events.publish(orderPlaced);
|
|
281
|
+
*
|
|
282
|
+
* // Downstream handler emits a child event:
|
|
283
|
+
* const reserved = createChildEvent(orderPlaced, 'inventory.reserved', {
|
|
284
|
+
* orderId: 'o1', skus: ['sku-1', 'sku-2'],
|
|
285
|
+
* });
|
|
286
|
+
* // reserved.meta.causationId === orderPlaced.meta.id
|
|
287
|
+
* // reserved.meta.correlationId === orderPlaced.meta.correlationId
|
|
288
|
+
* // reserved.meta.userId === user.id (inherited)
|
|
289
|
+
* ```
|
|
290
|
+
*/
|
|
291
|
+
declare function createChildEvent<T>(parent: DomainEvent, type: string, payload: T, meta?: Partial<EventMeta>): DomainEvent<T>;
|
|
292
|
+
//#endregion
|
|
293
|
+
export { EventMeta as a, MemoryEventTransportOptions as c, createEvent as d, EventLogger as i, PublishManyResult as l, DomainEvent as n, EventTransport as o, EventHandler as r, MemoryEventTransport as s, DeadLetteredEvent as t, createChildEvent as u };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as PrismaQueryParserOptions, c as MongooseAdapterOptions, i as PrismaQueryParser, l as createMongooseAdapter, n as PrismaAdapterOptions, o as createPrismaAdapter, r as PrismaQueryOptions, s as MongooseAdapter, t as PrismaAdapter } from "../index-
|
|
3
|
-
export { AdapterFactory, DataAdapter, FieldMetadata, MongooseAdapter, MongooseAdapterOptions, PrismaAdapter, PrismaAdapterOptions, PrismaQueryOptions, PrismaQueryParser, PrismaQueryParserOptions, RelationMetadata, RepositoryLike, SchemaMetadata, ValidationResult, createMongooseAdapter, createPrismaAdapter };
|
|
1
|
+
import { At as SchemaMetadata, Dt as FieldMetadata, Et as DataAdapter, Ot as RelationMetadata, jt as ValidationResult, kt as RepositoryLike, wt as AdapterFactory } from "../index-Cl0uoKd5.mjs";
|
|
2
|
+
import { a as PrismaQueryParserOptions, c as MongooseAdapterOptions, d as DrizzleAdapterOptions, f as createDrizzleAdapter, i as PrismaQueryParser, l as createMongooseAdapter, n as PrismaAdapterOptions, o as createPrismaAdapter, r as PrismaQueryOptions, s as MongooseAdapter, t as PrismaAdapter, u as DrizzleAdapter } from "../index-DStwgFUK.mjs";
|
|
3
|
+
export { AdapterFactory, DataAdapter, DrizzleAdapter, DrizzleAdapterOptions, FieldMetadata, MongooseAdapter, MongooseAdapterOptions, PrismaAdapter, PrismaAdapterOptions, PrismaQueryOptions, PrismaQueryParser, PrismaQueryParserOptions, RelationMetadata, RepositoryLike, SchemaMetadata, ValidationResult, createDrizzleAdapter, createMongooseAdapter, createPrismaAdapter };
|
package/dist/adapters/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as createMongooseAdapter, i as MongooseAdapter, n as PrismaQueryParser, r as createPrismaAdapter, t as PrismaAdapter } from "../adapters-
|
|
2
|
-
export { MongooseAdapter, PrismaAdapter, PrismaQueryParser, createMongooseAdapter, createPrismaAdapter };
|
|
1
|
+
import { a as createMongooseAdapter, i as MongooseAdapter, n as PrismaQueryParser, o as DrizzleAdapter, r as createPrismaAdapter, s as createDrizzleAdapter, t as PrismaAdapter } from "../adapters-BXY4i-hw.mjs";
|
|
2
|
+
export { DrizzleAdapter, MongooseAdapter, PrismaAdapter, PrismaQueryParser, createDrizzleAdapter, createMongooseAdapter, createPrismaAdapter };
|
|
@@ -1,4 +1,44 @@
|
|
|
1
|
-
import { h as SYSTEM_FIELDS, m as RESERVED_QUERY_PARAMS } from "./constants-
|
|
1
|
+
import { h as SYSTEM_FIELDS, m as RESERVED_QUERY_PARAMS } from "./constants-BhY1OHoH.mjs";
|
|
2
|
+
//#region src/adapters/field-rule-helpers.ts
|
|
3
|
+
/**
|
|
4
|
+
* Merge constraint-style `fieldRules` into an `OpenApiSchemas` bag in place.
|
|
5
|
+
*
|
|
6
|
+
* Operates on the three schema slots that carry property maps — `createBody`,
|
|
7
|
+
* `updateBody`, `response`. `listQuery` and `params` are skipped (their
|
|
8
|
+
* constraint vocabulary is owned by the kit's query parser).
|
|
9
|
+
*
|
|
10
|
+
* Existing constraints on a property always win — the merge only fills in
|
|
11
|
+
* gaps. Adapters that already walk `fieldRules` during base-schema assembly
|
|
12
|
+
* can call this helper for free (the checks are no-ops when constraints
|
|
13
|
+
* already exist).
|
|
14
|
+
*/
|
|
15
|
+
function mergeFieldRuleConstraints(schemas, schemaOptions) {
|
|
16
|
+
if (!schemas || typeof schemas !== "object") return;
|
|
17
|
+
const rules = schemaOptions?.fieldRules;
|
|
18
|
+
if (!rules || Object.keys(rules).length === 0) return;
|
|
19
|
+
for (const slot of [
|
|
20
|
+
"createBody",
|
|
21
|
+
"updateBody",
|
|
22
|
+
"response"
|
|
23
|
+
]) {
|
|
24
|
+
const slotSchema = schemas[slot];
|
|
25
|
+
if (!slotSchema || typeof slotSchema !== "object") continue;
|
|
26
|
+
const properties = slotSchema.properties;
|
|
27
|
+
if (!properties) continue;
|
|
28
|
+
for (const [field, rule] of Object.entries(rules)) {
|
|
29
|
+
const prop = properties[field];
|
|
30
|
+
if (!prop || typeof prop !== "object") continue;
|
|
31
|
+
if (rule.minLength != null && prop.minLength == null) prop.minLength = rule.minLength;
|
|
32
|
+
if (rule.maxLength != null && prop.maxLength == null) prop.maxLength = rule.maxLength;
|
|
33
|
+
if (rule.min != null && prop.minimum == null) prop.minimum = rule.min;
|
|
34
|
+
if (rule.max != null && prop.maximum == null) prop.maximum = rule.max;
|
|
35
|
+
if (rule.pattern != null && prop.pattern == null) prop.pattern = rule.pattern;
|
|
36
|
+
if (rule.enum != null && prop.enum == null) prop.enum = rule.enum;
|
|
37
|
+
if (rule.description != null && prop.description == null) prop.description = rule.description;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
2
42
|
//#region src/adapters/types.ts
|
|
3
43
|
/**
|
|
4
44
|
* Check if value is a Mongoose model
|
|
@@ -13,6 +53,168 @@ function isRepository(value) {
|
|
|
13
53
|
return typeof value === "object" && value !== null && "getAll" in value && "getById" in value && "create" in value && "update" in value && "delete" in value;
|
|
14
54
|
}
|
|
15
55
|
//#endregion
|
|
56
|
+
//#region src/adapters/drizzle.ts
|
|
57
|
+
const DRIZZLE_COLUMNS_SYMBOL = Symbol.for("drizzle:Columns");
|
|
58
|
+
function getColumns(table) {
|
|
59
|
+
const cols = table[DRIZZLE_COLUMNS_SYMBOL];
|
|
60
|
+
if (!cols || typeof cols !== "object") return {};
|
|
61
|
+
return cols;
|
|
62
|
+
}
|
|
63
|
+
function columnToJsonSchema(column) {
|
|
64
|
+
const { dataType, columnType, enumValues, length } = column;
|
|
65
|
+
if (dataType === "date") return {
|
|
66
|
+
type: "string",
|
|
67
|
+
format: "date-time"
|
|
68
|
+
};
|
|
69
|
+
if (dataType === "boolean") return { type: "boolean" };
|
|
70
|
+
if (dataType === "json") return {
|
|
71
|
+
type: "object",
|
|
72
|
+
additionalProperties: true
|
|
73
|
+
};
|
|
74
|
+
if (dataType === "buffer") return {
|
|
75
|
+
type: "string",
|
|
76
|
+
contentEncoding: "base64"
|
|
77
|
+
};
|
|
78
|
+
if (dataType === "number" || dataType === "bigint") return { type: columnType === "SQLiteInteger" ? "integer" : "number" };
|
|
79
|
+
if (dataType === "string") {
|
|
80
|
+
const result = { type: "string" };
|
|
81
|
+
if (Array.isArray(enumValues) && enumValues.length > 0) result.enum = [...enumValues];
|
|
82
|
+
if (typeof length === "number" && length > 0) result.maxLength = length;
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
return {};
|
|
86
|
+
}
|
|
87
|
+
function columnToFieldMetadata(column) {
|
|
88
|
+
const { dataType, enumValues } = column;
|
|
89
|
+
const meta = {
|
|
90
|
+
type: (dataType && {
|
|
91
|
+
number: "number",
|
|
92
|
+
bigint: "number",
|
|
93
|
+
string: "string",
|
|
94
|
+
date: "date",
|
|
95
|
+
boolean: "boolean",
|
|
96
|
+
json: "object",
|
|
97
|
+
buffer: "object"
|
|
98
|
+
}[dataType]) ?? (enumValues?.length ? "enum" : "object"),
|
|
99
|
+
required: !!column.notNull && !column.hasDefault
|
|
100
|
+
};
|
|
101
|
+
if (enumValues?.length) meta.enum = [...enumValues];
|
|
102
|
+
if (typeof column.length === "number") meta.maxLength = column.length;
|
|
103
|
+
return meta;
|
|
104
|
+
}
|
|
105
|
+
var DrizzleAdapter = class {
|
|
106
|
+
type = "drizzle";
|
|
107
|
+
name;
|
|
108
|
+
table;
|
|
109
|
+
repository;
|
|
110
|
+
schemaGenerator;
|
|
111
|
+
constructor(options) {
|
|
112
|
+
if (!options.table || typeof options.table !== "object") throw new TypeError("DrizzleAdapter: Invalid table. Expected a Drizzle table created with sqliteTable / pgTable / mysqlTable.");
|
|
113
|
+
if (!isRepository(options.repository)) throw new TypeError("DrizzleAdapter: Invalid repository. Expected an object implementing MinimalRepo (getAll / getById / create / update / delete).");
|
|
114
|
+
this.table = options.table;
|
|
115
|
+
this.repository = options.repository;
|
|
116
|
+
this.schemaGenerator = options.schemaGenerator;
|
|
117
|
+
this.name = options.name ?? "DrizzleAdapter";
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Introspect Drizzle columns into arc's schema metadata shape.
|
|
121
|
+
*/
|
|
122
|
+
getSchemaMetadata() {
|
|
123
|
+
const columns = getColumns(this.table);
|
|
124
|
+
const fields = {};
|
|
125
|
+
const indexes = [];
|
|
126
|
+
for (const [name, column] of Object.entries(columns)) {
|
|
127
|
+
fields[name] = columnToFieldMetadata(column);
|
|
128
|
+
if (column.primary) indexes.push({
|
|
129
|
+
fields: [name],
|
|
130
|
+
unique: true
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
name: this.name,
|
|
135
|
+
fields,
|
|
136
|
+
...indexes.length > 0 ? { indexes } : {}
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Generate OpenAPI schemas. Delegates to the user-provided
|
|
141
|
+
* `schemaGenerator` when available (strongly recommended — that's where
|
|
142
|
+
* field rules, omit lists, and param-type narrowing live). The built-in
|
|
143
|
+
* fallback emits a permissive entity + CRUD body shape so routes still
|
|
144
|
+
* register when no generator is provided.
|
|
145
|
+
*
|
|
146
|
+
* After the kit generator runs, arc merges constraint-style field rules
|
|
147
|
+
* (`minLength`, `maxLength`, `min`, `max`, `pattern`, `enum`, `description`)
|
|
148
|
+
* into the resulting property schemas so sqlitekit / pgkit behave
|
|
149
|
+
* identically to mongoose here — rule-driven AJV constraints apply
|
|
150
|
+
* regardless of backend.
|
|
151
|
+
*/
|
|
152
|
+
generateSchemas(schemaOptions, context) {
|
|
153
|
+
try {
|
|
154
|
+
if (this.schemaGenerator) {
|
|
155
|
+
const generated = this.schemaGenerator(this.table, schemaOptions, context);
|
|
156
|
+
mergeFieldRuleConstraints(generated, schemaOptions);
|
|
157
|
+
return generated;
|
|
158
|
+
}
|
|
159
|
+
const columns = getColumns(this.table);
|
|
160
|
+
if (Object.keys(columns).length === 0) return null;
|
|
161
|
+
const entityProperties = {};
|
|
162
|
+
const inputProperties = {};
|
|
163
|
+
const inputRequired = [];
|
|
164
|
+
const updateProperties = {};
|
|
165
|
+
const fieldRules = schemaOptions?.fieldRules ?? {};
|
|
166
|
+
const readonlySet = new Set(schemaOptions?.readonlyFields ?? []);
|
|
167
|
+
const optionalSet = new Set(schemaOptions?.optionalFields ?? []);
|
|
168
|
+
const blocked = new Set([
|
|
169
|
+
...Object.entries(fieldRules).filter(([, rules]) => rules.systemManaged || rules.hidden).map(([field]) => field),
|
|
170
|
+
...schemaOptions?.excludeFields ?? [],
|
|
171
|
+
...schemaOptions?.hiddenFields ?? []
|
|
172
|
+
]);
|
|
173
|
+
for (const [fieldName, column] of Object.entries(columns)) {
|
|
174
|
+
const schema = columnToJsonSchema(column);
|
|
175
|
+
entityProperties[fieldName] = schema;
|
|
176
|
+
if (blocked.has(fieldName)) continue;
|
|
177
|
+
if (column.primary && column.columnType === "SQLiteInteger") continue;
|
|
178
|
+
if (!readonlySet.has(fieldName)) {
|
|
179
|
+
inputProperties[fieldName] = schema;
|
|
180
|
+
if (!!column.notNull && !column.hasDefault && !optionalSet.has(fieldName)) inputRequired.push(fieldName);
|
|
181
|
+
updateProperties[fieldName] = schema;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
createBody: {
|
|
186
|
+
type: "object",
|
|
187
|
+
properties: inputProperties,
|
|
188
|
+
required: inputRequired.length > 0 ? inputRequired : void 0,
|
|
189
|
+
additionalProperties: true
|
|
190
|
+
},
|
|
191
|
+
updateBody: {
|
|
192
|
+
type: "object",
|
|
193
|
+
properties: updateProperties,
|
|
194
|
+
additionalProperties: true
|
|
195
|
+
},
|
|
196
|
+
response: {
|
|
197
|
+
type: "object",
|
|
198
|
+
properties: entityProperties,
|
|
199
|
+
additionalProperties: true
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
} catch {
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
async healthCheck() {
|
|
207
|
+
return typeof this.repository.getAll === "function";
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
/**
|
|
211
|
+
* Factory — preferred construction style for symmetry with
|
|
212
|
+
* `createMongooseAdapter` / `createPrismaAdapter`.
|
|
213
|
+
*/
|
|
214
|
+
function createDrizzleAdapter(options) {
|
|
215
|
+
return new DrizzleAdapter(options);
|
|
216
|
+
}
|
|
217
|
+
//#endregion
|
|
16
218
|
//#region src/adapters/mongoose.ts
|
|
17
219
|
/**
|
|
18
220
|
* Mongoose data adapter with proper type safety
|
|
@@ -27,7 +229,7 @@ var MongooseAdapter = class {
|
|
|
27
229
|
schemaGenerator;
|
|
28
230
|
constructor(options) {
|
|
29
231
|
if (!isMongooseModel(options.model)) throw new TypeError("MongooseAdapter: Invalid model. Expected Mongoose Model instance.\nUsage: createMongooseAdapter({ model: YourModel, repository: yourRepo })");
|
|
30
|
-
if (!isRepository(options.repository)) throw new TypeError("MongooseAdapter: Invalid repository. Expected
|
|
232
|
+
if (!isRepository(options.repository)) throw new TypeError("MongooseAdapter: Invalid repository. Expected StandardRepo instance.\nUsage: createMongooseAdapter({ model: YourModel, repository: yourRepo })");
|
|
31
233
|
this.model = options.model;
|
|
32
234
|
this.repository = options.repository;
|
|
33
235
|
this.schemaGenerator = options.schemaGenerator;
|
|
@@ -73,7 +275,11 @@ var MongooseAdapter = class {
|
|
|
73
275
|
*/
|
|
74
276
|
generateSchemas(schemaOptions, context) {
|
|
75
277
|
try {
|
|
76
|
-
if (this.schemaGenerator)
|
|
278
|
+
if (this.schemaGenerator) {
|
|
279
|
+
const generated = this.schemaGenerator(this.model, schemaOptions, context);
|
|
280
|
+
mergeFieldRuleConstraints(generated, schemaOptions);
|
|
281
|
+
return generated;
|
|
282
|
+
}
|
|
77
283
|
const paths = this.model.schema.paths;
|
|
78
284
|
const properties = {};
|
|
79
285
|
const required = [];
|
|
@@ -242,43 +448,6 @@ function createMongooseAdapter(modelOrOptions, repository) {
|
|
|
242
448
|
//#endregion
|
|
243
449
|
//#region src/adapters/prisma.ts
|
|
244
450
|
/**
|
|
245
|
-
* Prisma Adapter - PostgreSQL/MySQL/SQLite Implementation
|
|
246
|
-
*
|
|
247
|
-
* @experimental This adapter is implemented but has no integration tests yet.
|
|
248
|
-
* Use in production at your own risk. The Mongoose adapter is the recommended
|
|
249
|
-
* and battle-tested path.
|
|
250
|
-
*
|
|
251
|
-
* Bridges Prisma Client with Arc's DataAdapter interface.
|
|
252
|
-
* Supports Prisma 5+ with all database providers.
|
|
253
|
-
*
|
|
254
|
-
* Implemented features:
|
|
255
|
-
* - Schema generation (OpenAPI docs from DMMF)
|
|
256
|
-
* - Health checks (database connectivity)
|
|
257
|
-
* - Query parsing (URL params → Prisma where/orderBy)
|
|
258
|
-
* - Policy filter translation
|
|
259
|
-
* - Soft delete preset support
|
|
260
|
-
*
|
|
261
|
-
* Known gaps:
|
|
262
|
-
* - No integration test coverage
|
|
263
|
-
* - Multi-tenant isolation relies on caller-provided policyFilters (no auto-enforcement)
|
|
264
|
-
*
|
|
265
|
-
* @example
|
|
266
|
-
* ```typescript
|
|
267
|
-
* import { PrismaClient, Prisma } from '@prisma/client';
|
|
268
|
-
* import { createPrismaAdapter, PrismaQueryParser } from '@classytic/arc/adapters';
|
|
269
|
-
*
|
|
270
|
-
* const prisma = new PrismaClient();
|
|
271
|
-
*
|
|
272
|
-
* const userAdapter = createPrismaAdapter({
|
|
273
|
-
* client: prisma,
|
|
274
|
-
* modelName: 'user',
|
|
275
|
-
* repository: new UserRepository(prisma),
|
|
276
|
-
* dmmf: Prisma.dmmf, // For schema generation
|
|
277
|
-
* queryParser: new PrismaQueryParser(), // Optional: custom parser
|
|
278
|
-
* });
|
|
279
|
-
* ```
|
|
280
|
-
*/
|
|
281
|
-
/**
|
|
282
451
|
* Prisma Query Parser - Converts URL parameters to Prisma query format
|
|
283
452
|
*
|
|
284
453
|
* Translates Arc's query format to Prisma's where/orderBy/take/skip structure.
|
|
@@ -723,4 +892,4 @@ function createPrismaAdapter(options) {
|
|
|
723
892
|
return new PrismaAdapter(options);
|
|
724
893
|
}
|
|
725
894
|
//#endregion
|
|
726
|
-
export { createMongooseAdapter as a, MongooseAdapter as i, PrismaQueryParser as n, createPrismaAdapter as r, PrismaAdapter as t };
|
|
895
|
+
export { createMongooseAdapter as a, MongooseAdapter as i, PrismaQueryParser as n, DrizzleAdapter as o, createPrismaAdapter as r, createDrizzleAdapter as s, PrismaAdapter as t };
|