@voltro/runtime 0.86.0 → 0.88.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 (184) hide show
  1. package/CHANGELOG.md +5484 -0
  2. package/README.md +43 -0
  3. package/THIRD-PARTY-NOTICES.md +1511 -276
  4. package/dist/aggregate.js +1 -2
  5. package/dist/aggregateExtrema.js +1 -2
  6. package/dist/aggregateIvm.js +1 -2
  7. package/dist/analyticsMirror.js +1 -2
  8. package/dist/analyticsSink.js +9 -16
  9. package/dist/apiKeyUsage.js +1 -2
  10. package/dist/apiKeys.js +83 -80
  11. package/dist/apiKeysWiring.js +1 -2
  12. package/dist/apiRoleBucketSampler.js +63 -0
  13. package/dist/apiRoleWorkloadHistory.js +55 -0
  14. package/dist/apiRoleWorkloadMetrics.js +77 -0
  15. package/dist/apiRoleWorkloadStorage.js +94 -0
  16. package/dist/approvalBuiltins.js +1 -2
  17. package/dist/approvals.js +68 -76
  18. package/dist/authMiddlewareLayer.js +8 -8
  19. package/dist/bindEvent.js +49 -30
  20. package/dist/boot-refusal.d.ts +10 -0
  21. package/dist/{bootRefusal.js → boot-refusal.js} +1 -2
  22. package/dist/bootListener.js +203 -47
  23. package/dist/bootStoreCodec.js +39 -39
  24. package/dist/businessRules.js +1 -2
  25. package/dist/changeClaimsTable.js +1 -2
  26. package/dist/circuitBreaker.js +1 -72
  27. package/dist/columnOnUpdate.js +1 -2
  28. package/dist/composeAnalytics.js +32 -12
  29. package/dist/computedQuery.js +1 -2
  30. package/dist/computedQueryCache.js +289 -0
  31. package/dist/connectionBuiltins.js +1 -2
  32. package/dist/connectionCredentials.js +1 -2
  33. package/dist/connectionState.js +1 -2
  34. package/dist/connectionVault.js +1 -2
  35. package/dist/connectionsFacade.js +33 -32
  36. package/dist/coordinatedSchedule.js +85 -80
  37. package/dist/crdtHistory.js +1 -2
  38. package/dist/crdtMerge.js +1 -2
  39. package/dist/crdtVersionsTable.js +1 -2
  40. package/dist/credentialBound.js +1 -2
  41. package/dist/crud.js +1 -2
  42. package/dist/dataStore.js +155 -123
  43. package/dist/dataloader.js +1 -2
  44. package/dist/declaredTablesGuard.js +3 -3
  45. package/dist/defineExecutor.js +1 -2
  46. package/dist/dependencyGraph.js +1 -2
  47. package/dist/devices.js +1 -2
  48. package/dist/devicesWiring.js +1 -2
  49. package/dist/dialectReplicationAdapter.js +1 -2
  50. package/dist/dispatcher.js +404 -330
  51. package/dist/effectStore.js +3 -4
  52. package/dist/engineClients.js +23 -0
  53. package/dist/eventBus.js +1 -2
  54. package/dist/eventPublish.js +1 -2
  55. package/dist/events.js +1 -2
  56. package/dist/expectation.js +1 -2
  57. package/dist/expectationEvaluator.js +2 -3
  58. package/dist/experiment.js +1 -2
  59. package/dist/experimentEvaluator.js +1 -2
  60. package/dist/externalizedTasks.js +20 -8
  61. package/dist/fieldCipher.js +110 -42
  62. package/dist/fieldKeyRegistry.js +294 -0
  63. package/dist/fieldKeyRekey.js +285 -0
  64. package/dist/fieldKeyScan.js +135 -0
  65. package/dist/fieldKeyring.js +76 -0
  66. package/dist/fingerprint.js +1 -2
  67. package/dist/finops.js +1 -2
  68. package/dist/finopsAccountant.js +1 -2
  69. package/dist/handlerBody.js +1 -2
  70. package/dist/healthProbes.js +1 -2
  71. package/dist/hot.d.ts +56 -0
  72. package/dist/hot.js +3 -0
  73. package/dist/hotDataStore.js +147 -0
  74. package/dist/hotDataStoreSnapshot.js +97 -0
  75. package/dist/hotDataStoreTables.js +17 -0
  76. package/dist/http-range.d.ts +53 -0
  77. package/dist/http-range.js +51 -0
  78. package/dist/httpClientSsrf.js +13 -39
  79. package/dist/httpClientTracing.js +13 -11
  80. package/dist/httpCompression.js +18 -19
  81. package/dist/httpInputStream.js +81 -0
  82. package/dist/httpKeepAlive.js +1 -2
  83. package/dist/httpRouteMounts.js +2 -2
  84. package/dist/idempotencyStore.js +93 -54
  85. package/dist/idleDetector.js +1 -2
  86. package/dist/index.d.ts +1185 -452
  87. package/dist/index.js +144 -134
  88. package/dist/insertRequiredColumns.js +1 -2
  89. package/dist/instanceMembership.js +1 -2
  90. package/dist/ivm.js +1 -2
  91. package/dist/kvDataStore.js +1 -2
  92. package/dist/kvFacade.js +24 -19
  93. package/dist/matcher.js +1 -2
  94. package/dist/memoryColumnDefaults.js +1 -2
  95. package/dist/memoryQueryJoins.js +17 -18
  96. package/dist/memorySetOperations.js +42 -0
  97. package/dist/metrics.js +39 -26
  98. package/dist/observability.js +2 -3
  99. package/dist/observedGraph.js +1 -2
  100. package/dist/originGuard.js +1 -2
  101. package/dist/outbox.js +2 -3
  102. package/dist/pluginRefRules.js +1 -2
  103. package/dist/policyGuardResolver.js +1 -2
  104. package/dist/preview.js +1 -2
  105. package/dist/projectedRows.js +1 -2
  106. package/dist/provenance.js +1 -2
  107. package/dist/rangeIndex.js +1 -2
  108. package/dist/rawReadScope.js +2 -3
  109. package/dist/reaction.js +1 -2
  110. package/dist/reactiveConfig.js +1 -2
  111. package/dist/readClassification.js +1 -2
  112. package/dist/readRecorder.js +36 -36
  113. package/dist/readScopePredicate.js +11 -0
  114. package/dist/rebac.js +1 -2
  115. package/dist/rebacInterceptor.js +1 -2
  116. package/dist/registry.js +1 -2
  117. package/dist/relevantFields.js +1 -2
  118. package/dist/replicaHealth.js +1 -2
  119. package/dist/replicaLocality.js +1 -2
  120. package/dist/replicaObservations.js +1 -2
  121. package/dist/replicaSelection.js +1 -2
  122. package/dist/replicatedDataStore.js +23 -6
  123. package/dist/requestLoader.js +1 -2
  124. package/dist/resumeCensus.js +1 -2
  125. package/dist/revalidation.js +1 -2
  126. package/dist/rowFilter.js +57 -41
  127. package/dist/rowStateBytes.js +1 -2
  128. package/dist/rpcBodyCap.js +1 -2
  129. package/dist/rpcConnections.js +9 -10
  130. package/dist/rpcDefectDiagnostics.js +1 -2
  131. package/dist/rpcServer.js +523 -451
  132. package/dist/rpcWorkloadAdmission.js +49 -0
  133. package/dist/runAsSystem.js +1 -2
  134. package/dist/rywPositionStore.js +83 -49
  135. package/dist/schedule.js +1 -2
  136. package/dist/scheduleBackfillRequests.js +1 -2
  137. package/dist/scheduleClaimsTable.js +1 -2
  138. package/dist/scheduleRunsTable.js +1 -2
  139. package/dist/scheduler.js +7 -3
  140. package/dist/schemaRegistry.js +1 -2
  141. package/dist/secretsResolver.js +1 -2
  142. package/dist/securityHeaders.js +1 -2
  143. package/dist/servePipeline.js +238 -154
  144. package/dist/serverOnlyAudit.js +1 -2
  145. package/dist/serverTracer.js +1 -2
  146. package/dist/serviceCredentials.js +1 -2
  147. package/dist/setReadScopes.js +27 -0
  148. package/dist/singleNodeOrchestrator.js +1 -2
  149. package/dist/snapshotValueCodec.js +45 -0
  150. package/dist/sourceResolution.js +35 -26
  151. package/dist/storeMiddleware.js +213 -212
  152. package/dist/storeQuery.js +1 -2
  153. package/dist/storeRead.js +1 -2
  154. package/dist/subscriber.js +2 -2
  155. package/dist/subscriptionOutbox.js +1 -2
  156. package/dist/subscriptionRegistry.js +1 -2
  157. package/dist/subscriptionResume.js +1 -2
  158. package/dist/subscriptionSocketMetrics.js +1 -2
  159. package/dist/systemSubject.js +1 -2
  160. package/dist/tenantScope.js +9 -22
  161. package/dist/tenantSelection.js +1 -2
  162. package/dist/timeline.js +1 -2
  163. package/dist/traceContext.js +1 -2
  164. package/dist/traceSink.js +1 -2
  165. package/dist/traceSpansTable.js +1 -2
  166. package/dist/traceparent.js +9 -21
  167. package/dist/transactionSubject.js +1 -2
  168. package/dist/trustedProxy.js +2 -3
  169. package/dist/undo.js +1 -2
  170. package/dist/undoBuiltins.js +1 -2
  171. package/dist/undoCapture.js +1 -2
  172. package/dist/undoLogTable.js +1 -2
  173. package/dist/upsertBinding.js +1 -2
  174. package/dist/wakeOrchestrator.js +1 -2
  175. package/dist/wakeRegistry.js +1 -2
  176. package/dist/wakeRouter.js +1 -2
  177. package/dist/wakeSupervisor.js +1 -2
  178. package/dist/wakeupsTable.js +1 -2
  179. package/dist/webSocketGatewayRuntime.js +112 -73
  180. package/dist/webhookVerification.js +1 -2
  181. package/dist/wireColumnStrip.js +1 -2
  182. package/dist/workflowReadBuiltins.js +1 -2
  183. package/dist/workflowRuntime.js +10 -11
  184. package/package.json +36 -17
@@ -0,0 +1,51 @@
1
+ // src/httpRange.ts
2
+ var e = { _tag: "ignored" }, t = { _tag: "unsatisfiable" }, n = /^([!#$%&'*+.^_`|~0-9A-Za-z-]+)=(.*)$/s, r = /^(\d*)-(\d*)$/, i = (e) => {
3
+ let t = e.replace(/^0+(?=\d)/, "");
4
+ if (t.length > 16) return;
5
+ let n = Number(t);
6
+ return Number.isSafeInteger(n) ? n : void 0;
7
+ }, a = (e, t) => {
8
+ let n = e.replace(/^0+(?=\d)/, ""), r = t.replace(/^0+(?=\d)/, "");
9
+ return n.length === r.length ? n < r : n.length < r.length;
10
+ }, o = (o, s) => {
11
+ if (o === void 0) return e;
12
+ let c = n.exec(o.trim());
13
+ if (c === null || c[1].toLowerCase() !== "bytes") return e;
14
+ let l = c[2].split(",").map((e) => e.trim()).filter((e) => e !== "");
15
+ if (l.length !== 1) return e;
16
+ let u = r.exec(l[0]);
17
+ if (u === null) return e;
18
+ let [, d = "", f = ""] = u;
19
+ if (d === "") {
20
+ if (f === "") return e;
21
+ let n = i(f);
22
+ return n === 0 || s === 0 ? t : {
23
+ _tag: "satisfiable",
24
+ start: n === void 0 ? 0 : Math.max(0, s - n),
25
+ end: s - 1
26
+ };
27
+ }
28
+ if (f !== "" && a(f, d)) return e;
29
+ let p = i(d);
30
+ if (p === void 0 || p >= s) return t;
31
+ let m = f === "" ? void 0 : i(f);
32
+ return {
33
+ _tag: "satisfiable",
34
+ start: p,
35
+ end: m === void 0 ? s - 1 : Math.min(m, s - 1)
36
+ };
37
+ }, s = /^(W\/)?"[\x21\x23-\x7e\x80-\xff]*"$/, c = /^[A-Za-z]{3}/, l = (e) => {
38
+ let t = e.trim();
39
+ if (!c.test(t)) return;
40
+ let n = Date.parse(/(?:GMT|UTC)$/i.test(t) ? t : `${t} GMT`);
41
+ return Number.isNaN(n) ? void 0 : n;
42
+ }, u = (e, t, n = Date.now()) => {
43
+ if (e === void 0) return !0;
44
+ let r = e.trim();
45
+ if (r.startsWith("\"") || r.startsWith("W/")) return !s.test(r) || r.startsWith("W/") ? !1 : t.etag !== void 0 && !t.etag.startsWith("W/") && t.etag === r;
46
+ let i = l(r);
47
+ if (i === void 0 || t.lastModifiedMs === void 0) return !1;
48
+ let a = Math.floor(t.lastModifiedMs / 1e3);
49
+ return a * 1e3 === i && Math.floor(n / 1e3) > a;
50
+ };
51
+ export { u as ifRangeAllowsRange, o as parseByteRange, l as parseHttpDate };
@@ -1,49 +1,23 @@
1
1
  import { Effect as e, Layer as t } from "effect";
2
- import { HttpClient as n, HttpClientError as r } from "effect/http";
3
- //#region src/httpClientSsrf.ts
4
- var i = class extends Error {
2
+ import { ssrfReason as n, ssrfReason as r } from "@voltro/protocol";
3
+ import { HttpClient as i, HttpClientError as a } from "effect/http";
4
+ // src/httpClientSsrf.ts
5
+ var o = class extends Error {
5
6
  url;
6
7
  reason;
7
8
  _tag = "SsrfBlockedError";
8
9
  constructor(e, t) {
9
10
  super(`SSRF: blocked outbound request to ${e} — ${t}. If this target is intentional, add its host to \`http.allowHosts\` in app.config.ts.`), this.url = e, this.reason = t, this.name = "SsrfBlockedError";
10
11
  }
11
- }, a = (e, t) => e === 0 || e === 10 || e === 127 || e === 100 && t >= 64 && t <= 127 || e === 169 && t === 254 || e === 172 && t >= 16 && t <= 31 || e === 192 && t === 168 || e === 198 && (t === 18 || t === 19) || e >= 224, o = (e) => e === "::" || e === "::1" || e.startsWith("fc") || e.startsWith("fd") || e.startsWith("fe80") || e.startsWith("::ffff:"), s = (e, t, n) => n.some((n) => {
12
- let r = n.trim().toLowerCase();
13
- if (r === "") return !1;
14
- let i = t === "" ? e : `${e}:${t}`;
15
- return r === e || r === i ? !0 : r.startsWith("*.") ? e.endsWith(r.slice(1)) : !1;
16
- }), c = (e, t = {}) => {
17
- let n;
18
- try {
19
- n = new URL(e);
20
- } catch {
21
- return "malformed url";
22
- }
23
- if (n.protocol !== "http:" && n.protocol !== "https:") return `blocked scheme "${n.protocol}"`;
24
- let r = n.hostname.replace(/^\[|\]$/g, "").toLowerCase();
25
- if (s(r, n.port, t.allowHosts ?? [])) return null;
26
- if (r === "localhost" || r.endsWith(".localhost") || r.endsWith(".internal") || r.endsWith(".local")) return `blocked host "${r}"`;
27
- let i = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(r);
28
- if (i) {
29
- let e = Number(i[1]), t = Number(i[2]);
30
- return e > 255 || t > 255 || Number(i[3]) > 255 || Number(i[4]) > 255 ? "malformed ipv4 literal" : a(e, t) ? `blocked private/reserved address ${r}` : null;
31
- }
32
- if (r.includes(":")) {
33
- let e = /^::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/.exec(r);
34
- return e ? c(`${n.protocol}//${e[1]}`, t) : o(r) ? `blocked private/reserved address ${r}` : null;
35
- }
36
- return null;
37
- }, l = (a = {}) => t.effect(n.HttpClient, e.map(n.HttpClient, (t) => {
38
- let o = n.transform(t, (t, n) => e.suspend(() => {
39
- let o = c(n.url, a);
40
- return o === null ? t : e.fail(new r.HttpClientError({ reason: new r.TransportError({
41
- request: n,
42
- cause: new i(n.url, o),
43
- description: `SSRF policy: ${o}`
12
+ }, s = (r = {}) => t.effect(i.HttpClient, e.map(i.HttpClient, (t) => {
13
+ let s = i.transform(t, (t, i) => e.suspend(() => {
14
+ let s = n(i.url, r);
15
+ return s === null ? t : e.fail(new a.HttpClientError({ reason: new a.TransportError({
16
+ request: i,
17
+ cause: new o(i.url, s),
18
+ description: `SSRF policy: ${s}`
44
19
  }) }));
45
20
  }));
46
- return n.followRedirects(o, a.maxRedirects ?? 5);
21
+ return i.followRedirects(s, r.maxRedirects ?? 5);
47
22
  }));
48
- //#endregion
49
- export { i as SsrfBlockedError, l as ssrfGuardHttpClientLayer, c as ssrfReason };
23
+ export { o as SsrfBlockedError, s as ssrfGuardHttpClientLayer, r as ssrfReason };
@@ -1,11 +1,13 @@
1
- import { formatTraceparent as e } from "./traceparent.js";
2
- import { Effect as t, Layer as n } from "effect";
3
- import { HttpClient as r, HttpClientRequest as i } from "effect/http";
4
- //#region src/httpClientTracing.ts
5
- var a = n.effect(r.HttpClient, t.map(r.HttpClient, (n) => n.pipe(r.mapRequestEffect((n) => t.currentSpan.pipe(t.map((t) => n.headers.traceparent === void 0 ? i.setHeader(n, "traceparent", e({
6
- traceId: t.traceId,
7
- spanId: t.spanId,
8
- sampled: t.sampled
9
- })) : n), t.catch(() => t.succeed(n)))))));
10
- //#endregion
11
- export { a as tracingHttpClientLayer };
1
+ import { noteCacheVolatile as e } from "./computedQueryCache.js";
2
+ import { formatTraceparent as t } from "./traceparent.js";
3
+ import { Effect as n, Layer as r } from "effect";
4
+ import { HttpClient as i, HttpClientRequest as a } from "effect/http";
5
+ // src/httpClientTracing.ts
6
+ var o = r.effect(i.HttpClient, n.map(i.HttpClient, (r) => r.pipe(i.mapRequestEffect((r) => n.sync(() => {
7
+ e("HttpClient");
8
+ }).pipe(n.andThen(n.currentSpan), n.map((e) => r.headers.traceparent === void 0 ? a.setHeader(r, "traceparent", t({
9
+ traceId: e.traceId,
10
+ spanId: e.spanId,
11
+ sampled: e.sampled
12
+ })) : r), n.catch(() => n.succeed(r)))))));
13
+ export { o as tracingHttpClientLayer };
@@ -1,5 +1,5 @@
1
1
  import { brotliCompressSync as e, constants as t, gzipSync as n } from "node:zlib";
2
- //#region src/httpCompression.ts
2
+ // src/httpCompression.ts
3
3
  var r = 1024, i = [
4
4
  "text/",
5
5
  "application/json",
@@ -36,32 +36,32 @@ var r = 1024, i = [
36
36
  [t.BROTLI_PARAM_QUALITY]: 4,
37
37
  [t.BROTLI_PARAM_SIZE_HINT]: r.length
38
38
  } })) : new Uint8Array(n(r, { level: 6 })), c = (e) => {
39
- let t = e.options?.enabled ?? !0, n = e.options?.minBytes ?? 1024, r = a(e.contentType), i = r ? { vary: "Accept-Encoding" } : {};
40
- if (!t || !r || e.body.length < n) return {
39
+ let t = e.options?.enabled ?? !0, n = e.options?.minBytes ?? 1024;
40
+ if (!(!t || !a(e.contentType) || e.size < n)) return o(e.acceptEncoding);
41
+ }, l = (e) => {
42
+ let t = a(e.contentType) ? { vary: "Accept-Encoding" } : {}, n = c({
43
+ ...e,
44
+ size: e.body.length
45
+ });
46
+ if (n === void 0) return {
41
47
  bytes: e.body,
42
- headers: i,
48
+ headers: t,
43
49
  compressed: !1
44
50
  };
45
- let c = o(e.acceptEncoding);
46
- if (c === void 0) return {
51
+ let r = s(e.body, n);
52
+ return r.length >= e.body.length ? {
47
53
  bytes: e.body,
48
- headers: i,
49
- compressed: !1
50
- };
51
- let l = s(e.body, c);
52
- return l.length >= e.body.length ? {
53
- bytes: e.body,
54
- headers: i,
54
+ headers: t,
55
55
  compressed: !1
56
56
  } : {
57
- bytes: l,
57
+ bytes: r,
58
58
  headers: {
59
- ...i,
60
- "content-encoding": c
59
+ ...t,
60
+ "content-encoding": n
61
61
  },
62
62
  compressed: !0
63
63
  };
64
- }, l = (e, t) => {
64
+ }, u = (e, t) => {
65
65
  let n = {}, r = [], i = (e) => {
66
66
  for (let t of String(e).split(",")) {
67
67
  let e = t.trim();
@@ -72,5 +72,4 @@ var r = 1024, i = [
72
72
  for (let [e, r] of Object.entries(t)) e.toLowerCase() === "vary" ? i(r) : n[e] = r;
73
73
  return r.length > 0 && (n.vary = r.join(", ")), n;
74
74
  };
75
- //#endregion
76
- export { r as DEFAULT_COMPRESSION_MIN_BYTES, a as isCompressibleContentType, c as maybeCompress, l as mergeCompressionHeaders, o as negotiateEncoding };
75
+ export { r as DEFAULT_COMPRESSION_MIN_BYTES, a as isCompressibleContentType, l as maybeCompress, u as mergeCompressionHeaders, o as negotiateEncoding, c as negotiatedCompression };
@@ -0,0 +1,81 @@
1
+ // src/httpInputStream.ts
2
+ var e = async (e, t, n, r, i) => {
3
+ let a = new AbortController(), o, s = !1, c = e.readableEnded, l = e.destroyed && !c, u = !1, d = 0, f = !1, p = !1, m = () => {
4
+ o?.();
5
+ }, h = () => {
6
+ l = !0, a.abort(), m();
7
+ }, g = () => {
8
+ c = !0, m();
9
+ }, _ = () => {
10
+ e.complete || h();
11
+ };
12
+ e.once("end", g), e.once("error", h), e.once("aborted", h), e.once("close", _), i.addEventListener("abort", h, { once: !0 }), (i.aborted || l) && h();
13
+ let v = { [Symbol.asyncIterator]() {
14
+ if (f) throw Error("HTTP input can only be consumed once");
15
+ return f = !0, {
16
+ async next() {
17
+ if (p) throw Error("Concurrent HTTP input reads are not supported");
18
+ p = !0;
19
+ try {
20
+ for (;;) {
21
+ if (l || a.signal.aborted) throw Error("HTTP input aborted");
22
+ if (u) throw Error("HTTP input exceeds its byte limit");
23
+ if (s) return {
24
+ done: !0,
25
+ value: void 0
26
+ };
27
+ let n = e.read();
28
+ if (n !== null) {
29
+ if (d += n.byteLength, d > t) throw u = !0, Error("HTTP input exceeds its byte limit");
30
+ return {
31
+ done: !1,
32
+ value: n
33
+ };
34
+ }
35
+ if (c) return {
36
+ done: !0,
37
+ value: void 0
38
+ };
39
+ await new Promise((t) => {
40
+ let n = () => {
41
+ e.off("readable", n), o = void 0, t();
42
+ };
43
+ o = n, e.once("readable", n);
44
+ });
45
+ }
46
+ } finally {
47
+ p = !1;
48
+ }
49
+ },
50
+ async return() {
51
+ return s = !0, m(), {
52
+ done: !0,
53
+ value: void 0
54
+ };
55
+ }
56
+ };
57
+ } }, y = () => ({
58
+ status: 413,
59
+ body: "payload too large",
60
+ contentType: "text/plain"
61
+ }), b;
62
+ try {
63
+ let e = new Promise((e, t) => {
64
+ b = () => t(/* @__PURE__ */ Error("HTTP input aborted")), a.signal.addEventListener("abort", b, { once: !0 }), a.signal.aborted && b();
65
+ }), t = await Promise.race([e, Promise.resolve().then(() => {
66
+ if (a.signal.aborted) throw Error("HTTP input aborted");
67
+ return r({
68
+ ...n,
69
+ body: v,
70
+ signal: a.signal
71
+ });
72
+ })]);
73
+ return u ? y() : t;
74
+ } catch (e) {
75
+ if (u) return y();
76
+ throw e;
77
+ } finally {
78
+ s = !0, b !== void 0 && a.signal.removeEventListener("abort", b), a.abort(), m(), e.off("end", g), e.off("error", h), e.off("aborted", h), e.off("close", _), i.removeEventListener("abort", h), !e.destroyed && !e.readableEnded && e.resume();
79
+ }
80
+ };
81
+ export { e as dispatchHttpInputStream };
@@ -1,4 +1,4 @@
1
- //#region src/httpKeepAlive.ts
1
+ // src/httpKeepAlive.ts
2
2
  var e = 72e3, t = 5e3, n = (e) => typeof e == "number" && Number.isFinite(e) && e > 0 ? Math.floor(e) : void 0, r = (e) => {
3
3
  let r = n(e?.http?.keepAliveTimeoutMs) ?? 72e3, i = n(e?.http?.headersTimeoutMs);
4
4
  return {
@@ -8,5 +8,4 @@ var e = 72e3, t = 5e3, n = (e) => typeof e == "number" && Number.isFinite(e) &&
8
8
  }, i = (e, t) => {
9
9
  e.keepAliveTimeout = t.keepAliveTimeoutMs, e.headersTimeout = t.headersTimeoutMs;
10
10
  };
11
- //#endregion
12
11
  export { e as DEFAULT_KEEP_ALIVE_MS, t as HEADERS_TIMEOUT_MARGIN_MS, i as applyKeepAlive, r as resolveKeepAlive };
@@ -1,6 +1,6 @@
1
1
  import { FindMyWay as e } from "effect/http";
2
2
  import { routeAcceptsPath as t } from "@voltro/protocol/rest";
3
- //#region src/httpRouteMounts.ts
3
+ // src/httpRouteMounts.ts
4
4
  var n = (e) => e.split("/").map((e) => e.startsWith(":") ? ":param" : e).join("/"), r = (e) => {
5
5
  if (e.some((e) => e.method === "*")) return ["*"];
6
6
  let t = /* @__PURE__ */ new Set();
@@ -14,6 +14,7 @@ var n = (e) => e.split("/").map((e) => e.startsWith(":") ? ":param" : e).join("/
14
14
  }
15
15
  let i = [];
16
16
  t.forEach((e, t) => {
17
+ if (e.some((e) => e.handleStream !== void 0) && (e.length !== 1 || e[0].match !== "exact" || e[0].path.endsWith("/*"))) throw Error("A streamed HTTP input requires an exclusive exact route path");
17
18
  i.push({
18
19
  mountPath: t,
19
20
  routes: e,
@@ -43,5 +44,4 @@ var n = (e) => e.split("/").map((e) => e.startsWith(":") ? ":param" : e).join("/
43
44
  return n !== void 0 && n.routes.some((n) => t(n, e)) ? n : void 0;
44
45
  };
45
46
  }, o = (e) => a(e.filter((e) => !e.methods.includes("*") && (e.routes.length > 1 || e.routes[0]?.answersOtherMethods === !0)));
46
- //#endregion
47
47
  export { a as makeHttpRouteGroupFinder, o as makeUnmatchedGroupFinder, i as planHttpRouteMounts };
@@ -1,70 +1,109 @@
1
1
  import { and as e, eq as t, generateId as n, lte as r } from "@voltro/database";
2
- import { freshFor as i, tsMs as a } from "@voltro/protocol";
3
- //#region src/idempotencyStore.ts
4
- var o = "_voltro_idempotency", s = (e) => {
5
- if (e == null) return null;
6
- let t = typeof e == "string" ? JSON.parse(e) : e;
7
- return t && typeof t == "object" && "status" in t ? t : null;
8
- }, c = (e) => ({
9
- scope: e.scope,
10
- key: e.key,
11
- status: e.status === "completed" ? "completed" : "in_flight",
12
- response: s(e.response),
13
- createdAt: a(e.createdAt)
14
- }), l = async (n, r, i) => (await n.query({
15
- table: o,
2
+ import { freshFor as i } from "@voltro/protocol";
3
+ // src/idempotencyStore.ts
4
+ var a = "_voltro_idempotency", o = () => /* @__PURE__ */ Error("Stored idempotency receipt is invalid"), s = (e) => {
5
+ if (e === null) return null;
6
+ try {
7
+ let t = typeof e == "string" ? JSON.parse(e) : e;
8
+ if (t === null) return null;
9
+ if (typeof t != "object") throw o();
10
+ let n = Object.getPrototypeOf(t);
11
+ if (n !== Object.prototype && n !== null) throw o();
12
+ let r = Object.getOwnPropertyDescriptor(t, "status"), i = r && "value" in r ? r.value : void 0;
13
+ if (typeof i != "number" || !Number.isInteger(i) || i < 100 || i > 999) throw o();
14
+ let a = Object.getOwnPropertyDescriptor(t, "body");
15
+ if (a && !("value" in a)) throw o();
16
+ let s = a?.value, c = Object.getOwnPropertyDescriptor(t, "rest");
17
+ if (c && !("value" in c)) throw o();
18
+ return {
19
+ status: i,
20
+ body: s,
21
+ ...c ? { rest: c.value } : {}
22
+ };
23
+ } catch {
24
+ throw o();
25
+ }
26
+ }, c = (e) => {
27
+ try {
28
+ let t = e instanceof Date ? Date.prototype.getTime.call(e) : typeof e == "number" || typeof e == "string" ? new Date(e).getTime() : NaN;
29
+ if (!Number.isFinite(t) || typeof e == "number" && t !== e) throw o();
30
+ return t;
31
+ } catch {
32
+ throw o();
33
+ }
34
+ }, l = (e) => {
35
+ if (typeof e.id != "string" || e.id.length === 0 || typeof e.scope != "string" || typeof e.key != "string" || e.status !== "in_flight" && e.status !== "completed" || e.inputHash != null && (typeof e.inputHash != "string" || !/^[0-9a-f]{64}$/.test(e.inputHash))) throw o();
36
+ let t = c(e.createdAt), n = s(e.response);
37
+ if (e.status === "in_flight" != (n === null)) throw o();
38
+ return {
39
+ scope: e.scope,
40
+ key: e.key,
41
+ inputHash: e.inputHash ?? null,
42
+ status: e.status,
43
+ response: n,
44
+ createdAt: t
45
+ };
46
+ }, u = async (n, r, i) => (await n.query({
47
+ table: a,
16
48
  predicate: e(t("scope", r), t("key", i)),
17
49
  order: [],
18
50
  take: 1,
19
51
  skip: void 0,
20
52
  projection: void 0
21
- }))[0] ?? null, u = (a) => ({
53
+ }))[0] ?? null, d = (n) => e(t("id", n.id), t("scope", n.scope), t("key", n.key), t("inputHash", n.inputHash), t("status", "in_flight")), f = (o) => ({
22
54
  get: async (e, t) => {
23
- let n = await l(a, e, t);
24
- return n ? c(n) : null;
55
+ let n = await u(o, e, t);
56
+ return n ? l(n) : null;
25
57
  },
26
- claim: async (s, u, d, f, p) => {
27
- for (let l = 0; l < 2; l++) {
28
- let l = n({
58
+ claim: async (s, c, d, f, p, m) => {
59
+ for (let u = 0; u < 2; u++) {
60
+ let u = n({
29
61
  kind: "typeid",
30
62
  prefix: "idem"
31
- }, o), m = await a.insertIgnore(o, {
32
- id: l,
63
+ }, a), h = await o.insertIgnore(a, {
64
+ id: u,
33
65
  scope: s,
34
- key: u,
66
+ key: c,
67
+ inputHash: d,
35
68
  status: "in_flight",
36
69
  response: null,
37
- createdAt: new Date(d)
38
- }, { conflictColumns: ["scope", "key"] });
39
- if (m.id === l) return "claimed";
40
- let h = c(m), g = i(h.status, f, p);
41
- if (d - h.createdAt < g) return h;
42
- await a.deleteMany(o, { where: e(t("id", m.id), r("createdAt", new Date(d - g))) });
70
+ createdAt: new Date(f)
71
+ }, { conflictColumns: ["scope", "key"] }), g = l(h);
72
+ if (h.id === u) {
73
+ if (g.scope !== s || g.key !== c || g.inputHash !== d || g.status !== "in_flight" || g.response !== null) throw Error("Idempotency acquisition did not retain the expected input witness");
74
+ return {
75
+ kind: "claimed",
76
+ claim: Object.freeze({
77
+ scope: s,
78
+ key: c,
79
+ id: u,
80
+ inputHash: d
81
+ })
82
+ };
83
+ }
84
+ if (g.inputHash !== d) return {
85
+ kind: "existing",
86
+ record: g
87
+ };
88
+ let _ = i(g.status, p, m);
89
+ if (f - g.createdAt < _) return {
90
+ kind: "existing",
91
+ record: g
92
+ };
93
+ await o.deleteMany(a, { where: e(t("id", h.id), t("scope", s), t("key", c), t("inputHash", d), t("status", h.status), r("createdAt", new Date(f - _))) });
43
94
  }
44
- let m = await l(a, s, u);
45
- return m ? c(m) : {
46
- scope: s,
47
- key: u,
48
- status: "in_flight",
49
- response: null,
50
- createdAt: d
51
- };
95
+ let h = await u(o, s, c);
96
+ return h ? {
97
+ kind: "existing",
98
+ record: l(h)
99
+ } : { kind: "conflict" };
52
100
  },
53
- complete: async (e, t, n, r) => {
54
- let i = await l(a, e, t);
55
- i && await a.update(o, i.id, {
56
- status: "completed",
57
- response: n
58
- });
59
- },
60
- renew: async (e, t, n) => {
61
- let r = await l(a, e, t);
62
- r !== null && r.status === "in_flight" && await a.update(o, r.id, { createdAt: new Date(n) });
63
- },
64
- release: async (e, t) => {
65
- let n = await l(a, e, t);
66
- n && await a.delete(o, n.id);
67
- }
101
+ complete: async (e, t, n) => await o.updateMany(a, {
102
+ status: "completed",
103
+ response: t,
104
+ createdAt: new Date(n)
105
+ }, { where: d(e) }) === 1,
106
+ renew: async (e, t) => await o.updateMany(a, { createdAt: new Date(t) }, { where: d(e) }) === 1,
107
+ release: async (e) => await o.deleteMany(a, { where: d(e) }) === 1
68
108
  });
69
- //#endregion
70
- export { u as dataStoreIdempotencyStore };
109
+ export { f as dataStoreIdempotencyStore };
@@ -1,5 +1,5 @@
1
1
  import { nextWakeup as e } from "./wakeRegistry.js";
2
- //#region src/idleDetector.ts
2
+ // src/idleDetector.ts
3
3
  var t = async (t) => {
4
4
  if (t.signals.connectedClients() > 0 || t.signals.inFlightRequests() > 0 || t.signals.activeWorkflowExecutions() > 0) return !1;
5
5
  let n = (t.now?.() ?? /* @__PURE__ */ new Date()).getTime() + (t.wakeLookaheadMs ?? 3e4), r = await e(t.store);
@@ -17,5 +17,4 @@ var t = async (t) => {
17
17
  }
18
18
  };
19
19
  };
20
- //#endregion
21
20
  export { t as isIdleNow, n as makeIdleGate };