@voltro/kv 0.85.0 → 0.87.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/CHANGELOG.md +5987 -0
  2. package/README.md +110 -0
  3. package/THIRD-PARTY-NOTICES.md +865 -2
  4. package/dist/Kv.js +19 -0
  5. package/dist/KvStore.js +5 -0
  6. package/dist/analytics.d.ts +337 -0
  7. package/dist/analytics.js +16 -0
  8. package/dist/backendMemory.js +36 -0
  9. package/dist/backendRedis.js +48 -0
  10. package/dist/cacheAtomicProtocol.js +247 -0
  11. package/dist/cacheAtomicScript.js +309 -0
  12. package/dist/cacheAtomicState.js +141 -0
  13. package/dist/connection.d.ts +990 -9
  14. package/dist/connection.js +361 -2
  15. package/dist/connectionAnalyticsConfig.js +153 -0
  16. package/dist/connectionConfigProvider.js +111 -0
  17. package/dist/connectionDefinitions.js +285 -0
  18. package/dist/connectionMemory.js +207 -0
  19. package/dist/connectionMetrics.js +79 -0
  20. package/dist/connectionNamespace.js +19 -0
  21. package/dist/connectionNats.js +148 -0
  22. package/dist/connectionNatsConfig.js +87 -0
  23. package/dist/connectionNatsSubjects.js +16 -0
  24. package/dist/connectionOwner.js +44 -0
  25. package/dist/connectionPool.js +738 -0
  26. package/dist/connectionPrefix.js +37 -0
  27. package/dist/connectionScripts.js +4 -0
  28. package/dist/connectionSqlConfig.js +119 -0
  29. package/dist/connectionStorageConfig.js +190 -0
  30. package/dist/connectionStorageFacade.js +78 -0
  31. package/dist/connectionSubscriber.js +130 -0
  32. package/dist/errors.js +13 -0
  33. package/dist/expirySweep.js +26 -0
  34. package/dist/hot-contract.d.ts +297 -0
  35. package/dist/hot-contract.js +18 -0
  36. package/dist/hot-testing.d.ts +229 -0
  37. package/dist/hot-testing.js +1 -0
  38. package/dist/hot.d.ts +936 -0
  39. package/dist/hot.js +7 -0
  40. package/dist/hotMemory.js +46 -0
  41. package/dist/hotOperations.js +223 -0
  42. package/dist/hotRateLimit.js +103 -0
  43. package/dist/hotReadAvailability.js +19 -0
  44. package/dist/hotRedis.js +139 -0
  45. package/dist/hotRedisScript.js +4 -0
  46. package/dist/hotRouting.js +78 -0
  47. package/dist/hotState.js +182 -0
  48. package/dist/hotStoreConformance.js +367 -0
  49. package/dist/index.d.ts +113 -9
  50. package/dist/index.js +7 -115
  51. package/dist/nativeRedisReads.js +78 -0
  52. package/dist/nativeRedisTopology.js +221 -0
  53. package/dist/redisDiagnostics.js +27 -0
  54. package/dist/redisReadPolicy.js +39 -0
  55. package/dist/sql.d.ts +77 -0
  56. package/dist/sql.js +0 -0
  57. package/dist/storage.d.ts +166 -0
  58. package/dist/storage.js +48 -0
  59. package/dist/storageAddress.js +20 -0
  60. package/package.json +43 -3
  61. package/dist/connection-Dsn5fgcH.js +0 -84
@@ -0,0 +1,297 @@
1
+ import { Context } from 'effect';
2
+ import { Effect } from 'effect';
3
+ import { Option } from 'effect';
4
+ import { Schema } from 'effect';
5
+ import { Stream } from 'effect';
6
+ import { YieldableError } from 'effect/Cause';
7
+
8
+ /** Shared deterministic transition. No clock, store, socket or timer access. */
9
+ export declare const applyHotOperations: (state: Map<string, HotEntry>, ops: ReadonlyArray<HotOp>, now: number) => ReadonlyArray<unknown>;
10
+
11
+ /** Unicode scalar order matches Redis's UTF-8 byte order, including astral characters. */
12
+ export declare const compareHotMembers: (a: string, b: string) => number;
13
+
14
+ /** Consumers choose an explicit read fallback or preserve an unavailable failure. */
15
+ declare type ConnectionUnavailablePolicy = 'degrade' | 'fail';
16
+
17
+ /** Pure quota math shared by memory, database and HotStore consumers. */
18
+ export declare const consumeHotRateLimit: (previous: HotRateLimitState | undefined, config: HotRateLimitConfig, nowMs: number) => HotRateLimitTransition;
19
+
20
+ export declare interface HotBucketConfig {
21
+ readonly capacity: number;
22
+ readonly refillPerSec: number;
23
+ }
24
+
25
+ export declare interface HotBucketResult {
26
+ readonly allowed: boolean;
27
+ readonly remaining: number;
28
+ readonly retryAfterMs: number;
29
+ }
30
+
31
+ export declare interface HotCounterOptions extends HotTtl {
32
+ readonly max?: number;
33
+ }
34
+
35
+ export declare type HotEntry = HotValue & {
36
+ expiresAt: number;
37
+ };
38
+
39
+ /** Ephemeral data failures. SQL remains the durable source of truth. */
40
+ export declare class HotError extends HotError_base {
41
+ }
42
+
43
+ declare const HotError_base: Schema.Class<HotError, Schema.TaggedStruct<"HotError", {
44
+ readonly operation: Schema.String;
45
+ readonly key: Schema.String;
46
+ readonly reason: Schema.Literals<readonly ["invalid", "wrongType", "limit", "unavailable"]>;
47
+ }>, YieldableError>;
48
+
49
+ export declare interface HotMember {
50
+ readonly member: string;
51
+ readonly score: number;
52
+ }
53
+
54
+ /** Operations accepted by an atomic batch. A batch cannot contain a scan. */
55
+ export declare type HotOp = {
56
+ readonly op: 'zadd';
57
+ readonly key: string;
58
+ readonly members: ReadonlyArray<HotMember>;
59
+ readonly options?: HotZaddOptions;
60
+ } | {
61
+ readonly op: 'zrem';
62
+ readonly key: string;
63
+ readonly members: ReadonlyArray<string>;
64
+ } | {
65
+ readonly op: 'zrank';
66
+ readonly key: string;
67
+ readonly member: string;
68
+ readonly order: HotOrder;
69
+ } | {
70
+ readonly op: 'zscore';
71
+ readonly key: string;
72
+ readonly member: string;
73
+ } | {
74
+ readonly op: 'zrange';
75
+ readonly key: string;
76
+ readonly range: HotRange;
77
+ readonly order: HotOrder;
78
+ readonly options?: Pick<HotRangeOptions, 'limit'>;
79
+ } | {
80
+ readonly op: 'zcard';
81
+ readonly key: string;
82
+ } | {
83
+ readonly op: 'zremRange';
84
+ readonly key: string;
85
+ readonly range: HotRange;
86
+ } | {
87
+ readonly op: 'incrBy';
88
+ readonly key: string;
89
+ readonly delta: number;
90
+ readonly options?: HotCounterOptions;
91
+ } | {
92
+ readonly op: 'tokenBucket';
93
+ readonly key: string;
94
+ readonly config: HotBucketConfig;
95
+ readonly cost: number;
96
+ } | {
97
+ readonly op: 'rateLimit';
98
+ readonly key: string;
99
+ readonly config: HotRateLimitConfig;
100
+ readonly nowMs?: number;
101
+ } | {
102
+ readonly op: 'hset';
103
+ readonly key: string;
104
+ readonly fields: Readonly<Record<string, string>>;
105
+ readonly options?: HotTtl;
106
+ } | {
107
+ readonly op: 'hget';
108
+ readonly key: string;
109
+ readonly field: string;
110
+ } | {
111
+ readonly op: 'hgetAll';
112
+ readonly key: string;
113
+ } | {
114
+ readonly op: 'hdel';
115
+ readonly key: string;
116
+ readonly fields: ReadonlyArray<string>;
117
+ } | {
118
+ readonly op: 'sadd';
119
+ readonly key: string;
120
+ readonly members: ReadonlyArray<string>;
121
+ readonly options?: HotTtl;
122
+ } | {
123
+ readonly op: 'srem';
124
+ readonly key: string;
125
+ readonly members: ReadonlyArray<string>;
126
+ } | {
127
+ readonly op: 'smembers';
128
+ readonly key: string;
129
+ } | {
130
+ readonly op: 'sismember';
131
+ readonly key: string;
132
+ readonly member: string;
133
+ } | {
134
+ readonly op: 'setNx';
135
+ readonly key: string;
136
+ readonly value: string;
137
+ readonly ttlMs: number;
138
+ } | {
139
+ readonly op: 'compareDelete';
140
+ readonly key: string;
141
+ readonly value: string;
142
+ } | {
143
+ readonly op: 'compareExpire';
144
+ readonly key: string;
145
+ readonly value: string;
146
+ readonly ttlMs: number;
147
+ } | {
148
+ readonly op: 'expire';
149
+ readonly key: string;
150
+ readonly ttlMs: number;
151
+ } | {
152
+ readonly op: 'delete';
153
+ readonly key: string;
154
+ };
155
+
156
+ export declare type HotOrder = 'asc' | 'desc';
157
+
158
+ export declare type HotRange = {
159
+ readonly byRank: readonly [number, number];
160
+ } | {
161
+ readonly byScore: readonly [number, number];
162
+ };
163
+
164
+ export declare interface HotRangeOptions extends HotReadOptions {
165
+ readonly limit?: number;
166
+ }
167
+
168
+ export declare interface HotRateLimitConfig {
169
+ readonly algorithm: 'fixed-window' | 'sliding-window' | 'token-bucket';
170
+ readonly limit: number;
171
+ readonly windowMs: number;
172
+ readonly burst: number;
173
+ }
174
+
175
+ export declare interface HotRateLimitResult extends HotBucketResult {
176
+ readonly resetAtMs: number;
177
+ }
178
+
179
+ export declare type HotRateLimitState = {
180
+ readonly kind: 'fixed';
181
+ readonly windowStart: number;
182
+ readonly count: number;
183
+ } | {
184
+ readonly kind: 'sliding';
185
+ readonly currStart: number;
186
+ readonly currCount: number;
187
+ readonly prevCount: number;
188
+ } | {
189
+ readonly kind: 'token';
190
+ readonly tokens: number;
191
+ readonly lastRefill: number;
192
+ };
193
+
194
+ export declare interface HotRateLimitTransition {
195
+ readonly state: HotRateLimitState;
196
+ readonly decision: HotRateLimitResult;
197
+ }
198
+
199
+ /** Default reads use the primary. Eventual reads may observe a replica. */
200
+ export declare interface HotReadOptions {
201
+ readonly consistency?: 'primary' | 'eventual';
202
+ }
203
+
204
+ export declare class HotStore extends HotStore_base {
205
+ }
206
+
207
+ declare const HotStore_base: Context.ServiceClass<HotStore, "@voltro/HotStore", HotStoreShape>;
208
+
209
+ /** Backends return JSON-compatible results; the public read methods lift misses to Option. */
210
+ export declare const hotStoreFromRunner: (run: (operations: ReadonlyArray<HotOp>, options?: HotReadOptions) => Effect.Effect<ReadonlyArray<unknown>, HotError>, scanPrefix: (prefix: string) => Stream.Stream<string, HotError>, capabilities: HotStoreShape["capabilities"]) => HotStoreShape;
211
+
212
+ /** Only non-mutating, single-key reads; no leases, quota consumption, batch or scan. */
213
+ export declare type HotStoreReadShape = Pick<HotStoreShape, 'zrank' | 'zscore' | 'zrange' | 'zcard' | 'hget' | 'hgetAll' | 'smembers' | 'sismember'>;
214
+
215
+ export declare interface HotStoreShape {
216
+ readonly zadd: (key: string, members: ReadonlyArray<HotMember>, options?: HotZaddOptions) => Effect.Effect<void, HotError>;
217
+ readonly zrem: (key: string, members: ReadonlyArray<string>) => Effect.Effect<number, HotError>;
218
+ readonly zrank: (key: string, member: string, order: HotOrder, options?: HotReadOptions) => Effect.Effect<Option.Option<number>, HotError>;
219
+ readonly zscore: (key: string, member: string, options?: HotReadOptions) => Effect.Effect<Option.Option<number>, HotError>;
220
+ readonly zrange: (key: string, range: HotRange, order: HotOrder, options?: HotRangeOptions) => Effect.Effect<ReadonlyArray<HotMember>, HotError>;
221
+ readonly zcard: (key: string, options?: HotReadOptions) => Effect.Effect<number, HotError>;
222
+ readonly zremRange: (key: string, range: HotRange) => Effect.Effect<number, HotError>;
223
+ readonly incrBy: (key: string, delta: number, options?: HotCounterOptions) => Effect.Effect<number, HotError>;
224
+ readonly tokenBucket: (key: string, config: HotBucketConfig, cost?: number) => Effect.Effect<HotBucketResult, HotError>;
225
+ /** Atomically check and consume one request. nowMs is trusted server/test time. */
226
+ readonly rateLimit: (key: string, config: HotRateLimitConfig, nowMs?: number) => Effect.Effect<HotRateLimitResult, HotError>;
227
+ readonly hset: (key: string, fields: Readonly<Record<string, string>>, options?: HotTtl) => Effect.Effect<void, HotError>;
228
+ readonly hget: (key: string, field: string, options?: HotReadOptions) => Effect.Effect<Option.Option<string>, HotError>;
229
+ readonly hgetAll: (key: string, options?: HotReadOptions) => Effect.Effect<Readonly<Record<string, string>>, HotError>;
230
+ readonly hdel: (key: string, fields: ReadonlyArray<string>) => Effect.Effect<number, HotError>;
231
+ readonly sadd: (key: string, members: ReadonlyArray<string>, options?: HotTtl) => Effect.Effect<number, HotError>;
232
+ readonly srem: (key: string, members: ReadonlyArray<string>) => Effect.Effect<number, HotError>;
233
+ readonly smembers: (key: string, options?: HotReadOptions) => Effect.Effect<ReadonlyArray<string>, HotError>;
234
+ readonly sismember: (key: string, member: string, options?: HotReadOptions) => Effect.Effect<boolean, HotError>;
235
+ readonly setNx: (key: string, value: string, ttlMs: number) => Effect.Effect<boolean, HotError>;
236
+ /** Atomically delete a setNx lease only while its value matches. Missing/mismatch returns false. */
237
+ readonly compareDelete: (key: string, value: string) => Effect.Effect<boolean, HotError>;
238
+ /** Atomically reset a matching setNx lease's TTL. Other structures fail with wrongType. */
239
+ readonly compareExpire: (key: string, value: string, ttlMs: number) => Effect.Effect<boolean, HotError>;
240
+ readonly expire: (key: string, ttlMs: number) => Effect.Effect<void, HotError>;
241
+ readonly delete: (key: string) => Effect.Effect<boolean, HotError>;
242
+ readonly scanPrefix: (prefix: string) => Stream.Stream<string, HotError>;
243
+ /** Isolated batch. Arguments are validated first. Like Redis MULTI, a backend
244
+ * need not roll back commands preceding a server-side execution failure. */
245
+ readonly multi: (operations: ReadonlyArray<HotOp>) => Effect.Effect<ReadonlyArray<unknown>, HotError>;
246
+ readonly capabilities: {
247
+ readonly atomicMulti: boolean;
248
+ readonly crossNode: boolean;
249
+ readonly persistent: boolean;
250
+ };
251
+ }
252
+
253
+ export declare interface HotTtl {
254
+ readonly ttlMs?: number;
255
+ }
256
+
257
+ export declare type HotValue = {
258
+ readonly kind: 'z';
259
+ readonly values: Map<string, number>;
260
+ } | {
261
+ readonly kind: 'h';
262
+ readonly values: Map<string, string>;
263
+ } | {
264
+ readonly kind: 's';
265
+ readonly values: Set<string>;
266
+ } | {
267
+ readonly kind: 'counter';
268
+ value: number;
269
+ } | {
270
+ readonly kind: 'lease';
271
+ readonly value: string;
272
+ } | {
273
+ readonly kind: 'bucket';
274
+ tokens: number;
275
+ updatedAt: number;
276
+ } | {
277
+ readonly kind: 'rateLimit';
278
+ readonly state: HotRateLimitState;
279
+ };
280
+
281
+ export declare interface HotZaddOptions extends HotTtl {
282
+ readonly mode?: 'set' | 'max' | 'min' | 'incr';
283
+ }
284
+
285
+ /** One read callback invocation; only a typed unavailable error may select the explicit fallback.
286
+ * Never use this boundary in a Room tick or for a write/rebuild. */
287
+ export declare const readHotStoreWithFallback: <A, E, R, R2>(input: {
288
+ readonly store: HotStoreShape;
289
+ readonly onUnavailable: ConnectionUnavailablePolicy;
290
+ readonly read: (store: HotStoreReadShape) => Effect.Effect<A, HotError, R>;
291
+ readonly fallback: () => Effect.Effect<A, E, R2>;
292
+ }) => Effect.Effect<A, HotError | E, R | R2>;
293
+
294
+ /** Common argument validation, before a backend mutates anything. */
295
+ export declare const validateHotOp: (op: HotOp) => void;
296
+
297
+ export { }
@@ -0,0 +1,18 @@
1
+ import { consumeHotRateLimit as e } from "./hotRateLimit.js";
2
+ import { hotStoreFromRunner as t, validateHotOp as n } from "./hotOperations.js";
3
+ import { applyHotOperations as r, compareHotMembers as i } from "./hotState.js";
4
+ import { readHotStoreWithFallback as a } from "./hotReadAvailability.js";
5
+ import { Context as o, Schema as s } from "effect";
6
+ //#region src/HotStore.ts
7
+ var c = class extends s.TaggedError()("HotError", {
8
+ operation: s.String,
9
+ key: s.String,
10
+ reason: s.Literals([
11
+ "invalid",
12
+ "wrongType",
13
+ "limit",
14
+ "unavailable"
15
+ ])
16
+ }) {}, l = class extends o.Service()("@voltro/HotStore") {};
17
+ //#endregion
18
+ export { c as HotError, l as HotStore, r as applyHotOperations, i as compareHotMembers, e as consumeHotRateLimit, t as hotStoreFromRunner, a as readHotStoreWithFallback, n as validateHotOp };
@@ -0,0 +1,229 @@
1
+ import { Context } from 'effect';
2
+ import { Effect } from 'effect';
3
+ import { Layer } from 'effect';
4
+ import { Option } from 'effect';
5
+ import { Schema } from 'effect';
6
+ import { Stream } from 'effect';
7
+ import { YieldableError } from 'effect/Cause';
8
+
9
+ declare interface HotBucketConfig {
10
+ readonly capacity: number;
11
+ readonly refillPerSec: number;
12
+ }
13
+
14
+ declare interface HotBucketResult {
15
+ readonly allowed: boolean;
16
+ readonly remaining: number;
17
+ readonly retryAfterMs: number;
18
+ }
19
+
20
+ export declare interface HotConformanceFixture {
21
+ readonly layer: Layer.Layer<HotStore, unknown>;
22
+ readonly advance: (ms: number) => Effect.Effect<void>;
23
+ readonly capabilities: HotStoreShape['capabilities'];
24
+ }
25
+
26
+ declare interface HotCounterOptions extends HotTtl {
27
+ readonly max?: number;
28
+ }
29
+
30
+ /** Ephemeral data failures. SQL remains the durable source of truth. */
31
+ declare class HotError extends HotError_base {
32
+ }
33
+
34
+ declare const HotError_base: Schema.Class<HotError, Schema.TaggedStruct<"HotError", {
35
+ readonly operation: Schema.String;
36
+ readonly key: Schema.String;
37
+ readonly reason: Schema.Literals<readonly ["invalid", "wrongType", "limit", "unavailable"]>;
38
+ }>, YieldableError>;
39
+
40
+ declare interface HotMember {
41
+ readonly member: string;
42
+ readonly score: number;
43
+ }
44
+
45
+ /** Operations accepted by an atomic batch. A batch cannot contain a scan. */
46
+ declare type HotOp = {
47
+ readonly op: 'zadd';
48
+ readonly key: string;
49
+ readonly members: ReadonlyArray<HotMember>;
50
+ readonly options?: HotZaddOptions;
51
+ } | {
52
+ readonly op: 'zrem';
53
+ readonly key: string;
54
+ readonly members: ReadonlyArray<string>;
55
+ } | {
56
+ readonly op: 'zrank';
57
+ readonly key: string;
58
+ readonly member: string;
59
+ readonly order: HotOrder;
60
+ } | {
61
+ readonly op: 'zscore';
62
+ readonly key: string;
63
+ readonly member: string;
64
+ } | {
65
+ readonly op: 'zrange';
66
+ readonly key: string;
67
+ readonly range: HotRange;
68
+ readonly order: HotOrder;
69
+ readonly options?: Pick<HotRangeOptions, 'limit'>;
70
+ } | {
71
+ readonly op: 'zcard';
72
+ readonly key: string;
73
+ } | {
74
+ readonly op: 'zremRange';
75
+ readonly key: string;
76
+ readonly range: HotRange;
77
+ } | {
78
+ readonly op: 'incrBy';
79
+ readonly key: string;
80
+ readonly delta: number;
81
+ readonly options?: HotCounterOptions;
82
+ } | {
83
+ readonly op: 'tokenBucket';
84
+ readonly key: string;
85
+ readonly config: HotBucketConfig;
86
+ readonly cost: number;
87
+ } | {
88
+ readonly op: 'rateLimit';
89
+ readonly key: string;
90
+ readonly config: HotRateLimitConfig;
91
+ readonly nowMs?: number;
92
+ } | {
93
+ readonly op: 'hset';
94
+ readonly key: string;
95
+ readonly fields: Readonly<Record<string, string>>;
96
+ readonly options?: HotTtl;
97
+ } | {
98
+ readonly op: 'hget';
99
+ readonly key: string;
100
+ readonly field: string;
101
+ } | {
102
+ readonly op: 'hgetAll';
103
+ readonly key: string;
104
+ } | {
105
+ readonly op: 'hdel';
106
+ readonly key: string;
107
+ readonly fields: ReadonlyArray<string>;
108
+ } | {
109
+ readonly op: 'sadd';
110
+ readonly key: string;
111
+ readonly members: ReadonlyArray<string>;
112
+ readonly options?: HotTtl;
113
+ } | {
114
+ readonly op: 'srem';
115
+ readonly key: string;
116
+ readonly members: ReadonlyArray<string>;
117
+ } | {
118
+ readonly op: 'smembers';
119
+ readonly key: string;
120
+ } | {
121
+ readonly op: 'sismember';
122
+ readonly key: string;
123
+ readonly member: string;
124
+ } | {
125
+ readonly op: 'setNx';
126
+ readonly key: string;
127
+ readonly value: string;
128
+ readonly ttlMs: number;
129
+ } | {
130
+ readonly op: 'compareDelete';
131
+ readonly key: string;
132
+ readonly value: string;
133
+ } | {
134
+ readonly op: 'compareExpire';
135
+ readonly key: string;
136
+ readonly value: string;
137
+ readonly ttlMs: number;
138
+ } | {
139
+ readonly op: 'expire';
140
+ readonly key: string;
141
+ readonly ttlMs: number;
142
+ } | {
143
+ readonly op: 'delete';
144
+ readonly key: string;
145
+ };
146
+
147
+ declare type HotOrder = 'asc' | 'desc';
148
+
149
+ declare type HotRange = {
150
+ readonly byRank: readonly [number, number];
151
+ } | {
152
+ readonly byScore: readonly [number, number];
153
+ };
154
+
155
+ declare interface HotRangeOptions extends HotReadOptions {
156
+ readonly limit?: number;
157
+ }
158
+
159
+ declare interface HotRateLimitConfig {
160
+ readonly algorithm: 'fixed-window' | 'sliding-window' | 'token-bucket';
161
+ readonly limit: number;
162
+ readonly windowMs: number;
163
+ readonly burst: number;
164
+ }
165
+
166
+ declare interface HotRateLimitResult extends HotBucketResult {
167
+ readonly resetAtMs: number;
168
+ }
169
+
170
+ /** Default reads use the primary. Eventual reads may observe a replica. */
171
+ declare interface HotReadOptions {
172
+ readonly consistency?: 'primary' | 'eventual';
173
+ }
174
+
175
+ declare class HotStore extends HotStore_base {
176
+ }
177
+
178
+ declare const HotStore_base: Context.ServiceClass<HotStore, "@voltro/HotStore", HotStoreShape>;
179
+
180
+ /** Run exactly the same behavioral contract against a backend or a replacement port. */
181
+ export declare const hotStoreConformance: (name: string, fixture: () => HotConformanceFixture) => void;
182
+
183
+ declare interface HotStoreShape {
184
+ readonly zadd: (key: string, members: ReadonlyArray<HotMember>, options?: HotZaddOptions) => Effect.Effect<void, HotError>;
185
+ readonly zrem: (key: string, members: ReadonlyArray<string>) => Effect.Effect<number, HotError>;
186
+ readonly zrank: (key: string, member: string, order: HotOrder, options?: HotReadOptions) => Effect.Effect<Option.Option<number>, HotError>;
187
+ readonly zscore: (key: string, member: string, options?: HotReadOptions) => Effect.Effect<Option.Option<number>, HotError>;
188
+ readonly zrange: (key: string, range: HotRange, order: HotOrder, options?: HotRangeOptions) => Effect.Effect<ReadonlyArray<HotMember>, HotError>;
189
+ readonly zcard: (key: string, options?: HotReadOptions) => Effect.Effect<number, HotError>;
190
+ readonly zremRange: (key: string, range: HotRange) => Effect.Effect<number, HotError>;
191
+ readonly incrBy: (key: string, delta: number, options?: HotCounterOptions) => Effect.Effect<number, HotError>;
192
+ readonly tokenBucket: (key: string, config: HotBucketConfig, cost?: number) => Effect.Effect<HotBucketResult, HotError>;
193
+ /** Atomically check and consume one request. nowMs is trusted server/test time. */
194
+ readonly rateLimit: (key: string, config: HotRateLimitConfig, nowMs?: number) => Effect.Effect<HotRateLimitResult, HotError>;
195
+ readonly hset: (key: string, fields: Readonly<Record<string, string>>, options?: HotTtl) => Effect.Effect<void, HotError>;
196
+ readonly hget: (key: string, field: string, options?: HotReadOptions) => Effect.Effect<Option.Option<string>, HotError>;
197
+ readonly hgetAll: (key: string, options?: HotReadOptions) => Effect.Effect<Readonly<Record<string, string>>, HotError>;
198
+ readonly hdel: (key: string, fields: ReadonlyArray<string>) => Effect.Effect<number, HotError>;
199
+ readonly sadd: (key: string, members: ReadonlyArray<string>, options?: HotTtl) => Effect.Effect<number, HotError>;
200
+ readonly srem: (key: string, members: ReadonlyArray<string>) => Effect.Effect<number, HotError>;
201
+ readonly smembers: (key: string, options?: HotReadOptions) => Effect.Effect<ReadonlyArray<string>, HotError>;
202
+ readonly sismember: (key: string, member: string, options?: HotReadOptions) => Effect.Effect<boolean, HotError>;
203
+ readonly setNx: (key: string, value: string, ttlMs: number) => Effect.Effect<boolean, HotError>;
204
+ /** Atomically delete a setNx lease only while its value matches. Missing/mismatch returns false. */
205
+ readonly compareDelete: (key: string, value: string) => Effect.Effect<boolean, HotError>;
206
+ /** Atomically reset a matching setNx lease's TTL. Other structures fail with wrongType. */
207
+ readonly compareExpire: (key: string, value: string, ttlMs: number) => Effect.Effect<boolean, HotError>;
208
+ readonly expire: (key: string, ttlMs: number) => Effect.Effect<void, HotError>;
209
+ readonly delete: (key: string) => Effect.Effect<boolean, HotError>;
210
+ readonly scanPrefix: (prefix: string) => Stream.Stream<string, HotError>;
211
+ /** Isolated batch. Arguments are validated first. Like Redis MULTI, a backend
212
+ * need not roll back commands preceding a server-side execution failure. */
213
+ readonly multi: (operations: ReadonlyArray<HotOp>) => Effect.Effect<ReadonlyArray<unknown>, HotError>;
214
+ readonly capabilities: {
215
+ readonly atomicMulti: boolean;
216
+ readonly crossNode: boolean;
217
+ readonly persistent: boolean;
218
+ };
219
+ }
220
+
221
+ declare interface HotTtl {
222
+ readonly ttlMs?: number;
223
+ }
224
+
225
+ declare interface HotZaddOptions extends HotTtl {
226
+ readonly mode?: 'set' | 'max' | 'min' | 'incr';
227
+ }
228
+
229
+ export { }
@@ -0,0 +1 @@
1
+ export { hotStoreConformance } from "./hotStoreConformance.js";