@voltro/kv 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 (61) hide show
  1. package/CHANGELOG.md +5484 -0
  2. package/README.md +110 -0
  3. package/THIRD-PARTY-NOTICES.md +2 -482
  4. package/dist/Kv.js +1 -2
  5. package/dist/KvStore.js +1 -2
  6. package/dist/analytics.d.ts +337 -0
  7. package/dist/analytics.js +15 -0
  8. package/dist/backendMemory.js +1 -2
  9. package/dist/backendRedis.js +1 -2
  10. package/dist/cacheAtomicProtocol.js +257 -0
  11. package/dist/cacheAtomicScript.js +326 -0
  12. package/dist/cacheAtomicState.js +140 -0
  13. package/dist/connection.d.ts +990 -9
  14. package/dist/connection.js +336 -52
  15. package/dist/connectionAnalyticsConfig.js +152 -0
  16. package/dist/connectionConfigError.js +10 -0
  17. package/dist/connectionConfigProvider.js +110 -0
  18. package/dist/connectionDefinitions.js +284 -0
  19. package/dist/connectionMemory.js +206 -0
  20. package/dist/connectionMetrics.js +78 -0
  21. package/dist/connectionNamespace.js +18 -0
  22. package/dist/connectionNats.js +148 -0
  23. package/dist/connectionNatsConfig.js +86 -0
  24. package/dist/connectionNatsSubjects.js +15 -0
  25. package/dist/connectionOwner.js +43 -0
  26. package/dist/connectionPool.js +738 -0
  27. package/dist/connectionPrefix.js +36 -0
  28. package/dist/connectionScripts.js +3 -0
  29. package/dist/connectionSqlConfig.js +118 -0
  30. package/dist/connectionStorageConfig.js +189 -0
  31. package/dist/connectionStorageFacade.js +77 -0
  32. package/dist/connectionSubscriber.js +130 -0
  33. package/dist/driverModule.js +9 -0
  34. package/dist/errors.js +6 -3
  35. package/dist/expirySweep.js +1 -2
  36. package/dist/hot-contract.d.ts +297 -0
  37. package/dist/hot-contract.js +17 -0
  38. package/dist/hot-testing.d.ts +242 -0
  39. package/dist/hot-testing.js +1 -0
  40. package/dist/hot.d.ts +936 -0
  41. package/dist/hot.js +7 -0
  42. package/dist/hotMemory.js +45 -0
  43. package/dist/hotOperations.js +222 -0
  44. package/dist/hotRateLimit.js +102 -0
  45. package/dist/hotReadAvailability.js +18 -0
  46. package/dist/hotRedis.js +138 -0
  47. package/dist/hotRedisScript.js +3 -0
  48. package/dist/hotRouting.js +77 -0
  49. package/dist/hotState.js +181 -0
  50. package/dist/hotStoreConformance.js +365 -0
  51. package/dist/index.d.ts +113 -9
  52. package/dist/nativeRedisReads.js +77 -0
  53. package/dist/nativeRedisTopology.js +222 -0
  54. package/dist/redisDiagnostics.js +26 -0
  55. package/dist/redisReadPolicy.js +38 -0
  56. package/dist/sql.d.ts +77 -0
  57. package/dist/sql.js +0 -0
  58. package/dist/storage.d.ts +166 -0
  59. package/dist/storage.js +47 -0
  60. package/dist/storageAddress.js +19 -0
  61. package/package.json +49 -6
@@ -0,0 +1,78 @@
1
+ import { Effect as e, Metric as t } from "effect";
2
+ // src/connectionMetrics.ts
3
+ var n = /* @__PURE__ */ new Map(), r = t.gauge("voltro_connection_up", { description: "Whether every current pool for this reference has observed readiness and admits commands; not a persistence or capacity measurement." }), i = t.gauge("voltro_connection_pools", { description: "Owned physical generations, including draining generations." }), a = t.gauge("voltro_connection_active_commands", { description: "Borrowed generation leases, including complete streams and transactions." }), o = t.counter("voltro_connection_commands_total", { description: "Admitted commands and scoped streams; includes read-only probes." }), s = t.counter("voltro_connection_errors_total", { description: "Failed registry operations; includes rejected circuit admission and connection construction." }), c = t.gauge("voltro_connection_latency_ms", { description: "Duration of the most recently completed command or scoped stream in milliseconds." }), l = t.histogram("voltro_connection_duration_seconds", {
4
+ boundaries: t.exponentialBoundaries({
5
+ start: .001,
6
+ factor: 2,
7
+ count: 16
8
+ }),
9
+ description: "Complete command and scoped stream duration in seconds."
10
+ }), u = t.counter("voltro_connection_rotations_total", { description: "Completed whole-registry rotations by outcome, including rolled-back attempts." }), d = t.histogram("voltro_connection_rotation_duration_seconds", {
11
+ boundaries: t.exponentialBoundaries({
12
+ start: .001,
13
+ factor: 2,
14
+ count: 16
15
+ }),
16
+ description: "Whole-registry rotation duration in seconds."
17
+ }), f = (f) => {
18
+ let p = /* @__PURE__ */ new WeakMap(), m = (e, n) => t.withAttributes(t.withAttributes(e, { namespace: f }), { connection: n }), h = (o, s) => {
19
+ let c = [...n.get(o)?.values() ?? []], l = c.filter((e) => e.current);
20
+ e.runSync(e.all([
21
+ t.update(m(r, s), l.length > 0 && l.every((e) => e.available) ? 1 : 0),
22
+ t.update(m(i, s), c.length),
23
+ t.update(m(a, s), c.reduce((e, t) => e + t.active, 0))
24
+ ], { discard: !0 }));
25
+ }, g = (e, t) => {
26
+ let n = p.get(e);
27
+ n !== void 0 && (t(n.measurement), h(n.key, n.reference));
28
+ };
29
+ return {
30
+ register: (r, i) => {
31
+ let a = JSON.stringify([f, i]), c = {}, l = {
32
+ current: !1,
33
+ available: !1,
34
+ active: 0
35
+ }, u = n.get(a) ?? /* @__PURE__ */ new Map();
36
+ u.set(c, l), n.set(a, u), p.set(r, {
37
+ key: a,
38
+ reference: i,
39
+ token: c,
40
+ measurement: l
41
+ }), e.runSync(e.andThen(t.update(m(o, i), 0), t.update(m(s, i), 0))), h(a, i);
42
+ },
43
+ available: (e, t) => g(e, (e) => {
44
+ e.available = t;
45
+ }),
46
+ activate: (e) => g(e, (e) => {
47
+ e.current = !0;
48
+ }),
49
+ retire: (e) => g(e, (e) => {
50
+ e.current = !1;
51
+ }),
52
+ acquire: (e) => g(e, (e) => {
53
+ e.active++;
54
+ }),
55
+ release: (e) => g(e, (e) => {
56
+ e.active--;
57
+ }),
58
+ close: (e) => {
59
+ let t = p.get(e);
60
+ if (t === void 0) return;
61
+ let r = n.get(t.key);
62
+ r?.delete(t.token), r?.size === 0 && n.delete(t.key), p.delete(e), h(t.key, t.reference);
63
+ },
64
+ command: (n) => {
65
+ e.runSync(t.update(m(o, n), 1));
66
+ },
67
+ error: (n) => {
68
+ e.runSync(t.update(m(s, n), 1));
69
+ },
70
+ completed: (n, r) => {
71
+ e.runSync(e.andThen(t.update(m(c, n), r), t.update(m(l, n), r / 1e3)));
72
+ },
73
+ rotated: (n, r) => {
74
+ e.runSync(e.andThen(t.update(t.withAttributes(t.withAttributes(u, { namespace: f }), { outcome: n }), 1), t.update(t.withAttributes(d, { namespace: f }), r / 1e3)));
75
+ }
76
+ };
77
+ };
78
+ export { f as makeConnectionMetrics };
@@ -0,0 +1,18 @@
1
+ // src/connectionNamespace.ts
2
+ var e = (e) => encodeURIComponent(e).replace(/[!'()*]/g, (e) => `%${e.charCodeAt(0).toString(16).toUpperCase()}`), t = (t) => {
3
+ if (typeof t.appName != "string" || !t.appName.trim() || typeof t.environment != "string" || !t.environment.trim()) throw Error("Connection namespace requires a nonempty app name and environment");
4
+ return `voltro:${e(t.appName)}:${e(t.environment)}:`;
5
+ }, n = (e, n) => {
6
+ let r = t(n), i = e.keyPrefix ?? r;
7
+ if (typeof i != "string") throw Error("Connection keyPrefix must be a string");
8
+ if (e.allowSharedNamespace !== void 0 && typeof e.allowSharedNamespace != "boolean") throw Error("Connection allowSharedNamespace must be a boolean");
9
+ if (n.environment === "production") {
10
+ if (!i.trim()) throw Error("Production connection keyPrefix must be nonempty");
11
+ if (i !== r && e.allowSharedNamespace !== !0) throw Error("A custom production connection keyPrefix requires allowSharedNamespace: true");
12
+ }
13
+ return {
14
+ ...e,
15
+ keyPrefix: i
16
+ };
17
+ };
18
+ export { n as applyConnectionNamespace, t as connectionNamespace };
@@ -0,0 +1,148 @@
1
+ import { KvError as e } from "./errors.js";
2
+ import { missingDriver as t } from "./driverModule.js";
3
+ import { assertNatsSubject as n } from "./connectionNatsSubjects.js";
4
+ import { Effect as r } from "effect";
5
+ // src/connectionNats.ts
6
+ var i = new TextEncoder(), a = new TextDecoder(), o = 5e3, s = 1e3, c = async (e, t) => {
7
+ let n;
8
+ try {
9
+ return await Promise.race([e, new Promise((e, r) => {
10
+ n = setTimeout(() => {
11
+ r(/* @__PURE__ */ Error("NATS transport deadline elapsed"));
12
+ }, t);
13
+ })]);
14
+ } finally {
15
+ n !== void 0 && clearTimeout(n);
16
+ }
17
+ }, l = (e) => {
18
+ let t = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), l = /* @__PURE__ */ new Set(), u = /* @__PURE__ */ new Map(), d = !0, f = !1, p, m = (e) => {
19
+ for (let t of r) try {
20
+ t(e);
21
+ } catch {}
22
+ }, h = () => {
23
+ !f && d && (d = !1, m({ kind: "disconnected" }));
24
+ }, g = e.status()[Symbol.asyncIterator](), _ = (async () => {
25
+ try {
26
+ for (;;) {
27
+ let e = await g.next();
28
+ if (e.done) break;
29
+ f || (e.value.type === "disconnect" ? h() : e.value.type === "reconnect" && !d && (d = !0, m({ kind: "reconnected" })));
30
+ }
31
+ } finally {
32
+ h();
33
+ }
34
+ })().catch(() => {
35
+ h();
36
+ }), v = () => {
37
+ if (f) throw Error("NATS transport is closed");
38
+ if (!d) throw Error("NATS transport is disconnected");
39
+ }, y = async (e) => {
40
+ let t = u.get(e);
41
+ t !== void 0 && (t.released = !0, u.delete(e), t.subscription.unsubscribe(), await t.done);
42
+ };
43
+ return {
44
+ publish: async (t, r) => {
45
+ n(t), v(), e.publish(t, i.encode(r));
46
+ },
47
+ flush: async () => {
48
+ v(), await c(e.flush(), o);
49
+ },
50
+ subscribe: async (r) => {
51
+ n(r), v();
52
+ let i = u.get(r);
53
+ if (i !== void 0) return i.ready;
54
+ let s = e.subscribe(r), d = {
55
+ subscription: s,
56
+ released: !1,
57
+ done: Promise.resolve(),
58
+ ready: Promise.resolve()
59
+ };
60
+ u.set(r, d), d.done = (async () => {
61
+ try {
62
+ for await (let e of s) {
63
+ if (f || d.released) continue;
64
+ let n = a.decode(e.data);
65
+ for (let e of t) try {
66
+ e(r, n);
67
+ } catch {}
68
+ }
69
+ } finally {
70
+ d.released || h();
71
+ }
72
+ })().catch(() => {
73
+ d.released || h();
74
+ }), l.add(d.done), d.done.then(() => {
75
+ l.delete(d.done);
76
+ }), d.ready = c(e.flush(), o).then(() => {
77
+ if (v(), d.released) throw Error("NATS subscription is closed");
78
+ }).catch(async (e) => {
79
+ throw u.get(r) === d && await y(r), e;
80
+ }), await d.ready;
81
+ },
82
+ unsubscribe: y,
83
+ onMessage: (e) => {
84
+ if (f) throw Error("NATS transport is closed");
85
+ return t.add(e), () => {
86
+ t.delete(e);
87
+ };
88
+ },
89
+ onTransportEvent: (e) => {
90
+ if (f) throw Error("NATS transport is closed");
91
+ return r.add(e), () => {
92
+ r.delete(e);
93
+ };
94
+ },
95
+ close: () => p ??= (async () => {
96
+ f = !0, t.clear(), r.clear();
97
+ for (let e of u.values()) {
98
+ e.released = !0;
99
+ try {
100
+ e.subscription.unsubscribe();
101
+ } catch {}
102
+ }
103
+ u.clear();
104
+ try {
105
+ await c(e.drain(), s);
106
+ } catch {} finally {
107
+ await e.close(), await g.return?.(), await Promise.all([...l]), await _;
108
+ }
109
+ })()
110
+ };
111
+ }, u = (n) => r.callback((i) => {
112
+ let a = !1, s, c = (async () => {
113
+ let e = await (await import("@nats-io/transport-node").catch(t("@nats-io/transport-node", "A NATS connection"))).connect({
114
+ servers: n.url.split(",").map((e) => e.trim()),
115
+ maxReconnectAttempts: -1,
116
+ waitOnFirstConnect: !0,
117
+ reconnectTimeWait: 2e3,
118
+ timeout: o,
119
+ ...n.tls === "required" ? { tls: {} } : {},
120
+ ...n.token === void 0 ? {} : { token: n.token },
121
+ ...n.user === void 0 ? {} : { user: n.user },
122
+ ...n.pass === void 0 ? {} : { pass: n.pass },
123
+ reconnectToServer: () => {
124
+ if (a) throw Error("NATS acquisition cancelled");
125
+ return null;
126
+ }
127
+ });
128
+ if (a) await e.close();
129
+ else {
130
+ try {
131
+ s = l(e);
132
+ } catch (t) {
133
+ throw await e.close(), t;
134
+ }
135
+ i(r.succeed(s));
136
+ }
137
+ })().catch(() => {
138
+ a || i(r.fail(new e({
139
+ operation: "connect",
140
+ key: "",
141
+ cause: "NATS driver could not be opened"
142
+ })));
143
+ });
144
+ return r.promise(async () => {
145
+ a = !0, await c, await s?.close();
146
+ });
147
+ });
148
+ export { u as connectNats };
@@ -0,0 +1,86 @@
1
+ import { connectionDefinitionsProblem as e, natsConnectionName as t } from "./connectionDefinitions.js";
2
+ import { Config as n, ConfigProvider as r, Effect as i, Option as a } from "effect";
3
+ // src/connectionNatsConfig.ts
4
+ var o = (e) => e.toUpperCase().replace(/[^A-Z0-9]+/g, "_"), s = (e) => {
5
+ if (typeof e.url != "string" || !e.url.trim()) return "A NATS connection requires an endpoint";
6
+ for (let t of e.url.split(",")) try {
7
+ let e = new URL(t.trim());
8
+ if (!["nats:", "tls:"].includes(e.protocol) || !e.hostname || e.pathname && e.pathname !== "/" || e.search || e.hash) return "A NATS connection requires nats:// or tls:// servers";
9
+ if (e.username || e.password) return "NATS credentials must use token or user/pass declarations, not endpoint userinfo";
10
+ } catch {
11
+ return "A NATS connection requires valid servers";
12
+ }
13
+ for (let t of [
14
+ e.token,
15
+ e.user,
16
+ e.pass
17
+ ]) if (t !== void 0 && (typeof t != "string" || !t.trim())) return "NATS credentials must be nonempty";
18
+ if (e.user === void 0 != (e.pass === void 0)) return "NATS user and pass must resolve together";
19
+ if (e.token !== void 0 && e.user !== void 0) return "NATS token and user/pass authentication are exclusive";
20
+ if (e.tls !== void 0 && !["auto", "required"].includes(e.tls)) return "Connection tls must be auto or required";
21
+ if (e.keyPrefix !== void 0 && typeof e.keyPrefix != "string") return "Connection keyPrefix must be a string";
22
+ if (e.keyPrefix !== void 0 && (/[\s*>]/u.test(e.keyPrefix) || e.keyPrefix.startsWith(".") || e.keyPrefix.includes(".."))) return "A NATS namespace must preserve exact subjects";
23
+ if (e.allowSharedNamespace !== void 0 && typeof e.allowSharedNamespace != "boolean") return "Connection allowSharedNamespace must be a boolean";
24
+ }, c = (c, l = {}, u) => {
25
+ let d = u === void 0 ? void 0 : Object.freeze({ tenantId: u.tenantId });
26
+ return i.gen(function* () {
27
+ let u = e(l);
28
+ if (u) return yield* i.fail(new n.ConfigError(new r.SourceError({ message: u })));
29
+ if (c.includes(":") && !/^nats:[A-Za-z][A-Za-z0-9_-]*$/.test(c)) return yield* i.fail(new n.ConfigError(new r.SourceError({ message: "A NATS consumer requires a nats:name connection reference" })));
30
+ if (c && !c.includes(":") && !/^[A-Za-z][A-Za-z0-9_-]*$/.test(c)) return yield* i.fail(new n.ConfigError(new r.SourceError({ message: "Malformed NATS connection reference" })));
31
+ let f = t(c, l), p = l.nats ?? {}, m = Object.keys(p), h = Object.hasOwn(p, f) ? p[f] : void 0;
32
+ if (h === void 0 && m.length > 0) return yield* i.fail(new n.ConfigError(new r.SourceError({ message: `Unknown NATS connection ${f || "(default)"}. Known names: ${m.sort().join(", ")}` })));
33
+ let g = `CONNECTIONS_NATS_${o(f)}`, _ = yield* n.String(`${g}_URL`).pipe(n.option), v = yield* n.String(`${g}_TOKEN`).pipe(n.option), y = yield* n.String(`${g}_USER`).pipe(n.option), b = yield* n.String(`${g}_PASS`).pipe(n.option), x = yield* n.String(`${g}_KEY_PREFIX`).pipe(n.option), S = {
34
+ ...a.isSome(_) ? { url: _.value } : {},
35
+ ...a.isSome(v) ? { token: v.value } : {},
36
+ ...a.isSome(y) ? { user: y.value } : {},
37
+ ...a.isSome(b) ? { pass: b.value } : {},
38
+ ...a.isSome(x) ? { keyPrefix: x.value } : {}
39
+ }, C;
40
+ if (h !== void 0 && "_tag" in h) {
41
+ if (!d?.tenantId) return yield* i.fail(new n.ConfigError(new r.SourceError({ message: "A dynamic NATS connection requires tenantId" })));
42
+ C = {
43
+ ...yield* h.resolve(d),
44
+ ...S
45
+ };
46
+ } else if (h !== void 0) {
47
+ let { url: e, token: t, user: o, pass: s, ...c } = h, l = (e) => e === void 0 ? i.succeed(a.none()) : n.String(e.name).pipe(n.option), u = a.isSome(v) ? v : yield* l(t), d = a.isSome(y) ? y : yield* l(o), f = a.isSome(b) ? b : yield* l(s);
48
+ for (let [e, c] of [
49
+ [t, u],
50
+ [o, d],
51
+ [s, f]
52
+ ]) if (e !== void 0 && a.isNone(c)) return yield* i.fail(new n.ConfigError(new r.SourceError({ message: `Missing declared NATS credential ${e.name}` })));
53
+ C = {
54
+ ...c,
55
+ url: a.isSome(_) ? _.value : yield* n.String(e.name),
56
+ ...a.isSome(u) ? { token: u.value } : {},
57
+ ...a.isSome(d) ? { user: d.value } : {},
58
+ ...a.isSome(f) ? { pass: f.value } : {},
59
+ ...a.isSome(x) ? { keyPrefix: x.value } : {}
60
+ };
61
+ } else {
62
+ let e = o(f), t = (t) => n.String(`${e}_NATS_${t}`).pipe(n.orElse(() => n.String(`NATS_${t}`)), n.option), r = a.isSome(v) ? v : yield* t("TOKEN"), i = a.isSome(y) ? y : yield* t("USER"), s = a.isSome(b) ? b : yield* t("PASS");
63
+ C = {
64
+ url: a.isSome(_) ? _.value : yield* n.String(`${e}_NATS_URL`).pipe(n.orElse(() => n.String("NATS_URL"))),
65
+ ...a.isSome(r) ? { token: r.value } : {},
66
+ ...a.isSome(i) ? { user: i.value } : {},
67
+ ...a.isSome(s) ? { pass: s.value } : {},
68
+ ...a.isSome(x) ? { keyPrefix: x.value } : {}
69
+ };
70
+ }
71
+ let w = s(C);
72
+ if (w) return yield* i.fail(new n.ConfigError(new r.SourceError({ message: w })));
73
+ let T = [
74
+ _,
75
+ v,
76
+ y,
77
+ b,
78
+ x
79
+ ].some(a.isSome);
80
+ return {
81
+ ...C,
82
+ source: T ? "override" : h === void 0 ? "environment" : "config"
83
+ };
84
+ });
85
+ };
86
+ export { s as natsConfigProblem, c as natsConnectionConfig };
@@ -0,0 +1,15 @@
1
+ // src/connectionNatsSubjects.ts
2
+ var e = (e) => {
3
+ if (!e || /[\s*>]/u.test(e) || e.split(".").some((e) => !e)) throw Error("Registry NATS channels must be exact nonempty subjects");
4
+ }, t = (e, t = "") => ({
5
+ publish: (n, r) => e.publish(t + n, r),
6
+ subscribe: (n) => e.subscribe(t + n),
7
+ unsubscribe: (n) => e.unsubscribe(t + n),
8
+ onMessage: (n) => e.onMessage((e, r) => {
9
+ e.startsWith(t) && n(e.slice(t.length), r);
10
+ }),
11
+ onTransportEvent: e.onTransportEvent,
12
+ flush: e.flush,
13
+ close: e.close
14
+ });
15
+ export { e as assertNatsSubject, t as withNatsSubjectPrefix };
@@ -0,0 +1,43 @@
1
+ import { KvError as e } from "./errors.js";
2
+ import { Deferred as t, Effect as n, Scope as r } from "effect";
3
+ // src/connectionOwner.ts
4
+ var i = (i) => n.gen(function* () {
5
+ let a = yield* n.scope, o = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Set(), c = !1, l = (e) => n.uninterruptible(n.suspend(() => e.closed ? t.await(e.closedSignal) : (e.closed = !0, i.dispose(e).pipe(n.ensuring(n.sync(() => {
6
+ o.delete(e);
7
+ }).pipe(n.andThen(t.succeed(e.closedSignal, void 0))))))));
8
+ return yield* r.addFinalizer(a, n.gen(function* () {
9
+ c = !0, i.onStopping(), yield* n.forEach([...s], t.await, {
10
+ concurrency: "unbounded",
11
+ discard: !0
12
+ }), yield* n.forEach([...o], (e) => n.gen(function* () {
13
+ e.retired = !0, e.active > 0 && !e.closed && (yield* (e.drainUntilReleased ? t.await(e.closedSignal) : n.raceFirst(n.sleep(i.rotationGraceMs), t.await(e.closedSignal))).pipe(n.interruptible)), yield* l(e);
14
+ }), {
15
+ concurrency: "unbounded",
16
+ discard: !0
17
+ }), i.onStopped();
18
+ })), {
19
+ get stopped() {
20
+ return c;
21
+ },
22
+ register: (e) => {
23
+ o.add(e);
24
+ },
25
+ close: l,
26
+ retire: (e) => n.gen(function* () {
27
+ e.retired = !0, e.active === 0 ? yield* l(e) : e.drainUntilReleased || (yield* n.raceFirst(n.sleep(i.rotationGraceMs), t.await(e.closedSignal)).pipe(n.andThen(l(e)), n.interruptible, n.forkIn(a)));
28
+ }),
29
+ release: (e) => n.suspend(() => (e.active--, e.retired && e.active === 0 ? l(e) : n.void)),
30
+ trackOpen: (r) => n.uninterruptibleMask((i) => n.gen(function* () {
31
+ if (c) return yield* n.fail(new e({
32
+ operation: "connect",
33
+ key: "",
34
+ cause: "Connection registry is closed"
35
+ }));
36
+ let a = yield* t.make();
37
+ return s.add(a), yield* i(r).pipe(n.ensuring(n.sync(() => {
38
+ s.delete(a);
39
+ }).pipe(n.andThen(t.succeed(a, void 0)))));
40
+ }))
41
+ };
42
+ });
43
+ export { i as makeConnectionOwner };