@zeltjs/kv 0.5.0 → 0.6.1

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.
@@ -1,2 +1,2 @@
1
- import { t as MemoryKVAdaptor } from "../index-BKwavBZX.js";
1
+ import { t as MemoryKVAdaptor } from "../index-BlASVNzQ.js";
2
2
  export { MemoryKVAdaptor };
@@ -1,2 +1,2 @@
1
- import { t as MemoryKVAdaptor } from "../adaptor-memory-B2nsNQ-e.js";
1
+ import { t as MemoryKVAdaptor } from "../adaptor-memory-BcPJjrIS.js";
2
2
  export { MemoryKVAdaptor };
@@ -51,6 +51,7 @@ var MemoryKVStore = class MemoryKVStore {
51
51
  const entry = this.current(key);
52
52
  return entry ? deserialize(entry.raw) : void 0;
53
53
  }
54
+ /** @throws {ZeltKVInvalidTtlError} */
54
55
  async set(key, value, opts) {
55
56
  validateTtl(opts?.ttlSec);
56
57
  const raw = serialize(value);
@@ -62,6 +63,7 @@ var MemoryKVStore = class MemoryKVStore {
62
63
  async has(key) {
63
64
  return this.current(key) !== void 0;
64
65
  }
66
+ /** @throws {ZeltKVInvalidTtlError} */
65
67
  async expire(key, ttlSec) {
66
68
  validateTtl(ttlSec);
67
69
  const entry = this.current(key);
@@ -72,6 +74,7 @@ var MemoryKVStore = class MemoryKVStore {
72
74
  namespace(sub) {
73
75
  return new MemoryKVStore(this.data, joinPrefix(this.prefix, sub));
74
76
  }
77
+ /** @throws {ZeltKVInvalidTtlError} */
75
78
  async incr(key, by = 1, opts) {
76
79
  validateTtl(opts?.ttlSec);
77
80
  const k = this.k(key);
@@ -85,6 +88,7 @@ var MemoryKVStore = class MemoryKVStore {
85
88
  entry.raw = serialize(next);
86
89
  return next;
87
90
  }
91
+ /** @throws {ZeltKVInvalidTtlError} */
88
92
  async setnx(key, value, opts) {
89
93
  validateTtl(opts?.ttlSec);
90
94
  if (this.current(key)) return false;
@@ -96,4 +100,4 @@ var MemoryKVStore = class MemoryKVStore {
96
100
  //#endregion
97
101
  export { MemoryKVAdaptor as t };
98
102
 
99
- //# sourceMappingURL=adaptor-memory-B2nsNQ-e.js.map
103
+ //# sourceMappingURL=adaptor-memory-BcPJjrIS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adaptor-memory-BcPJjrIS.js","names":[],"sources":["../src/adaptor-memory/memory-kv.adaptor.ts"],"sourcesContent":["import type { Lifecycle } from '@zeltjs/core';\nimport { Injectable, inject, LifecycleManager } from '@zeltjs/core';\n\nimport { ZeltKVInvalidTtlError } from '../errors';\nimport { joinPrefix } from '../namespace';\nimport { deserialize, serialize } from '../serialize';\nimport type { AtomicKVAdaptor, AtomicKVStore, Defined, NonEmptyString, SetOptions } from '../types';\n\ntype Entry = {\n raw: string;\n /** epoch ms。undefined は永続 */\n expiresAt?: number;\n};\n\n/** @throws {ZeltKVInvalidTtlError} */\nfunction validateTtl(ttlSec: number | undefined): void {\n if (ttlSec !== undefined && ttlSec <= 0) throw new ZeltKVInvalidTtlError({ ttlSec });\n}\n\nfunction makeEntry(raw: string, ttlSec?: number): Entry {\n return ttlSec !== undefined ? { raw, expiresAt: Date.now() + ttlSec * 1000 } : { raw };\n}\n\n@Injectable()\nexport class MemoryKVAdaptor implements AtomicKVAdaptor, Lifecycle {\n private readonly data = new Map<string, Entry>();\n private readonly gcInterval: ReturnType<typeof setInterval>;\n\n constructor(lifecycle = inject(LifecycleManager)) {\n this.gcInterval = setInterval(() => this.gc(), 60_000);\n this.gcInterval.unref();\n lifecycle.register(this);\n }\n\n private gc(): void {\n const now = Date.now();\n for (const [key, entry] of this.data) {\n if (entry.expiresAt !== undefined && entry.expiresAt <= now) {\n this.data.delete(key);\n }\n }\n }\n\n async startup(): Promise<void> {}\n\n async shutdown(): Promise<void> {\n clearInterval(this.gcInterval);\n }\n\n namespace<const S extends string>(prefix: NonEmptyString<S>): AtomicKVStore {\n return new MemoryKVStore(this.data, prefix);\n }\n}\n\nclass MemoryKVStore implements AtomicKVStore {\n constructor(\n private readonly data: Map<string, Entry>,\n private readonly prefix: string,\n ) {}\n\n private k(key: string): string {\n return this.prefix + key;\n }\n\n private current(key: string): Entry | undefined {\n const entry = this.data.get(this.k(key));\n if (!entry) return undefined;\n if (entry.expiresAt !== undefined && entry.expiresAt <= Date.now()) {\n this.data.delete(this.k(key));\n return undefined;\n }\n return entry;\n }\n\n async get<T>(key: string): Promise<T | undefined> {\n const entry = this.current(key);\n return entry ? deserialize<T>(entry.raw) : undefined;\n }\n\n /** @throws {ZeltKVInvalidTtlError} */\n async set<T extends Defined>(key: string, value: T, opts?: SetOptions): Promise<void> {\n validateTtl(opts?.ttlSec);\n const raw = serialize(value);\n this.data.set(this.k(key), makeEntry(raw, opts?.ttlSec));\n }\n\n async del(key: string): Promise<void> {\n this.data.delete(this.k(key));\n }\n\n async has(key: string): Promise<boolean> {\n return this.current(key) !== undefined;\n }\n\n /** @throws {ZeltKVInvalidTtlError} */\n async expire(key: string, ttlSec: number): Promise<boolean> {\n validateTtl(ttlSec);\n const entry = this.current(key);\n if (!entry) return false;\n entry.expiresAt = Date.now() + ttlSec * 1000;\n return true;\n }\n\n namespace<const S extends string>(sub: NonEmptyString<S>): AtomicKVStore {\n return new MemoryKVStore(this.data, joinPrefix(this.prefix, sub));\n }\n\n /** @throws {ZeltKVInvalidTtlError} */\n async incr(key: string, by = 1, opts?: { ttlSec?: number }): Promise<number> {\n validateTtl(opts?.ttlSec);\n const k = this.k(key);\n const entry = this.current(key);\n if (!entry) {\n const raw = serialize(by);\n this.data.set(k, makeEntry(raw, opts?.ttlSec));\n return by;\n }\n const next = (deserialize<number>(entry.raw) ?? 0) + by;\n entry.raw = serialize(next);\n return next;\n }\n\n /** @throws {ZeltKVInvalidTtlError} */\n async setnx<T extends Defined>(key: string, value: T, opts?: SetOptions): Promise<boolean> {\n validateTtl(opts?.ttlSec);\n if (this.current(key)) return false;\n const raw = serialize(value);\n this.data.set(this.k(key), makeEntry(raw, opts?.ttlSec));\n return true;\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { n as AtomicKVStore, o as NonEmptyString, t as AtomicKVAdaptor } from "../types-PctPMJzq.js";
1
+ import { n as AtomicKVStore, o as NonEmptyString, t as AtomicKVAdaptor } from "../types-PDNBLwuJ.js";
2
2
  import { RedisService } from "@zeltjs/redis";
3
3
 
4
4
  //#region src/adaptor-redis/redis-kv-adaptor.d.ts
@@ -30,6 +30,7 @@ var RedisKVStore = class RedisKVStore {
30
30
  const raw = await this.client.get(this.k(key));
31
31
  return raw === null ? void 0 : deserialize(raw);
32
32
  }
33
+ /** @throws {ZeltKVInvalidTtlError} */
33
34
  async set(key, value, opts) {
34
35
  validateTtl(opts?.ttlSec);
35
36
  const json = serialize(value);
@@ -42,6 +43,7 @@ var RedisKVStore = class RedisKVStore {
42
43
  async has(key) {
43
44
  return await this.client.exists(this.k(key)) === 1;
44
45
  }
46
+ /** @throws {ZeltKVInvalidTtlError} */
45
47
  async expire(key, ttlSec) {
46
48
  validateTtl(ttlSec);
47
49
  return await this.client.expire(this.k(key), ttlSec) === 1;
@@ -49,10 +51,12 @@ var RedisKVStore = class RedisKVStore {
49
51
  namespace(sub) {
50
52
  return new RedisKVStore(this.client, joinPrefix(this.prefix, sub));
51
53
  }
54
+ /** @throws {ZeltKVInvalidTtlError} */
52
55
  async incr(key, by = 1, opts) {
53
56
  validateTtl(opts?.ttlSec);
54
57
  return incrWithTtl(this.client, this.k(key), by, opts?.ttlSec);
55
58
  }
59
+ /** @throws {ZeltKVInvalidTtlError} */
56
60
  async setnx(key, value, opts) {
57
61
  validateTtl(opts?.ttlSec);
58
62
  const json = serialize(value);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/adaptor-redis/lua-scripts.ts","../../src/adaptor-redis/redis-kv-store.ts","../../src/adaptor-redis/redis-kv-adaptor.ts"],"sourcesContent":["export const INCR_WITH_TTL_LUA = `\n if ARGV[2] ~= '' then\n redis.call('SET', KEYS[1], 0, 'EX', ARGV[2], 'NX')\n end\n return redis.call('INCRBY', KEYS[1], ARGV[1])\n`;\n","import type Redis from 'ioredis';\nimport { ZeltKVInvalidTtlError } from '../errors';\nimport { joinPrefix } from '../namespace';\nimport { deserialize, serialize } from '../serialize';\nimport type { AtomicKVStore, Defined, NonEmptyString, SetOptions } from '../types';\n\nimport { INCR_WITH_TTL_LUA } from './lua-scripts';\n\n/** @throws {ZeltKVInvalidTtlError} */\nconst validateTtl = (ttlSec: number | undefined): void => {\n if (ttlSec !== undefined && ttlSec <= 0) throw new ZeltKVInvalidTtlError({ ttlSec });\n};\n\nconst incrWithTtl = async (\n client: Redis,\n key: string,\n by: number,\n ttlSec: number | undefined,\n): Promise<number> => {\n const ttlArg = ttlSec !== undefined ? String(ttlSec) : '';\n return client.eval(INCR_WITH_TTL_LUA, 1, key, by, ttlArg) as Promise<number>;\n};\n\nexport class RedisKVStore implements AtomicKVStore {\n constructor(\n private readonly client: Redis,\n private readonly prefix: string,\n ) {}\n\n private k(key: string): string {\n return this.prefix + key;\n }\n\n async get<T>(key: string): Promise<T | undefined> {\n const raw = await this.client.get(this.k(key));\n return raw === null ? undefined : deserialize<T>(raw);\n }\n\n async set<T extends Defined>(key: string, value: T, opts?: SetOptions): Promise<void> {\n validateTtl(opts?.ttlSec);\n const json = serialize(value);\n if (opts?.ttlSec !== undefined) {\n await this.client.set(this.k(key), json, 'EX', opts.ttlSec);\n } else {\n await this.client.set(this.k(key), json);\n }\n }\n\n async del(key: string): Promise<void> {\n await this.client.del(this.k(key));\n }\n\n async has(key: string): Promise<boolean> {\n const n = await this.client.exists(this.k(key));\n return n === 1;\n }\n\n async expire(key: string, ttlSec: number): Promise<boolean> {\n validateTtl(ttlSec);\n const n = await this.client.expire(this.k(key), ttlSec);\n return n === 1;\n }\n\n namespace<const S extends string>(sub: NonEmptyString<S>): AtomicKVStore {\n return new RedisKVStore(this.client, joinPrefix(this.prefix, sub));\n }\n\n async incr(key: string, by = 1, opts?: { ttlSec?: number }): Promise<number> {\n validateTtl(opts?.ttlSec);\n return incrWithTtl(this.client, this.k(key), by, opts?.ttlSec);\n }\n\n async setnx<T extends Defined>(key: string, value: T, opts?: SetOptions): Promise<boolean> {\n validateTtl(opts?.ttlSec);\n const json = serialize(value);\n const result =\n opts?.ttlSec !== undefined\n ? await this.client.set(this.k(key), json, 'EX', opts.ttlSec, 'NX')\n : await this.client.set(this.k(key), json, 'NX');\n return result === 'OK';\n }\n}\n","import { inject } from '@zeltjs/core';\nimport { RedisService } from '@zeltjs/redis';\n\nimport type { AtomicKVAdaptor, AtomicKVStore, NonEmptyString } from '../types';\n\nimport { RedisKVStore } from './redis-kv-store';\n\nexport class RedisKVAdaptor implements AtomicKVAdaptor {\n constructor(private readonly redis = inject(RedisService)) {}\n\n namespace<const S extends string>(prefix: NonEmptyString<S>): AtomicKVStore {\n return new RedisKVStore(this.redis.client, prefix);\n }\n}\n"],"mappings":";;;;AAAA,MAAa,oBAAoB;;;;;;;;;ACSjC,MAAM,eAAe,WAAqC;AACxD,KAAI,WAAW,KAAA,KAAa,UAAU,EAAG,OAAM,IAAI,sBAAsB,EAAE,QAAQ,CAAC;;AAGtF,MAAM,cAAc,OAClB,QACA,KACA,IACA,WACoB;CACpB,MAAM,SAAS,WAAW,KAAA,IAAY,OAAO,OAAO,GAAG;AACvD,QAAO,OAAO,KAAK,mBAAmB,GAAG,KAAK,IAAI,OAAO;;AAG3D,IAAa,eAAb,MAAa,aAAsC;CACjD,YACE,QACA,QACA;AAFiB,OAAA,SAAA;AACA,OAAA,SAAA;;CAGnB,EAAU,KAAqB;AAC7B,SAAO,KAAK,SAAS;;CAGvB,MAAM,IAAO,KAAqC;EAChD,MAAM,MAAM,MAAM,KAAK,OAAO,IAAI,KAAK,EAAE,IAAI,CAAC;AAC9C,SAAO,QAAQ,OAAO,KAAA,IAAY,YAAe,IAAI;;CAGvD,MAAM,IAAuB,KAAa,OAAU,MAAkC;AACpF,cAAY,MAAM,OAAO;EACzB,MAAM,OAAO,UAAU,MAAM;AAC7B,MAAI,MAAM,WAAW,KAAA,EACnB,OAAM,KAAK,OAAO,IAAI,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,KAAK,OAAO;MAE3D,OAAM,KAAK,OAAO,IAAI,KAAK,EAAE,IAAI,EAAE,KAAK;;CAI5C,MAAM,IAAI,KAA4B;AACpC,QAAM,KAAK,OAAO,IAAI,KAAK,EAAE,IAAI,CAAC;;CAGpC,MAAM,IAAI,KAA+B;AAEvC,SAAO,MADS,KAAK,OAAO,OAAO,KAAK,EAAE,IAAI,CAAC,KAClC;;CAGf,MAAM,OAAO,KAAa,QAAkC;AAC1D,cAAY,OAAO;AAEnB,SAAO,MADS,KAAK,OAAO,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,KAC1C;;CAGf,UAAkC,KAAuC;AACvE,SAAO,IAAI,aAAa,KAAK,QAAQ,WAAW,KAAK,QAAQ,IAAI,CAAC;;CAGpE,MAAM,KAAK,KAAa,KAAK,GAAG,MAA6C;AAC3E,cAAY,MAAM,OAAO;AACzB,SAAO,YAAY,KAAK,QAAQ,KAAK,EAAE,IAAI,EAAE,IAAI,MAAM,OAAO;;CAGhE,MAAM,MAAyB,KAAa,OAAU,MAAqC;AACzF,cAAY,MAAM,OAAO;EACzB,MAAM,OAAO,UAAU,MAAM;AAK7B,UAHE,MAAM,WAAW,KAAA,IACb,MAAM,KAAK,OAAO,IAAI,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,KAAK,QAAQ,KAAK,GACjE,MAAM,KAAK,OAAO,IAAI,KAAK,EAAE,IAAI,EAAE,MAAM,KAAK,MAClC;;;;;ACxEtB,IAAa,iBAAb,MAAuD;CACrD,YAAY,QAAyB,OAAO,aAAa,EAAE;AAA9B,OAAA,QAAA;;CAE7B,UAAkC,QAA0C;AAC1E,SAAO,IAAI,aAAa,KAAK,MAAM,QAAQ,OAAO"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/adaptor-redis/lua-scripts.ts","../../src/adaptor-redis/redis-kv-store.ts","../../src/adaptor-redis/redis-kv-adaptor.ts"],"sourcesContent":["export const INCR_WITH_TTL_LUA = `\n if ARGV[2] ~= '' then\n redis.call('SET', KEYS[1], 0, 'EX', ARGV[2], 'NX')\n end\n return redis.call('INCRBY', KEYS[1], ARGV[1])\n`;\n","import type Redis from 'ioredis';\nimport { ZeltKVInvalidTtlError } from '../errors';\nimport { joinPrefix } from '../namespace';\nimport { deserialize, serialize } from '../serialize';\nimport type { AtomicKVStore, Defined, NonEmptyString, SetOptions } from '../types';\n\nimport { INCR_WITH_TTL_LUA } from './lua-scripts';\n\n/** @throws {ZeltKVInvalidTtlError} */\nconst validateTtl = (ttlSec: number | undefined): void => {\n if (ttlSec !== undefined && ttlSec <= 0) throw new ZeltKVInvalidTtlError({ ttlSec });\n};\n\nconst incrWithTtl = async (\n client: Redis,\n key: string,\n by: number,\n ttlSec: number | undefined,\n): Promise<number> => {\n const ttlArg = ttlSec !== undefined ? String(ttlSec) : '';\n return client.eval(INCR_WITH_TTL_LUA, 1, key, by, ttlArg) as Promise<number>;\n};\n\nexport class RedisKVStore implements AtomicKVStore {\n constructor(\n private readonly client: Redis,\n private readonly prefix: string,\n ) {}\n\n private k(key: string): string {\n return this.prefix + key;\n }\n\n async get<T>(key: string): Promise<T | undefined> {\n const raw = await this.client.get(this.k(key));\n return raw === null ? undefined : deserialize<T>(raw);\n }\n\n /** @throws {ZeltKVInvalidTtlError} */\n async set<T extends Defined>(key: string, value: T, opts?: SetOptions): Promise<void> {\n validateTtl(opts?.ttlSec);\n const json = serialize(value);\n if (opts?.ttlSec !== undefined) {\n await this.client.set(this.k(key), json, 'EX', opts.ttlSec);\n } else {\n await this.client.set(this.k(key), json);\n }\n }\n\n async del(key: string): Promise<void> {\n await this.client.del(this.k(key));\n }\n\n async has(key: string): Promise<boolean> {\n const n = await this.client.exists(this.k(key));\n return n === 1;\n }\n\n /** @throws {ZeltKVInvalidTtlError} */\n async expire(key: string, ttlSec: number): Promise<boolean> {\n validateTtl(ttlSec);\n const n = await this.client.expire(this.k(key), ttlSec);\n return n === 1;\n }\n\n namespace<const S extends string>(sub: NonEmptyString<S>): AtomicKVStore {\n return new RedisKVStore(this.client, joinPrefix(this.prefix, sub));\n }\n\n /** @throws {ZeltKVInvalidTtlError} */\n async incr(key: string, by = 1, opts?: { ttlSec?: number }): Promise<number> {\n validateTtl(opts?.ttlSec);\n return incrWithTtl(this.client, this.k(key), by, opts?.ttlSec);\n }\n\n /** @throws {ZeltKVInvalidTtlError} */\n async setnx<T extends Defined>(key: string, value: T, opts?: SetOptions): Promise<boolean> {\n validateTtl(opts?.ttlSec);\n const json = serialize(value);\n const result =\n opts?.ttlSec !== undefined\n ? await this.client.set(this.k(key), json, 'EX', opts.ttlSec, 'NX')\n : await this.client.set(this.k(key), json, 'NX');\n return result === 'OK';\n }\n}\n","import { inject } from '@zeltjs/core';\nimport { RedisService } from '@zeltjs/redis';\n\nimport type { AtomicKVAdaptor, AtomicKVStore, NonEmptyString } from '../types';\n\nimport { RedisKVStore } from './redis-kv-store';\n\nexport class RedisKVAdaptor implements AtomicKVAdaptor {\n constructor(private readonly redis = inject(RedisService)) {}\n\n namespace<const S extends string>(prefix: NonEmptyString<S>): AtomicKVStore {\n return new RedisKVStore(this.redis.client, prefix);\n }\n}\n"],"mappings":";;;;AAAA,MAAa,oBAAoB;;;;;;;;;ACSjC,MAAM,eAAe,WAAqC;AACxD,KAAI,WAAW,KAAA,KAAa,UAAU,EAAG,OAAM,IAAI,sBAAsB,EAAE,QAAQ,CAAC;;AAGtF,MAAM,cAAc,OAClB,QACA,KACA,IACA,WACoB;CACpB,MAAM,SAAS,WAAW,KAAA,IAAY,OAAO,OAAO,GAAG;AACvD,QAAO,OAAO,KAAK,mBAAmB,GAAG,KAAK,IAAI,OAAO;;AAG3D,IAAa,eAAb,MAAa,aAAsC;CACjD,YACE,QACA,QACA;AAFiB,OAAA,SAAA;AACA,OAAA,SAAA;;CAGnB,EAAU,KAAqB;AAC7B,SAAO,KAAK,SAAS;;CAGvB,MAAM,IAAO,KAAqC;EAChD,MAAM,MAAM,MAAM,KAAK,OAAO,IAAI,KAAK,EAAE,IAAI,CAAC;AAC9C,SAAO,QAAQ,OAAO,KAAA,IAAY,YAAe,IAAI;;;CAIvD,MAAM,IAAuB,KAAa,OAAU,MAAkC;AACpF,cAAY,MAAM,OAAO;EACzB,MAAM,OAAO,UAAU,MAAM;AAC7B,MAAI,MAAM,WAAW,KAAA,EACnB,OAAM,KAAK,OAAO,IAAI,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,KAAK,OAAO;MAE3D,OAAM,KAAK,OAAO,IAAI,KAAK,EAAE,IAAI,EAAE,KAAK;;CAI5C,MAAM,IAAI,KAA4B;AACpC,QAAM,KAAK,OAAO,IAAI,KAAK,EAAE,IAAI,CAAC;;CAGpC,MAAM,IAAI,KAA+B;AAEvC,SAAO,MADS,KAAK,OAAO,OAAO,KAAK,EAAE,IAAI,CAAC,KAClC;;;CAIf,MAAM,OAAO,KAAa,QAAkC;AAC1D,cAAY,OAAO;AAEnB,SAAO,MADS,KAAK,OAAO,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,KAC1C;;CAGf,UAAkC,KAAuC;AACvE,SAAO,IAAI,aAAa,KAAK,QAAQ,WAAW,KAAK,QAAQ,IAAI,CAAC;;;CAIpE,MAAM,KAAK,KAAa,KAAK,GAAG,MAA6C;AAC3E,cAAY,MAAM,OAAO;AACzB,SAAO,YAAY,KAAK,QAAQ,KAAK,EAAE,IAAI,EAAE,IAAI,MAAM,OAAO;;;CAIhE,MAAM,MAAyB,KAAa,OAAU,MAAqC;AACzF,cAAY,MAAM,OAAO;EACzB,MAAM,OAAO,UAAU,MAAM;AAK7B,UAHE,MAAM,WAAW,KAAA,IACb,MAAM,KAAK,OAAO,IAAI,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,KAAK,QAAQ,KAAK,GACjE,MAAM,KAAK,OAAO,IAAI,KAAK,EAAE,IAAI,EAAE,MAAM,KAAK,MAClC;;;;;AC5EtB,IAAa,iBAAb,MAAuD;CACrD,YAAY,QAAyB,OAAO,aAAa,EAAE;AAA9B,OAAA,QAAA;;CAE7B,UAAkC,QAA0C;AAC1E,SAAO,IAAI,aAAa,KAAK,MAAM,QAAQ,OAAO"}
@@ -1,4 +1,4 @@
1
- import { n as AtomicKVStore, o as NonEmptyString, t as AtomicKVAdaptor } from "./types-PctPMJzq.js";
1
+ import { n as AtomicKVStore, o as NonEmptyString, t as AtomicKVAdaptor } from "./types-PDNBLwuJ.js";
2
2
  import { Lifecycle, LifecycleManager } from "@zeltjs/core";
3
3
 
4
4
  //#region src/adaptor-memory/memory-kv.adaptor.d.ts
@@ -13,4 +13,4 @@ declare class MemoryKVAdaptor implements AtomicKVAdaptor, Lifecycle {
13
13
  }
14
14
  //#endregion
15
15
  export { MemoryKVAdaptor as t };
16
- //# sourceMappingURL=index-BKwavBZX.d.ts.map
16
+ //# sourceMappingURL=index-BlASVNzQ.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-BKwavBZX.d.ts","names":[],"sources":["../src/adaptor-memory/memory-kv.adaptor.ts"],"mappings":";;;;cAwBa,eAAA,YAA2B,eAAA,EAAiB,SAAA;EAAA,iBACtC,IAAA;EAAA,iBACA,UAAA;cAEL,SAAA,GAAS,gBAAA;EAAA,QAMb,EAAA;EASF,OAAA,CAAA,GAAW,OAAA;EAEX,QAAA,CAAA,GAAY,OAAA;EAIlB,SAAA,wBAAA,CAAkC,MAAA,EAAQ,cAAA,CAAe,CAAA,IAAK,aAAA;AAAA"}
1
+ {"version":3,"file":"index-BlASVNzQ.d.ts","names":[],"sources":["../src/adaptor-memory/memory-kv.adaptor.ts"],"mappings":";;;;cAwBa,eAAA,YAA2B,eAAA,EAAiB,SAAA;EAAA,iBACtC,IAAA;EAAA,iBACA,UAAA;cAEL,SAAA,GAAS,gBAAA;EAAA,QAMb,EAAA;EASF,OAAA,CAAA,GAAW,OAAA;EAEX,QAAA,CAAA,GAAY,OAAA;EAIlB,SAAA,wBAAA,CAAkC,MAAA,EAAQ,cAAA,CAAe,CAAA,IAAK,aAAA;AAAA"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { a as KVStore, i as KVAdaptor, n as AtomicKVStore, o as NonEmptyString, r as Defined, s as SetOptions, t as AtomicKVAdaptor } from "./types-PctPMJzq.js";
2
- import { t as MemoryKVAdaptor } from "./index-BKwavBZX.js";
1
+ import { a as KVStore, i as KVAdaptor, n as AtomicKVStore, o as NonEmptyString, r as Defined, s as SetOptions, t as AtomicKVAdaptor } from "./types-PDNBLwuJ.js";
2
+ import { t as MemoryKVAdaptor } from "./index-BlASVNzQ.js";
3
3
 
4
4
  //#region src/errors.d.ts
5
5
  declare const ZeltKVInvalidTtlError: new (context: {
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  import { a as isZeltKVInvalidTtlError, i as ZeltKVInvalidTtlError, n as serialize, r as joinPrefix, t as deserialize } from "./serialize-DwL5y2vb.js";
2
- import { t as MemoryKVAdaptor } from "./adaptor-memory-B2nsNQ-e.js";
2
+ import { t as MemoryKVAdaptor } from "./adaptor-memory-BcPJjrIS.js";
3
3
  export { MemoryKVAdaptor as MemoryKV, MemoryKVAdaptor, MemoryKVAdaptor as MemoryKVService, ZeltKVInvalidTtlError, deserialize, isZeltKVInvalidTtlError, joinPrefix, serialize };
@@ -14,21 +14,33 @@ interface AtomicKVAdaptor extends KVAdaptor {
14
14
  /** namespaced view。実際の data ops はここ */
15
15
  interface KVStore {
16
16
  get<T>(key: string): Promise<T | undefined>;
17
+ /**
18
+ * @throws {ZeltKVInvalidTtlError}
19
+ */
17
20
  set<T extends Defined>(key: string, value: T, opts?: SetOptions): Promise<void>;
18
21
  del(key: string): Promise<void>;
19
22
  has(key: string): Promise<boolean>;
20
- /** TTL 延長 (session touch / lock extend 用)。key 不在時は false。 */
23
+ /**
24
+ * TTL 延長 (session touch / lock extend 用)。key 不在時は false。
25
+ * @throws {ZeltKVInvalidTtlError}
26
+ */
21
27
  expire(key: string, ttlSec: number): Promise<boolean>;
22
28
  /** 子 namespace。チェーン可能。 */
23
29
  namespace<const S extends string>(prefix: NonEmptyString<S>): KVStore;
24
30
  }
25
31
  /** atomic 操作対応 view */
26
32
  interface AtomicKVStore extends KVStore {
27
- /** atomic incr。最初の incr 時のみ TTL をセット。 */
33
+ /**
34
+ * atomic incr。最初の incr 時のみ TTL をセット。
35
+ * @throws {ZeltKVInvalidTtlError}
36
+ */
28
37
  incr(key: string, by?: number, opts?: {
29
38
  ttlSec?: number;
30
39
  }): Promise<number>;
31
- /** atomic set if not exists。set されたら true、既存なら false。 */
40
+ /**
41
+ * atomic set if not exists。set されたら true、既存なら false。
42
+ * @throws {ZeltKVInvalidTtlError}
43
+ */
32
44
  setnx<T extends Defined>(key: string, value: T, opts?: SetOptions): Promise<boolean>;
33
45
  namespace<const S extends string>(prefix: NonEmptyString<S>): AtomicKVStore;
34
46
  }
@@ -37,4 +49,4 @@ type SetOptions = {
37
49
  };
38
50
  //#endregion
39
51
  export { KVStore as a, KVAdaptor as i, AtomicKVStore as n, NonEmptyString as o, Defined as r, SetOptions as s, AtomicKVAdaptor as t };
40
- //# sourceMappingURL=types-PctPMJzq.d.ts.map
52
+ //# sourceMappingURL=types-PDNBLwuJ.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-PDNBLwuJ.d.ts","names":[],"sources":["../src/types.ts"],"mappings":";;KACY,cAAA,qBAAmC,CAAA,sBAAuB,CAAA;;KAI1D,OAAA;;UAGK,SAAA;EACf,SAAA,yBAAkC,MAAA,EAAQ,cAAA,CAAe,CAAA,IAAK,OAAA;AAAA;;UAI/C,eAAA,SAAwB,SAAA;EACvC,SAAA,yBAAkC,MAAA,EAAQ,cAAA,CAAe,CAAA,IAAK,aAAA;AAAA;;UAI/C,OAAA;EACf,GAAA,IAAO,GAAA,WAAc,OAAA,CAAQ,CAAA;EAXd;;;EAef,GAAA,WAAc,OAAA,EAAS,GAAA,UAAa,KAAA,EAAO,CAAA,EAAG,IAAA,GAAO,UAAA,GAAa,OAAA;EAClE,GAAA,CAAI,GAAA,WAAc,OAAA;EAClB,GAAA,CAAI,GAAA,WAAc,OAAA;EAhBmD;;;;EAqBrE,MAAA,CAAO,GAAA,UAAa,MAAA,WAAiB,OAAA;EArBoB;EAuBzD,SAAA,yBAAkC,MAAA,EAAQ,cAAA,CAAe,CAAA,IAAK,OAAA;AAAA;;UAI/C,aAAA,SAAsB,OAAA;EAvBtB;;;;EA4Bf,IAAA,CAAK,GAAA,UAAa,EAAA,WAAa,IAAA;IAAS,MAAA;EAAA,IAAoB,OAAA;EA5BZ;;;;EAiChD,KAAA,WAAgB,OAAA,EAAS,GAAA,UAAa,KAAA,EAAO,CAAA,EAAG,IAAA,GAAO,UAAA,GAAa,OAAA;EACpE,SAAA,yBAAkC,MAAA,EAAQ,cAAA,CAAe,CAAA,IAAK,aAAA;AAAA;AAAA,KAGpD,UAAA;EACV,MAAA;AAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeltjs/kv",
3
- "version": "0.5.0",
3
+ "version": "0.6.1",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -30,8 +30,8 @@
30
30
  ],
31
31
  "peerDependencies": {
32
32
  "vitest": ">=4 <5",
33
- "@zeltjs/core": "0.5.0",
34
- "@zeltjs/redis": "0.5.0"
33
+ "@zeltjs/core": "0.6.1",
34
+ "@zeltjs/redis": "0.6.1"
35
35
  },
36
36
  "peerDependenciesMeta": {
37
37
  "@zeltjs/redis": {
@@ -41,8 +41,8 @@
41
41
  "devDependencies": {
42
42
  "@types/node": "22.19.17",
43
43
  "ioredis": "5.10.1",
44
- "@zeltjs/core": "0.5.0",
45
- "@zeltjs/redis": "0.5.0"
44
+ "@zeltjs/core": "0.6.1",
45
+ "@zeltjs/redis": "0.6.1"
46
46
  },
47
47
  "volta": {
48
48
  "extends": "../../package.json"
@@ -1 +0,0 @@
1
- {"version":3,"file":"adaptor-memory-B2nsNQ-e.js","names":[],"sources":["../src/adaptor-memory/memory-kv.adaptor.ts"],"sourcesContent":["import type { Lifecycle } from '@zeltjs/core';\nimport { Injectable, inject, LifecycleManager } from '@zeltjs/core';\n\nimport { ZeltKVInvalidTtlError } from '../errors';\nimport { joinPrefix } from '../namespace';\nimport { deserialize, serialize } from '../serialize';\nimport type { AtomicKVAdaptor, AtomicKVStore, Defined, NonEmptyString, SetOptions } from '../types';\n\ntype Entry = {\n raw: string;\n /** epoch ms。undefined は永続 */\n expiresAt?: number;\n};\n\n/** @throws {ZeltKVInvalidTtlError} */\nfunction validateTtl(ttlSec: number | undefined): void {\n if (ttlSec !== undefined && ttlSec <= 0) throw new ZeltKVInvalidTtlError({ ttlSec });\n}\n\nfunction makeEntry(raw: string, ttlSec?: number): Entry {\n return ttlSec !== undefined ? { raw, expiresAt: Date.now() + ttlSec * 1000 } : { raw };\n}\n\n@Injectable()\nexport class MemoryKVAdaptor implements AtomicKVAdaptor, Lifecycle {\n private readonly data = new Map<string, Entry>();\n private readonly gcInterval: ReturnType<typeof setInterval>;\n\n constructor(lifecycle = inject(LifecycleManager)) {\n this.gcInterval = setInterval(() => this.gc(), 60_000);\n this.gcInterval.unref();\n lifecycle.register(this);\n }\n\n private gc(): void {\n const now = Date.now();\n for (const [key, entry] of this.data) {\n if (entry.expiresAt !== undefined && entry.expiresAt <= now) {\n this.data.delete(key);\n }\n }\n }\n\n async startup(): Promise<void> {}\n\n async shutdown(): Promise<void> {\n clearInterval(this.gcInterval);\n }\n\n namespace<const S extends string>(prefix: NonEmptyString<S>): AtomicKVStore {\n return new MemoryKVStore(this.data, prefix);\n }\n}\n\nclass MemoryKVStore implements AtomicKVStore {\n constructor(\n private readonly data: Map<string, Entry>,\n private readonly prefix: string,\n ) {}\n\n private k(key: string): string {\n return this.prefix + key;\n }\n\n private current(key: string): Entry | undefined {\n const entry = this.data.get(this.k(key));\n if (!entry) return undefined;\n if (entry.expiresAt !== undefined && entry.expiresAt <= Date.now()) {\n this.data.delete(this.k(key));\n return undefined;\n }\n return entry;\n }\n\n async get<T>(key: string): Promise<T | undefined> {\n const entry = this.current(key);\n return entry ? deserialize<T>(entry.raw) : undefined;\n }\n\n async set<T extends Defined>(key: string, value: T, opts?: SetOptions): Promise<void> {\n validateTtl(opts?.ttlSec);\n const raw = serialize(value);\n this.data.set(this.k(key), makeEntry(raw, opts?.ttlSec));\n }\n\n async del(key: string): Promise<void> {\n this.data.delete(this.k(key));\n }\n\n async has(key: string): Promise<boolean> {\n return this.current(key) !== undefined;\n }\n\n async expire(key: string, ttlSec: number): Promise<boolean> {\n validateTtl(ttlSec);\n const entry = this.current(key);\n if (!entry) return false;\n entry.expiresAt = Date.now() + ttlSec * 1000;\n return true;\n }\n\n namespace<const S extends string>(sub: NonEmptyString<S>): AtomicKVStore {\n return new MemoryKVStore(this.data, joinPrefix(this.prefix, sub));\n }\n\n async incr(key: string, by = 1, opts?: { ttlSec?: number }): Promise<number> {\n validateTtl(opts?.ttlSec);\n const k = this.k(key);\n const entry = this.current(key);\n if (!entry) {\n const raw = serialize(by);\n this.data.set(k, makeEntry(raw, opts?.ttlSec));\n return by;\n }\n const next = (deserialize<number>(entry.raw) ?? 0) + by;\n entry.raw = serialize(next);\n return next;\n }\n\n async setnx<T extends Defined>(key: string, value: T, opts?: SetOptions): Promise<boolean> {\n validateTtl(opts?.ttlSec);\n if (this.current(key)) return false;\n const raw = serialize(value);\n this.data.set(this.k(key), makeEntry(raw, opts?.ttlSec));\n return true;\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"types-PctPMJzq.d.ts","names":[],"sources":["../src/types.ts"],"mappings":";;KACY,cAAA,qBAAmC,CAAA,sBAAuB,CAAA;;KAI1D,OAAA;;UAGK,SAAA;EACf,SAAA,yBAAkC,MAAA,EAAQ,cAAA,CAAe,CAAA,IAAK,OAAA;AAAA;;UAI/C,eAAA,SAAwB,SAAA;EACvC,SAAA,yBAAkC,MAAA,EAAQ,cAAA,CAAe,CAAA,IAAK,aAAA;AAAA;;UAI/C,OAAA;EACf,GAAA,IAAO,GAAA,WAAc,OAAA,CAAQ,CAAA;EAC7B,GAAA,WAAc,OAAA,EAAS,GAAA,UAAa,KAAA,EAAO,CAAA,EAAG,IAAA,GAAO,UAAA,GAAa,OAAA;EAClE,GAAA,CAAI,GAAA,WAAc,OAAA;EAClB,GAAA,CAAI,GAAA,WAAc,OAAA;EAbuC;EAezD,MAAA,CAAO,GAAA,UAAa,MAAA,WAAiB,OAAA;EAfyB;EAiB9D,SAAA,yBAAkC,MAAA,EAAQ,cAAA,CAAe,CAAA,IAAK,OAAA;AAAA;;UAI/C,aAAA,SAAsB,OAAA;EArBK;EAuB1C,IAAA,CAAK,GAAA,UAAa,EAAA,WAAa,IAAA;IAAS,MAAA;EAAA,IAAoB,OAAA;EAvBS;EAyBrE,KAAA,WAAgB,OAAA,EAAS,GAAA,UAAa,KAAA,EAAO,CAAA,EAAG,IAAA,GAAO,UAAA,GAAa,OAAA;EACpE,SAAA,yBAAkC,MAAA,EAAQ,cAAA,CAAe,CAAA,IAAK,aAAA;AAAA;AAAA,KAGpD,UAAA;EACV,MAAA;AAAA"}