valkyries 0.4.0 → 0.6.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 (68) hide show
  1. package/README.md +2 -0
  2. package/dist/bloom-filter/lookups.mjs +5 -3
  3. package/dist/bloom-filter/lookups.mjs.map +1 -1
  4. package/dist/cache/batch-read.d.mts.map +1 -1
  5. package/dist/cache/batch-read.mjs +28 -11
  6. package/dist/cache/batch-read.mjs.map +1 -1
  7. package/dist/cache/deletes.d.mts +1 -0
  8. package/dist/cache/deletes.d.mts.map +1 -1
  9. package/dist/cache/deletes.mjs +44 -4
  10. package/dist/cache/deletes.mjs.map +1 -1
  11. package/dist/cache/multi-batch-read.d.mts +1 -1
  12. package/dist/cache/multi-batch-read.d.mts.map +1 -1
  13. package/dist/cache/multi-batch-read.mjs +7 -6
  14. package/dist/cache/multi-batch-read.mjs.map +1 -1
  15. package/dist/cache/mutations.mjs +4 -4
  16. package/dist/cache/mutations.mjs.map +1 -1
  17. package/dist/cache/stale-refresh.d.mts.map +1 -1
  18. package/dist/cache/stale-refresh.mjs +2 -1
  19. package/dist/cache/stale-refresh.mjs.map +1 -1
  20. package/dist/clients.d.mts.map +1 -1
  21. package/dist/clients.mjs +8 -1
  22. package/dist/clients.mjs.map +1 -1
  23. package/dist/conditional.d.mts +8 -0
  24. package/dist/conditional.d.mts.map +1 -0
  25. package/dist/conditional.mjs +19 -0
  26. package/dist/conditional.mjs.map +1 -0
  27. package/dist/delete.d.mts +2 -1
  28. package/dist/delete.d.mts.map +1 -1
  29. package/dist/delete.mjs +19 -22
  30. package/dist/delete.mjs.map +1 -1
  31. package/dist/dynamic-config/storage.mjs +2 -2
  32. package/dist/dynamic-config/storage.mjs.map +1 -1
  33. package/dist/dynamic-config.mjs +2 -2
  34. package/dist/dynamic-config.mjs.map +1 -1
  35. package/dist/errors.d.mts.map +1 -1
  36. package/dist/errors.mjs +12 -2
  37. package/dist/errors.mjs.map +1 -1
  38. package/dist/idempotency-key.d.mts +5 -0
  39. package/dist/idempotency-key.d.mts.map +1 -1
  40. package/dist/idempotency-key.mjs +22 -20
  41. package/dist/idempotency-key.mjs.map +1 -1
  42. package/dist/index.d.mts +1 -0
  43. package/dist/index.d.mts.map +1 -1
  44. package/dist/index.mjs +1 -0
  45. package/dist/index.mjs.map +1 -1
  46. package/dist/rate-limiter.d.mts.map +1 -1
  47. package/dist/rate-limiter.mjs +21 -18
  48. package/dist/rate-limiter.mjs.map +1 -1
  49. package/dist/retry.d.mts.map +1 -1
  50. package/dist/retry.mjs +3 -1
  51. package/dist/retry.mjs.map +1 -1
  52. package/dist/scripts/idempotency-key-release-if-current.lua +2 -1
  53. package/dist/scripts/idempotency-key-reserve.lua +26 -0
  54. package/dist/scripts/unlink-if-value-matches.lua +14 -0
  55. package/dist/types.d.mts +28 -10
  56. package/dist/types.d.mts.map +1 -1
  57. package/dist/valkey-result.d.mts +2 -0
  58. package/dist/valkey-result.d.mts.map +1 -0
  59. package/dist/valkey-result.mjs +9 -0
  60. package/dist/valkey-result.mjs.map +1 -0
  61. package/docs/api.md +1 -1
  62. package/docs/cache.md +13 -0
  63. package/docs/clients.md +0 -8
  64. package/docs/conditional-operations.md +24 -0
  65. package/docs/idempotency-key.md +13 -2
  66. package/docs/lua-scripts.md +5 -1
  67. package/docs/utilities.md +1 -39
  68. package/package.json +9 -4
package/dist/types.d.mts CHANGED
@@ -12,11 +12,13 @@ export type RateLimiterOptions = {
12
12
  /** Optional Valkey client. Defaults to the package rate limiter client. */
13
13
  client?: GlideClient;
14
14
  /**
15
- * Maximum number of retry attempts on inflight-saturation errors (default: VALKEY_INFLIGHT_RETRY_ATTEMPTS env or 3).
15
+ * Maximum number of retry attempts on inflight-saturation errors
16
+ * (default: VALKEY_INFLIGHT_RETRY_ATTEMPTS env or 3).
16
17
  */
17
18
  inflightRetryAttempts?: number;
18
19
  /**
19
- * Minimum delay in milliseconds between saturation-retry attempts (default: VALKEY_INFLIGHT_RETRY_DELAY_MS env or 1000).
20
+ * Minimum delay in milliseconds between saturation-retry attempts
21
+ * (default: VALKEY_INFLIGHT_RETRY_DELAY_MS env or 1000).
20
22
  * Actual delay is jittered in [delayMs, delayMs * 5].
21
23
  */
22
24
  inflightRetryDelayMs?: number;
@@ -38,14 +40,19 @@ export type RateLimiterWindow = {
38
40
  export type RateLimiterAddAndCheckWindowsOptions = {
39
41
  /** Optional Valkey client. Defaults to the package rate limiter client. */
40
42
  client?: GlideClient;
41
- /** Stop processing later windows as soon as an earlier window is limited. Defaults to record-all. */
43
+ /**
44
+ * Stop processing later windows as soon as an earlier window is limited.
45
+ * Defaults to record-all.
46
+ */
42
47
  mode?: "record-all" | "stop-on-limited";
43
48
  /**
44
- * Maximum number of retry attempts on inflight-saturation errors (default: VALKEY_INFLIGHT_RETRY_ATTEMPTS env or 3).
49
+ * Maximum number of retry attempts on inflight-saturation errors
50
+ * (default: VALKEY_INFLIGHT_RETRY_ATTEMPTS env or 3).
45
51
  */
46
52
  inflightRetryAttempts?: number;
47
53
  /**
48
- * Minimum delay in milliseconds between saturation-retry attempts (default: VALKEY_INFLIGHT_RETRY_DELAY_MS env or 1000).
54
+ * Minimum delay in milliseconds between saturation-retry attempts
55
+ * (default: VALKEY_INFLIGHT_RETRY_DELAY_MS env or 1000).
49
56
  * Actual delay is jittered in [delayMs, delayMs * 5].
50
57
  */
51
58
  inflightRetryDelayMs?: number;
@@ -57,7 +64,10 @@ export type ValkeyCacheOptions<K = string> = {
57
64
  ttlSeconds: number;
58
65
  /** The TTL in seconds for null values, defaults to ttlSeconds / 60 */
59
66
  nullTtlSeconds?: number;
60
- /** The mode to use: 'json' (default) for JSON serialization, 'text' for raw text storage, 'buffer' for Buffer storage */
67
+ /**
68
+ * The mode to use: 'json' (default) for JSON serialization, 'text' for raw
69
+ * text storage, 'buffer' for Buffer storage
70
+ */
61
71
  mode?: "json" | "text" | "buffer";
62
72
  /**
63
73
  * Fraction of ttlSeconds representing the age threshold; values are stale when
@@ -66,9 +76,15 @@ export type ValkeyCacheOptions<K = string> = {
66
76
  staleTtlAge?: number;
67
77
  /** When false, stale cache hits are returned without a background refresh. Defaults to true. */
68
78
  staleRefresh?: boolean;
69
- /** Optional bloom filter for negative lookups — skip DB calls for entities that definitely don't exist */
79
+ /**
80
+ * Optional bloom filter for negative lookups — skip DB calls for entities
81
+ * that definitely don't exist
82
+ */
70
83
  bloomFilter?: import("./bloom-filter.mts").ValkeyBloomFilter;
71
- /** Optional runtime feature flag — if provided, called per-request; bloom filter is bypassed when it returns false */
84
+ /**
85
+ * Optional runtime feature flag — if provided, called per-request;
86
+ * bloom filter is bypassed when it returns false
87
+ */
72
88
  bloomFilterEnabled?: () => boolean;
73
89
  /** Optional Valkey client. Defaults to the package cache client. */
74
90
  client?: GlideClient;
@@ -80,11 +96,13 @@ export type ValkeyCacheOptions<K = string> = {
80
96
  */
81
97
  fallbackOnReadError?: boolean;
82
98
  /**
83
- * Maximum number of retry attempts on inflight-saturation errors (default: VALKEY_INFLIGHT_RETRY_ATTEMPTS env or 3).
99
+ * Maximum number of retry attempts on inflight-saturation errors
100
+ * (default: VALKEY_INFLIGHT_RETRY_ATTEMPTS env or 3).
84
101
  */
85
102
  inflightRetryAttempts?: number;
86
103
  /**
87
- * Minimum delay in milliseconds between saturation-retry attempts (default: VALKEY_INFLIGHT_RETRY_DELAY_MS env or 1000).
104
+ * Minimum delay in milliseconds between saturation-retry attempts
105
+ * (default: VALKEY_INFLIGHT_RETRY_DELAY_MS env or 1000).
88
106
  * Actual delay is jittered in [delayMs, delayMs * 5].
89
107
  */
90
108
  inflightRetryDelayMs?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.mts","sourceRoot":"","sources":["../types.mts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.mts","sourceRoot":"","sources":["../types.mts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function stringifyValkeyResult(result: unknown): string;
2
+ //# sourceMappingURL=valkey-result.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"valkey-result.d.mts","sourceRoot":"","sources":["../valkey-result.mts"],"names":[],"mappings":"AAAA,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAM7D"}
@@ -0,0 +1,9 @@
1
+ export function stringifyValkeyResult(result) {
2
+ if (typeof result === "string")
3
+ return result;
4
+ if (typeof result === "number" || typeof result === "bigint" || typeof result === "boolean") {
5
+ return result.toString();
6
+ }
7
+ return JSON.stringify(result) ?? "[unserializable]";
8
+ }
9
+ //# sourceMappingURL=valkey-result.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"valkey-result.mjs","sourceRoot":"","sources":["../valkey-result.mts"],"names":[],"mappings":"AAAA,MAAM,UAAU,qBAAqB,CAAC,MAAe;IACnD,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC;IAC9C,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,MAAM,KAAK,SAAS,EAAE,CAAC;QAC5F,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC3B,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,kBAAkB,CAAC;AACtD,CAAC"}
package/docs/api.md CHANGED
@@ -16,7 +16,7 @@ This is the entry point for the public `valkyries` API. Detailed API documentati
16
16
  - [Events and metrics](events-and-metrics.md) - `valkeyEvents`, cache metrics, event payloads, and error handling hooks.
17
17
  - [Lua scripts](lua-scripts.md) - packaged Lua scripts and script-loading helpers.
18
18
  - [Configuration](configuration.md) - environment variables and connection behavior.
19
- - [Utilities](utilities.md) - key normalization, cache serialization helpers, TTL/count normalization, and timing helpers.
19
+ - [Utilities](utilities.md) - key and Valkey result normalization helpers.
20
20
 
21
21
  ## Package Entry Points
22
22
 
package/docs/cache.md CHANGED
@@ -209,6 +209,19 @@ ValkeyCache.invalidate(prefix: string, client?: GlideClient): Promise<void>
209
209
 
210
210
  Deletes every cache key for `prefix`. Passing an empty prefix invalidates all cache namespaces visible to the client.
211
211
 
212
+ ## `ValkeyCache.invalidateMany(prefixes, client?)`
213
+
214
+ ```ts
215
+ ValkeyCache.invalidateMany(
216
+ prefixes: readonly string[],
217
+ client?: GlideClient,
218
+ ): Promise<void>
219
+ ```
220
+
221
+ Deletes every cache key for the supplied prefixes with one cursor scan. Duplicate prefixes are
222
+ ignored, an empty list is a no-op, and an empty prefix invalidates all cache namespaces visible to
223
+ the client.
224
+
212
225
  ## `getKey(key)`
213
226
 
214
227
  ```ts
package/docs/clients.md CHANGED
@@ -107,11 +107,3 @@ onGracefulShutdown(): Promise<void>
107
107
  ```
108
108
 
109
109
  Both exports point to the same idempotent shutdown function. It closes all live dynamic configs, package-managed clients, and the dynamic-config subscription client.
110
-
111
- ## `deleteKeysWithPrefix(client, pattern)`
112
-
113
- ```ts
114
- deleteKeysWithPrefix(client: GlideClient, pattern: string): Promise<void>
115
- ```
116
-
117
- Scans keys matching `pattern` and unlinks them in batches. This helper is used by cache and rate-limiter invalidation APIs.
@@ -0,0 +1,24 @@
1
+ # Conditional Operations
2
+
3
+ Generic single-key operations for application-owned Valkey values.
4
+
5
+ ## `unlinkIfValueMatches(key, expectedValue, options?)`
6
+
7
+ ```ts
8
+ unlinkIfValueMatches(
9
+ key: string,
10
+ expectedValue: string,
11
+ options?: { client?: GlideClient },
12
+ ): Promise<boolean>
13
+ ```
14
+
15
+ Atomically reads and unlinks one key using a Lua script.
16
+
17
+ - Returns `true` only when the stored string matched `expectedValue` and was unlinked.
18
+ - Returns `false` when the key is absent or its value changed.
19
+ - Accepts an empty expected value, but the key must be non-empty.
20
+ - Throws Valkey/client errors and unexpected script responses.
21
+ - Defaults to the package cache client.
22
+
23
+ The helper is single-key and Redis Cluster safe. Callers own key naming and any hash tags needed
24
+ to colocate this key with other application operations.
@@ -26,6 +26,9 @@ reserveIdempotencyKey(
26
26
  processingPrefix?: string;
27
27
  completedValue?: string;
28
28
  token?: string;
29
+ repairMissingExpiry?: {
30
+ completedTtlSeconds?: number;
31
+ };
29
32
  },
30
33
  ): Promise<
31
34
  | { state: "reserved"; token: string }
@@ -38,6 +41,10 @@ Atomically reserves a key when it is absent by storing `processing:<token>` with
38
41
  - Generates a random token by default.
39
42
  - Returns `processing` when another reservation is active.
40
43
  - Returns `completed` when the dedup key has already completed.
44
+ - When `repairMissingExpiry` is present, persistent existing processing values receive
45
+ `ttlSeconds` and persistent completed values receive `completedTtlSeconds`.
46
+ - `completedTtlSeconds` defaults to `ttlSeconds`; `EXPIRE ... NX` preserves existing expirations.
47
+ - Missing-expiry repair is disabled by default.
41
48
  - The caller owns key naming and Redis Cluster hash tags.
42
49
 
43
50
  ## `completeIdempotencyKey(key, token, ttlSeconds, options?)`
@@ -53,10 +60,14 @@ completeIdempotencyKey(
53
60
 
54
61
  Atomically changes `processing:<token>` to `completed` with `EX ttlSeconds`.
55
62
 
56
- - `completed`: the caller still owned the reservation and completion was recorded.
63
+ - `completed`: completion is recorded, including when the key was already completed.
57
64
  - `missing`: the key was absent.
58
65
  - `changed`: the key existed but did not match the caller's token.
59
66
 
67
+ Completed values do not retain their reservation token, so an already-completed result cannot
68
+ prove which owner originally completed it. Treating that result as success makes completion safe
69
+ to retry after an ambiguous client or network failure.
70
+
60
71
  ## `releaseIdempotencyKey(key, token, options?)`
61
72
 
62
73
  ```ts
@@ -93,7 +104,7 @@ try {
93
104
  ## Validation
94
105
 
95
106
  - `key`, `token`, `processingPrefix`, and `completedValue` must be non-empty.
96
- - `ttlSeconds` must be greater than `0`.
107
+ - `ttlSeconds` and `completedTtlSeconds` must be positive safe integers.
97
108
  - `processingPrefix` must not equal `completedValue`.
98
109
  - `processingPrefix` and `completedValue` must not equal script result sentinels:
99
110
  `reserved`, `missing`, or `changed`.
@@ -48,9 +48,13 @@ Dynamic config scripts:
48
48
  Idempotency key scripts:
49
49
 
50
50
  - `idempotency-key-complete-if-current.lua`
51
- - `idempotency-key-release-if-current.lua`
51
+ - `idempotency-key-release-if-current.lua` (compatibility filename; new code uses conditional unlink)
52
52
  - `idempotency-key-reserve.lua`
53
53
 
54
+ Conditional operation scripts:
55
+
56
+ - `unlink-if-value-matches.lua`
57
+
54
58
  Rate limiter scripts:
55
59
 
56
60
  - `rate-limiter-add.lua`
package/docs/utilities.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Utilities
2
2
 
3
- These helpers are exported from the package root for applications that need the same normalization and serialization behavior as the built-in classes.
3
+ These normalization helpers are exported from the package root.
4
4
 
5
5
  ## `normalizeKey(key)`
6
6
 
@@ -25,41 +25,3 @@ normalizeCountResult(value: unknown): number
25
25
  ```
26
26
 
27
27
  Normalizes numeric or bigint Valkey counts. Returns `0` for unexpected values.
28
-
29
- ## `ValkeyCacheTypeError`
30
-
31
- ```ts
32
- class ValkeyCacheTypeError extends TypeError
33
- ```
34
-
35
- Thrown when a cache value does not match the configured mode.
36
-
37
- ## `serializeValue(value, mode)`
38
-
39
- ```ts
40
- serializeValue(
41
- value: unknown,
42
- mode: "json" | "text" | "buffer",
43
- ): Promise<string | Buffer>
44
- ```
45
-
46
- Serializes values for cache storage and gzip-compresses payloads larger than 2 KiB.
47
-
48
- ## `decodeValue(result, mode)`
49
-
50
- ```ts
51
- decodeValue(
52
- result: GlideString | null,
53
- mode: "json" | "text" | "buffer",
54
- ): Promise<string | Buffer | Record<string, unknown> | null>
55
- ```
56
-
57
- Decodes and decompresses cache values. Returns `null` for Valkey misses.
58
-
59
- ## `durationInMilliseconds(start)`
60
-
61
- ```ts
62
- durationInMilliseconds(start: bigint): number
63
- ```
64
-
65
- Converts a `process.hrtime.bigint()` start timestamp to elapsed milliseconds.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "valkyries",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Valkey utilities for caches, bloom filters, dynamic configuration, and rate limiting.",
5
5
  "homepage": "https://github.com/jonathanong/valkyries#readme",
6
6
  "bugs": {
@@ -32,6 +32,11 @@
32
32
  "import": "./dist/cache.mjs",
33
33
  "default": "./dist/cache.mjs"
34
34
  },
35
+ "./conditional": {
36
+ "types": "./dist/conditional.d.mts",
37
+ "import": "./dist/conditional.mjs",
38
+ "default": "./dist/conditional.mjs"
39
+ },
35
40
  "./bloom-filter": {
36
41
  "types": "./dist/bloom-filter.d.mts",
37
42
  "import": "./dist/bloom-filter.mjs",
@@ -57,12 +62,12 @@
57
62
  "@valkey/valkey-glide": "^2.4.0"
58
63
  },
59
64
  "devDependencies": {
60
- "@types/node": "^25.8.0",
65
+ "@types/node": "^26.1.0",
61
66
  "@vitest/coverage-v8": "^4.1.6",
62
67
  "github-actionlint": "^1.7.12",
63
- "oxfmt": "^0.52.0",
68
+ "oxfmt": "^0.57.0",
64
69
  "oxlint": "^1.65.0",
65
- "oxlint-tsgolint": "^0.23.0",
70
+ "oxlint-tsgolint": "^0.24.0",
66
71
  "tsx": "^4.22.1",
67
72
  "typescript": "^6.0.3",
68
73
  "vitest": "^4.1.6"