@voltro/runtime 0.84.0 → 0.86.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 (160) hide show
  1. package/CHANGELOG.md +1215 -0
  2. package/THIRD-PARTY-NOTICES.md +118 -600
  3. package/dist/aggregate.js +42 -0
  4. package/dist/aggregateExtrema.js +80 -0
  5. package/dist/aggregateIvm.js +115 -0
  6. package/dist/analyticsMirror.js +228 -0
  7. package/dist/analyticsSink.js +38 -0
  8. package/dist/apiKeyUsage.js +33 -0
  9. package/dist/apiKeys.js +223 -0
  10. package/dist/apiKeysWiring.js +114 -0
  11. package/dist/approvalBuiltins.js +10 -0
  12. package/dist/approvals.js +269 -0
  13. package/dist/authMiddlewareLayer.js +47 -0
  14. package/dist/bindEvent.js +72 -0
  15. package/dist/bootListener.js +76 -0
  16. package/dist/bootRefusal.js +7 -0
  17. package/dist/bootStoreCodec.js +70 -0
  18. package/dist/businessRules.js +67 -0
  19. package/dist/changeClaimsTable.js +12 -0
  20. package/dist/circuitBreaker.js +72 -0
  21. package/dist/columnOnUpdate.js +23 -0
  22. package/dist/composeAnalytics.js +108 -0
  23. package/dist/computedQuery.js +4 -0
  24. package/dist/connectionBuiltins.js +81 -0
  25. package/dist/connectionCredentials.js +66 -0
  26. package/dist/connectionState.js +34 -0
  27. package/dist/connectionVault.js +410 -0
  28. package/dist/connectionsFacade.js +54 -0
  29. package/dist/coordinatedSchedule.js +139 -0
  30. package/dist/crdtHistory.js +138 -0
  31. package/dist/crdtMerge.js +179 -0
  32. package/dist/crdtVersionsTable.js +25 -0
  33. package/dist/credentialBound.js +12 -0
  34. package/dist/crud.js +72 -0
  35. package/dist/dataStore.js +679 -0
  36. package/dist/dataloader.js +61 -0
  37. package/dist/declaredTablesGuard.js +48 -0
  38. package/dist/defineExecutor.js +4 -0
  39. package/dist/dependencyGraph.js +32 -0
  40. package/dist/devices.js +228 -0
  41. package/dist/devicesWiring.js +168 -0
  42. package/dist/dialectReplicationAdapter.js +29 -0
  43. package/dist/dispatcher.js +447 -0
  44. package/dist/effectStore.js +71 -0
  45. package/dist/eventBus.js +260 -0
  46. package/dist/eventPublish.js +49 -0
  47. package/dist/events.js +193 -0
  48. package/dist/expectation.js +52 -0
  49. package/dist/expectationEvaluator.js +308 -0
  50. package/dist/experiment.js +96 -0
  51. package/dist/experimentEvaluator.js +245 -0
  52. package/dist/externalizedTasks.js +25 -0
  53. package/dist/fieldCipher.js +61 -0
  54. package/dist/fingerprint.js +21 -0
  55. package/dist/finops.js +42 -0
  56. package/dist/finopsAccountant.js +216 -0
  57. package/dist/handlerBody.js +8 -0
  58. package/dist/healthProbes.js +55 -0
  59. package/dist/httpClientSsrf.js +49 -0
  60. package/dist/httpClientTracing.js +11 -0
  61. package/dist/httpCompression.js +76 -0
  62. package/dist/httpKeepAlive.js +12 -0
  63. package/dist/httpRouteMounts.js +47 -0
  64. package/dist/idempotencyStore.js +70 -0
  65. package/dist/idleDetector.js +21 -0
  66. package/dist/index.d.ts +252 -233
  67. package/dist/index.js +144 -14405
  68. package/dist/insertRequiredColumns.js +19 -0
  69. package/dist/inspectWorkflow.js +1 -0
  70. package/dist/instanceMembership.js +98 -0
  71. package/dist/ivm.js +125 -0
  72. package/dist/kvDataStore.js +86 -0
  73. package/dist/kvFacade.js +32 -0
  74. package/dist/matcher.js +304 -0
  75. package/dist/memoryColumnDefaults.js +11 -0
  76. package/dist/memoryQueryJoins.js +114 -0
  77. package/dist/metrics.js +161 -0
  78. package/dist/observability.js +123 -0
  79. package/dist/observedGraph.js +52 -0
  80. package/dist/originGuard.js +116 -0
  81. package/dist/outbox.js +352 -0
  82. package/dist/pluginRefRules.js +65 -0
  83. package/dist/policyGuardResolver.js +55 -0
  84. package/dist/preview.js +62 -0
  85. package/dist/projectedRows.js +12 -0
  86. package/dist/provenance.js +63 -0
  87. package/dist/rangeIndex.js +89 -0
  88. package/dist/rawReadScope.js +17 -0
  89. package/dist/reaction.js +85 -0
  90. package/dist/reactiveConfig.js +11 -0
  91. package/dist/readClassification.js +57 -0
  92. package/dist/readRecorder.js +66 -0
  93. package/dist/rebac.js +104 -0
  94. package/dist/rebacInterceptor.js +81 -0
  95. package/dist/registry.js +29 -0
  96. package/dist/relevantFields.js +65 -0
  97. package/dist/replicaHealth.js +42 -0
  98. package/dist/replicaLocality.js +44 -0
  99. package/dist/replicaObservations.js +121 -0
  100. package/dist/replicaSelection.js +32 -0
  101. package/dist/replicatedDataStore.js +239 -0
  102. package/dist/requestLoader.js +7 -0
  103. package/dist/resumeCensus.js +28 -0
  104. package/dist/revalidation.js +22 -0
  105. package/dist/rowFilter.js +65 -0
  106. package/dist/rowStateBytes.js +45 -0
  107. package/dist/rpcBodyCap.js +63 -0
  108. package/dist/rpcConnections.js +83 -0
  109. package/dist/rpcDefectDiagnostics.js +15 -0
  110. package/dist/rpcServer.js +992 -0
  111. package/dist/runAsSystem.js +23 -0
  112. package/dist/rywPositionStore.js +84 -0
  113. package/dist/schedule.js +23 -0
  114. package/dist/scheduleBackfillRequests.js +151 -0
  115. package/dist/scheduleClaimsTable.js +11 -0
  116. package/dist/scheduleRunsTable.js +37 -0
  117. package/dist/scheduler.js +835 -0
  118. package/dist/schemaRegistry.js +65 -0
  119. package/dist/secretsResolver.js +35 -0
  120. package/dist/securityHeaders.js +33 -0
  121. package/dist/servePipeline.js +305 -0
  122. package/dist/serverOnlyAudit.js +66 -0
  123. package/dist/serverTracer.js +15 -0
  124. package/dist/serviceCredentials.js +40 -0
  125. package/dist/singleNodeOrchestrator.js +91 -0
  126. package/dist/sourceResolution.js +42 -0
  127. package/dist/storeMiddleware.js +880 -0
  128. package/dist/storeQuery.js +204 -0
  129. package/dist/storeRead.js +10 -0
  130. package/dist/subscriber.js +7 -0
  131. package/dist/subscriptionOutbox.js +139 -0
  132. package/dist/subscriptionRegistry.js +82 -0
  133. package/dist/subscriptionResume.js +132 -0
  134. package/dist/subscriptionSocketMetrics.js +65 -0
  135. package/dist/systemSubject.js +5 -0
  136. package/dist/tenantScope.js +23 -0
  137. package/dist/tenantSelection.js +27 -0
  138. package/dist/timeline.js +105 -0
  139. package/dist/traceContext.js +5 -0
  140. package/dist/traceSink.js +63 -0
  141. package/dist/traceSpansTable.js +29 -0
  142. package/dist/traceparent.js +34 -0
  143. package/dist/transactionSubject.js +12 -0
  144. package/dist/trustedProxy.js +155 -0
  145. package/dist/undo.js +129 -0
  146. package/dist/undoBuiltins.js +69 -0
  147. package/dist/undoCapture.js +74 -0
  148. package/dist/undoLogTable.js +16 -0
  149. package/dist/upsertBinding.js +20 -0
  150. package/dist/wakeOrchestrator.js +34 -0
  151. package/dist/wakeRegistry.js +71 -0
  152. package/dist/wakeRouter.js +63 -0
  153. package/dist/wakeSupervisor.js +62 -0
  154. package/dist/wakeupsTable.js +12 -0
  155. package/dist/webSocketGatewayRuntime.js +114 -0
  156. package/dist/webhookVerification.js +18 -0
  157. package/dist/wireColumnStrip.js +84 -0
  158. package/dist/workflowReadBuiltins.js +87 -0
  159. package/dist/workflowRuntime.js +708 -0
  160. package/package.json +10 -13
@@ -0,0 +1,447 @@
1
+ import { IndexedMatcher as e } from "./matcher.js";
2
+ import { canonicalize as t } from "./fingerprint.js";
3
+ import { SubscriptionRegistry as n } from "./subscriptionRegistry.js";
4
+ import { resolveReactiveConfig as r } from "./reactiveConfig.js";
5
+ import { currentRawReads as i, runWithRawReadScope as a } from "./rawReadScope.js";
6
+ import { crdtIncrementalCell as o } from "./crdtMerge.js";
7
+ import { resolveDependentTables as s } from "./dependencyGraph.js";
8
+ import { isEventRelevant as c, resolveRelevantFields as l } from "./relevantFields.js";
9
+ import { recordSubscriptionActive as u } from "./metrics.js";
10
+ import { applyRowFilterToDescriptor as d, rowFilterRegistered as f } from "./rowFilter.js";
11
+ import { createDispatchWireStrip as p, stripForbiddenForWire as m } from "./wireColumnStrip.js";
12
+ import { buildSubjectKey as h } from "./rywPositionStore.js";
13
+ import { runWithRoutingContext as g } from "./replicatedDataStore.js";
14
+ import { committedChangeBatchOf as _ } from "@voltro/database";
15
+ import { randomUUID as v } from "node:crypto";
16
+ import { diffRows as y, isIdKeyed as b } from "@voltro/protocol";
17
+ import { createLogger as x } from "@voltro/logger";
18
+ //#region src/dispatcher.ts
19
+ var S = /* @__PURE__ */ new Set(), C = x({ scope: "voltro:dispatcher" }), w = (e) => Array.isArray(e) ? e.length : e == null ? 0 : 1, T = (e) => typeof e == "object" && !!e && (e._tag === "ScopeError" || e._tag === "Unauthenticated" || e._tag === "RequestedTenantRefused"), E = 1e3, D = 3e4, O = Object.freeze({
20
+ _tag: "QueryRecomputeFailed",
21
+ message: "The live query could not be refreshed. Retrying automatically."
22
+ }), k = class {
23
+ deps;
24
+ subscriptionRegistry;
25
+ matcher;
26
+ subscriptions = /* @__PURE__ */ new Map();
27
+ unsubscribeChange;
28
+ dependentByTable = /* @__PURE__ */ new Map();
29
+ computedSubs = /* @__PURE__ */ new Map();
30
+ computedByTable = /* @__PURE__ */ new Map();
31
+ reactive;
32
+ rawReadWarned = /* @__PURE__ */ new Set();
33
+ changeEpoch = 0;
34
+ committedReads = /* @__PURE__ */ new WeakMap();
35
+ crdtColumnsFor(e) {
36
+ return this.deps.crdtColumnsOf?.(e) ?? S;
37
+ }
38
+ constructor(t) {
39
+ this.deps = t, this.matcher = new e(), this.subscriptionRegistry = new n(this.matcher), this.reactive = r(t.reactive), this.unsubscribeChange = t.store.onChange((e) => {
40
+ let t = _(e), n = t === void 0 ? void 0 : this.committedReads.get(t);
41
+ n === void 0 && (this.changeEpoch++, t !== void 0 && (n = {
42
+ epoch: this.changeEpoch,
43
+ reads: /* @__PURE__ */ new Map()
44
+ }, this.committedReads.set(t, n))), this.handleChange(e, !1, n);
45
+ });
46
+ }
47
+ warnUndeclaredRawReads(e, t) {
48
+ if (t.length !== 0 && !this.rawReadWarned.has(e)) {
49
+ this.rawReadWarned.add(e);
50
+ for (let n of t) C.warn(`${e}: a raw SQL read in this live query declares no dependsOn, so no write can invalidate it — every subscriber keeps its first result until it reconnects. Declare the tables it reads: ctx.store.raw(fragment, { dependsOn: ['orders'] }) — or on the fragment itself. The read: ${n.sql}`, {
51
+ label: e,
52
+ sql: n.sql
53
+ });
54
+ }
55
+ }
56
+ async subscribe(e, t, n, r, a, o, c, p, _ = !1) {
57
+ let y = `sub_${v()}`, b = a ?? `subscription.${e.table}`, x = s(e);
58
+ if (p === void 0 && f()) throw Error(`subscription "${b}" was opened without a row-filter resolver while a row filter is registered — this would read every row the filter exists to hide. Pass the resolver from \`makeDefaultRefilter(subject)\`, or pass one returning \`NO_ROW_FILTER\` to read unfiltered deliberately.`);
59
+ let S = l(e);
60
+ e.predicate !== void 0 && this.subscriptionRegistry.subscribe(y, e.table, e.predicate, r);
61
+ let C = e.predicate !== void 0 && (e.dependentTables?.length ?? 0) === 0 && e.eager === void 0 && e.setOp === void 0 && e.ctes === void 0 && e.alias === void 0 && (e.joins?.length ?? 0) === 0 && x.size === 1 && x.has(e.table);
62
+ for (let t of x) {
63
+ if (C && t === e.table) continue;
64
+ let n = this.dependentByTable.get(t);
65
+ n === void 0 && (n = /* @__PURE__ */ new Set(), this.dependentByTable.set(t, n)), n.add(y);
66
+ }
67
+ let w = Date.now(), T = Array.from(x), E = () => {
68
+ this.subscriptionRegistry.unsubscribe(y);
69
+ for (let e of x) {
70
+ let t = this.dependentByTable.get(e);
71
+ t !== void 0 && (t.delete(y), t.size === 0 && this.dependentByTable.delete(e));
72
+ }
73
+ }, D, O;
74
+ try {
75
+ D = p === void 0 ? e : d(await p(), e);
76
+ let t = _ ? await g({
77
+ subjectKey: h(n.subject.id, n.clientId),
78
+ forcePrimary: !0
79
+ }, () => this.deps.store.query(D)) : this.deps.cache !== void 0 && o !== void 0 ? await this.deps.cache.wrap(o, T, () => this.deps.store.query(D)) : await this.deps.store.query(D);
80
+ if (c !== void 0) {
81
+ let e = await c();
82
+ if (e) throw e;
83
+ }
84
+ O = m(D.table, t, n.subject);
85
+ } catch (e) {
86
+ throw E(), e;
87
+ }
88
+ this.warnUndeclaredRawReads(b, i().filter((e) => e.dependsOn.length === 0)), this.subscriptions.set(y, {
89
+ id: y,
90
+ descriptor: D,
91
+ baseDescriptor: e,
92
+ context: n,
93
+ emit: t,
94
+ label: b,
95
+ dependentTables: x,
96
+ relevantFields: S,
97
+ lastDelivered: O,
98
+ cacheBinding: o,
99
+ readFromPrimary: _,
100
+ reauthorize: c,
101
+ refilter: p,
102
+ memoKey: void 0
103
+ }), u(b, 1), t({
104
+ _tag: "snapshot",
105
+ revision: 0,
106
+ data: O
107
+ });
108
+ let k = Date.now();
109
+ return this.deps.recordDelivery?.({
110
+ traceId: n.traceId,
111
+ parentSpanId: n.spanId,
112
+ label: b,
113
+ kind: "snapshot",
114
+ startMs: w,
115
+ endMs: k,
116
+ durationMs: k - w,
117
+ rowCount: O.length
118
+ }), () => {
119
+ this.subscriptions.delete(y), u(b, -1), E();
120
+ };
121
+ }
122
+ revokeSubscription(e, t, n = "guards no longer satisfied") {
123
+ this.subscriptions.delete(e.id), u(e.label, -1), this.subscriptionRegistry.unsubscribe(e.id);
124
+ for (let t of e.dependentTables) {
125
+ let n = this.dependentByTable.get(t);
126
+ n !== void 0 && (n.delete(e.id), n.size === 0 && this.dependentByTable.delete(t));
127
+ }
128
+ C.warn(`subscription revoked mid-stream — ${n}`, {
129
+ id: e.id,
130
+ label: e.label,
131
+ traceId: e.context.traceId
132
+ }), e.emit({
133
+ _tag: "error",
134
+ error: t
135
+ });
136
+ }
137
+ removeComputed(e) {
138
+ if (this.computedSubs.get(e.id) !== e) return !1;
139
+ this.computedSubs.delete(e.id), e.retryTimer !== void 0 && clearTimeout(e.retryTimer), e.retryTimer = void 0, u(e.label, -1);
140
+ for (let t of e.tables) {
141
+ let n = this.computedByTable.get(t);
142
+ n !== void 0 && (n.delete(e.id), n.size === 0 && this.computedByTable.delete(t));
143
+ }
144
+ return !0;
145
+ }
146
+ revokeComputed(e, t) {
147
+ this.removeComputed(e) && (C.warn("computed subscription revoked mid-stream — guards no longer satisfied", {
148
+ id: e.id,
149
+ label: e.label,
150
+ traceId: e.context.traceId
151
+ }), e.emit({
152
+ _tag: "error",
153
+ error: t
154
+ }));
155
+ }
156
+ async subscribeComputed(e, t, n, r) {
157
+ let o = `csub_${v()}`, s = r ?? "subscription.computed", c = i(), l = new Set(e.dependentTables);
158
+ for (let e of c) for (let t of e.dependsOn) l.add(t);
159
+ let d = Array.from(l);
160
+ this.warnUndeclaredRawReads(s, c.filter((e) => e.dependsOn.length === 0));
161
+ let f = {
162
+ id: o,
163
+ recompute: () => a(e.recompute),
164
+ tenantId: e.tenantId,
165
+ emit: t,
166
+ context: n,
167
+ label: s,
168
+ tables: d,
169
+ lastJson: A(e.value),
170
+ revision: 0,
171
+ failed: !1,
172
+ retryAttempts: 0,
173
+ retryTimer: void 0,
174
+ running: !1,
175
+ rerunRequested: !1
176
+ };
177
+ this.computedSubs.set(o, f), u(f.label, 1);
178
+ for (let e of d) {
179
+ let t = this.computedByTable.get(e);
180
+ t === void 0 && (t = /* @__PURE__ */ new Set(), this.computedByTable.set(e, t)), t.add(o);
181
+ }
182
+ let p = Date.now();
183
+ return t({
184
+ _tag: "snapshot",
185
+ revision: 0,
186
+ data: e.value
187
+ }), this.deps.recordDelivery?.({
188
+ traceId: n.traceId,
189
+ parentSpanId: n.spanId,
190
+ label: f.label,
191
+ kind: "snapshot",
192
+ startMs: p,
193
+ endMs: Date.now(),
194
+ durationMs: Date.now() - p,
195
+ rowCount: w(e.value)
196
+ }), () => {
197
+ this.removeComputed(f);
198
+ };
199
+ }
200
+ async recomputeComputed(e) {
201
+ if (this.computedSubs.get(e.id) === e) {
202
+ if (e.running) e.rerunRequested = !0;
203
+ else {
204
+ e.retryTimer !== void 0 && clearTimeout(e.retryTimer), e.retryTimer = void 0, e.running = !0;
205
+ try {
206
+ do {
207
+ e.rerunRequested = !1;
208
+ let t = Date.now(), n = await e.recompute();
209
+ if (this.computedSubs.get(e.id) !== e) return;
210
+ if (e.rerunRequested) continue;
211
+ let r = A(n), i = e.failed;
212
+ if (e.failed = !1, e.retryAttempts = 0, r === e.lastJson && !i) return;
213
+ e.lastJson = r, e.revision += 1;
214
+ let a = Date.now();
215
+ e.emit({
216
+ _tag: "snapshot",
217
+ revision: e.revision,
218
+ data: n
219
+ }), this.deps.recordDelivery?.({
220
+ traceId: e.context.traceId,
221
+ parentSpanId: e.context.spanId,
222
+ label: e.label,
223
+ kind: "delta",
224
+ startMs: t,
225
+ endMs: a,
226
+ durationMs: a - t,
227
+ rowCount: w(n)
228
+ }), this.deps.recordCost !== void 0 && this.deps.recordCost({
229
+ tenantId: e.tenantId,
230
+ subscriptionId: e.id,
231
+ unit: "recompute",
232
+ amount: 1,
233
+ traceId: e.context.traceId
234
+ });
235
+ } while (e.rerunRequested);
236
+ } catch (t) {
237
+ if (this.computedSubs.get(e.id) !== e) return;
238
+ if (T(t)) {
239
+ this.revokeComputed(e, t);
240
+ return;
241
+ }
242
+ e.failed || (e.failed = !0, e.emit({
243
+ _tag: "error",
244
+ error: O
245
+ }), C.warn("computed recompute failed; retrying with last value marked stale", {
246
+ id: e.id,
247
+ label: e.label,
248
+ traceId: e.context.traceId
249
+ }, t));
250
+ let n = Math.min(D, E * 2 ** Math.min(e.retryAttempts, 5));
251
+ if (e.retryAttempts += 1, this.computedSubs.get(e.id) !== e) return;
252
+ e.retryTimer = setTimeout(() => {
253
+ e.retryTimer = void 0, this.recomputeComputed(e);
254
+ }, n), e.retryTimer.unref();
255
+ } finally {
256
+ e.running = !1;
257
+ }
258
+ }
259
+ }
260
+ }
261
+ subscriptionSnapshot() {
262
+ return this.subscriptionRegistry.snapshot();
263
+ }
264
+ matcherStats() {
265
+ return this.matcher.stats?.() ?? { perTable: [] };
266
+ }
267
+ onSubscriptionsChange(e) {
268
+ return this.subscriptionRegistry.onChange(e);
269
+ }
270
+ close() {
271
+ this.unsubscribeChange();
272
+ for (let e of this.computedSubs.values()) this.removeComputed(e);
273
+ }
274
+ async refreshAll(e) {
275
+ let t = /* @__PURE__ */ new Set();
276
+ for (let e of this.subscriptions.values()) t.add(e.descriptor.table);
277
+ for (let e of this.computedByTable.keys()) t.add(e);
278
+ if (t.size !== 0) {
279
+ C.warn("refreshing every live subscription", {
280
+ reason: e,
281
+ tables: t.size,
282
+ subscriptions: this.subscriptions.size
283
+ });
284
+ for (let e of t) await this.handleChange({
285
+ table: e,
286
+ op: "insert",
287
+ new: {},
288
+ old: void 0
289
+ }, !0);
290
+ }
291
+ }
292
+ async handleChange(e, n = !1, r) {
293
+ n && this.changeEpoch++;
294
+ let i = this.computedByTable.get(e.table);
295
+ if (i !== void 0 && i.size > 0) for (let e of i) {
296
+ let t = this.computedSubs.get(e);
297
+ t !== void 0 && this.recomputeComputed(t);
298
+ }
299
+ let a = n || e.oversized === "tombstone" || e.oversized === "unrecovered", s = a ? [] : this.subscriptionRegistry.notify(e), l = /* @__PURE__ */ new Set();
300
+ for (let e of s) l.add(e.subscriberId);
301
+ if (a) for (let [t, n] of this.subscriptions) n.descriptor.table === e.table && l.add(t);
302
+ let u = this.dependentByTable.get(e.table);
303
+ if (u !== void 0) for (let e of u) l.add(e);
304
+ if (C.trace("handleChange", {
305
+ table: e.table,
306
+ op: e.op,
307
+ matcher: s.length,
308
+ dependent: u?.size ?? 0,
309
+ triggered: l.size
310
+ }), l.size === 0) return;
311
+ let f = Date.now(), _ = 0, v = /* @__PURE__ */ new Map(), x = l.size > 1 ? p() : void 0, w = /* @__PURE__ */ new Map(), T = /* @__PURE__ */ new Map(), E = async (i) => {
312
+ let a = this.subscriptions.get(i);
313
+ if (!a) {
314
+ C.trace("missing subscription", { subscriberId: i });
315
+ return;
316
+ }
317
+ if (!n && !c(e, a.relevantFields)) {
318
+ _++;
319
+ return;
320
+ }
321
+ let s = Date.now();
322
+ try {
323
+ if (a.reauthorize !== void 0) {
324
+ let e = await a.reauthorize();
325
+ if (e) {
326
+ this.revokeSubscription(a, e);
327
+ return;
328
+ }
329
+ }
330
+ let n, c;
331
+ if (a.refilter === void 0) n = a.descriptor, a.memoKey ??= JSON.stringify(t(n)), c = a.memoKey;
332
+ else {
333
+ let e;
334
+ try {
335
+ e = await a.refilter();
336
+ } catch (e) {
337
+ this.revokeSubscription(a, e, "row filter unavailable");
338
+ return;
339
+ }
340
+ try {
341
+ n = d(e, a.baseDescriptor);
342
+ } catch (e) {
343
+ this.revokeSubscription(a, e, "row filter declaration violated");
344
+ return;
345
+ }
346
+ c = JSON.stringify(t(n));
347
+ }
348
+ c = `${a.readFromPrimary ? "primary" : "policy"}:${c}`;
349
+ let l = r?.epoch === this.changeEpoch ? r.reads : v, u = l.get(c);
350
+ u === void 0 && (u = a.readFromPrimary ? g({
351
+ subjectKey: h(a.context.subject.id, a.context.clientId),
352
+ forcePrimary: !0
353
+ }, () => this.deps.store.query(n)) : this.deps.store.query(n), l.set(c, u));
354
+ let p = await u;
355
+ if (a.reauthorize !== void 0) {
356
+ let e = await a.reauthorize();
357
+ if (e) {
358
+ this.revokeSubscription(a, e);
359
+ return;
360
+ }
361
+ }
362
+ let _ = x?.(n.table, p, a.context.subject), E = _?.rows ?? m(n.table, p, a.context.subject);
363
+ _ !== void 0 && (c = JSON.stringify([c, _.visibilityKey]));
364
+ let D = a.lastDelivered, O = T.get(c);
365
+ O === void 0 && (O = /* @__PURE__ */ new Map(), T.set(c, O));
366
+ let k = O.get(D);
367
+ if (k === void 0 && (k = !j(E, D), O.set(D, k)), !k) {
368
+ C.trace("suppressed no-op delta", {
369
+ subscriberId: i,
370
+ table: e.table
371
+ });
372
+ return;
373
+ }
374
+ if (a.lastDelivered = E, this.deps.cache !== void 0 && a.cacheBinding !== void 0 && this.deps.cache.put(a.cacheBinding, Array.from(a.dependentTables), E), b(D) && b(E)) {
375
+ let e = w.get(c);
376
+ e === void 0 && (e = /* @__PURE__ */ new Map(), w.set(c, e));
377
+ let t = e.get(D);
378
+ if (t === void 0) {
379
+ let n = this.deps.crdtColumnsOf?.(a.descriptor.table) ?? S;
380
+ t = n.size === 0 ? y(D, E) : y(D, E, { crdt: {
381
+ columns: n,
382
+ incremental: o
383
+ } }), e.set(D, t);
384
+ }
385
+ a.emit({
386
+ _tag: "delta",
387
+ revision: f,
388
+ emittedAt: f,
389
+ patch: t
390
+ });
391
+ } else a.emit({
392
+ _tag: "snapshot",
393
+ revision: f,
394
+ data: E
395
+ });
396
+ let A = Date.now();
397
+ this.deps.recordDelivery?.({
398
+ traceId: a.context.traceId,
399
+ parentSpanId: a.context.spanId,
400
+ label: a.label,
401
+ kind: "delta",
402
+ startMs: s,
403
+ endMs: A,
404
+ durationMs: A - s,
405
+ rowCount: E.length
406
+ }), this.deps.recordCost !== void 0 && this.deps.recordCost({
407
+ tenantId: a.context.subject.tenantId,
408
+ subscriptionId: a.id,
409
+ unit: "recompute",
410
+ amount: 1,
411
+ traceId: a.context.traceId
412
+ });
413
+ } catch (t) {
414
+ C.warn("reactive re-query failed; subscriber left on last snapshot", {
415
+ subscriberId: i,
416
+ label: a.label,
417
+ table: e.table,
418
+ traceId: a.context.traceId
419
+ }, t);
420
+ }
421
+ }, D = Array.from(l), O = Math.max(1, Math.min(this.reactive.deliveryConcurrency, D.length)), k = 0, A = async () => {
422
+ for (;;) {
423
+ let e = k++;
424
+ if (e >= D.length) return;
425
+ await E(D[e]);
426
+ }
427
+ };
428
+ await Promise.all(Array.from({ length: O }, () => A())), _ > 0 && C.trace("handleChange/prefiltered", {
429
+ table: e.table,
430
+ op: e.op,
431
+ skipped: _
432
+ });
433
+ }
434
+ }, A = (e) => {
435
+ try {
436
+ return JSON.stringify(e) ?? "null";
437
+ } catch {
438
+ return String(e);
439
+ }
440
+ }, j = (e, t) => {
441
+ if (e === t) return !0;
442
+ if (e.length !== t.length) return !1;
443
+ for (let n = 0; n < e.length; n++) if (JSON.stringify(e[n]) !== JSON.stringify(t[n])) return !1;
444
+ return !0;
445
+ };
446
+ //#endregion
447
+ export { k as Dispatcher, w as deliveredRowCount };
@@ -0,0 +1,71 @@
1
+ import { Context as e, Effect as t, Exit as n, Layer as r } from "effect";
2
+ import { authoredError as i, describeDriverError as a, wireSafeCause as o } from "@voltro/database";
3
+ import { StoreOperationFailed as s } from "@voltro/protocol";
4
+ import { createLogger as c } from "@voltro/logger";
5
+ //#region src/effectStore.ts
6
+ var l = c({ scope: "store" }), u = class extends e.Service()("@voltro/EffectStore") {}, d = {
7
+ TenantScopeViolation: !0,
8
+ TenantRowNotFound: !0,
9
+ ServerOnlyColumnWrite: !0,
10
+ StoreOperationFailed: !0,
11
+ TableValidationFailed: !0,
12
+ ConstraintViolation: !0
13
+ }, f = (e) => {
14
+ let t = e?._tag;
15
+ return typeof t == "string" && Object.hasOwn(d, t);
16
+ }, p = (e, t) => (n) => f(n) ? n : (l.warn("store operation failed", {
17
+ operation: e,
18
+ table: t,
19
+ detail: a(n) ?? String(n)
20
+ }), new s({
21
+ operation: e,
22
+ table: t,
23
+ cause: o(n, e)
24
+ })), m = (e, n, r) => t.tryPromise({
25
+ try: r,
26
+ catch: p(e, n)
27
+ }), h = (e) => ("descriptor" in e ? e.descriptor : e).table, g = (e, n) => t.tryPromise({
28
+ try: n,
29
+ catch: (t) => t?._tag === "NoRowFound" ? t : p("one", e)(t)
30
+ }), _ = class extends Error {
31
+ effectCause;
32
+ constructor(e) {
33
+ super("Effect program failed inside store transaction"), this.effectCause = e;
34
+ }
35
+ }, v = (e) => ({
36
+ query: ((t) => m("query", t.table, () => e.query(t))),
37
+ insert: (t, n) => m("insert", t, () => e.insert(t, n)),
38
+ insertMany: (t, n) => m("insertMany", t, () => e.insertMany(t, n)),
39
+ patchJson: (t, n, r, i, a) => m("patchJson", t, () => e.patchJson(t, n, r, i, a)),
40
+ update: (t, n, r) => m("update", t, () => e.update(t, n, r)),
41
+ updateMany: (t, n, r) => m("updateMany", t, () => e.updateMany(t, n, r)),
42
+ delete: (t, n) => m("delete", t, () => e.delete(t, n)),
43
+ deleteMany: (t, n) => m("deleteMany", t, () => e.deleteMany(t, n)),
44
+ upsert: (t, n, r) => m("upsert", t, () => e.upsert(t, n, r)),
45
+ upsertWithOutcome: (t, n, r) => m("upsertWithOutcome", t, async () => {
46
+ if (e.upsertWithOutcome === void 0) throw i("upsertWithOutcome: this store does not implement it — the framework's store wrapper does; a hand-written DataStore must add it");
47
+ return e.upsertWithOutcome(t, n, r);
48
+ }),
49
+ insertIgnore: (t, n, r) => m("insertIgnore", t, () => e.insertIgnore(t, n, r)),
50
+ insertIgnoreWithOutcome: (t, n, r) => m("insertIgnoreWithOutcome", t, async () => e.insertIgnoreWithOutcome(t, n, r)),
51
+ one: ((t) => g(h(t), () => e.one(t))),
52
+ maybeOne: ((t) => m("maybeOne", h(t), () => e.maybeOne(t))),
53
+ first: ((t) => m("first", h(t), () => e.first(t))),
54
+ hardDelete: (t, n) => m("hardDelete", t, () => e.hardDelete(t, n)),
55
+ transactional: (r) => t.flatMap(t.context(), (i) => t.callback((o) => {
56
+ let s;
57
+ e.transactional(async (e) => {
58
+ let a = await t.runPromiseExitWith(i)(r(v(e)));
59
+ if (n.isFailure(a)) throw s = a.cause, new _(a.cause);
60
+ return a.value;
61
+ }).then((e) => o(t.succeed(e)), (e) => {
62
+ e instanceof _ ? o(t.failCause(e.effectCause)) : s === void 0 ? o(t.fail(p("transactional", "<transaction>")(e))) : (l.warn("transaction rollback failed after the work did", { detail: a(e) ?? String(e) }), o(t.failCause(s)));
63
+ });
64
+ }))
65
+ }), y = (e) => r.succeed(u, v(e)), b = (e) => ({
66
+ conflictColumns: e.conflictColumns,
67
+ ...e.update === void 0 ? {} : { update: e.update },
68
+ ...e.updateValues === void 0 ? {} : { updateValues: e.updateValues }
69
+ }), x = (e, t, n) => e.insert(t.tableName, n), S = (e, t, n) => e.insertMany(t.tableName, n), C = (e, t, n, r) => e.upsert(t.tableName, n, b(r)), w = (e, t, n, r) => e.upsertWithOutcome(t.tableName, n, b(r)), T = (e, t, n, r) => e.insertIgnoreWithOutcome(t.tableName, n, { conflictColumns: r.conflictColumns });
70
+ //#endregion
71
+ export { u as EffectStore, T as insertIgnoreRowOutcomeEffect, S as insertManyRowsEffect, x as insertRowEffect, y as makeEffectStoreLayer, C as upsertRowEffect, w as upsertRowOutcomeEffect };