@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.
- package/CHANGELOG.md +5321 -0
- package/README.md +43 -0
- package/THIRD-PARTY-NOTICES.md +860 -221
- package/dist/analyticsSink.js +8 -14
- package/dist/apiKeys.js +82 -78
- package/dist/apiRoleBucketSampler.js +64 -0
- package/dist/apiRoleWorkloadHistory.js +56 -0
- package/dist/apiRoleWorkloadMetrics.js +78 -0
- package/dist/apiRoleWorkloadStorage.js +95 -0
- package/dist/approvals.js +67 -74
- package/dist/authMiddlewareLayer.js +7 -6
- package/dist/bindEvent.js +48 -28
- package/dist/bootListener.js +106 -39
- package/dist/bootStoreCodec.js +38 -37
- package/dist/circuitBreaker.js +1 -72
- package/dist/composeAnalytics.js +31 -10
- package/dist/computedQueryCache.js +231 -0
- package/dist/connectionsFacade.js +32 -30
- package/dist/coordinatedSchedule.js +84 -78
- package/dist/dataStore.js +154 -121
- package/dist/declaredTablesGuard.js +2 -1
- package/dist/dispatcher.js +403 -328
- package/dist/effectStore.js +2 -2
- package/dist/engineClients.js +24 -0
- package/dist/externalizedTasks.js +19 -6
- package/dist/fieldCipher.js +109 -40
- package/dist/fieldKeyRegistry.js +295 -0
- package/dist/fieldKeyRekey.js +286 -0
- package/dist/fieldKeyScan.js +136 -0
- package/dist/fieldKeyring.js +77 -0
- package/dist/hot.d.ts +56 -0
- package/dist/hot.js +3 -0
- package/dist/hotDataStore.js +148 -0
- package/dist/hotDataStoreSnapshot.js +98 -0
- package/dist/hotDataStoreTables.js +18 -0
- package/dist/http-range.d.ts +53 -0
- package/dist/http-range.js +52 -0
- package/dist/httpClientSsrf.js +12 -37
- package/dist/httpClientTracing.js +12 -9
- package/dist/httpCompression.js +17 -17
- package/dist/httpInputStream.js +82 -0
- package/dist/httpRouteMounts.js +1 -0
- package/dist/idempotencyStore.js +92 -52
- package/dist/index.d.ts +1164 -451
- package/dist/index.js +143 -132
- package/dist/kvFacade.js +23 -17
- package/dist/memoryQueryJoins.js +16 -16
- package/dist/memorySetOperations.js +43 -0
- package/dist/metrics.js +38 -24
- package/dist/outbox.js +1 -1
- package/dist/readRecorder.js +35 -34
- package/dist/readScopePredicate.js +12 -0
- package/dist/replicatedDataStore.js +22 -4
- package/dist/rowFilter.js +56 -39
- package/dist/rpcConnections.js +8 -8
- package/dist/rpcServer.js +522 -449
- package/dist/rpcWorkloadAdmission.js +50 -0
- package/dist/rywPositionStore.js +82 -47
- package/dist/scheduler.js +6 -1
- package/dist/servePipeline.js +215 -146
- package/dist/setReadScopes.js +28 -0
- package/dist/snapshotValueCodec.js +46 -0
- package/dist/sourceResolution.js +34 -24
- package/dist/storeMiddleware.js +211 -209
- package/dist/subscriber.js +1 -0
- package/dist/tenantScope.js +8 -20
- package/dist/traceparent.js +8 -19
- package/dist/webSocketGatewayRuntime.js +111 -71
- package/dist/workflowRuntime.js +9 -9
- package/package.json +19 -7
package/dist/bootStoreCodec.js
CHANGED
|
@@ -1,70 +1,71 @@
|
|
|
1
1
|
import { getFieldCipher as e } from "./fieldCipher.js";
|
|
2
2
|
import { upsertDestinationId as t } from "./upsertBinding.js";
|
|
3
|
-
import { decryptFieldsOnRead as n, deserializeArraysOnRead as r, encryptFieldsForWrite as i, encryptFieldsForWriteBatch as a, encryptedColumnsOf as o, getTable as s, jsonPatchAssignments as c,
|
|
4
|
-
import { createLogger as
|
|
3
|
+
import { decryptFieldsOnRead as n, deserializeArraysOnRead as r, encryptFieldsForWrite as i, encryptFieldsForWriteBatch as a, encryptedColumnsOf as o, getTable as s, jsonPatchAssignments as c, refuseIdChangeOfSealedRow as l, serializeArraysForWrite as u, upsertUpdateValues as d } from "@voltro/database";
|
|
4
|
+
import { createLogger as f } from "@voltro/logger";
|
|
5
5
|
//#region src/bootStoreCodec.ts
|
|
6
|
-
var
|
|
7
|
-
let
|
|
6
|
+
var p = f({ scope: "store.fieldEncryption" }), m = (f, h) => {
|
|
7
|
+
let g = h, _ = process.env.VOLTRO_FIELD_DECRYPT_ON_ERROR === "null" ? "null" : "throw", v = /* @__PURE__ */ new Set(), y = (e) => {
|
|
8
8
|
let t = `${e.table}.${e.column}`;
|
|
9
|
-
|
|
9
|
+
v.has(t) || (v.add(t), p.warn("encrypted column degraded to null — could not decrypt with the active key", {
|
|
10
10
|
table: e.table,
|
|
11
11
|
column: e.column,
|
|
12
12
|
reason: e.reason,
|
|
13
13
|
hint: "VOLTRO_FIELD_DECRYPT_ON_ERROR=null is set — this row was likely encrypted under a different key"
|
|
14
14
|
}));
|
|
15
|
-
},
|
|
16
|
-
let a = s(t), o =
|
|
15
|
+
}, b = (t, n, r) => {
|
|
16
|
+
let a = s(t), o = g ? u(n, a, g) : n;
|
|
17
17
|
return i(o, a, e(), r);
|
|
18
|
-
},
|
|
18
|
+
}, x = (t, i, a) => {
|
|
19
19
|
let o = s(t), c = n(i, o, e(), {
|
|
20
|
-
onError:
|
|
21
|
-
...
|
|
20
|
+
onError: _,
|
|
21
|
+
..._ === "null" ? { warn: y } : {},
|
|
22
22
|
...a === void 0 ? {} : { rowId: a }
|
|
23
23
|
});
|
|
24
|
-
return
|
|
25
|
-
},
|
|
24
|
+
return g ? r(c, o, g) : c;
|
|
25
|
+
}, S = (e, t, n) => t === null ? null : x(e, [t], n)[0];
|
|
26
26
|
return {
|
|
27
|
-
delete: (e, t) =>
|
|
28
|
-
deleteMany: (e, t) =>
|
|
29
|
-
onChange: (e) =>
|
|
27
|
+
delete: (e, t) => f.delete(e, t),
|
|
28
|
+
deleteMany: (e, t) => f.deleteMany(e, t),
|
|
29
|
+
onChange: (e) => f.onChange(e),
|
|
30
30
|
injectExternalChange: (e) => {
|
|
31
|
-
|
|
31
|
+
f.injectExternalChange(e);
|
|
32
32
|
},
|
|
33
|
-
...
|
|
34
|
-
...
|
|
35
|
-
...
|
|
36
|
-
...
|
|
37
|
-
...
|
|
38
|
-
query: async (e) =>
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
...f.changeScope === void 0 ? {} : { changeScope: f.changeScope },
|
|
34
|
+
...f.withNamespace === void 0 ? {} : { withNamespace: (e) => m(f.withNamespace(e), h) },
|
|
35
|
+
...f.raw === void 0 ? {} : { raw: ((...e) => f.raw(...e)) },
|
|
36
|
+
...f.close === void 0 ? {} : { close: (e) => f.close(e) },
|
|
37
|
+
...f.ping === void 0 ? {} : { ping: () => f.ping() },
|
|
38
|
+
query: async (e) => x(e.table, await f.query(e)),
|
|
39
|
+
...f.integrityQuery === void 0 ? {} : { integrityQuery: async (e) => x(e.table, await f.integrityQuery(e)) },
|
|
40
|
+
insert: async (e, t) => S(e, await f.insert(e, b(e, t))),
|
|
41
|
+
insertMany: async (t, n, r) => {
|
|
42
|
+
let i = s(t), o = g ? n.map((e) => u(e, i, g)) : n, c = a(o, i, e());
|
|
43
|
+
return x(t, await f.insertMany(t, c, r));
|
|
43
44
|
},
|
|
44
|
-
update: async (e, t, n) =>
|
|
45
|
+
update: async (e, t, n) => S(e, await f.update(e, t, (l(n, s(e), t), b(e, n, t))), t),
|
|
45
46
|
updateMany: async (e, t, n) => {
|
|
46
47
|
let r = s(e), i = (r === void 0 ? [] : o(r)).filter((e) => t[e] !== void 0 && t[e] !== null);
|
|
47
48
|
if (i.length > 0) throw Error(`updateMany on the boot store cannot write the .encrypted() column(s) ${i.join(", ")} on "${e}": an encrypted value is bound to its row and a set-based write has no row. Write them through the request-scoped store, or key the write with update(table, id, patch).`);
|
|
48
|
-
return
|
|
49
|
+
return f.updateMany(e, b(e, t), n);
|
|
49
50
|
},
|
|
50
51
|
upsert: async (e, n, r) => {
|
|
51
|
-
let i =
|
|
52
|
-
return
|
|
52
|
+
let i = d(r), a = await t(f, e, n, r.conflictColumns);
|
|
53
|
+
return S(e, await f.upsert(e, b(e, n, a), {
|
|
53
54
|
...r,
|
|
54
|
-
...r.updateValues === void 0 ? {} : { updateValues:
|
|
55
|
+
...r.updateValues === void 0 ? {} : { updateValues: b(e, i, a) }
|
|
55
56
|
}), a);
|
|
56
57
|
},
|
|
57
|
-
insertIgnore: async (e, t, n) =>
|
|
58
|
+
insertIgnore: async (e, t, n) => S(e, await f.insertIgnore(e, b(e, t), n)),
|
|
58
59
|
insertIgnoreWithOutcome: async (e, t, n) => {
|
|
59
|
-
let r = await
|
|
60
|
+
let r = await f.insertIgnoreWithOutcome(e, b(e, t), n);
|
|
60
61
|
return {
|
|
61
|
-
row:
|
|
62
|
+
row: S(e, r.row),
|
|
62
63
|
outcome: r.outcome
|
|
63
64
|
};
|
|
64
65
|
},
|
|
65
|
-
patchJson: async (e, t, n, r, i) =>
|
|
66
|
-
transactional: (e) =>
|
|
66
|
+
patchJson: async (e, t, n, r, i) => S(e, await f.patchJson(e, t, n, r, b(e, c(t, n, i), t)), t),
|
|
67
|
+
transactional: (e) => f.transactional((t) => e(m(t, h)))
|
|
67
68
|
};
|
|
68
69
|
};
|
|
69
70
|
//#endregion
|
|
70
|
-
export {
|
|
71
|
+
export { m as wrapStoreWithBootCodec };
|
package/dist/circuitBreaker.js
CHANGED
|
@@ -1,72 +1 @@
|
|
|
1
|
-
|
|
2
|
-
//#region src/circuitBreaker.ts
|
|
3
|
-
var o = class extends a.TaggedError()("CircuitOpen", {
|
|
4
|
-
name: a.String,
|
|
5
|
-
retryAfterMs: a.Number
|
|
6
|
-
}) {}, s = {
|
|
7
|
-
tag: "closed",
|
|
8
|
-
failureCount: 0,
|
|
9
|
-
halfOpenSuccesses: 0,
|
|
10
|
-
openedAt: 0
|
|
11
|
-
}, c = { make: (a) => r.gen(function* () {
|
|
12
|
-
let c = a.name ?? "circuit", l = n.toMillis(n.fromInputUnsafe(a.resetTimeout)), u = a.halfOpenSuccessThreshold ?? 1, d = a.isFailure ?? (() => !0), f = yield* i.make(s), p = r.gen(function* () {
|
|
13
|
-
let e = yield* i.get(f);
|
|
14
|
-
if (e.tag === "half-open") {
|
|
15
|
-
let t = e.halfOpenSuccesses + 1;
|
|
16
|
-
yield* i.set(f, t >= u ? s : {
|
|
17
|
-
...e,
|
|
18
|
-
halfOpenSuccesses: t
|
|
19
|
-
});
|
|
20
|
-
} else e.failureCount !== 0 && (yield* i.set(f, s));
|
|
21
|
-
}), m = r.gen(function* () {
|
|
22
|
-
let e = yield* t.currentTimeMillis, n = yield* i.get(f);
|
|
23
|
-
if (n.tag === "half-open" || n.tag === "open") {
|
|
24
|
-
yield* i.set(f, {
|
|
25
|
-
tag: "open",
|
|
26
|
-
failureCount: a.failureThreshold,
|
|
27
|
-
halfOpenSuccesses: 0,
|
|
28
|
-
openedAt: e
|
|
29
|
-
});
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
let r = n.failureCount + 1;
|
|
33
|
-
yield* i.set(f, r >= a.failureThreshold ? {
|
|
34
|
-
tag: "open",
|
|
35
|
-
failureCount: r,
|
|
36
|
-
halfOpenSuccesses: 0,
|
|
37
|
-
openedAt: e
|
|
38
|
-
} : {
|
|
39
|
-
...n,
|
|
40
|
-
failureCount: r
|
|
41
|
-
});
|
|
42
|
-
}), h = r.gen(function* () {
|
|
43
|
-
let e = yield* i.get(f);
|
|
44
|
-
if (e.tag !== "open") return null;
|
|
45
|
-
let n = (yield* t.currentTimeMillis) - e.openedAt;
|
|
46
|
-
return n >= l ? (yield* i.set(f, {
|
|
47
|
-
tag: "half-open",
|
|
48
|
-
failureCount: 0,
|
|
49
|
-
halfOpenSuccesses: 0,
|
|
50
|
-
openedAt: e.openedAt
|
|
51
|
-
}), null) : l - n;
|
|
52
|
-
}), g = (t) => r.gen(function* () {
|
|
53
|
-
let n = yield* h;
|
|
54
|
-
return n === null ? yield* t.pipe(r.tap(() => p), r.tapCause((t) => {
|
|
55
|
-
if (e.hasInterruptsOnly(t)) return r.void;
|
|
56
|
-
let n = e.findErrorOption(t), i = n._tag === "Some" ? n.value : void 0;
|
|
57
|
-
return d(i) ? m : r.void;
|
|
58
|
-
})) : yield* r.fail(new o({
|
|
59
|
-
name: c,
|
|
60
|
-
retryAfterMs: n
|
|
61
|
-
}));
|
|
62
|
-
}), _ = ((e) => g(e));
|
|
63
|
-
return Object.defineProperty(_, "state", {
|
|
64
|
-
value: i.get(f).pipe(r.map((e) => e.tag)),
|
|
65
|
-
enumerable: !0
|
|
66
|
-
}), Object.defineProperty(_, "reset", {
|
|
67
|
-
value: i.set(f, s),
|
|
68
|
-
enumerable: !0
|
|
69
|
-
}), _;
|
|
70
|
-
}) };
|
|
71
|
-
//#endregion
|
|
72
|
-
export { c as CircuitBreaker, o as CircuitOpen };
|
|
1
|
+
export { CircuitBreaker, CircuitOpen } from "@voltro/shared";
|
package/dist/composeAnalytics.js
CHANGED
|
@@ -86,22 +86,43 @@ var n = "noop", r = () => {
|
|
|
86
86
|
...d === void 0 ? {} : { mirror: d }
|
|
87
87
|
};
|
|
88
88
|
}, a = (e) => {
|
|
89
|
-
let n = e.
|
|
90
|
-
|
|
89
|
+
let n = [...e], r, a, o = () => t.suspend(() => t.forEach([...r ?? []].reverse(), (e) => e.released ? t.void : (e.released = !0, e.spec.dispose === void 0 ? t.void : t.suspend(() => e.spec.dispose(e.sink)).pipe(t.catchCause(() => t.logWarning("analytics member teardown failed")))), {
|
|
90
|
+
concurrency: 1,
|
|
91
|
+
discard: !0
|
|
92
|
+
})), s = () => t.promise(() => a ??= t.runPromise(o())), c = (e) => {
|
|
93
|
+
if (r !== void 0) throw Error("An analytics composite belongs to one app owner");
|
|
94
|
+
r = [];
|
|
95
|
+
for (let t of n) {
|
|
96
|
+
if (t.sql === "required" && e === void 0) throw Error("Analytics member requires SQL");
|
|
97
|
+
let n = t.sql === "required" ? t.build(e) : t.build();
|
|
98
|
+
r.push({
|
|
99
|
+
spec: t,
|
|
100
|
+
sink: n,
|
|
101
|
+
released: !1
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
return i(r.map((e) => e.sink));
|
|
105
|
+
}, l = {
|
|
91
106
|
kind: "compose",
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
initialize: (n) => t.forEach(e, (e) => e.initialize ? e.initialize(n) : t.void, {
|
|
107
|
+
tables: n.flatMap((e) => e.tables ?? []),
|
|
108
|
+
initialize: () => t.suspend(() => r === void 0 ? t.die(/* @__PURE__ */ Error("Build analytics members before initialization")) : t.forEach(r, (e) => e.spec.initialize === void 0 ? t.void : t.suspend(() => e.spec.initialize(e.sink)), {
|
|
95
109
|
concurrency: 1,
|
|
96
110
|
discard: !0
|
|
97
|
-
}),
|
|
98
|
-
...n.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
111
|
+
}).pipe(t.onError(s))),
|
|
112
|
+
...n.some((e) => e.dispose !== void 0) ? { dispose: s } : {}
|
|
113
|
+
};
|
|
114
|
+
return n.some((e) => e.sql === "required") ? {
|
|
115
|
+
...l,
|
|
116
|
+
sql: "required",
|
|
117
|
+
build: (e) => c(e)
|
|
118
|
+
} : {
|
|
119
|
+
...l,
|
|
120
|
+
sql: "none",
|
|
121
|
+
build: () => c()
|
|
102
122
|
};
|
|
103
123
|
}, o = {
|
|
104
124
|
kind: "noop",
|
|
125
|
+
sql: "none",
|
|
105
126
|
build: () => r()
|
|
106
127
|
};
|
|
107
128
|
//#endregion
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { canonicalize as e } from "./fingerprint.js";
|
|
2
|
+
import { currentRawReads as t, runWithRawReadScope as n } from "./rawReadScope.js";
|
|
3
|
+
import { classifyRead as r } from "./readClassification.js";
|
|
4
|
+
import { buildSubjectKey as i } from "./rywPositionStore.js";
|
|
5
|
+
import { runWithRoutingContext as a } from "./replicatedDataStore.js";
|
|
6
|
+
import { Effect as o, Option as s, Schema as c } from "effect";
|
|
7
|
+
import { createHash as l } from "node:crypto";
|
|
8
|
+
import { parseRevalidateMs as u, schemaShape as d, shapeDigest as f } from "@voltro/protocol";
|
|
9
|
+
import { AsyncLocalStorage as p } from "node:async_hooks";
|
|
10
|
+
//#region src/computedQueryCache.ts
|
|
11
|
+
var m = Symbol.for("@voltro/runtime:computed-query-cache-capture"), h = () => {
|
|
12
|
+
let e = globalThis, t = e[m];
|
|
13
|
+
return t === void 0 && (t = {
|
|
14
|
+
storage: new p(),
|
|
15
|
+
installed: !1
|
|
16
|
+
}, e[m] = t), t;
|
|
17
|
+
}, g = () => {
|
|
18
|
+
h().installed = !0;
|
|
19
|
+
}, _ = () => h().installed, v = () => {
|
|
20
|
+
h().installed = !1;
|
|
21
|
+
}, y = (e) => {
|
|
22
|
+
let t = h().storage.getStore();
|
|
23
|
+
if (t === void 0) return;
|
|
24
|
+
let { composed: n, restricting: i } = r(e, !1);
|
|
25
|
+
for (let e of n) t.tables.add(e);
|
|
26
|
+
for (let e of i) t.tables.add(e);
|
|
27
|
+
}, b = Symbol.for("@voltro/runtime:query-dependencies"), x = () => {
|
|
28
|
+
let e = globalThis, t = e[b];
|
|
29
|
+
return t === void 0 && (t = { storage: new p() }, e[b] = t), t;
|
|
30
|
+
}, S = () => {
|
|
31
|
+
x().storage.enterWith(/* @__PURE__ */ new Set());
|
|
32
|
+
}, C = () => [...x().storage.getStore() ?? []], w = (e) => {
|
|
33
|
+
x().storage.getStore()?.add(e), h().storage.getStore()?.tables.add(e);
|
|
34
|
+
}, T = (e) => {
|
|
35
|
+
h().storage.getStore()?.volatile.add(e);
|
|
36
|
+
}, E = (e, t) => h().storage.run(e, t), D = () => ({
|
|
37
|
+
tables: /* @__PURE__ */ new Set(),
|
|
38
|
+
caller: /* @__PURE__ */ new Set(),
|
|
39
|
+
volatile: /* @__PURE__ */ new Set()
|
|
40
|
+
}), O = /* @__PURE__ */ new Set([
|
|
41
|
+
"connections",
|
|
42
|
+
"apis",
|
|
43
|
+
"kv",
|
|
44
|
+
"cache",
|
|
45
|
+
"webhooks",
|
|
46
|
+
"workflows",
|
|
47
|
+
"events",
|
|
48
|
+
"outbox",
|
|
49
|
+
"transaction",
|
|
50
|
+
"storeForTenant"
|
|
51
|
+
]), k = /* @__PURE__ */ new Set(["access", "connectionState"]), A = (e, t, n) => new Proxy(e, { get(e, r) {
|
|
52
|
+
return typeof r == "string" && !t.has(r) && n.caller.add(`subject.${r}`), Reflect.get(e, r, e);
|
|
53
|
+
} }), j = (e, t, n) => {
|
|
54
|
+
let r = e.request, i = r === void 0 ? void 0 : new Proxy(r, { get(e, r) {
|
|
55
|
+
return r === "subject" ? t : ((r === "clientId" || r === "cookieHeader") && n.caller.add(`request.${r}`), Reflect.get(e, r, e));
|
|
56
|
+
} });
|
|
57
|
+
return new Proxy(e, { get(e, t) {
|
|
58
|
+
if (t === "request" && i !== void 0) return i;
|
|
59
|
+
typeof t == "string" && (O.has(t) && n.volatile.add(`ctx.${t}`), k.has(t) && n.caller.add(`ctx.${t}`));
|
|
60
|
+
let r = Reflect.get(e, t, e);
|
|
61
|
+
return typeof r == "function" ? r.bind(e) : r;
|
|
62
|
+
} });
|
|
63
|
+
}, M = /* @__PURE__ */ new WeakMap(), N = (e) => {
|
|
64
|
+
let t = M.get(e);
|
|
65
|
+
return t === void 0 && (t = c.toCodecJson(e), M.set(e, t)), t;
|
|
66
|
+
}, P = /* @__PURE__ */ new WeakMap(), F = (e) => {
|
|
67
|
+
if (e === void 0) return "none";
|
|
68
|
+
let t = P.get(e);
|
|
69
|
+
return t === void 0 && (t = f(d(e.ast)), P.set(e, t)), t;
|
|
70
|
+
}, I = (t) => {
|
|
71
|
+
let n = t.input === void 0 ? s.some(t.decodedInput) : c.encodeUnknownOption(N(t.input))(t.decodedInput);
|
|
72
|
+
if (s.isNone(n)) return { bypass: "input-not-encodable" };
|
|
73
|
+
let r;
|
|
74
|
+
if (t.scope === "global") r = "g";
|
|
75
|
+
else if (t.scope === "tenant") {
|
|
76
|
+
if (t.subject.tenantId == null) return { bypass: "no-tenant" };
|
|
77
|
+
r = `t:${t.subject.tenantId}`;
|
|
78
|
+
} else {
|
|
79
|
+
if (t.subject.type === "anonymous" || t.subject.id == null || t.subject.id === "") return { bypass: "anonymous-subject" };
|
|
80
|
+
r = `s:${t.subject.id}`;
|
|
81
|
+
}
|
|
82
|
+
let i = t.rowFilter === void 0 ? [] : [...t.declaredSources].sort().map((n) => [n, e(t.rowFilter(n) ?? null)]), a;
|
|
83
|
+
try {
|
|
84
|
+
a = JSON.stringify([
|
|
85
|
+
t.codeIdentity,
|
|
86
|
+
F(t.output),
|
|
87
|
+
e(n.value),
|
|
88
|
+
i
|
|
89
|
+
]);
|
|
90
|
+
} catch {
|
|
91
|
+
return { bypass: "input-not-encodable" };
|
|
92
|
+
}
|
|
93
|
+
let o = l("sha256").update(a).digest("base64url");
|
|
94
|
+
return { key: `cq:${t.name}:${o}:${r}` };
|
|
95
|
+
}, L = (e) => {
|
|
96
|
+
if (e.aborted) return { refused: {
|
|
97
|
+
reason: "aborted",
|
|
98
|
+
detail: []
|
|
99
|
+
} };
|
|
100
|
+
if (e.cacheScope !== "subject" && e.scope.caller.size > 0) return { refused: {
|
|
101
|
+
reason: "caller",
|
|
102
|
+
detail: [...e.scope.caller].sort()
|
|
103
|
+
} };
|
|
104
|
+
if (!e.volatileAllowed && e.scope.volatile.size > 0) return { refused: {
|
|
105
|
+
reason: "volatile",
|
|
106
|
+
detail: [...e.scope.volatile].sort()
|
|
107
|
+
} };
|
|
108
|
+
let t = e.rawReads.filter((e) => e.dependsOn.length === 0).map((e) => e.sql);
|
|
109
|
+
if (t.length > 0) return { refused: {
|
|
110
|
+
reason: "undeclared-raw-read",
|
|
111
|
+
detail: t
|
|
112
|
+
} };
|
|
113
|
+
let n = new Set(e.declaredSources);
|
|
114
|
+
for (let t of e.scope.tables) n.add(t);
|
|
115
|
+
for (let t of e.rawReads) for (let e of t.dependsOn) n.add(e);
|
|
116
|
+
if (e.rowFilter !== void 0) {
|
|
117
|
+
let t = new Set(e.declaredSources), r = [...n].filter((n) => !t.has(n) && e.rowFilter(n) !== void 0).sort();
|
|
118
|
+
if (r.length > 0) return { refused: {
|
|
119
|
+
reason: "row-filter-outside-source",
|
|
120
|
+
detail: r
|
|
121
|
+
} };
|
|
122
|
+
}
|
|
123
|
+
let r = e.output === void 0 ? s.some(e.value) : c.encodeUnknownOption(N(e.output))(e.value);
|
|
124
|
+
if (s.isNone(r)) return { refused: {
|
|
125
|
+
reason: "output-not-encodable",
|
|
126
|
+
detail: []
|
|
127
|
+
} };
|
|
128
|
+
let i;
|
|
129
|
+
try {
|
|
130
|
+
i = Buffer.byteLength(JSON.stringify(r.value) ?? "", "utf8");
|
|
131
|
+
} catch {
|
|
132
|
+
return { refused: {
|
|
133
|
+
reason: "output-not-encodable",
|
|
134
|
+
detail: []
|
|
135
|
+
} };
|
|
136
|
+
}
|
|
137
|
+
return i > e.maxEntryBytes ? { refused: {
|
|
138
|
+
reason: "oversized",
|
|
139
|
+
detail: [`${i} bytes`]
|
|
140
|
+
} } : { store: {
|
|
141
|
+
stored: r.value,
|
|
142
|
+
tags: [...n].sort()
|
|
143
|
+
} };
|
|
144
|
+
}, R = (e, t) => e === void 0 ? s.some(t) : c.decodeUnknownOption(N(e))(t), z = (e, t) => {
|
|
145
|
+
let n = t.detail.join(", ");
|
|
146
|
+
switch (t.reason) {
|
|
147
|
+
case "caller": return `${e}: \`cache:\` result NOT kept — the handler read ${n}, which its cache scope does not key on, so the value is specific to this caller. Use \`scope: 'subject'\`, or derive the result without reading the caller (declare access in \`guards:\`; a membership the handler READS through ctx.store is fine — it becomes a dependency).`;
|
|
148
|
+
case "volatile": return `${e}: \`cache:\` result NOT kept — the handler used ${n}, which no table write invalidates. Declare \`cache: { …, volatile: true }\` to accept the ttl as the bound on that staleness, or drop \`cache:\`.`;
|
|
149
|
+
case "undeclared-raw-read": return `${e}: \`cache:\` result NOT kept — a raw read declares no tables, so no write could invalidate it: ${n}. Declare them: ctx.store.raw(fragment, { dependsOn: ['…'] }).`;
|
|
150
|
+
case "row-filter-outside-source": return `${e}: \`cache:\` result NOT kept — the registered row filter restricts ${n}, which the query reads but does not declare in \`source:\`. Add it to \`source:\` so the entry is keyed by what this caller may see there.`;
|
|
151
|
+
case "output-not-encodable": return `${e}: \`cache:\` result NOT kept — the value does not encode through the query's \`output\` schema.`;
|
|
152
|
+
case "oversized": return `${e}: \`cache:\` result NOT kept — ${n} exceeds the cache's maxEntryBytes.`;
|
|
153
|
+
case "aborted": return `${e}: \`cache:\` result NOT kept — the subscription closed while it was computed.`;
|
|
154
|
+
}
|
|
155
|
+
}, B = (e) => {
|
|
156
|
+
let r = o.suspend(() => {
|
|
157
|
+
let r = D(), s = new Set(e.policy.scope === "tenant" ? ["tenantId"] : []), c = e.policy.scope === "subject" ? e.subject : A(e.subject, s, r), l = j(e.ctx, c, r), u = [], d = e.subject.id ?? "anonymous", f = {
|
|
158
|
+
subjectKey: i(d, void 0),
|
|
159
|
+
forcePrimary: !0
|
|
160
|
+
};
|
|
161
|
+
return o.tryPromise({
|
|
162
|
+
try: () => E(r, () => a(f, () => n(async () => {
|
|
163
|
+
let n = await e.execute(l, c);
|
|
164
|
+
return u = t(), n;
|
|
165
|
+
}))),
|
|
166
|
+
catch: (e) => e
|
|
167
|
+
}).pipe(o.map((t) => {
|
|
168
|
+
let n = new Set(e.sources), i = (e) => [...new Set(e)].filter((e) => !n.has(e)).sort();
|
|
169
|
+
if (e.isDescriptor(t)) return e.onDescriptor(), {
|
|
170
|
+
value: {
|
|
171
|
+
value: t,
|
|
172
|
+
dependencies: []
|
|
173
|
+
},
|
|
174
|
+
notApplicable: !0
|
|
175
|
+
};
|
|
176
|
+
let a = L({
|
|
177
|
+
scope: r,
|
|
178
|
+
cacheScope: e.policy.scope,
|
|
179
|
+
volatileAllowed: e.policy.volatile,
|
|
180
|
+
rawReads: u,
|
|
181
|
+
declaredSources: e.sources,
|
|
182
|
+
rowFilter: e.rowFilter,
|
|
183
|
+
output: e.output,
|
|
184
|
+
value: e.unwrap(t),
|
|
185
|
+
maxEntryBytes: e.cache.maxEntryBytes,
|
|
186
|
+
aborted: e.signal?.aborted === !0
|
|
187
|
+
});
|
|
188
|
+
if ("refused" in a) return a.refused.reason !== "aborted" && e.cache.notice(e.name, a.refused.reason, z(e.name, a.refused)), { value: {
|
|
189
|
+
value: t,
|
|
190
|
+
dependencies: i(r.tables)
|
|
191
|
+
} };
|
|
192
|
+
let o = i(a.store.tags);
|
|
193
|
+
return {
|
|
194
|
+
value: {
|
|
195
|
+
value: t,
|
|
196
|
+
dependencies: o
|
|
197
|
+
},
|
|
198
|
+
store: {
|
|
199
|
+
stored: {
|
|
200
|
+
v: a.store.stored,
|
|
201
|
+
d: o
|
|
202
|
+
},
|
|
203
|
+
tags: a.store.tags
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
}));
|
|
207
|
+
});
|
|
208
|
+
return e.cache.wrapDynamic(e.key, {
|
|
209
|
+
ttlMs: e.policy.ttlMs,
|
|
210
|
+
...e.policy.swrMs === void 0 ? {} : { swrMs: e.policy.swrMs },
|
|
211
|
+
...e.cache.leaseMs === void 0 ? {} : { leaseMs: e.cache.leaseMs },
|
|
212
|
+
label: e.name
|
|
213
|
+
}, r, (t) => o.succeed(V(e.output, t))).pipe(o.map(({ value: e }) => e));
|
|
214
|
+
}, V = (e, t) => {
|
|
215
|
+
if (typeof t != "object" || !t || !("v" in t) || !("d" in t)) return s.none();
|
|
216
|
+
let n = t;
|
|
217
|
+
return !Array.isArray(n.d) || !n.d.every((e) => typeof e == "string") ? s.none() : s.map(R(e, n.v), (e) => ({
|
|
218
|
+
value: e,
|
|
219
|
+
dependencies: n.d
|
|
220
|
+
}));
|
|
221
|
+
}, H = (e) => {
|
|
222
|
+
let t = u(e.ttl);
|
|
223
|
+
if (t !== null) return {
|
|
224
|
+
ttlMs: t,
|
|
225
|
+
swrMs: e.swr === void 0 ? void 0 : u(e.swr) ?? void 0,
|
|
226
|
+
scope: e.scope,
|
|
227
|
+
volatile: e.volatile === !0
|
|
228
|
+
};
|
|
229
|
+
};
|
|
230
|
+
//#endregion
|
|
231
|
+
export { B as cachedComputedCall, I as computedCacheKey, _ as computedQueryCacheCaptureInstalled, C as currentQueryDependencies, L as decideComputedStore, R as decodeComputedStored, z as describeComputedRefusal, S as enterQueryDependencies, g as installComputedQueryCacheCapture, D as newComputedCaptureScope, y as noteCacheRead, T as noteCacheVolatile, w as noteDependency, j as observedContext, A as observedSubject, H as queryCachePolicy, v as resetComputedQueryCacheCaptureForTests, E as runWithComputedCapture };
|
|
@@ -1,42 +1,44 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { noteCacheVolatile as e } from "./computedQueryCache.js";
|
|
2
|
+
import { ConnectionNotConnected as t, listConnectionStates as n, resolveConnection as r } from "./connectionVault.js";
|
|
2
3
|
//#region src/connectionsFacade.ts
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
},
|
|
6
|
-
let n =
|
|
4
|
+
var i, a = (e) => {
|
|
5
|
+
i = e;
|
|
6
|
+
}, o = () => i, s = (e, t) => {
|
|
7
|
+
let n = i;
|
|
7
8
|
return n === void 0 ? Promise.reject(/* @__PURE__ */ Error(`resolveConnectionForSubject("${t}"): no connection vault is registered — the app declares no \`*.connection.ts\`, or this call ran before boot completed.`)) : n(e, t);
|
|
8
|
-
},
|
|
9
|
-
let a =
|
|
10
|
-
if (a === void 0) throw Error(`connection "${i}" is not declared. Declared: ${
|
|
11
|
-
let o =
|
|
12
|
-
if (o === null || o === "") throw new
|
|
13
|
-
return
|
|
14
|
-
store:
|
|
9
|
+
}, c = (e) => async (n, i) => {
|
|
10
|
+
let a = e.registry.get(i);
|
|
11
|
+
if (a === void 0) throw Error(`connection "${i}" is not declared. Declared: ${e.registry.list().map((e) => e.id).join(", ") || "(none)"}.`);
|
|
12
|
+
let o = n.id ?? null;
|
|
13
|
+
if (o === null || o === "") throw new t(i, "<anonymous>");
|
|
14
|
+
return r({
|
|
15
|
+
store: e.store,
|
|
15
16
|
definition: a,
|
|
16
17
|
subjectId: o
|
|
17
18
|
});
|
|
18
|
-
},
|
|
19
|
-
let
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
}, l = (i) => {
|
|
20
|
+
let a = i.subject.id ?? null, o = async (n) => {
|
|
21
|
+
e("ctx.connections");
|
|
22
|
+
let o = i.registry.get(n);
|
|
23
|
+
if (o === void 0) throw Error(`ctx.connections.get("${n}"): no such connection is declared. Declared: ${i.registry.list().map((e) => e.id).join(", ") || "(none)"}.`);
|
|
24
|
+
if (a === null || a === "") throw new t(n, "<anonymous>");
|
|
25
|
+
return r({
|
|
26
|
+
store: i.store,
|
|
27
|
+
definition: o,
|
|
28
|
+
subjectId: a
|
|
27
29
|
});
|
|
28
30
|
};
|
|
29
31
|
return {
|
|
30
|
-
get:
|
|
31
|
-
tryGet: async (
|
|
32
|
+
get: o,
|
|
33
|
+
tryGet: async (e) => {
|
|
32
34
|
try {
|
|
33
|
-
return await
|
|
34
|
-
} catch (
|
|
35
|
-
if (
|
|
36
|
-
throw
|
|
35
|
+
return await o(e);
|
|
36
|
+
} catch (e) {
|
|
37
|
+
if (e instanceof t) return null;
|
|
38
|
+
throw e;
|
|
37
39
|
}
|
|
38
40
|
},
|
|
39
|
-
list: async () =>
|
|
41
|
+
list: async () => a === null || a === "" ? i.registry.list().map((e) => ({
|
|
40
42
|
connectionId: e.id,
|
|
41
43
|
kind: e.kind,
|
|
42
44
|
label: e.label ?? e.id,
|
|
@@ -47,8 +49,8 @@ var r, i = (e) => {
|
|
|
47
49
|
expiresAt: null,
|
|
48
50
|
lastError: null,
|
|
49
51
|
connectedAt: null
|
|
50
|
-
})) :
|
|
52
|
+
})) : n(i.store, i.registry, a)
|
|
51
53
|
};
|
|
52
54
|
};
|
|
53
55
|
//#endregion
|
|
54
|
-
export {
|
|
56
|
+
export { o as getConnectionResolver, c as makeConnectionResolver, l as makeConnectionsFacade, s as resolveConnectionForSubject, a as setConnectionResolver };
|