@voltro/kv 0.87.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 (50) hide show
  1. package/CHANGELOG.md +169 -6
  2. package/THIRD-PARTY-NOTICES.md +2 -1345
  3. package/dist/Kv.js +1 -2
  4. package/dist/KvStore.js +1 -2
  5. package/dist/analytics.js +1 -2
  6. package/dist/backendMemory.js +1 -2
  7. package/dist/backendRedis.js +1 -2
  8. package/dist/cacheAtomicProtocol.js +34 -24
  9. package/dist/cacheAtomicScript.js +19 -2
  10. package/dist/cacheAtomicState.js +1 -2
  11. package/dist/connection.js +74 -70
  12. package/dist/connectionAnalyticsConfig.js +1 -2
  13. package/dist/connectionConfigError.js +10 -0
  14. package/dist/connectionConfigProvider.js +1 -2
  15. package/dist/connectionDefinitions.js +1 -2
  16. package/dist/connectionMemory.js +1 -2
  17. package/dist/connectionMetrics.js +1 -2
  18. package/dist/connectionNamespace.js +1 -2
  19. package/dist/connectionNats.js +44 -44
  20. package/dist/connectionNatsConfig.js +1 -2
  21. package/dist/connectionNatsSubjects.js +1 -2
  22. package/dist/connectionOwner.js +1 -2
  23. package/dist/connectionPool.js +252 -252
  24. package/dist/connectionPrefix.js +1 -2
  25. package/dist/connectionScripts.js +1 -2
  26. package/dist/connectionSqlConfig.js +1 -2
  27. package/dist/connectionStorageConfig.js +1 -2
  28. package/dist/connectionStorageFacade.js +1 -2
  29. package/dist/connectionSubscriber.js +47 -47
  30. package/dist/driverModule.js +9 -0
  31. package/dist/errors.js +1 -2
  32. package/dist/expirySweep.js +1 -2
  33. package/dist/hot-contract.js +1 -2
  34. package/dist/hot-testing.d.ts +14 -1
  35. package/dist/hotMemory.js +1 -2
  36. package/dist/hotOperations.js +1 -2
  37. package/dist/hotRateLimit.js +1 -2
  38. package/dist/hotReadAvailability.js +1 -2
  39. package/dist/hotRedis.js +1 -2
  40. package/dist/hotRedisScript.js +1 -2
  41. package/dist/hotRouting.js +2 -3
  42. package/dist/hotState.js +1 -2
  43. package/dist/hotStoreConformance.js +76 -78
  44. package/dist/nativeRedisReads.js +2 -3
  45. package/dist/nativeRedisTopology.js +64 -63
  46. package/dist/redisDiagnostics.js +1 -2
  47. package/dist/redisReadPolicy.js +1 -2
  48. package/dist/storage.js +1 -2
  49. package/dist/storageAddress.js +1 -2
  50. package/package.json +13 -10
package/dist/Kv.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { KvStore as e } from "./KvStore.js";
2
2
  import { Context as t, Effect as n, Layer as r, Option as i } from "effect";
3
- //#region src/Kv.ts
3
+ // src/Kv.ts
4
4
  var a = class a extends t.Service()("@voltro/Kv", { make: n.gen(function* () {
5
5
  let t = yield* e;
6
6
  return {
@@ -15,5 +15,4 @@ var a = class a extends t.Service()("@voltro/Kv", { make: n.gen(function* () {
15
15
  }) }) {
16
16
  static layer = r.effect(a, a.make);
17
17
  };
18
- //#endregion
19
18
  export { a as Kv };
package/dist/KvStore.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { Context as e } from "effect";
2
- //#region src/KvStore.ts
2
+ // src/KvStore.ts
3
3
  var t = class extends e.Service()("@voltro/KvStore") {};
4
- //#endregion
5
4
  export { t as KvStore };
package/dist/analytics.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Schema as e } from "effect";
2
- //#region src/connectionAnalytics.ts
2
+ // src/connectionAnalytics.ts
3
3
  var t = class extends e.TaggedError()("AnalyticsError", {
4
4
  provider: e.String,
5
5
  operation: e.String,
@@ -12,5 +12,4 @@ var t = class extends e.TaggedError()("AnalyticsError", {
12
12
  provider: e.String,
13
13
  capability: e.String
14
14
  }) {};
15
- //#endregion
16
15
  export { n as AnalyticsCapabilityNotSupported, t as AnalyticsError };
@@ -1,7 +1,7 @@
1
1
  import { KvStore as e } from "./KvStore.js";
2
2
  import { makeExpirySweep as t } from "./expirySweep.js";
3
3
  import { Clock as n, Effect as r, HashMap as i, Layer as a, Option as o, Ref as s } from "effect";
4
- //#region src/backendMemory.ts
4
+ // src/backendMemory.ts
5
5
  var c = (e, t) => t === void 0 ? Infinity : e + t, l = (e) => r.gen(function* () {
6
6
  let a = yield* s.make(i.empty()), l = e.now === void 0 ? n.currentTimeMillis : r.sync(e.now), u = t(), d = u.sweep;
7
7
  return {
@@ -32,5 +32,4 @@ var c = (e, t) => t === void 0 ? Infinity : e + t, l = (e) => r.gen(function* ()
32
32
  clear: () => r.sync(u.reset).pipe(r.andThen(s.set(a, i.empty())))
33
33
  };
34
34
  }), u = (t = {}) => a.effect(e, l(t));
35
- //#endregion
36
35
  export { u as layerMemory };
@@ -2,7 +2,7 @@ import { KvStore as e } from "./KvStore.js";
2
2
  import { KvError as t } from "./errors.js";
3
3
  import { RedisConnections as n, commandRetry as r } from "./connection.js";
4
4
  import { Effect as i, Layer as a, Option as o } from "effect";
5
- //#region src/backendRedis.ts
5
+ // src/backendRedis.ts
6
6
  var s = (e, n = "voltro:kv") => {
7
7
  let a = (e) => `${n}:${e}`, s = (e) => e.slice(n.length + 1), c = (n, a, o) => i.tryPromise({
8
8
  try: () => o(e),
@@ -44,5 +44,4 @@ var s = (e, n = "voltro:kv") => {
44
44
  cause: String(e)
45
45
  })))), r.keyPrefix ?? "voltro:kv");
46
46
  }));
47
- //#endregion
48
47
  export { c as layerRedis, s as makeRedisKvStore };
@@ -1,4 +1,4 @@
1
- //#region src/cacheAtomicProtocol.ts
1
+ // src/cacheAtomicProtocol.ts
2
2
  var e = class extends Error {
3
3
  constructor() {
4
4
  super("Invalid atomic cache command or state."), this.name = "CacheAtomicProtocolError";
@@ -148,49 +148,60 @@ var e = class extends Error {
148
148
  default: return n();
149
149
  }
150
150
  }, h = (e, t) => {
151
- if (typeof e != "string" || !/\{voltro:cache:atomic:(?:[a-f0-9]{2})+\}:r$/.test(e)) return n();
152
- let r = e.slice(0, -2), i = /* @__PURE__ */ new Set(), o = (e) => {
153
- i.add(`${r}:v:${a(e)}`);
154
- }, s = (e) => {
155
- i.add(`${r}:t:${a(e)}`);
156
- }, c = () => {
157
- i.add(`${r}:s`);
158
- }, l = (e) => {
159
- i.add(`${r}:e:${a(e)}`);
151
+ let r = typeof e == "string" ? e.match(/\{voltro:cache:atomic:(?:[a-f0-9]{2})+\}:r$/)?.[0] : void 0;
152
+ if (r === void 0) return n();
153
+ let i = e.slice(0, -2), o = /* @__PURE__ */ new Set(), s = (e) => {
154
+ o.add(`${i}:v:${a(e)}`);
155
+ }, c = (e) => {
156
+ o.add(`${i}:t:${a(e)}`);
157
+ }, l = () => {
158
+ o.add(`${i}:s`);
159
+ }, u = (e) => {
160
+ o.add(`${i}:e:${a(e)}`);
160
161
  };
161
162
  switch (t.op) {
162
163
  case "inspect":
163
- o(t.key);
164
+ s(t.key);
164
165
  break;
165
166
  case "inspect-values":
166
- t.keys.forEach(o);
167
+ t.keys.forEach(s);
167
168
  break;
168
169
  case "read":
169
- o(t.key), t.snapshot?.tags.forEach(s);
170
+ s(t.key), t.snapshot?.tags.forEach(c);
170
171
  break;
171
172
  case "fence":
172
- c();
173
+ l();
173
174
  break;
174
175
  case "write":
175
- o(t.key), t.tags.forEach(s), t.snapshot?.tags.forEach(s), t.fence !== null && t.tags.forEach(l);
176
+ s(t.key), t.tags.forEach(c), t.snapshot?.tags.forEach(c), t.fence !== null && t.tags.forEach(u);
176
177
  break;
177
178
  case "remove":
178
- o(t.key), t.snapshot?.tags.forEach(s);
179
+ s(t.key), t.snapshot?.tags.forEach(c);
179
180
  break;
180
181
  case "tag":
181
- s(t.tag);
182
+ c(t.tag);
182
183
  break;
183
184
  case "invalidate":
184
- s(t.tag), c(), l(t.tag), t.snapshots.forEach((e) => {
185
- o(e.key), e.snapshot?.tags.forEach(s);
185
+ c(t.tag), l(), u(t.tag), t.snapshots.forEach((e) => {
186
+ s(e.key), e.snapshot?.tags.forEach(c);
186
187
  });
187
188
  break;
188
- case "clear": for (let o of t.keys) if (o !== e) {
189
- if (!o.startsWith(`${r}:v:`) && !o.startsWith(`${r}:t:`)) return n();
190
- a(o.slice(r.length + 3)), i.add(o);
189
+ case "clear": {
190
+ let s = r.slice(0, -2), c = /* @__PURE__ */ new Set();
191
+ for (let l of t.keys) {
192
+ let t = l;
193
+ if (l !== e && !l.startsWith(`${i}:v:`) && !l.startsWith(`${i}:t:`)) {
194
+ if (l === r) t = e;
195
+ else if (l.startsWith(`${s}:v:`) || l.startsWith(`${s}:t:`)) t = i + l.slice(s.length);
196
+ else return n();
197
+ }
198
+ if (c.has(t)) return n();
199
+ c.add(t), t !== e && (a(t.slice(i.length + 3)), o.add(t));
200
+ }
201
+ break;
191
202
  }
192
203
  }
193
- return [e, ...[...i].sort()];
204
+ return [e, ...[...o].sort()];
194
205
  }, g = (e, t) => `${o(t)}:${a(e)}`, _ = (e) => e === void 0 ? null : !Number.isFinite(e) || !Number.isSafeInteger(Math.ceil(e)) ? n() : Math.max(0, Math.ceil(e)), v = (e) => {
195
206
  if (typeof e != "object" || !e || Array.isArray(e) || Object.getPrototypeOf(e) !== Object.prototype && Object.getPrototypeOf(e) !== null) return n();
196
207
  let t = e;
@@ -243,5 +254,4 @@ var e = class extends Error {
243
254
  "tag",
244
255
  "scan"
245
256
  ].includes(e.op);
246
- //#endregion
247
257
  export { t as CACHE_FENCE_RETENTION_MS, e as CacheAtomicProtocolError, l as cacheAtomicArray, f as cacheAtomicComponent, h as cacheAtomicKeys, d as cacheAtomicMember, g as cacheAtomicMembership, p as cacheAtomicRoot, x as cacheAtomicScanPage, u as cacheAtomicSnapshot, _ as cacheAtomicTtl, b as cacheAtomicValueSnapshots, m as decodeCacheAtomicCommand, v as decodeCacheAtomicPolicy, y as decodeCacheAtomicReply, S as isCacheAtomicRead };
@@ -1,5 +1,5 @@
1
1
  import { CACHE_FENCE_RETENTION_MS as e } from "./cacheAtomicProtocol.js";
2
- //#region src/cacheAtomicScript.ts
2
+ // src/cacheAtomicScript.ts
3
3
  var t = String.raw`
4
4
  local c = cjson.decode(ARGV[1])
5
5
  local policy = ARGV[2] and cjson.decode(ARGV[2]) or {}
@@ -126,8 +126,26 @@ elseif c.op == 'invalidate' then
126
126
  for i = 2, #c.snapshots do if c.snapshots[i - 1].key >= c.snapshots[i].key then invalid() end end
127
127
  elseif c.op == 'clear' then
128
128
  if not null(c.revision) then version(c.revision) end
129
+ -- KEYS may carry a registry prefix; ARGV retains caller-logical keys.
130
+ -- The canonical cache token binds those two domains exactly, without
131
+ -- accepting a foreign connection prefix or another cache namespace.
132
+ local logicalRoot = string.match(root, '({voltro:cache:atomic:[a-f0-9]+}:r)$')
133
+ if not logicalRoot then invalid() end
134
+ id(string.match(logicalRoot, '^{voltro:cache:atomic:([a-f0-9]+)}:r$'))
135
+ local logicalSpace = string.sub(logicalRoot, 1, #logicalRoot - 2)
136
+ local selected = {}
129
137
  array(c.keys, function(key)
130
138
  if type(key) ~= 'string' then invalid() end
139
+ local kind = string.sub(key, 1, #space + 3)
140
+ if key ~= root and kind ~= space .. ':v:' and kind ~= space .. ':t:' then
141
+ local logicalKind = string.sub(key, 1, #logicalSpace + 3)
142
+ if key == logicalRoot then key = root
143
+ elseif logicalKind == logicalSpace .. ':v:' or logicalKind == logicalSpace .. ':t:' then
144
+ key = space .. string.sub(key, #logicalSpace + 1)
145
+ else invalid() end
146
+ end
147
+ if selected[key] then invalid() end
148
+ selected[key] = true
131
149
  if key ~= root then
132
150
  local prefix = string.sub(key, 1, #space + 3)
133
151
  if prefix ~= space .. ':v:' and prefix ~= space .. ':t:' then invalid() end
@@ -305,5 +323,4 @@ elseif c.op == 'clear' then
305
323
  end
306
324
  invalid()
307
325
  `;
308
- //#endregion
309
326
  export { t as CACHE_ATOMIC_SCRIPT };
@@ -1,5 +1,5 @@
1
1
  import { CACHE_FENCE_RETENTION_MS as e, CacheAtomicProtocolError as t, cacheAtomicKeys as n, cacheAtomicMember as r, cacheAtomicMembership as i, cacheAtomicSnapshot as a, decodeCacheAtomicCommand as o, decodeCacheAtomicPolicy as s } from "./cacheAtomicProtocol.js";
2
- //#region src/cacheAtomicState.ts
2
+ // src/cacheAtomicState.ts
3
3
  var c = 9e15, l = () => {
4
4
  throw new t();
5
5
  }, u = (t, u, d, f = {}) => {
@@ -137,5 +137,4 @@ var c = 9e15, l = () => {
137
137
  return O("ok");
138
138
  }
139
139
  };
140
- //#endregion
141
140
  export { u as applyCacheAtomicCommand };
@@ -3,19 +3,20 @@ import { withRespKeyPrefix as t } from "./connectionPrefix.js";
3
3
  import { dynamicSql as n } from "./connectionSqlConfig.js";
4
4
  import { dynamicAnalytics as r } from "./connectionAnalyticsConfig.js";
5
5
  import { byTenant as i, connectionDefinitionsProblem as a, connectionMetadataProblem as o, declaredConnectionEnv as s, dynamic as c, dynamicNats as l, env as u, memory as d, redisConnectionName as f, redisTimeoutsProblem as p, roundRobin as m, shardBy as h } from "./connectionDefinitions.js";
6
- import { createNativeRedisConnection as g, disconnectNativeRedis as _, nativeRedisTopology as v, scanNativeRedis as y } from "./nativeRedisTopology.js";
7
- import { connectRedisSubscriber as b } from "./connectionSubscriber.js";
8
- import { dynamicStorage as x } from "./connectionStorageConfig.js";
9
- import { withConnectionRegistryConfigProvider as S } from "./connectionConfigProvider.js";
10
- import { ConnectionRegistry as C, layerConfiguredConnections as w, makeConnectionRegistry as T } from "./connectionPool.js";
11
- import { httpRedisReaders as ee } from "./redisReadPolicy.js";
12
- import { nativeRedisReadConfigs as E, openNativeRedisReaders as te } from "./nativeRedisReads.js";
6
+ import { missingDriver as g } from "./driverModule.js";
7
+ import { createNativeRedisConnection as _, disconnectNativeRedis as v, nativeRedisTopology as y, scanNativeRedis as b } from "./nativeRedisTopology.js";
8
+ import { connectRedisSubscriber as x } from "./connectionSubscriber.js";
9
+ import { dynamicStorage as S } from "./connectionStorageConfig.js";
10
+ import { withConnectionRegistryConfigProvider as C } from "./connectionConfigProvider.js";
11
+ import { ConnectionRegistry as ee, layerConfiguredConnections as w, makeConnectionRegistry as T } from "./connectionPool.js";
12
+ import { httpRedisReaders as E } from "./redisReadPolicy.js";
13
+ import { nativeRedisReadConfigs as D, openNativeRedisReaders as te } from "./nativeRedisReads.js";
13
14
  import { readRedisNodeDiagnostics as ne } from "./redisDiagnostics.js";
14
- import { CACHE_FENCE_RETENTION_MS as D, CacheAtomicProtocolError as O, cacheAtomicArray as k, cacheAtomicComponent as A, cacheAtomicKeys as re, cacheAtomicMember as ie, cacheAtomicMembership as ae, cacheAtomicRoot as oe, cacheAtomicScanPage as j, cacheAtomicSnapshot as M, cacheAtomicTtl as N, cacheAtomicValueSnapshots as P, decodeCacheAtomicCommand as F, decodeCacheAtomicPolicy as I, decodeCacheAtomicReply as L, isCacheAtomicRead as R } from "./cacheAtomicProtocol.js";
15
- import { CACHE_ATOMIC_SCRIPT as z } from "./cacheAtomicScript.js";
16
- import { Config as B, ConfigProvider as V, Context as H, Effect as U, Layer as W, Option as G, Schedule as K } from "effect";
17
- //#region src/connection.ts
18
- var q = (e) => new B.ConfigError(new V.SourceError({ message: e })), se = (e, t) => {
15
+ import { CACHE_FENCE_RETENTION_MS as re, CacheAtomicProtocolError as ie, cacheAtomicArray as ae, cacheAtomicComponent as oe, cacheAtomicKeys as se, cacheAtomicMember as ce, cacheAtomicMembership as O, cacheAtomicRoot as k, cacheAtomicScanPage as A, cacheAtomicSnapshot as j, cacheAtomicTtl as M, cacheAtomicValueSnapshots as N, decodeCacheAtomicCommand as P, decodeCacheAtomicPolicy as F, decodeCacheAtomicReply as I, isCacheAtomicRead as L } from "./cacheAtomicProtocol.js";
16
+ import { CACHE_ATOMIC_SCRIPT as R } from "./cacheAtomicScript.js";
17
+ import { Config as z, ConfigProvider as B, Context as V, Effect as H, Layer as U, Option as W, Schedule as G } from "effect";
18
+ // src/connection.ts
19
+ var K = (e) => new z.ConfigError(new B.SourceError({ message: e })), le = (e, t) => {
19
20
  let n = e.client;
20
21
  return {
21
22
  readOnly: {
@@ -29,11 +30,15 @@ var q = (e) => new B.ConfigError(new V.SourceError({ message: e })), se = (e, t)
29
30
  },
30
31
  zrange: async (e) => {
31
32
  let n = await t.select();
32
- return await n.ready(), n.client.zrange(e, 0, -1);
33
+ return await n.ready(), n.client.zrange(e, 0, "-1");
33
34
  },
34
35
  eval: async (e, n, ...r) => {
35
36
  let i = await t.select();
36
- return await i.ready(), i.client.call("eval_ro", e, n, ...r);
37
+ return await i.ready(), i.client.call("eval_ro", [
38
+ e,
39
+ n,
40
+ ...r
41
+ ]);
37
42
  }
38
43
  },
39
44
  ping: async () => (await e.ready(), n.ping()),
@@ -65,8 +70,8 @@ var q = (e) => new B.ConfigError(new V.SourceError({ message: e })), se = (e, t)
65
70
  },
66
71
  exists: async (t) => (await e.ready(), n.exists(t)),
67
72
  eval: async (t, r, ...i) => (await e.ready(), n.eval(t, r, ...i)),
68
- zrange: async (t) => (await e.ready(), n.zrange(t, 0, -1)),
69
- scan: async (t, n, r) => (await e.ready(), y(e, t, n, r)),
73
+ zrange: async (t) => (await e.ready(), n.zrange(t, 0, "-1")),
74
+ scan: async (t, n, r) => (await e.ready(), b(e, t, n, r)),
70
75
  close: async () => {
71
76
  let r, i = () => {
72
77
  try {
@@ -80,11 +85,11 @@ var q = (e) => new B.ConfigError(new V.SourceError({ message: e })), se = (e, t)
80
85
  }, 1e3);
81
86
  })]);
82
87
  } finally {
83
- r !== void 0 && clearTimeout(r), await Promise.all([t.close(), _(e)]).then(() => void 0);
88
+ r !== void 0 && clearTimeout(r), await Promise.all([t.close(), v(e)]).then(() => void 0);
84
89
  }
85
90
  }
86
91
  };
87
- }, J = (e) => ({
92
+ }, q = (e) => ({
88
93
  readOnly: {
89
94
  get: (t) => e.get(t),
90
95
  exists: (t) => e.exists(t),
@@ -110,7 +115,7 @@ var q = (e) => new B.ConfigError(new V.SourceError({ message: e })), se = (e, t)
110
115
  };
111
116
  },
112
117
  close: () => Promise.resolve()
113
- }), Y = (e) => e.toUpperCase().replace(/[^A-Z0-9]+/g, "_"), X = (e) => {
118
+ }), J = (e) => e.toUpperCase().replace(/[^A-Z0-9]+/g, "_"), Y = (e) => {
114
119
  if (![
115
120
  "resp",
116
121
  "http",
@@ -148,79 +153,79 @@ var q = (e) => new B.ConfigError(new V.SourceError({ message: e })), se = (e, t)
148
153
  "none"
149
154
  ].includes(e.persistence)) return "Connection persistence must be required, optional or none";
150
155
  if (e.maxmemoryPolicyHint !== void 0 && typeof e.maxmemoryPolicyHint != "string") return "Redis maxmemoryPolicyHint must be a string";
151
- }, Z = (e) => {
152
- let t = X(e);
153
- return t ? U.fail(q(t)) : e.driver === "resp" ? U.try({
156
+ }, X = (e) => {
157
+ let t = Y(e);
158
+ return t ? H.fail(K(t)) : e.driver === "resp" ? H.try({
154
159
  try: () => {
155
- let t = v(e);
156
- if (E(e), e.readFrom === "replica" && t.kind === "standalone" && !e.replicas?.length) throw Error("Standalone replica reads require replica endpoints");
160
+ let t = y(e);
161
+ if (D(e), e.readFrom === "replica" && t.kind === "standalone" && !e.replicas?.length) throw Error("Standalone replica reads require replica endpoints");
157
162
  return t.kind === "cluster" && e.cluster === void 0 ? {
158
163
  ...e,
159
164
  cluster: !0
160
165
  } : e;
161
166
  },
162
- catch: () => q("Invalid native Redis topology declaration")
163
- }) : U.succeed(e);
164
- }, Q = ["resp", "http"], ce = (e, t = {}) => U.gen(function* () {
165
- let n = Y(e), r = t.url ?? (yield* B.String(`${n}_REDIS_URL`).pipe(B.orElse(() => B.String("REDIS_URL")))), i = t.driver === void 0 ? yield* B.Literals(Q, `${n}_REDIS_DRIVER`).pipe(B.option) : G.none(), a = t.driver ?? (G.isSome(i) ? i.value : yield* B.Literals(Q, "REDIS_DRIVER").pipe(B.withDefault("resp"))), o = t.token === void 0 ? yield* B.String(`${n}_REDIS_TOKEN`).pipe(B.orElse(() => B.String("REDIS_TOKEN")), B.orElse(() => B.String("UPSTASH_REDIS_REST_TOKEN")), B.option) : G.some(t.token), s = t.keyPrefix === void 0 ? yield* B.String(`${n}_REDIS_KEY_PREFIX`).pipe(B.option) : G.some(t.keyPrefix);
167
+ catch: () => K("Invalid native Redis topology declaration")
168
+ }) : H.succeed(e);
169
+ }, Z = ["resp", "http"], ue = (e, t = {}) => H.gen(function* () {
170
+ let n = J(e), r = t.url ?? (yield* z.String(`${n}_REDIS_URL`).pipe(z.orElse(() => z.String("REDIS_URL")))), i = t.driver === void 0 ? yield* z.Literals(Z, `${n}_REDIS_DRIVER`).pipe(z.option) : W.none(), a = t.driver ?? (W.isSome(i) ? i.value : yield* z.Literals(Z, "REDIS_DRIVER").pipe(z.withDefault("resp"))), o = t.token === void 0 ? yield* z.String(`${n}_REDIS_TOKEN`).pipe(z.orElse(() => z.String("REDIS_TOKEN")), z.orElse(() => z.String("UPSTASH_REDIS_REST_TOKEN")), z.option) : W.some(t.token), s = t.keyPrefix === void 0 ? yield* z.String(`${n}_REDIS_KEY_PREFIX`).pipe(z.option) : W.some(t.keyPrefix);
166
171
  return {
167
172
  url: r,
168
173
  driver: a,
169
- ...G.isSome(o) ? { token: o.value } : {},
170
- ...G.isSome(s) ? { keyPrefix: s.value } : {},
174
+ ...W.isSome(o) ? { token: o.value } : {},
175
+ ...W.isSome(s) ? { keyPrefix: s.value } : {},
171
176
  ...t.source === void 0 ? {} : { source: t.source },
172
177
  ...t.connectTimeoutMs === void 0 ? {} : { connectTimeoutMs: t.connectTimeoutMs },
173
178
  ...t.commandTimeoutMs === void 0 ? {} : { commandTimeoutMs: t.commandTimeoutMs }
174
179
  };
175
- }).pipe(U.flatMap(Z));
176
- function le(e, t, n) {
180
+ }).pipe(H.flatMap(X));
181
+ function Q(e, t, n) {
177
182
  let r = n === void 0 ? void 0 : Object.freeze({ tenantId: n.tenantId });
178
- return U.gen(function* () {
183
+ return H.gen(function* () {
179
184
  let n = a(t ?? {});
180
- if (n) return yield* U.fail(q(n));
185
+ if (n) return yield* H.fail(K(n));
181
186
  let i = e.includes(":"), o = i ? e.slice(e.indexOf(":") + 1) : e;
182
- if (i && !e.startsWith("redis:")) return yield* U.fail(q("A Redis consumer requires a redis:name connection reference"));
183
- if (i && o && !/^[A-Za-z][A-Za-z0-9_-]*$/.test(o)) return yield* U.fail(q("Malformed Redis connection reference"));
187
+ if (i && !e.startsWith("redis:")) return yield* H.fail(K("A Redis consumer requires a redis:name connection reference"));
188
+ if (i && o && !/^[A-Za-z][A-Za-z0-9_-]*$/.test(o)) return yield* H.fail(K("Malformed Redis connection reference"));
184
189
  let s = t?.redis ?? {}, c = Object.keys(s), l = f(o, t ?? {}), u = Object.hasOwn(s, l) ? s[l] : void 0;
185
- if (!u && c.length > 0) return yield* U.fail(q(`Unknown Redis connection ${l || "(default)"}. Known names: ${c.sort().join(", ") || "(none)"}`));
186
- let d = `CONNECTIONS_REDIS_${Y(l)}`, p = yield* B.String(`${d}_URL`).pipe(B.option), m = yield* B.Literals(["resp", "http"], `${d}_DRIVER`).pipe(B.option), h = yield* B.String(`${d}_TOKEN`).pipe(B.option), g = yield* B.String(`${d}_KEY_PREFIX`).pipe(B.option), _ = {
187
- ...G.isSome(p) ? { url: p.value } : {},
188
- ...G.isSome(m) ? { driver: m.value } : {},
189
- ...G.isSome(h) ? { token: h.value } : {},
190
- ...G.isSome(g) ? { keyPrefix: g.value } : {},
190
+ if (!u && c.length > 0) return yield* H.fail(K(`Unknown Redis connection ${l || "(default)"}. Known names: ${c.sort().join(", ") || "(none)"}`));
191
+ let d = `CONNECTIONS_REDIS_${J(l)}`, p = yield* z.String(`${d}_URL`).pipe(z.option), m = yield* z.Literals(["resp", "http"], `${d}_DRIVER`).pipe(z.option), h = yield* z.String(`${d}_TOKEN`).pipe(z.option), g = yield* z.String(`${d}_KEY_PREFIX`).pipe(z.option), _ = {
192
+ ...W.isSome(p) ? { url: p.value } : {},
193
+ ...W.isSome(m) ? { driver: m.value } : {},
194
+ ...W.isSome(h) ? { token: h.value } : {},
195
+ ...W.isSome(g) ? { keyPrefix: g.value } : {},
191
196
  ...[
192
197
  p,
193
198
  m,
194
199
  h,
195
200
  g
196
- ].some(G.isSome) ? { source: "override" } : {}
201
+ ].some(W.isSome) ? { source: "override" } : {}
197
202
  };
198
203
  if (u && "_tag" in u && u._tag === "MemoryRedisConnection") return [
199
204
  p,
200
205
  m,
201
206
  h,
202
207
  g
203
- ].some(G.isSome) ? yield* U.fail(q("A local memory connection cannot be redirected by transport environment overrides")) : {
208
+ ].some(W.isSome) ? yield* H.fail(K("A local memory connection cannot be redirected by transport environment overrides")) : {
204
209
  url: `memory:${l}`,
205
210
  driver: "memory",
206
211
  source: "config",
207
212
  ...u.now === void 0 ? {} : { memoryClock: u.now }
208
213
  };
209
214
  if (u && "_tag" in u) {
210
- if (!r?.tenantId) return yield* U.fail(q("A dynamic Redis connection requires tenantId"));
215
+ if (!r?.tenantId) return yield* H.fail(K("A dynamic Redis connection requires tenantId"));
211
216
  let e = {
212
217
  ...yield* u.resolve(r),
213
218
  ..._
214
- }, t = X(e);
215
- return t ? yield* U.fail(q(t)) : e.driver === "memory" ? yield* U.fail(q("Local memory connections require a memory() declaration, not a tenant credential resolver")) : e.keyPrefix !== void 0 && typeof e.keyPrefix != "string" ? yield* U.fail(q("Connection keyPrefix must be a string")) : e.allowSharedNamespace !== void 0 && typeof e.allowSharedNamespace != "boolean" ? yield* U.fail(q("Connection allowSharedNamespace must be a boolean")) : e.driver === "http" && !e.token ? yield* U.fail(q("An HTTP Redis connection requires a declared token")) : e.tls === "required" && !/^rediss(?:\+cluster|\+sentinel)?:\/\//i.test(e.url) && !(e.driver === "http" && /^https:\/\//i.test(e.url)) ? yield* U.fail(q("A Redis connection with tls: required needs a secure Redis scheme or HTTPS")) : yield* Z(e);
219
+ }, t = Y(e);
220
+ return t ? yield* H.fail(K(t)) : e.driver === "memory" ? yield* H.fail(K("Local memory connections require a memory() declaration, not a tenant credential resolver")) : e.keyPrefix !== void 0 && typeof e.keyPrefix != "string" ? yield* H.fail(K("Connection keyPrefix must be a string")) : e.allowSharedNamespace !== void 0 && typeof e.allowSharedNamespace != "boolean" ? yield* H.fail(K("Connection allowSharedNamespace must be a boolean")) : e.driver === "http" && !e.token ? yield* H.fail(K("An HTTP Redis connection requires a declared token")) : e.tls === "required" && !/^rediss(?:\+cluster|\+sentinel)?:\/\//i.test(e.url) && !(e.driver === "http" && /^https:\/\//i.test(e.url)) ? yield* H.fail(K("A Redis connection with tls: required needs a secure Redis scheme or HTTPS")) : yield* X(e);
216
221
  }
217
- if (!u) return yield* ce(l || e, _);
218
- let v = G.isSome(p) ? p.value : yield* B.String(u.url.name), y = G.isSome(m) ? m.value : u.driver ?? "resp", b = G.isSome(h) ? G.some(h.value) : u.token ? G.some(yield* B.String(u.token.name)) : G.none();
219
- if (y === "http" && G.isNone(b)) return yield* U.fail(q("An HTTP Redis connection requires a declared token"));
220
- let x = G.isSome(g) ? g.value : u.keyPrefix, S = u.cluster ?? /^rediss?\+cluster:\/\//i.test(v);
221
- if (u.tls === "required" && !/^rediss(?:\+cluster|\+sentinel)?:\/\//i.test(v) && !(y === "http" && /^https:\/\//i.test(v))) return yield* U.fail(q("A Redis connection with tls: required needs a secure Redis scheme or HTTPS"));
222
- let C = yield* U.forEach(u.replicas ?? [], (e) => B.String(e.name));
223
- return yield* Z({
222
+ if (!u) return yield* ue(l || e, _);
223
+ let v = W.isSome(p) ? p.value : yield* z.String(u.url.name), y = W.isSome(m) ? m.value : u.driver ?? "resp", b = W.isSome(h) ? W.some(h.value) : u.token ? W.some(yield* z.String(u.token.name)) : W.none();
224
+ if (y === "http" && W.isNone(b)) return yield* H.fail(K("An HTTP Redis connection requires a declared token"));
225
+ let x = W.isSome(g) ? g.value : u.keyPrefix, S = u.cluster ?? /^rediss?\+cluster:\/\//i.test(v);
226
+ if (u.tls === "required" && !/^rediss(?:\+cluster|\+sentinel)?:\/\//i.test(v) && !(y === "http" && /^https:\/\//i.test(v))) return yield* H.fail(K("A Redis connection with tls: required needs a secure Redis scheme or HTTPS"));
227
+ let C = yield* H.forEach(u.replicas ?? [], (e) => z.String(e.name));
228
+ return yield* X({
224
229
  url: v,
225
230
  driver: y,
226
231
  cluster: S,
@@ -229,8 +234,8 @@ function le(e, t, n) {
229
234
  m,
230
235
  h,
231
236
  g
232
- ].some(G.isSome) ? "override" : "config",
233
- ...G.isSome(b) ? { token: b.value } : {},
237
+ ].some(W.isSome) ? "override" : "config",
238
+ ...W.isSome(b) ? { token: b.value } : {},
234
239
  ...x === void 0 ? {} : { keyPrefix: x },
235
240
  ...u.allowSharedNamespace === void 0 ? {} : { allowSharedNamespace: u.allowSharedNamespace },
236
241
  ...u.tls === void 0 ? {} : { tls: u.tls },
@@ -246,12 +251,12 @@ function le(e, t, n) {
246
251
  });
247
252
  });
248
253
  }
249
- var ue = (n) => U.tryPromise({
254
+ var de = (n) => H.tryPromise({
250
255
  try: async (e) => {
251
256
  e.throwIfAborted();
252
- let t = X(n);
257
+ let t = Y(n);
253
258
  if (t) throw Error(t);
254
- if (n.driver === "resp" && E(n), n.driver === "memory") {
259
+ if (n.driver === "resp" && D(n), n.driver === "memory") {
255
260
  let { makeMemoryConnectionState: e } = await import("./connectionMemory.js"), t = e(n.memoryClock), r = t.command();
256
261
  return {
257
262
  ...r,
@@ -261,7 +266,7 @@ var ue = (n) => U.tryPromise({
261
266
  };
262
267
  }
263
268
  if (n.driver === "http") {
264
- let t = await import("@upstash/redis");
269
+ let t = await import("@upstash/redis").catch(g("@upstash/redis", "An Upstash HTTP connection"));
265
270
  e.throwIfAborted();
266
271
  let r = typeof t.default == "function" ? t.default : t.default?.Redis, i = t.Redis ?? r;
267
272
  if (!i) throw Error("@upstash/redis: Redis constructor not found in module");
@@ -280,7 +285,7 @@ var ue = (n) => U.tryPromise({
280
285
  signal: r.signal
281
286
  });
282
287
  if (await a.ping() !== "PONG") throw Error("HTTP reader readiness failed");
283
- let o = J(a);
288
+ let o = q(a);
284
289
  if (Number(await o.readOnly.eval("return 1", 0)) !== 1) throw Error("HTTP read-only Lua readiness failed");
285
290
  return e.throwIfAborted(), {
286
291
  ...o,
@@ -309,14 +314,14 @@ var ue = (n) => U.tryPromise({
309
314
  if (await t.ping() !== "PONG") throw Error("HTTP primary readiness failed");
310
315
  e.throwIfAborted();
311
316
  let r = {
312
- ...J(t),
317
+ ...q(t),
313
318
  close: async () => {
314
319
  o.abort();
315
320
  }
316
321
  }, s = [];
317
322
  try {
318
323
  if (n.readFrom !== void 0 && n.readFrom !== "primary") for (let e of n.replicas ?? []) s.push(await a(e));
319
- let t = ee(r, s, n.readFrom);
324
+ let t = E(r, s, n.readFrom);
320
325
  return (n.readFrom === "replica" || n.readFrom === "nearest") && await t.readOnly.eval("return 1", 0), e.throwIfAborted(), t;
321
326
  } catch (e) {
322
327
  throw await Promise.all([r, ...s].map((e) => e.close())), e;
@@ -327,7 +332,7 @@ var ue = (n) => U.tryPromise({
327
332
  e.removeEventListener("abort", s);
328
333
  }
329
334
  }
330
- let r = await g(n), i = r.client;
335
+ let r = await _(n), i = r.client;
331
336
  i.on("error", () => {});
332
337
  let a = () => {
333
338
  i.disconnect();
@@ -336,19 +341,19 @@ var ue = (n) => U.tryPromise({
336
341
  try {
337
342
  e.throwIfAborted(), await i.connect(), await r.ready(), e.throwIfAborted();
338
343
  } catch (e) {
339
- throw await _(r), e;
344
+ throw await v(r), e;
340
345
  } finally {
341
346
  e.removeEventListener("abort", a);
342
347
  }
343
348
  try {
344
349
  let t = await te(n, r, e);
345
350
  try {
346
- return e.throwIfAborted(), se(r, t);
351
+ return e.throwIfAborted(), le(r, t);
347
352
  } catch (e) {
348
353
  throw await t.close(), e;
349
354
  }
350
355
  } catch (e) {
351
- throw await _(r), e;
356
+ throw await v(r), e;
352
357
  }
353
358
  },
354
359
  catch: () => new e({
@@ -356,6 +361,5 @@ var ue = (n) => U.tryPromise({
356
361
  key: "",
357
362
  cause: n.keyPrefix !== void 0 && typeof n.keyPrefix != "string" ? "Connection keyPrefix must be a string" : "Redis connection could not be opened"
358
363
  })
359
- }).pipe(U.map((e) => t(e, n.keyPrefix))), de = K.max([K.exponential("10 millis"), K.recurs(2)]), $ = class extends H.Service()("@voltro/RedisConnections") {}, fe = W.effect($, U.suspend(() => T()).pipe(U.orDie, U.map((e) => e.redis)));
360
- //#endregion
361
- export { z as CACHE_ATOMIC_SCRIPT, D as CACHE_FENCE_RETENTION_MS, O as CacheAtomicProtocolError, C as ConnectionRegistry, $ as RedisConnections, i as byTenant, k as cacheAtomicArray, A as cacheAtomicComponent, re as cacheAtomicKeys, ie as cacheAtomicMember, ae as cacheAtomicMembership, oe as cacheAtomicRoot, j as cacheAtomicScanPage, M as cacheAtomicSnapshot, N as cacheAtomicTtl, P as cacheAtomicValueSnapshots, de as commandRetry, ue as connect, b as connectRedisSubscriber, le as connectionConfig, a as connectionDefinitionsProblem, s as declaredConnectionEnv, F as decodeCacheAtomicCommand, I as decodeCacheAtomicPolicy, L as decodeCacheAtomicReply, c as dynamic, r as dynamicAnalytics, l as dynamicNats, n as dynamicSql, x as dynamicStorage, u as env, R as isCacheAtomicRead, w as layerConfiguredConnections, fe as layerConnections, T as makeConnectionRegistry, d as memory, m as roundRobin, h as shardBy, S as withConnectionRegistryConfigProvider };
364
+ }).pipe(H.map((e) => t(e, n.keyPrefix))), fe = G.max([G.exponential("10 millis"), G.recurs(2)]), $ = class extends V.Service()("@voltro/RedisConnections") {}, pe = U.effect($, H.suspend(() => T()).pipe(H.orDie, H.map((e) => e.redis)));
365
+ export { R as CACHE_ATOMIC_SCRIPT, re as CACHE_FENCE_RETENTION_MS, ie as CacheAtomicProtocolError, ee as ConnectionRegistry, $ as RedisConnections, i as byTenant, ae as cacheAtomicArray, oe as cacheAtomicComponent, se as cacheAtomicKeys, ce as cacheAtomicMember, O as cacheAtomicMembership, k as cacheAtomicRoot, A as cacheAtomicScanPage, j as cacheAtomicSnapshot, M as cacheAtomicTtl, N as cacheAtomicValueSnapshots, fe as commandRetry, de as connect, x as connectRedisSubscriber, Q as connectionConfig, a as connectionDefinitionsProblem, s as declaredConnectionEnv, P as decodeCacheAtomicCommand, F as decodeCacheAtomicPolicy, I as decodeCacheAtomicReply, c as dynamic, r as dynamicAnalytics, l as dynamicNats, n as dynamicSql, S as dynamicStorage, u as env, L as isCacheAtomicRead, w as layerConfiguredConnections, pe as layerConnections, T as makeConnectionRegistry, d as memory, m as roundRobin, h as shardBy, C as withConnectionRegistryConfigProvider };
@@ -1,6 +1,6 @@
1
1
  import { connectionDefinitionsProblem as e, connectionMetadataProblem as t } from "./connectionDefinitions.js";
2
2
  import { Config as n, ConfigProvider as r, Effect as i, Option as a } from "effect";
3
- //#region src/connectionAnalyticsConfig.ts
3
+ // src/connectionAnalyticsConfig.ts
4
4
  var o = (e, t = {}) => {
5
5
  let n = t.ttlMs ?? 6e4;
6
6
  if (typeof e != "function" || !Number.isSafeInteger(n) || n <= 0) throw Error("Dynamic analytics requires a resolver and positive ttlMs");
@@ -149,5 +149,4 @@ var o = (e, t = {}) => {
149
149
  source: _ ? "override" : "config"
150
150
  };
151
151
  });
152
- //#endregion
153
152
  export { h as analyticsConfigProblem, _ as analyticsConnectionConfig, g as analyticsConnectionName, m as analyticsDefinitionProblem, o as dynamicAnalytics };
@@ -0,0 +1,10 @@
1
+ import { Config as e, ConfigProvider as t } from "effect";
2
+ // src/connectionConfigError.ts
3
+ var n = {
4
+ redis: "Dynamic connection credentials could not be resolved",
5
+ nats: "Dynamic connection credentials could not be resolved",
6
+ storage: "Dynamic storage credentials could not be resolved",
7
+ analytics: "Dynamic analytics credentials could not be resolved",
8
+ sql: "Dynamic SQL credentials could not be resolved"
9
+ }, r = (r, i) => r._tag === "ConfigError" ? r : new e.ConfigError(new t.SourceError({ message: n[i] }));
10
+ export { r as connectionConfigError };
@@ -1,5 +1,5 @@
1
1
  import { ConfigProvider as e, Effect as t, Stream as n } from "effect";
2
- //#region src/connectionConfigProvider.ts
2
+ // src/connectionConfigProvider.ts
3
3
  var r = /* @__PURE__ */ new WeakMap(), i = (i, s) => {
4
4
  i = r.get(i) ?? i;
5
5
  function c(n, r) {
@@ -107,5 +107,4 @@ var r = /* @__PURE__ */ new WeakMap(), i = (i, s) => {
107
107
  maxVersion: (i) => n.mirror.maxVersion(i).pipe(t.provideService(e.ConfigProvider, r))
108
108
  } }
109
109
  });
110
- //#endregion
111
110
  export { i as withConnectionRegistryConfigProvider };
@@ -1,6 +1,6 @@
1
1
  import { sqlDefinitionProblem as e } from "./connectionSqlConfig.js";
2
2
  import { analyticsDefinitionProblem as t } from "./connectionAnalyticsConfig.js";
3
- //#region src/connectionDefinitions.ts
3
+ // src/connectionDefinitions.ts
4
4
  var n = (e) => {
5
5
  if (!/^[A-Z][A-Z0-9_]*$/.test(e)) throw Error("Connection env names must use uppercase letters, digits and underscores");
6
6
  return Object.freeze({
@@ -281,5 +281,4 @@ var n = (e) => {
281
281
  for (let n of [...Object.values(e.analytics ?? {}), ...Object.values(e.sql ?? {})]) if (!("_tag" in n)) for (let e of Object.values(n)) typeof e == "object" && e && "_tag" in e && e._tag === "ConnectionEnv" && t.add(e.name);
282
282
  return [...t].sort();
283
283
  };
284
- //#endregion
285
284
  export { p as byTenant, l as connectionDefinitionsProblem, u as connectionMetadataProblem, m as declaredConnectionEnv, a as dynamic, o as dynamicNats, n as env, i as memory, s as natsConnectionName, c as redisConnectionName, r as redisTimeoutsProblem, f as roundRobin, d as shardBy };
@@ -6,7 +6,7 @@ import { applyHotOperations as i, compareHotMembers as a } from "./hotState.js";
6
6
  import { HotError as o } from "./hot-contract.js";
7
7
  import "./hotRedisScript.js";
8
8
  import { applyCacheAtomicCommand as s } from "./cacheAtomicState.js";
9
- //#region src/connectionMemory.ts
9
+ // src/connectionMemory.ts
10
10
  var c = (c = Date.now) => {
11
11
  let l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Set(), p = !1, m = () => {
12
12
  if (p) throw Error("Memory connection is closed");
@@ -203,5 +203,4 @@ var c = (c = Date.now) => {
203
203
  }
204
204
  };
205
205
  };
206
- //#endregion
207
206
  export { c as makeMemoryConnectionState };
@@ -1,5 +1,5 @@
1
1
  import { Effect as e, Metric as t } from "effect";
2
- //#region src/connectionMetrics.ts
2
+ // src/connectionMetrics.ts
3
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
4
  boundaries: t.exponentialBoundaries({
5
5
  start: .001,
@@ -75,5 +75,4 @@ var n = /* @__PURE__ */ new Map(), r = t.gauge("voltro_connection_up", { descrip
75
75
  }
76
76
  };
77
77
  };
78
- //#endregion
79
78
  export { f as makeConnectionMetrics };
@@ -1,4 +1,4 @@
1
- //#region src/connectionNamespace.ts
1
+ // src/connectionNamespace.ts
2
2
  var e = (e) => encodeURIComponent(e).replace(/[!'()*]/g, (e) => `%${e.charCodeAt(0).toString(16).toUpperCase()}`), t = (t) => {
3
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
4
  return `voltro:${e(t.appName)}:${e(t.environment)}:`;
@@ -15,5 +15,4 @@ var e = (e) => encodeURIComponent(e).replace(/[!'()*]/g, (e) => `%${e.charCodeAt
15
15
  keyPrefix: i
16
16
  };
17
17
  };
18
- //#endregion
19
18
  export { n as applyConnectionNamespace, t as connectionNamespace };