@voltro/runtime 0.86.0 → 0.87.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 (70) hide show
  1. package/CHANGELOG.md +5321 -0
  2. package/README.md +43 -0
  3. package/THIRD-PARTY-NOTICES.md +860 -221
  4. package/dist/analyticsSink.js +8 -14
  5. package/dist/apiKeys.js +82 -78
  6. package/dist/apiRoleBucketSampler.js +64 -0
  7. package/dist/apiRoleWorkloadHistory.js +56 -0
  8. package/dist/apiRoleWorkloadMetrics.js +78 -0
  9. package/dist/apiRoleWorkloadStorage.js +95 -0
  10. package/dist/approvals.js +67 -74
  11. package/dist/authMiddlewareLayer.js +7 -6
  12. package/dist/bindEvent.js +48 -28
  13. package/dist/bootListener.js +106 -39
  14. package/dist/bootStoreCodec.js +38 -37
  15. package/dist/circuitBreaker.js +1 -72
  16. package/dist/composeAnalytics.js +31 -10
  17. package/dist/computedQueryCache.js +231 -0
  18. package/dist/connectionsFacade.js +32 -30
  19. package/dist/coordinatedSchedule.js +84 -78
  20. package/dist/dataStore.js +154 -121
  21. package/dist/declaredTablesGuard.js +2 -1
  22. package/dist/dispatcher.js +403 -328
  23. package/dist/effectStore.js +2 -2
  24. package/dist/engineClients.js +24 -0
  25. package/dist/externalizedTasks.js +19 -6
  26. package/dist/fieldCipher.js +109 -40
  27. package/dist/fieldKeyRegistry.js +295 -0
  28. package/dist/fieldKeyRekey.js +286 -0
  29. package/dist/fieldKeyScan.js +136 -0
  30. package/dist/fieldKeyring.js +77 -0
  31. package/dist/hot.d.ts +56 -0
  32. package/dist/hot.js +3 -0
  33. package/dist/hotDataStore.js +148 -0
  34. package/dist/hotDataStoreSnapshot.js +98 -0
  35. package/dist/hotDataStoreTables.js +18 -0
  36. package/dist/http-range.d.ts +53 -0
  37. package/dist/http-range.js +52 -0
  38. package/dist/httpClientSsrf.js +12 -37
  39. package/dist/httpClientTracing.js +12 -9
  40. package/dist/httpCompression.js +17 -17
  41. package/dist/httpInputStream.js +82 -0
  42. package/dist/httpRouteMounts.js +1 -0
  43. package/dist/idempotencyStore.js +92 -52
  44. package/dist/index.d.ts +1164 -451
  45. package/dist/index.js +143 -132
  46. package/dist/kvFacade.js +23 -17
  47. package/dist/memoryQueryJoins.js +16 -16
  48. package/dist/memorySetOperations.js +43 -0
  49. package/dist/metrics.js +38 -24
  50. package/dist/outbox.js +1 -1
  51. package/dist/readRecorder.js +35 -34
  52. package/dist/readScopePredicate.js +12 -0
  53. package/dist/replicatedDataStore.js +22 -4
  54. package/dist/rowFilter.js +56 -39
  55. package/dist/rpcConnections.js +8 -8
  56. package/dist/rpcServer.js +522 -449
  57. package/dist/rpcWorkloadAdmission.js +50 -0
  58. package/dist/rywPositionStore.js +82 -47
  59. package/dist/scheduler.js +6 -1
  60. package/dist/servePipeline.js +215 -146
  61. package/dist/setReadScopes.js +28 -0
  62. package/dist/snapshotValueCodec.js +46 -0
  63. package/dist/sourceResolution.js +34 -24
  64. package/dist/storeMiddleware.js +211 -209
  65. package/dist/subscriber.js +1 -0
  66. package/dist/tenantScope.js +8 -20
  67. package/dist/traceparent.js +8 -19
  68. package/dist/webSocketGatewayRuntime.js +111 -71
  69. package/dist/workflowRuntime.js +9 -9
  70. package/package.json +19 -7
@@ -1,26 +1,28 @@
1
- import { enterReadRecording as e } from "./readRecorder.js";
2
- import { getRowFilter as t, makeDefaultRefilter as n, resolveRowFilterScope as r } from "./rowFilter.js";
3
- import { isComputedQuery as i } from "./computedQuery.js";
4
- import { TX_READ_VERSIONS_KEY as a, isTransactionReadConflict as o } from "./storeMiddleware.js";
5
- import { evaluateTouchedRules as s, makeRuleCapture as c } from "./businessRules.js";
6
- import { enforceApproval as l } from "./approvals.js";
7
- import { Cause as u, Effect as d, Exit as f, Option as p } from "effect";
8
- import { isTransientContention as m } from "@voltro/database";
9
- import { SubjectService as h, checkGuardsEffect as g, currentSubjectAuthority as _, recheckGuardsEffect as v } from "@voltro/protocol";
10
- import { createLogger as y } from "@voltro/logger";
1
+ import { cachedComputedCall as e, computedCacheKey as t, currentQueryDependencies as n, enterQueryDependencies as r } from "./computedQueryCache.js";
2
+ import { enterReadRecording as i } from "./readRecorder.js";
3
+ import { getRowFilter as a, makeDefaultRefilter as o, resolveRowFilterScope as s } from "./rowFilter.js";
4
+ import { isComputedQuery as c } from "./computedQuery.js";
5
+ import { TX_READ_VERSIONS_KEY as l, isTransactionReadConflict as u } from "./storeMiddleware.js";
6
+ import { evaluateTouchedRules as d, makeRuleCapture as f } from "./businessRules.js";
7
+ import { enforceApproval as p } from "./approvals.js";
8
+ import { observeApiRoleEffect as m } from "./apiRoleWorkloadMetrics.js";
9
+ import { Cause as h, Effect as g, Exit as _, Option as v } from "effect";
10
+ import { isTransientContention as y } from "@voltro/database";
11
+ import { SubjectService as b, checkGuardsEffect as x, currentSubjectAuthority as S, recheckGuardsEffect as C } from "@voltro/protocol";
12
+ import { createLogger as w } from "@voltro/logger";
11
13
  //#region src/servePipeline.ts
12
- var b = (e, t) => d.runPromiseExit(e, t).then((e) => {
13
- if (f.isSuccess(e)) return e.value;
14
- let t = u.findErrorOption(e.cause);
15
- throw p.isSome(t) ? t.value : u.squash(e.cause);
16
- }), x = (e) => b(e), S = (e, t) => e.pipe(d.provideService(h, t)), C = async (e, t, n, r) => {
17
- let i = await d.runPromise(g(t, e.guards, n, {
14
+ var T = (e, t) => g.runPromiseExit(e, t).then((e) => {
15
+ if (_.isSuccess(e)) return e.value;
16
+ let t = h.findErrorOption(e.cause);
17
+ throw v.isSome(t) ? t.value : h.squash(e.cause);
18
+ }), E = (e) => T(e), D = (e, t) => e.pipe(g.provideService(b, t)), O = async (e, t, n, r) => {
19
+ let i = await g.runPromise(x(t, e.guards, n, {
18
20
  defaultDeny: r === !0,
19
21
  procedure: e.name
20
22
  }));
21
23
  if (i) throw i;
22
- }, w = async (e, t, n, r) => {
23
- e.requiresApproval !== void 0 && await l({
24
+ }, k = async (e, t, n, r) => {
25
+ e.requiresApproval !== void 0 && await p({
24
26
  procedure: e.name,
25
27
  kind: t,
26
28
  policy: e.requiresApproval,
@@ -28,20 +30,20 @@ var b = (e, t) => d.runPromiseExit(e, t).then((e) => {
28
30
  input: r,
29
31
  traceId: n.traceId
30
32
  });
31
- }, T = y({ scope: "voltro:rpc" }), E = async (e) => {
32
- if (t() === void 0) return e;
33
- let n = await x(r(e.subject, (e) => {
34
- T.error("row filter failed to load", {}, e instanceof Error ? e : Error(String(e)));
33
+ }, A = w({ scope: "voltro:rpc" }), j = async (e) => {
34
+ if (a() === void 0) return e;
35
+ let t = await E(s(e.subject, (e) => {
36
+ A.error("row filter failed to load", {}, e instanceof Error ? e : Error(String(e)));
35
37
  }));
36
38
  return {
37
39
  ...e,
38
- rowFilter: n
40
+ rowFilter: t
39
41
  };
40
- }, D = (e) => ({
42
+ }, M = (e) => ({
41
43
  ...e.surface === void 0 ? {} : { surface: e.surface },
42
44
  ...e.publicApi === void 0 ? {} : { publicApi: e.publicApi },
43
45
  ...e.remoteAddr === void 0 ? {} : { remoteAddr: e.remoteAddr }
44
- }), O = (e) => {
46
+ }), N = (e) => {
45
47
  let t = e.descriptor.target;
46
48
  if (t == null) return [];
47
49
  let n = Array.isArray(t) ? t : [t], r = /* @__PURE__ */ new Set();
@@ -50,7 +52,7 @@ var b = (e, t) => d.runPromiseExit(e, t).then((e) => {
50
52
  typeof t == "string" && t.length > 0 && r.add(t);
51
53
  }
52
54
  return [...r];
53
- }, k = async (e) => {
55
+ }, P = async (e) => {
54
56
  let { store: t, target: n, procedure: r, input: i, output: a } = e;
55
57
  if (n == null) return;
56
58
  let o = Array.isArray(n) ? n : [n];
@@ -67,15 +69,15 @@ var b = (e, t) => d.runPromiseExit(e, t).then((e) => {
67
69
  await u.set(c.map((e) => String(e)));
68
70
  }
69
71
  }
70
- }, A = (e, t) => e === void 0 ? {} : { enqueueOutcome: async (n, r, i) => {
72
+ }, F = (e, t) => e === void 0 ? {} : { enqueueOutcome: async (n, r, i) => {
71
73
  let a = e(t);
72
74
  if (a === void 0) throw TypeError("Invocation outcome outbox is unavailable");
73
75
  return a.enqueue(n, r, i);
74
- } }, j = async (e) => {
76
+ } }, I = async (e) => {
75
77
  let t = `${e.kind}.${e.name}`, n = Date.now(), r = "ok";
76
78
  try {
77
79
  if (e.interceptor) {
78
- let t = d.tryPromise({
80
+ let t = g.tryPromise({
79
81
  try: () => e.runExecutor(),
80
82
  catch: (e) => e
81
83
  }), n = e.interceptor(t, {
@@ -87,10 +89,10 @@ var b = (e, t) => d.runPromiseExit(e, t).then((e) => {
87
89
  ...e.enqueueOutcome === void 0 ? {} : { enqueueOutcome: e.enqueueOutcome },
88
90
  ...e.requestContext.spanId === void 0 ? {} : { spanId: e.requestContext.spanId },
89
91
  ...e.target !== void 0 && e.target.length > 0 ? { target: e.target } : {},
90
- ...D(e.requestContext)
91
- }), r = await d.runPromiseExit(n, e.requestContext.signal === void 0 ? void 0 : { signal: e.requestContext.signal });
92
- if (f.isSuccess(r)) return r.value;
93
- throw u.squash(r.cause);
92
+ ...M(e.requestContext)
93
+ }), r = await g.runPromiseExit(n, e.requestContext.signal === void 0 ? void 0 : { signal: e.requestContext.signal });
94
+ if (_.isSuccess(r)) return r.value;
95
+ throw h.squash(r.cause);
94
96
  }
95
97
  return await e.runExecutor();
96
98
  } catch (e) {
@@ -103,50 +105,55 @@ var b = (e, t) => d.runPromiseExit(e, t).then((e) => {
103
105
  status: r
104
106
  });
105
107
  }
106
- }, M = (e) => m(e) || o(e), N = 3, P = (e) => new Promise((t) => setTimeout(t, e)), F = async (e, t) => {
107
- let n = t?.delay ?? ((e) => P(e * 20 + Math.floor(Math.random() * 30))), r = t?.attempts ?? 3;
108
+ }, L = (e) => y(e) || u(e), R = 3, z = (e) => new Promise((t) => setTimeout(t, e)), B = async (e, t) => {
109
+ let n = t?.delay ?? ((e) => z(e * 20 + Math.floor(Math.random() * 30))), r = t?.attempts ?? 3;
108
110
  for (let t = 1;; t++) try {
109
111
  return await e();
110
112
  } catch (e) {
111
- if (t >= r || !M(e)) throw o(e) ? e.conflict : e;
113
+ if (t >= r || !L(e)) throw u(e) ? e.conflict : e;
112
114
  await n(t);
113
115
  }
114
- }, I = (e) => (t, n, r) => j({
116
+ }, V = (e) => (t, n, r) => I({
115
117
  name: t.descriptor.name,
116
118
  kind: "mutation",
117
119
  input: n,
118
120
  requestContext: r,
119
- ...A(e.outcomeOutbox, r),
120
- target: O(t),
121
+ ...F(e.outcomeOutbox, r),
122
+ target: N(t),
121
123
  ...e.interceptor ? { interceptor: e.interceptor } : {},
122
124
  ...e.recordMetric ? { recordMetric: e.recordMetric } : {},
123
125
  runExecutor: async () => {
124
126
  let i = Date.now();
125
- await C(t.descriptor, r.subject, n, e.defaultDeny), await w(t.descriptor, "mutation", r, n);
126
- let o = await E(r), l = e.resolveStore === void 0 ? e.store : await e.resolveStore(o), u = [], f = [], p = await F(async () => l.transactional(async (p) => {
127
- u.length = 0, f.length = 0, p[Symbol.for("@voltro/runtime:tx-fold-releases")] = f, p[a] = /* @__PURE__ */ new Map();
128
- let m = e.undoCapture?.(p), h = m ? m.tx : p, g = c(h), _ = e.buildContext(o, g.tx, {
129
- committedStore: l,
127
+ await q(t, "mutation", { defaultDeny: e.defaultDeny === !0 })(n, r);
128
+ let a = {
129
+ ...r,
130
+ subject: S(r.subject)
131
+ };
132
+ await k(t.descriptor, "mutation", a, n);
133
+ let o = await j(a), s = e.resolveStore === void 0 ? e.store : await e.resolveStore(o), c = [], u = [], p = await B(async () => s.transactional(async (a) => {
134
+ c.length = 0, u.length = 0, a[Symbol.for("@voltro/runtime:tx-fold-releases")] = u, a[l] = /* @__PURE__ */ new Map();
135
+ let p = t.descriptor.undo?.capture === !1 ? void 0 : e.undoCapture?.(a), m = p ? p.tx : a, h = f(m), _ = e.buildContext(o, h.tx, {
136
+ committedStore: s,
130
137
  afterCommit: (e) => {
131
- u.push(e);
138
+ c.push(e);
132
139
  }
133
- }), v = t.executor(n, _), y = d.isEffect(v) ? await e.runEffect(S(v, r.subject), _.store) : await v;
134
- if (await k({
140
+ }), v = e.measureSync ? e.measureSync(() => t.executor(n, _)) : t.executor(n, _), y = g.isEffect(v) ? await e.runEffect(D(v, o.subject), _.store) : await v;
141
+ if (await P({
135
142
  store: _.store,
136
143
  target: t.descriptor.target,
137
144
  procedure: t.descriptor.name,
138
145
  input: n,
139
146
  output: y
140
- }), m && await m.persist(_.store, {
147
+ }), p && await p.persist(_.store, {
141
148
  tag: t.descriptor.name,
142
- subject: r.subject,
149
+ subject: o.subject,
143
150
  traceId: r.traceId
144
- }), await s({
145
- touched: g.drain(),
151
+ }), await d({
152
+ touched: h.drain(),
146
153
  store: _.store,
147
- subject: r.subject
154
+ subject: o.subject
148
155
  }), e.beforeMutationCommit !== void 0) {
149
- let a = O(t), s = e.beforeMutationCommit({
156
+ let r = N(t), a = e.beforeMutationCommit({
150
157
  tag: t.descriptor.name,
151
158
  kind: "mutation",
152
159
  input: n,
@@ -158,122 +165,179 @@ var b = (e, t) => d.runPromiseExit(e, t).then((e) => {
158
165
  startedAt: i,
159
166
  durationMs: Math.max(0, Date.now() - i),
160
167
  ...o.spanId === void 0 ? {} : { spanId: o.spanId },
161
- ...a.length > 0 ? { target: a } : {},
162
- ...D(o)
168
+ ...r.length > 0 ? { target: r } : {},
169
+ ...M(o)
163
170
  });
164
- await e.runEffect(S(s, r.subject), _.store);
171
+ await e.runEffect(D(a, o.subject), _.store);
165
172
  }
166
173
  return y;
167
174
  }), { ...e.replayAttempts === void 0 ? {} : { attempts: e.replayAttempts } });
168
- if (f.length > 0) {
169
- let t = e.buildContext(o, l, {
170
- committedStore: l,
175
+ if (u.length > 0) {
176
+ let t = e.buildContext(o, s, {
177
+ committedStore: s,
171
178
  afterCommit: () => {}
172
179
  }).store;
173
- for (let e of f.splice(0)) await t.update(e.table, e.pk, e.patch);
180
+ for (let e of u.splice(0)) await t.update(e.table, e.pk, e.patch);
174
181
  }
175
- for (let e of u) await e();
176
- return p;
182
+ for (let e of c) await e();
183
+ return e.settleCacheInvalidations !== void 0 && await e.settleCacheInvalidations(), p;
177
184
  }
178
- }), L = (e) => (t, n, r, i) => j({
185
+ }), H = (e) => (t, n, r, i) => I({
179
186
  name: t.name,
180
187
  kind: "workflow",
181
188
  input: n,
182
189
  requestContext: r,
183
- ...A(e.outcomeOutbox, r),
190
+ ...F(e.outcomeOutbox, r),
184
191
  ...e.interceptor ? { interceptor: e.interceptor } : {},
185
192
  ...e.recordMetric ? { recordMetric: e.recordMetric } : {},
186
- runExecutor: async () => (await C(t, r.subject, n, e.defaultDeny), i())
187
- }), R = (e) => e && typeof e == "object" && "descriptor" in e ? e.descriptor : e, z = (e) => typeof e == "object" && !!e && !Array.isArray(e) && "table" in e && "order" in e, B = (e) => {
193
+ runExecutor: async () => (await O(t, r.subject, n, e.defaultDeny), i())
194
+ }), U = (e) => e && typeof e == "object" && "descriptor" in e ? e.descriptor : e, W = (e) => typeof e == "object" && !!e && !Array.isArray(e) && "table" in e && "order" in e, G = (e) => {
188
195
  let t = e.descriptor.source;
189
196
  return t == null ? [] : typeof t == "string" ? [t] : [...t];
190
- }, V = (e, t, n) => (r) => () => d.runPromise(v(r, e.descriptor.guards, t, {
197
+ }, K = (e, t, n) => (r) => () => g.runPromise(C(r, e.descriptor.guards, t, {
191
198
  defaultDeny: n === !0,
192
199
  procedure: e.descriptor.name
193
- })), H = (e, n) => e.rowFilter !== void 0 || t() === void 0 ? n(e) : d.promise(() => E(e)).pipe(d.flatMap((e) => {
194
- let t = n(e);
195
- return d.isEffect(t) ? t : d.succeed(t);
196
- })), U = (n) => (r, a) => (o) => {
197
- if (o.rowFilter === void 0 && t() !== void 0) return H(o, (e) => U(n)(r, a)(e));
198
- let s = n.buildContext(o), c = V(r, a, n.defaultDeny)(o.subject), l = async () => {
199
- let e = await c();
200
+ })), q = (e, t, n = {}) => async (r, i) => {
201
+ let a = i.subject;
202
+ n.bindReplayAuthority?.({
203
+ tag: e.descriptor.name,
204
+ kind: t,
205
+ input: r,
206
+ subject: a,
207
+ traceId: i.traceId,
208
+ ...i.surface === void 0 ? {} : { surface: i.surface },
209
+ ...i.publicApi === void 0 ? {} : { publicApi: i.publicApi },
210
+ ...i.remoteAddr === void 0 ? {} : { remoteAddr: i.remoteAddr }
211
+ });
212
+ let o = await K(e, r, n.defaultDeny)(a)();
213
+ if (o) throw o;
214
+ }, J = (e, t) => e.rowFilter !== void 0 || a() === void 0 ? t(e) : g.promise(() => j(e)).pipe(g.flatMap((e) => {
215
+ let n = t(e);
216
+ return g.isEffect(n) ? n : g.succeed(n);
217
+ })), Y = (e, t) => X(e, t, /* @__PURE__ */ new Set()), X = (o, s, l) => (u, d) => (f) => {
218
+ if (f.rowFilter === void 0 && a() !== void 0) return J(f, (e) => X(o, s, l)(u, d)(e));
219
+ let p = s ?? (f.connection?.transport === "http" ? "rpc" : "subscriptions"), h = (e) => o.workloadMetrics ? o.workloadMetrics.measureSync(p, e) : e(), _ = (e, t) => {
220
+ let n = o.provideEffect(e, t);
221
+ return o.workloadMetrics ? m(n, o.workloadMetrics, p) : n;
222
+ }, v = o.buildContext(f), y = K(u, d, o.defaultDeny)(f.subject), b = async () => {
223
+ let e = await y();
200
224
  if (e) throw e;
201
225
  let t = {
202
- ...o,
203
- subject: _(o.subject)
204
- }, i = n.buildContext(await E(t)), s = r.executor(a, i), l = d.isEffect(s) ? await b(n.provideEffect(S(s, t.subject), i.store), o.signal === void 0 ? void 0 : { signal: o.signal }) : R(await Promise.resolve(s)), u = await c();
205
- if (u) throw u;
206
- return l;
207
- }, u = (e) => {
208
- let t = R(e);
209
- if (z(t)) {
210
- let e = n.finalize(t, o), i = B(r);
211
- if (i.length === 0) return e;
212
- let a = e.dependentTables ?? [];
226
+ ...f,
227
+ subject: S(f.subject)
228
+ }, n = o.buildContext(await j(t)), r = h(() => u.executor(d, n)), i = g.isEffect(r) ? await T(_(D(r, t.subject), n.store), f.signal === void 0 ? void 0 : { signal: f.signal }) : U(await Promise.resolve(r)), a = await y();
229
+ if (a) throw a;
230
+ return i;
231
+ }, C = (e, t = n()) => {
232
+ let r = U(e);
233
+ if (W(r)) {
234
+ let e = o.finalize(r, f), t = G(u);
235
+ if (t.length === 0) return e;
236
+ let n = e.dependentTables ?? [];
213
237
  return {
214
238
  ...e,
215
- dependentTables: [.../* @__PURE__ */ new Set([...a, ...i])]
239
+ dependentTables: [.../* @__PURE__ */ new Set([...n, ...t])]
216
240
  };
217
241
  }
218
242
  return {
219
243
  __voltroComputed: !0,
220
- value: t,
221
- dependentTables: B(r),
222
- tenantId: o.subject?.tenantId ?? null,
223
- recompute: l
244
+ value: r,
245
+ dependentTables: [.../* @__PURE__ */ new Set([...G(u), ...t])],
246
+ tenantId: f.subject?.tenantId ?? null,
247
+ recompute: b
224
248
  };
225
- }, f = (e) => {
226
- let t = u(e);
227
- return i(t) ? d.tryPromise({
228
- try: c,
249
+ }, w = (e, t) => {
250
+ let n = C(e, t);
251
+ return c(n) ? g.tryPromise({
252
+ try: y,
229
253
  catch: (e) => e
230
- }).pipe(d.flatMap((e) => e ? d.fail(e) : d.succeed(t))) : t;
231
- }, p = (e) => {
232
- let t = f(e);
233
- return d.isEffect(t) ? t : d.succeed(t);
234
- }, m = () => {
235
- e(r.descriptor.name, B(r));
236
- let t = r.executor(a, s);
237
- return d.isEffect(t) ? n.provideEffect(S(t, o.subject), s.store).pipe(d.flatMap(p)) : t instanceof Promise ? d.promise(() => t).pipe(d.flatMap(p)) : f(t);
238
- }, h = () => {
239
- let e = r.descriptor.guards;
240
- return (!e || e.length === 0) && n.defaultDeny !== !0 && o.subject.type !== "service" ? m() : g(o.subject, e, a, {
241
- defaultDeny: n.defaultDeny === !0,
242
- procedure: r.descriptor.name
243
- }).pipe(d.flatMap((e) => {
244
- if (e) return d.fail(e);
245
- let t = m();
246
- return d.isEffect(t) ? t : d.succeed(t);
254
+ }).pipe(g.flatMap((e) => e ? g.fail(e) : g.succeed(n))) : n;
255
+ }, E = (e, t) => {
256
+ let n = w(e, t);
257
+ return g.isEffect(n) ? n : g.succeed(n);
258
+ }, O = () => {
259
+ let n = o.computedCache, r = u.descriptor.cache;
260
+ if (n === void 0 || r === void 0 || l.has(u.descriptor.name)) return;
261
+ let i = n.policyFor(r);
262
+ if (i === void 0) return;
263
+ let a = f.subject, s = G(u), c = t({
264
+ name: u.descriptor.name,
265
+ codeIdentity: n.codeIdentity,
266
+ output: u.descriptor.output,
267
+ input: u.descriptor.input,
268
+ decodedInput: d,
269
+ scope: i.scope,
270
+ subject: a,
271
+ rowFilter: f.rowFilter,
272
+ declaredSources: s
273
+ });
274
+ if ("bypass" in c) c.bypass === "input-not-encodable" && n.notice(u.descriptor.name, c.bypass, `${u.descriptor.name}: \`cache:\` NOT applied — the input does not encode through its \`input\` schema, so it has no key.`);
275
+ else return e({
276
+ cache: n,
277
+ policy: i,
278
+ key: c.key,
279
+ name: u.descriptor.name,
280
+ sources: s,
281
+ output: u.descriptor.output,
282
+ subject: f.subject,
283
+ rowFilter: f.rowFilter,
284
+ ctx: v,
285
+ ...f.signal === void 0 ? {} : { signal: f.signal },
286
+ execute: (e, t) => {
287
+ let n = h(() => u.executor(d, e));
288
+ return g.isEffect(n) ? T(_(D(n, t), v.store), f.signal === void 0 ? void 0 : { signal: f.signal }) : Promise.resolve(n);
289
+ },
290
+ onDescriptor: () => {
291
+ l.add(u.descriptor.name);
292
+ },
293
+ isDescriptor: (e) => W(U(e)),
294
+ unwrap: (e) => U(e)
295
+ }).pipe(g.flatMap(({ value: e, dependencies: t }) => E(e, t)));
296
+ }, k = () => {
297
+ i(u.descriptor.name, G(u)), r();
298
+ let e = O();
299
+ if (e !== void 0) return e;
300
+ let t = h(() => u.executor(d, v));
301
+ return g.isEffect(t) ? _(D(t, f.subject), v.store).pipe(g.flatMap(E)) : t instanceof Promise ? g.promise(() => t).pipe(g.flatMap(E)) : w(t);
302
+ }, A = () => {
303
+ let e = u.descriptor.guards;
304
+ return (!e || e.length === 0) && o.defaultDeny !== !0 && f.subject.type !== "service" ? k() : x(f.subject, e, d, {
305
+ defaultDeny: o.defaultDeny === !0,
306
+ procedure: u.descriptor.name
307
+ }).pipe(g.flatMap((e) => {
308
+ if (e) return g.fail(e);
309
+ let t = k();
310
+ return g.isEffect(t) ? t : g.succeed(t);
247
311
  }));
248
312
  };
249
- if (!n.interceptor) return h();
250
- let v = d.suspend(() => {
251
- let e = h();
252
- return d.isEffect(e) ? e : d.succeed(e);
313
+ if (!o.interceptor) return A();
314
+ let N = g.suspend(() => {
315
+ let e = A();
316
+ return g.isEffect(e) ? e : g.succeed(e);
253
317
  });
254
- return n.interceptor(v, {
255
- tag: r.descriptor.name,
318
+ return o.interceptor(N, {
319
+ tag: u.descriptor.name,
256
320
  kind: "query",
257
- input: a,
258
- subject: o.subject,
259
- traceId: o.traceId,
260
- ...o.spanId === void 0 ? {} : { spanId: o.spanId },
261
- ...D(o)
321
+ input: d,
322
+ subject: f.subject,
323
+ traceId: f.traceId,
324
+ ...f.spanId === void 0 ? {} : { spanId: f.spanId },
325
+ ...M(f)
262
326
  });
263
- }, W = (e) => async (t, n, r) => {
264
- let a = await E(r), o = U(e)(t, n)(a), s = d.isEffect(o) ? await x(o) : o;
265
- if (i(s)) return s.value;
266
- let c = e.buildContext(a), l = await e.queryRows(s, a, c.store), u = await V(t, n, e.defaultDeny)(a.subject)();
327
+ }, Z = (e) => async (t, n, r) => {
328
+ let i = await j(r), a = Y(e, "rpc")(t, n)(i), o = g.isEffect(a) ? await E(a) : a;
329
+ if (c(o)) return o.value;
330
+ let s = e.buildContext(i), l = await e.queryRows(o, i, s.store), u = await K(t, n, e.defaultDeny)(i.subject)();
267
331
  if (u) throw u;
268
332
  return l;
269
- }, G = (e) => (t, r, a, o) => {
270
- let s = !1, c;
333
+ }, Q = (e) => (t, n, r, i) => {
334
+ let a = !1, s;
271
335
  return (async () => {
272
336
  try {
273
- let l = await E(a), u = U(e)(t, r)(l), f = d.isEffect(u) ? await x(u) : u, p = (e) => o(e), m = i(f) ? await e.subscribeComputed(f, p, l) : await e.subscribeDescriptor(f, p, l, V(t, r, e.defaultDeny)(l.subject), n(l.subject));
274
- s ? m() : c = m;
337
+ let l = await j(r), u = Y(e, "subscriptions")(t, n)(l), d = g.isEffect(u) ? await E(u) : u, f = (e) => i(e), p = c(d) ? await e.subscribeComputed(d, f, l) : await e.subscribeDescriptor(d, f, l, K(t, n, e.defaultDeny)(l.subject), o(l.subject));
338
+ a ? p() : s = p;
275
339
  } catch (e) {
276
- o({
340
+ i({
277
341
  _tag: "error",
278
342
  error: e instanceof Error ? {
279
343
  message: e.message,
@@ -282,24 +346,29 @@ var b = (e, t) => d.runPromiseExit(e, t).then((e) => {
282
346
  });
283
347
  }
284
348
  })(), () => {
285
- s = !0, c?.();
349
+ a = !0, s?.();
286
350
  };
287
- }, K = (t) => (n, r, i) => j({
288
- name: n.descriptor.name,
351
+ }, $ = (e) => (t, n, r) => I({
352
+ name: t.descriptor.name,
289
353
  kind: "action",
290
- input: r,
291
- requestContext: i,
292
- ...A(t.outcomeOutbox, i),
293
- target: O(n),
294
- ...t.interceptor ? { interceptor: t.interceptor } : {},
295
- ...t.recordMetric ? { recordMetric: t.recordMetric } : {},
354
+ input: n,
355
+ requestContext: r,
356
+ ...F(e.outcomeOutbox, r),
357
+ target: N(t),
358
+ ...e.interceptor ? { interceptor: e.interceptor } : {},
359
+ ...e.recordMetric ? { recordMetric: e.recordMetric } : {},
296
360
  runExecutor: async () => {
297
- await C(n.descriptor, i.subject, r, t.defaultDeny), await w(n.descriptor, "action", i, r);
298
- let a = t.buildContext(await E(i));
299
- e(n.descriptor.name, B(n));
300
- let o = n.executor(r, a);
301
- return d.isEffect(o) ? t.runEffect(S(o, i.subject), a.store) : o;
361
+ await q(t, "action", { defaultDeny: e.defaultDeny === !0 })(n, r);
362
+ let a = {
363
+ ...r,
364
+ subject: S(r.subject)
365
+ };
366
+ await k(t.descriptor, "action", a, n);
367
+ let o = e.buildContext(await j(a));
368
+ i(t.descriptor.name, G(t));
369
+ let s = e.measureSync ? e.measureSync(() => t.executor(n, o)) : t.executor(n, o), c = g.isEffect(s) ? await e.runEffect(D(s, a.subject), o.store) : await s;
370
+ return e.settleCacheInvalidations !== void 0 && await e.settleCacheInvalidations(), c;
302
371
  }
303
372
  });
304
373
  //#endregion
305
- export { N as DEFAULT_MUTATION_REPLAY_ATTEMPTS, k as applyDeclaredRelations, K as makeActionRunner, I as makeMutationRunner, W as makeOneShotQueryRunner, U as makeQueryDescriptorProducer, V as makeQueryReauthorizer, G as makeQuerySubscriber, L as makeWorkflowStartRunner, x as runProvidedEffect, F as runWithDeadlockRetry, E as withRowFilter, H as withScopedRequest };
374
+ export { R as DEFAULT_MUTATION_REPLAY_ATTEMPTS, P as applyDeclaredRelations, $ as makeActionRunner, q as makeMutationReplayAdmission, V as makeMutationRunner, Z as makeOneShotQueryRunner, Y as makeQueryDescriptorProducer, K as makeQueryReauthorizer, Q as makeQuerySubscriber, H as makeWorkflowStartRunner, E as runProvidedEffect, B as runWithDeadlockRetry, j as withRowFilter, J as withScopedRequest };
@@ -0,0 +1,28 @@
1
+ //#region src/setReadScopes.ts
2
+ var e = [
3
+ "crossTenant",
4
+ "includeDeleted",
5
+ "includeExpired"
6
+ ], t = (t, n) => {
7
+ let r = (t, i) => {
8
+ let a = t;
9
+ for (let t of e) i?.[t] === !0 && a[t] !== !0 && (a = {
10
+ ...a,
11
+ [t]: !0
12
+ });
13
+ let o = a.setOp;
14
+ if (o === void 0) return n(a);
15
+ if (o.queries.length < 2) throw Error("A set operation requires at least two inputs");
16
+ let s = o.queries.map((e) => r(e, a));
17
+ return s.every((e, t) => e === o.queries[t]) ? a : {
18
+ ...a,
19
+ setOp: {
20
+ ...o,
21
+ queries: s
22
+ }
23
+ };
24
+ };
25
+ return r(t);
26
+ };
27
+ //#endregion
28
+ export { t as mapSetReadScopes };
@@ -0,0 +1,46 @@
1
+ //#region src/snapshotValueCodec.ts
2
+ var e = "\0", t = `${e}d`, n = `${e}n`, r = `${e}b`, i = `${e}o`, a = 1, o = (e) => {
3
+ if (typeof e != "object" || !e) return !1;
4
+ let t = Object.getPrototypeOf(e);
5
+ return t === Object.prototype || t === null;
6
+ }, s = (a) => {
7
+ if (typeof a != "object" || !a) return typeof a == "bigint" ? { [n]: a.toString() } : a;
8
+ if (a instanceof Date) return { [t]: Number.isNaN(a.getTime()) ? null : a.toISOString() };
9
+ if (a instanceof Uint8Array) return { [r]: Buffer.from(a.buffer, a.byteOffset, a.byteLength).toString("base64") };
10
+ if (Array.isArray(a)) return a.map(s);
11
+ if (o(a)) {
12
+ let t = {}, n = !1;
13
+ for (let [r, i] of Object.entries(a)) r.startsWith(e) && (n = !0), t[r] = s(i);
14
+ return n ? { [i]: t } : t;
15
+ }
16
+ throw TypeError("A snapshot value carries a non-plain object; it cannot be cached faithfully.");
17
+ }, c = (e) => {
18
+ if (typeof e != "object" || !e) return e;
19
+ if (Array.isArray(e)) return e.map(c);
20
+ let a = e, o = Object.keys(a);
21
+ if (o.length === 1) {
22
+ let e = o[0], s = a[e];
23
+ if (e === t) return s === null ? /* @__PURE__ */ new Date(NaN) : new Date(s);
24
+ if (e === n) return BigInt(s);
25
+ if (e === r) return new Uint8Array(Buffer.from(s, "base64"));
26
+ if (e === i) {
27
+ let e = {};
28
+ for (let [t, n] of Object.entries(s)) e[t] = c(n);
29
+ return e;
30
+ }
31
+ }
32
+ let s = {};
33
+ for (let [e, t] of Object.entries(a)) s[e] = c(t);
34
+ return s;
35
+ }, l = (e) => ({
36
+ v: a,
37
+ value: s(e)
38
+ }), u = (e) => {
39
+ if (o(e) && e.v === a && "value" in e) try {
40
+ return { value: c(e.value) };
41
+ } catch {
42
+ return;
43
+ }
44
+ };
45
+ //#endregion
46
+ export { u as decodeSnapshotValue, l as encodeSnapshotValue };
@@ -1,6 +1,6 @@
1
- import { declaredReactivityChannelKeys as e, isReactivityChannelKey as t, sourceKeys as n } from "@voltro/protocol";
1
+ import { captureOptionalQuerySources as e, declaredReactivityChannelKeys as t, isReactivityChannelKey as n, sourceKeys as r } from "@voltro/protocol";
2
2
  //#region src/sourceResolution.ts
3
- var r = (e, t) => {
3
+ var i = (e, t) => {
4
4
  let n, r = 0;
5
5
  for (let i of t) {
6
6
  let t = 0;
@@ -11,32 +11,42 @@ var r = (e, t) => {
11
11
  o > r && o >= .6 && (r = o, n = i);
12
12
  }
13
13
  return n;
14
- }, i = (i, a) => {
15
- let o = e(), s = [], c = /* @__PURE__ */ new Map();
16
- for (let e of i) for (let i of n(e.source)) if (t(i)) {
17
- if (o.has(i)) continue;
18
- s.push({
19
- procedure: e.name,
20
- source: i,
21
- didYouMean: void 0,
22
- channel: !0
23
- });
24
- } else a.size === 0 || a.has(i) || (c.has(i) || c.set(i, r(i, a)), s.push({
25
- procedure: e.name,
26
- source: i,
27
- didYouMean: c.get(i),
28
- channel: !1
29
- }));
30
- return s;
31
- }, a = (e) => {
14
+ }, a = (a, o) => {
15
+ let s = t(), c = [], l = /* @__PURE__ */ new Map();
16
+ for (let t of a) {
17
+ let a = new Set(e(t.name, t.source, t.optionalSource));
18
+ for (let e of r(t.source)) if (n(e)) {
19
+ if (s.has(e)) continue;
20
+ c.push({
21
+ procedure: t.name,
22
+ source: e,
23
+ didYouMean: void 0,
24
+ channel: !0,
25
+ ...a.has(e) ? { optional: !0 } : {}
26
+ });
27
+ } else o.size === 0 || o.has(e) || (l.has(e) || l.set(e, i(e, o)), c.push({
28
+ procedure: t.name,
29
+ source: e,
30
+ didYouMean: a.has(e) ? void 0 : l.get(e),
31
+ channel: !1,
32
+ ...a.has(e) ? { optional: !0 } : {}
33
+ }));
34
+ }
35
+ return c;
36
+ }, o = (e) => {
32
37
  if (e.length === 0) return;
33
- let t = e.map((e) => e.channel ? ` ${e.procedure}: source '${e.source}' names a reactivity channel nobody declared` : ` ${e.procedure}: source '${e.source}' matches no declared table` + (e.didYouMean === void 0 ? "" : ` — did you mean '${e.didYouMean}'?`)), n = e.some((e) => e.channel) ? "\nFor the `channel:` entries: declare it with `reactivityChannel(<name>)` and pass the\nCHANNEL as `source:`, not its key as a string. Authoring against the object is what\nmakes a channel source impossible to leave stale — you cannot import a declaration\nthat does not exist." : "";
34
- return `${e.length} reactive source(s) name a table that does not exist:\n${t.join("\n")}\n
38
+ let t = e.filter((e) => e.optional === !0);
39
+ if (t.length > 0) {
40
+ let n = o(e.filter((e) => e.optional !== !0)), r = t.map((e) => ` ${e.procedure}: optional integration source '${e.source}' is unavailable`);
41
+ return [n, `${t.length} optional integration source(s) are unavailable:\n${r.join("\n")}\nTheir observers remain declared. Installed sources still trigger recomputation; executor authorization still applies.`].filter((e) => e !== void 0).join("\n\n");
42
+ }
43
+ let n = e.map((e) => e.channel ? ` ${e.procedure}: source '${e.source}' names a reactivity channel nobody declared` : ` ${e.procedure}: source '${e.source}' matches no declared table` + (e.didYouMean === void 0 ? "" : ` — did you mean '${e.didYouMean}'?`)), r = e.some((e) => e.channel) ? "\nFor the `channel:` entries: declare it with `reactivityChannel(<name>)` and pass the\nCHANNEL as `source:`, not its key as a string. Authoring against the object is what\nmakes a channel source impossible to leave stale — you cannot import a declaration\nthat does not exist." : "";
44
+ return `${e.length} reactive source(s) name a table that does not exist:\n${n.join("\n")}\n
35
45
  These queries are NOT broken. They serve their first snapshot and then never
36
46
  update again, which is indistinguishable from "nothing has changed" — so the
37
47
  symptom is silence, and silence is what this surface exists to eliminate.
38
48
  A \`source:\` is a STRING, so \`tsc\` cannot see a stale one and a rename leaves it
39
- behind quietly.` + n;
49
+ behind quietly.` + r;
40
50
  };
41
51
  //#endregion
42
- export { a as formatUnresolvedSources, i as unresolvedSources };
52
+ export { o as formatUnresolvedSources, a as unresolvedSources };