@kikiutils/shared 18.0.0 → 18.1.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 (156) hide show
  1. package/dist/buffer.d.ts +19 -21
  2. package/dist/buffer.d.ts.map +1 -1
  3. package/dist/buffer.js +18 -19
  4. package/dist/buffer.js.map +1 -1
  5. package/dist/classes/enhanced-date.d.ts +425 -0
  6. package/dist/classes/enhanced-date.d.ts.map +1 -0
  7. package/dist/classes/enhanced-date.js +591 -0
  8. package/dist/classes/enhanced-date.js.map +1 -0
  9. package/dist/classes/path.d.ts +211 -48
  10. package/dist/classes/path.d.ts.map +1 -1
  11. package/dist/classes/path.js +181 -52
  12. package/dist/classes/path.js.map +1 -1
  13. package/dist/classes/precision-number.d.ts +44 -39
  14. package/dist/classes/precision-number.d.ts.map +1 -1
  15. package/dist/classes/precision-number.js +51 -45
  16. package/dist/classes/precision-number.js.map +1 -1
  17. package/dist/classes/ssh-client.d.ts +3 -4
  18. package/dist/classes/ssh-client.d.ts.map +1 -1
  19. package/dist/classes/ssh-client.js +2 -2
  20. package/dist/classes/ssh-client.js.map +1 -1
  21. package/dist/clipboard.d.ts +25 -26
  22. package/dist/clipboard.d.ts.map +1 -1
  23. package/dist/clipboard.js +23 -23
  24. package/dist/clipboard.js.map +1 -1
  25. package/dist/consola.d.ts +12 -15
  26. package/dist/consola.d.ts.map +1 -1
  27. package/dist/consola.js +10 -12
  28. package/dist/consola.js.map +1 -1
  29. package/dist/crypto-hash.d.ts +65 -56
  30. package/dist/crypto-hash.d.ts.map +1 -1
  31. package/dist/crypto-hash.js +55 -45
  32. package/dist/crypto-hash.js.map +1 -1
  33. package/dist/datetime.d.ts +41 -53
  34. package/dist/datetime.d.ts.map +1 -1
  35. package/dist/datetime.js +53 -66
  36. package/dist/datetime.js.map +1 -1
  37. package/dist/element-plus.d.ts +13 -14
  38. package/dist/element-plus.d.ts.map +1 -1
  39. package/dist/element-plus.js +11 -11
  40. package/dist/element-plus.js.map +1 -1
  41. package/dist/enum.d.ts +39 -36
  42. package/dist/enum.d.ts.map +1 -1
  43. package/dist/enum.js +36 -32
  44. package/dist/enum.js.map +1 -1
  45. package/dist/env.d.ts +22 -15
  46. package/dist/env.d.ts.map +1 -1
  47. package/dist/env.js +20 -12
  48. package/dist/env.js.map +1 -1
  49. package/dist/event-awaiter.d.ts +47 -52
  50. package/dist/event-awaiter.d.ts.map +1 -1
  51. package/dist/event-awaiter.js +46 -50
  52. package/dist/event-awaiter.js.map +1 -1
  53. package/dist/general.d.ts +22 -17
  54. package/dist/general.d.ts.map +1 -1
  55. package/dist/general.js.map +1 -1
  56. package/dist/hash.d.ts +24 -21
  57. package/dist/hash.d.ts.map +1 -1
  58. package/dist/hash.js +20 -16
  59. package/dist/hash.js.map +1 -1
  60. package/dist/math.d.ts +20 -19
  61. package/dist/math.d.ts.map +1 -1
  62. package/dist/math.js +14 -12
  63. package/dist/math.js.map +1 -1
  64. package/dist/number.d.ts +10 -9
  65. package/dist/number.d.ts.map +1 -1
  66. package/dist/number.js +9 -7
  67. package/dist/number.js.map +1 -1
  68. package/dist/object.d.ts +22 -10
  69. package/dist/object.d.ts.map +1 -1
  70. package/dist/object.js +21 -8
  71. package/dist/object.js.map +1 -1
  72. package/dist/pino.d.ts +12 -15
  73. package/dist/pino.d.ts.map +1 -1
  74. package/dist/pino.js +10 -15
  75. package/dist/pino.js.map +1 -1
  76. package/dist/random.d.ts +17 -15
  77. package/dist/random.d.ts.map +1 -1
  78. package/dist/random.js +16 -13
  79. package/dist/random.js.map +1 -1
  80. package/dist/redis/script-runner.d.ts +57 -0
  81. package/dist/redis/script-runner.d.ts.map +1 -0
  82. package/dist/redis/script-runner.js +46 -0
  83. package/dist/redis/script-runner.js.map +1 -0
  84. package/dist/storages/lru/keyed-store.d.ts +18 -14
  85. package/dist/storages/lru/keyed-store.d.ts.map +1 -1
  86. package/dist/storages/lru/keyed-store.js +17 -12
  87. package/dist/storages/lru/keyed-store.js.map +1 -1
  88. package/dist/storages/redis/keyed-store.d.ts +11 -21
  89. package/dist/storages/redis/keyed-store.d.ts.map +1 -1
  90. package/dist/storages/redis/keyed-store.js +10 -19
  91. package/dist/storages/redis/keyed-store.js.map +1 -1
  92. package/dist/storages/redis/msgpack.d.ts +33 -13
  93. package/dist/storages/redis/msgpack.d.ts.map +1 -1
  94. package/dist/storages/redis/msgpack.js +32 -11
  95. package/dist/storages/redis/msgpack.js.map +1 -1
  96. package/dist/storages/redis/types.d.ts +34 -17
  97. package/dist/storages/redis/types.d.ts.map +1 -1
  98. package/dist/string.d.ts +12 -11
  99. package/dist/string.d.ts.map +1 -1
  100. package/dist/string.js +20 -15
  101. package/dist/string.js.map +1 -1
  102. package/dist/time.d.ts +35 -10
  103. package/dist/time.d.ts.map +1 -1
  104. package/dist/time.js +49 -9
  105. package/dist/time.js.map +1 -1
  106. package/dist/types/filtered-key-path.d.ts +4 -15
  107. package/dist/types/filtered-key-path.d.ts.map +1 -1
  108. package/dist/types/index.d.ts +10 -10
  109. package/dist/types/index.d.ts.map +1 -1
  110. package/dist/types/vue.d.ts +7 -7
  111. package/dist/types/vue.d.ts.map +1 -1
  112. package/dist/url.d.ts +15 -14
  113. package/dist/url.d.ts.map +1 -1
  114. package/dist/url.js +12 -10
  115. package/dist/url.js.map +1 -1
  116. package/dist/vue.d.ts +19 -21
  117. package/dist/vue.d.ts.map +1 -1
  118. package/dist/vue.js +15 -16
  119. package/dist/vue.js.map +1 -1
  120. package/dist/web.d.ts +14 -11
  121. package/dist/web.d.ts.map +1 -1
  122. package/dist/web.js +12 -8
  123. package/dist/web.js.map +1 -1
  124. package/package.json +20 -20
  125. package/src/buffer.ts +18 -19
  126. package/src/classes/enhanced-date.ts +665 -0
  127. package/src/classes/path.ts +232 -91
  128. package/src/classes/precision-number.ts +61 -53
  129. package/src/classes/ssh-client.ts +8 -5
  130. package/src/clipboard.ts +23 -23
  131. package/src/consola.ts +10 -12
  132. package/src/crypto-hash.ts +55 -45
  133. package/src/datetime.ts +65 -85
  134. package/src/element-plus.ts +11 -11
  135. package/src/enum.ts +36 -32
  136. package/src/env.ts +20 -12
  137. package/src/event-awaiter.ts +49 -50
  138. package/src/general.ts +20 -14
  139. package/src/hash.ts +20 -16
  140. package/src/math.ts +18 -16
  141. package/src/number.ts +9 -7
  142. package/src/object.ts +21 -8
  143. package/src/pino.ts +11 -15
  144. package/src/random.ts +16 -13
  145. package/src/redis/script-runner.ts +107 -0
  146. package/src/storages/lru/keyed-store.ts +17 -12
  147. package/src/storages/redis/keyed-store.ts +10 -19
  148. package/src/storages/redis/msgpack.ts +32 -11
  149. package/src/storages/redis/types.ts +32 -14
  150. package/src/string.ts +10 -8
  151. package/src/time.ts +52 -8
  152. package/src/types/filtered-key-path.ts +9 -14
  153. package/src/types/vue.ts +6 -5
  154. package/src/url.ts +12 -10
  155. package/src/vue.ts +15 -16
  156. package/src/web.ts +12 -8
@@ -1,28 +1,19 @@
1
1
  //#region src/storages/redis/keyed-store.ts
2
2
  /**
3
- * Creates a keyed store wrapper around a Redis-like storage.
3
+ * Creates a keyed store factory sharing a caller-owned Redis-like storage facade.
4
4
  *
5
- * @template D - The data type stored in the keyed store
5
+ * @remarks
6
+ * The key resolver is called synchronously once per operation with the operation's key arguments.
7
+ * Resolver exceptions propagate synchronously; asynchronous storage failures retain the underlying rejection.
8
+ * `setItemWithTtl` accepts its TTL in seconds before the value and key arguments.
9
+ * The factory does not open or close the underlying connection; cleanup remains the caller's responsibility.
6
10
  *
7
- * @param {MaybeReadonly<RedisLikeStorage>} storage - The underlying Redis-like storage instance
11
+ * @typeParam D - The stored value type used by reads and writes.
8
12
  *
9
- * @returns {(keyFn: (...args: P) => string) => Readonly<{
10
- * getItem, getItemTtl, hasItem, removeItem, resolveKey, setItem, setItemWithTtl
11
- * }>} A factory that accepts a key resolver and returns a frozen Redis keyed-store facade
13
+ * @param storage - The shared Redis-like storage instance.
12
14
  *
13
- * @example
14
- * ```typescript
15
- * import { createRedisKeyedStore } from '@kikiutils/shared/storages/redis/keyed-store';
16
- * import { createRedisMsgpackStorage } from '@kikiutils/shared/storages/redis/msgpack';
17
- * import { createClient } from 'redis';
18
- *
19
- * const client = createClient();
20
- * await client.connect();
21
- * const storage = createRedisMsgpackStorage(client as unknown as RedisLikeAdapter);
22
- * const keyedStore = createRedisKeyedStore(storage)((userId: string) => `user:${userId}`);
23
- * await keyedStore.setItem({ name: 'Alice' }, 'user-123');
24
- * const user = await keyedStore.getItem('user-123'); // { name: 'Alice' }
25
- * ```
15
+ * @returns A factory accepting a key resolver and returning a new frozen keyed facade sharing the storage.
16
+ * Reads, writes, removals, and TTL results retain the underlying storage contract.
26
17
  */
27
18
  function createRedisKeyedStore(storage) {
28
19
  return (keyFn) => Object.freeze({
@@ -1 +1 @@
1
- {"version":3,"file":"keyed-store.js","names":[],"sources":["../../../src/storages/redis/keyed-store.ts"],"sourcesContent":["import type { MaybeReadonly } from '../../types';\n\nimport type { RedisLikeStorage } from './types';\n\n/**\n * Creates a keyed store wrapper around a Redis-like storage.\n *\n * @template D - The data type stored in the keyed store\n *\n * @param {MaybeReadonly<RedisLikeStorage>} storage - The underlying Redis-like storage instance\n *\n * @returns {(keyFn: (...args: P) => string) => Readonly<{\n * getItem, getItemTtl, hasItem, removeItem, resolveKey, setItem, setItemWithTtl\n * }>} A factory that accepts a key resolver and returns a frozen Redis keyed-store facade\n *\n * @example\n * ```typescript\n * import { createRedisKeyedStore } from '@kikiutils/shared/storages/redis/keyed-store';\n * import { createRedisMsgpackStorage } from '@kikiutils/shared/storages/redis/msgpack';\n * import { createClient } from 'redis';\n *\n * const client = createClient();\n * await client.connect();\n * const storage = createRedisMsgpackStorage(client as unknown as RedisLikeAdapter);\n * const keyedStore = createRedisKeyedStore(storage)((userId: string) => `user:${userId}`);\n * await keyedStore.setItem({ name: 'Alice' }, 'user-123');\n * const user = await keyedStore.getItem('user-123'); // { name: 'Alice' }\n * ```\n */\nexport function createRedisKeyedStore<D = unknown>(storage: MaybeReadonly<RedisLikeStorage>) {\n return <P extends any[]>(keyFn: (...args: P) => string) => Object.freeze({\n getItem: (...args: P) => storage.getItem<D>(keyFn(...args)),\n getItemTtl: (...args: P) => storage.getItemTtl(keyFn(...args)),\n hasItem: (...args: P) => storage.hasItem(keyFn(...args)),\n removeItem: (...args: P) => storage.removeItem(keyFn(...args)),\n resolveKey: (...args: P) => keyFn(...args),\n setItem: (value: D, ...args: P) => storage.setItem(keyFn(...args), value),\n setItemWithTtl(ttlSeconds: number, value: D, ...args: P) {\n return storage.setItemWithTtl(keyFn(...args), ttlSeconds, value);\n },\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,SAAgB,sBAAmC,SAA0C;CACzF,QAAyB,UAAkC,OAAO,OAAO;EACrE,UAAU,GAAG,SAAY,QAAQ,QAAW,MAAM,GAAG,IAAI,CAAC;EAC1D,aAAa,GAAG,SAAY,QAAQ,WAAW,MAAM,GAAG,IAAI,CAAC;EAC7D,UAAU,GAAG,SAAY,QAAQ,QAAQ,MAAM,GAAG,IAAI,CAAC;EACvD,aAAa,GAAG,SAAY,QAAQ,WAAW,MAAM,GAAG,IAAI,CAAC;EAC7D,aAAa,GAAG,SAAY,MAAM,GAAG,IAAI;EACzC,UAAU,OAAU,GAAG,SAAY,QAAQ,QAAQ,MAAM,GAAG,IAAI,GAAG,KAAK;EACxE,eAAe,YAAoB,OAAU,GAAG,MAAS;GACrD,OAAO,QAAQ,eAAe,MAAM,GAAG,IAAI,GAAG,YAAY,KAAK;EACnE;CACJ,CAAC;AACL"}
1
+ {"version":3,"file":"keyed-store.js","names":[],"sources":["../../../src/storages/redis/keyed-store.ts"],"sourcesContent":["import type { MaybeReadonly } from '../../types';\n\nimport type { RedisLikeStorage } from './types';\n\n/**\n * Creates a keyed store factory sharing a caller-owned Redis-like storage facade.\n *\n * @remarks\n * The key resolver is called synchronously once per operation with the operation's key arguments.\n * Resolver exceptions propagate synchronously; asynchronous storage failures retain the underlying rejection.\n * `setItemWithTtl` accepts its TTL in seconds before the value and key arguments.\n * The factory does not open or close the underlying connection; cleanup remains the caller's responsibility.\n *\n * @typeParam D - The stored value type used by reads and writes.\n *\n * @param storage - The shared Redis-like storage instance.\n *\n * @returns A factory accepting a key resolver and returning a new frozen keyed facade sharing the storage.\n * Reads, writes, removals, and TTL results retain the underlying storage contract.\n */\nexport function createRedisKeyedStore<D = unknown>(storage: MaybeReadonly<RedisLikeStorage>) {\n return <P extends any[]>(keyFn: (...args: P) => string) => Object.freeze({\n getItem: (...args: P) => storage.getItem<D>(keyFn(...args)),\n getItemTtl: (...args: P) => storage.getItemTtl(keyFn(...args)),\n hasItem: (...args: P) => storage.hasItem(keyFn(...args)),\n removeItem: (...args: P) => storage.removeItem(keyFn(...args)),\n resolveKey: (...args: P) => keyFn(...args),\n setItem: (value: D, ...args: P) => storage.setItem(keyFn(...args), value),\n setItemWithTtl(ttlSeconds: number, value: D, ...args: P) {\n return storage.setItemWithTtl(keyFn(...args), ttlSeconds, value);\n },\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAoBA,SAAgB,sBAAmC,SAA0C;CACzF,QAAyB,UAAkC,OAAO,OAAO;EACrE,UAAU,GAAG,SAAY,QAAQ,QAAW,MAAM,GAAG,IAAI,CAAC;EAC1D,aAAa,GAAG,SAAY,QAAQ,WAAW,MAAM,GAAG,IAAI,CAAC;EAC7D,UAAU,GAAG,SAAY,QAAQ,QAAQ,MAAM,GAAG,IAAI,CAAC;EACvD,aAAa,GAAG,SAAY,QAAQ,WAAW,MAAM,GAAG,IAAI,CAAC;EAC7D,aAAa,GAAG,SAAY,MAAM,GAAG,IAAI;EACzC,UAAU,OAAU,GAAG,SAAY,QAAQ,QAAQ,MAAM,GAAG,IAAI,GAAG,KAAK;EACxE,eAAe,YAAoB,OAAU,GAAG,MAAS;GACrD,OAAO,QAAQ,eAAe,MAAM,GAAG,IAAI,GAAG,YAAY,KAAK;EACnE;CACJ,CAAC;AACL"}
@@ -1,26 +1,46 @@
1
1
  import { RedisLikeAdapter, RedisLikeStorage } from "./types.js";
2
2
  //#region src/storages/redis/msgpack.d.ts
3
3
  /**
4
- * Creates a Redis-like storage using msgpack serialization.
4
+ * Creates a frozen Redis-like storage facade using MessagePack serialization.
5
5
  *
6
- * @param {RedisLikeAdapter} adapter - The Redis-like adapter to use for raw buffer operations
6
+ * @remarks
7
+ * Adapter rejections and MessagePack serialization errors propagate to the caller.
8
+ * Reads resolve to `null` when no raw value exists. Writes resolve to `true` only when the adapter returns `OK`;
9
+ * removal resolves to `true` only when exactly one key is deleted.
10
+ * The adapter remains caller-owned; creating the facade does not open or close a connection.
7
11
  *
8
- * @returns {Readonly<RedisLikeStorage>} A readonly storage instance
9
- * with getItem, setItem, hasItem, removeItem, getItemTtl, setItemWithTtl
12
+ * @param adapter - The caller-owned adapter for raw binary operations.
13
+ *
14
+ * @returns A new frozen facade sharing the supplied adapter.
10
15
  *
11
16
  * @example
12
- * ```typescript
17
+ *
18
+ * ```ts
13
19
  * import { createRedisMsgpackStorage } from '@kikiutils/shared/storages/redis/msgpack';
14
- * import { createClient } from 'redis';
20
+ * import type { RedisLikeAdapter } from '@kikiutils/shared/storages/redis/types';
21
+ *
22
+ * // This in-memory adapter demonstrates non-expiring operations without an external service.
23
+ * const values = new Map<string, Uint8Array>();
24
+ * const adapter: RedisLikeAdapter = {
25
+ * delete: async (key) => values.delete(key) ? 1 : 0,
26
+ * getBuffer: async (key) => values.get(key) ?? null,
27
+ * has: async (key) => values.has(key),
28
+ * setBuffer: async (key, value) => {
29
+ * values.set(key, value);
30
+ * return 'OK';
31
+ * },
32
+ * setBufferEx: async () => {
33
+ * throw new Error('TTL writes are not supported by this example adapter');
34
+ * },
35
+ * ttl: async (key) => values.has(key) ? -1 : -2,
36
+ * };
15
37
  *
16
- * const client = createClient();
17
- * await client.connect();
18
- * const storage = createRedisMsgpackStorage(client as unknown as RedisLikeAdapter);
19
- * await storage.setItem('key', { foo: 'bar' });
20
- * const value = await storage.getItem('key'); // { foo: 'bar' }
38
+ * const storage = createRedisMsgpackStorage(adapter);
39
+ * await storage.setItem('profile', { name: 'Alice' });
40
+ * const profile = await storage.getItem<{ name: string }>('profile');
41
+ * console.log(profile); // => { name: 'Alice' }
21
42
  * ```
22
43
  */
23
- declare function createRedisMsgpackStorage(adapter: RedisLikeAdapter): Readonly<RedisLikeStorage>;
44
+ export declare function createRedisMsgpackStorage(adapter: RedisLikeAdapter): Readonly<RedisLikeStorage>;
24
45
  //#endregion
25
- export { createRedisMsgpackStorage };
26
46
  //# sourceMappingURL=msgpack.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"msgpack.d.ts","names":[],"sources":["../../../src/storages/redis/msgpack.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;iBAmCgB,0BAA0B,SAAS,mBAAmB,SAAS"}
1
+ {"version":3,"file":"msgpack.d.ts","names":[],"sources":["../../../src/storages/redis/msgpack.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAwDgB,0BAA0B,SAAS,mBAAmB,SAAS"}
@@ -2,23 +2,44 @@ import { decode, encode, isNativeAccelerationEnabled } from "msgpackr";
2
2
  //#region src/storages/redis/msgpack.ts
3
3
  if (!isNativeAccelerationEnabled) console.warn("Native acceleration not enabled for msgpackr, verify that install finished properly");
4
4
  /**
5
- * Creates a Redis-like storage using msgpack serialization.
5
+ * Creates a frozen Redis-like storage facade using MessagePack serialization.
6
6
  *
7
- * @param {RedisLikeAdapter} adapter - The Redis-like adapter to use for raw buffer operations
7
+ * @remarks
8
+ * Adapter rejections and MessagePack serialization errors propagate to the caller.
9
+ * Reads resolve to `null` when no raw value exists. Writes resolve to `true` only when the adapter returns `OK`;
10
+ * removal resolves to `true` only when exactly one key is deleted.
11
+ * The adapter remains caller-owned; creating the facade does not open or close a connection.
8
12
  *
9
- * @returns {Readonly<RedisLikeStorage>} A readonly storage instance
10
- * with getItem, setItem, hasItem, removeItem, getItemTtl, setItemWithTtl
13
+ * @param adapter - The caller-owned adapter for raw binary operations.
14
+ *
15
+ * @returns A new frozen facade sharing the supplied adapter.
11
16
  *
12
17
  * @example
13
- * ```typescript
18
+ *
19
+ * ```ts
14
20
  * import { createRedisMsgpackStorage } from '@kikiutils/shared/storages/redis/msgpack';
15
- * import { createClient } from 'redis';
21
+ * import type { RedisLikeAdapter } from '@kikiutils/shared/storages/redis/types';
22
+ *
23
+ * // This in-memory adapter demonstrates non-expiring operations without an external service.
24
+ * const values = new Map<string, Uint8Array>();
25
+ * const adapter: RedisLikeAdapter = {
26
+ * delete: async (key) => values.delete(key) ? 1 : 0,
27
+ * getBuffer: async (key) => values.get(key) ?? null,
28
+ * has: async (key) => values.has(key),
29
+ * setBuffer: async (key, value) => {
30
+ * values.set(key, value);
31
+ * return 'OK';
32
+ * },
33
+ * setBufferEx: async () => {
34
+ * throw new Error('TTL writes are not supported by this example adapter');
35
+ * },
36
+ * ttl: async (key) => values.has(key) ? -1 : -2,
37
+ * };
16
38
  *
17
- * const client = createClient();
18
- * await client.connect();
19
- * const storage = createRedisMsgpackStorage(client as unknown as RedisLikeAdapter);
20
- * await storage.setItem('key', { foo: 'bar' });
21
- * const value = await storage.getItem('key'); // { foo: 'bar' }
39
+ * const storage = createRedisMsgpackStorage(adapter);
40
+ * await storage.setItem('profile', { name: 'Alice' });
41
+ * const profile = await storage.getItem<{ name: string }>('profile');
42
+ * console.log(profile); // => { name: 'Alice' }
22
43
  * ```
23
44
  */
24
45
  function createRedisMsgpackStorage(adapter) {
@@ -1 +1 @@
1
- {"version":3,"file":"msgpack.js","names":[],"sources":["../../../src/storages/redis/msgpack.ts"],"sourcesContent":["import {\n decode,\n encode,\n isNativeAccelerationEnabled,\n} from 'msgpackr';\n\nimport type {\n RedisLikeAdapter,\n RedisLikeStorage,\n} from './types';\n\nif (!isNativeAccelerationEnabled) {\n console.warn('Native acceleration not enabled for msgpackr, verify that install finished properly');\n}\n\n/**\n * Creates a Redis-like storage using msgpack serialization.\n *\n * @param {RedisLikeAdapter} adapter - The Redis-like adapter to use for raw buffer operations\n *\n * @returns {Readonly<RedisLikeStorage>} A readonly storage instance\n * with getItem, setItem, hasItem, removeItem, getItemTtl, setItemWithTtl\n *\n * @example\n * ```typescript\n * import { createRedisMsgpackStorage } from '@kikiutils/shared/storages/redis/msgpack';\n * import { createClient } from 'redis';\n *\n * const client = createClient();\n * await client.connect();\n * const storage = createRedisMsgpackStorage(client as unknown as RedisLikeAdapter);\n * await storage.setItem('key', { foo: 'bar' });\n * const value = await storage.getItem('key'); // { foo: 'bar' }\n * ```\n */\nexport function createRedisMsgpackStorage(adapter: RedisLikeAdapter): Readonly<RedisLikeStorage> {\n return Object.freeze({\n async getItem<T = unknown>(key: string) {\n const rawValue = await adapter.getBuffer(key);\n return rawValue ? decode(rawValue) as T : null;\n },\n getItemTtl: (key: string) => adapter.ttl(key),\n hasItem: (key: string) => adapter.has(key),\n removeItem: async (key: string) => await adapter.delete(key) === 1,\n setItem: async (key: string, value: any) => await adapter.setBuffer(key, encode(value)) === 'OK',\n async setItemWithTtl(key: string, ttlSeconds: number, value: any) {\n return await adapter.setBufferEx(key, ttlSeconds, encode(value)) === 'OK';\n },\n });\n}\n"],"mappings":";;AAWA,IAAI,CAAC,6BACD,QAAQ,KAAK,qFAAqF;;;;;;;;;;;;;;;;;;;;;AAuBtG,SAAgB,0BAA0B,SAAuD;CAC7F,OAAO,OAAO,OAAO;EACjB,MAAM,QAAqB,KAAa;GACpC,MAAM,WAAW,MAAM,QAAQ,UAAU,GAAG;GAC5C,OAAO,WAAW,OAAO,QAAQ,IAAS;EAC9C;EACA,aAAa,QAAgB,QAAQ,IAAI,GAAG;EAC5C,UAAU,QAAgB,QAAQ,IAAI,GAAG;EACzC,YAAY,OAAO,QAAgB,MAAM,QAAQ,OAAO,GAAG,MAAM;EACjE,SAAS,OAAO,KAAa,UAAe,MAAM,QAAQ,UAAU,KAAK,OAAO,KAAK,CAAC,MAAM;EAC5F,MAAM,eAAe,KAAa,YAAoB,OAAY;GAC9D,OAAO,MAAM,QAAQ,YAAY,KAAK,YAAY,OAAO,KAAK,CAAC,MAAM;EACzE;CACJ,CAAC;AACL"}
1
+ {"version":3,"file":"msgpack.js","names":[],"sources":["../../../src/storages/redis/msgpack.ts"],"sourcesContent":["import {\n decode,\n encode,\n isNativeAccelerationEnabled,\n} from 'msgpackr';\n\nimport type {\n RedisLikeAdapter,\n RedisLikeStorage,\n} from './types';\n\nif (!isNativeAccelerationEnabled) {\n console.warn('Native acceleration not enabled for msgpackr, verify that install finished properly');\n}\n\n/**\n * Creates a frozen Redis-like storage facade using MessagePack serialization.\n *\n * @remarks\n * Adapter rejections and MessagePack serialization errors propagate to the caller.\n * Reads resolve to `null` when no raw value exists. Writes resolve to `true` only when the adapter returns `OK`;\n * removal resolves to `true` only when exactly one key is deleted.\n * The adapter remains caller-owned; creating the facade does not open or close a connection.\n *\n * @param adapter - The caller-owned adapter for raw binary operations.\n *\n * @returns A new frozen facade sharing the supplied adapter.\n *\n * @example\n *\n * ```ts\n * import { createRedisMsgpackStorage } from '@kikiutils/shared/storages/redis/msgpack';\n * import type { RedisLikeAdapter } from '@kikiutils/shared/storages/redis/types';\n *\n * // This in-memory adapter demonstrates non-expiring operations without an external service.\n * const values = new Map<string, Uint8Array>();\n * const adapter: RedisLikeAdapter = {\n * delete: async (key) => values.delete(key) ? 1 : 0,\n * getBuffer: async (key) => values.get(key) ?? null,\n * has: async (key) => values.has(key),\n * setBuffer: async (key, value) => {\n * values.set(key, value);\n * return 'OK';\n * },\n * setBufferEx: async () => {\n * throw new Error('TTL writes are not supported by this example adapter');\n * },\n * ttl: async (key) => values.has(key) ? -1 : -2,\n * };\n *\n * const storage = createRedisMsgpackStorage(adapter);\n * await storage.setItem('profile', { name: 'Alice' });\n * const profile = await storage.getItem<{ name: string }>('profile');\n * console.log(profile); // => { name: 'Alice' }\n * ```\n */\nexport function createRedisMsgpackStorage(adapter: RedisLikeAdapter): Readonly<RedisLikeStorage> {\n return Object.freeze({\n async getItem<T = unknown>(key: string) {\n const rawValue = await adapter.getBuffer(key);\n return rawValue ? decode(rawValue) as T : null;\n },\n getItemTtl: (key: string) => adapter.ttl(key),\n hasItem: (key: string) => adapter.has(key),\n removeItem: async (key: string) => await adapter.delete(key) === 1,\n setItem: async (key: string, value: any) => await adapter.setBuffer(key, encode(value)) === 'OK',\n async setItemWithTtl(key: string, ttlSeconds: number, value: any) {\n return await adapter.setBufferEx(key, ttlSeconds, encode(value)) === 'OK';\n },\n });\n}\n"],"mappings":";;AAWA,IAAI,CAAC,6BACD,QAAQ,KAAK,qFAAqF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CtG,SAAgB,0BAA0B,SAAuD;CAC7F,OAAO,OAAO,OAAO;EACjB,MAAM,QAAqB,KAAa;GACpC,MAAM,WAAW,MAAM,QAAQ,UAAU,GAAG;GAC5C,OAAO,WAAW,OAAO,QAAQ,IAAS;EAC9C;EACA,aAAa,QAAgB,QAAQ,IAAI,GAAG;EAC5C,UAAU,QAAgB,QAAQ,IAAI,GAAG;EACzC,YAAY,OAAO,QAAgB,MAAM,QAAQ,OAAO,GAAG,MAAM;EACjE,SAAS,OAAO,KAAa,UAAe,MAAM,QAAQ,UAAU,KAAK,OAAO,KAAK,CAAC,MAAM;EAC5F,MAAM,eAAe,KAAa,YAAoB,OAAY;GAC9D,OAAO,MAAM,QAAQ,YAAY,KAAK,YAAY,OAAO,KAAK,CAAC,MAAM;EACzE;CACJ,CAAC;AACL"}
@@ -1,62 +1,79 @@
1
1
  //#region src/storages/redis/types.d.ts
2
2
  /**
3
- * Low-level Redis-like adapter interface for raw buffer operations.
3
+ * A caller-owned asynchronous adapter for Redis-like binary operations.
4
+ *
5
+ * @remarks
6
+ * Each callback performs one operation and rejects its promise on backend failure.
7
+ * TTL results use Redis conventions: `-1` means no expiry, and `-2` means the key is missing.
4
8
  */
5
- interface RedisLikeAdapter {
9
+ export interface RedisLikeAdapter {
6
10
  /**
7
- * Deletes a key and returns the number of keys deleted.
11
+ * Deletes a key and resolves to the number of keys deleted.
8
12
  */
9
13
  delete: (key: string) => Promise<number>;
10
14
  /**
11
- * Gets the raw buffer value for a key.
15
+ * Reads a key and resolves to its raw bytes, or `null` when the key is missing.
12
16
  */
13
17
  getBuffer: (key: string) => Promise<null | Uint8Array>;
14
18
  /**
15
- * Checks if a key exists.
19
+ * Checks a key and resolves to whether it exists.
16
20
  */
17
21
  has: (key: string) => Promise<boolean>;
18
22
  /**
19
- * Sets a raw buffer value for a key.
23
+ * Writes raw bytes and resolves to the backend acknowledgment, or no value.
20
24
  */
21
25
  setBuffer: (key: string, value: Uint8Array) => Promise<'OK' | void>;
22
26
  /**
23
- * Sets a raw buffer value for a key with a TTL.
27
+ * Writes raw bytes with an expiry and resolves to the backend acknowledgment, or no value.
28
+ *
29
+ * @param key - The storage key.
30
+ * @param ttlSeconds - The expiry duration in seconds.
31
+ * @param value - The raw bytes to store.
24
32
  */
25
33
  setBufferEx: (key: string, ttlSeconds: number, value: Uint8Array) => Promise<'OK' | void>;
26
34
  /**
27
- * Gets the TTL of a key in seconds.
35
+ * Reads a key's remaining TTL in seconds, or `-1` for no expiry and `-2` for a missing key.
28
36
  */
29
37
  ttl: (key: string) => Promise<number>;
30
38
  }
31
39
  /**
32
- * High-level Redis-like storage interface with typed get/set operations.
40
+ * An asynchronous Redis-like storage contract with typed reads and serialized writes.
41
+ *
42
+ * @remarks
43
+ * Operations reject on backend or serialization failure. TTL values are in seconds;
44
+ * `-1` means no expiry, and `-2` means the key is missing. Connection cleanup remains caller-owned.
33
45
  */
34
- interface RedisLikeStorage {
46
+ export interface RedisLikeStorage {
35
47
  /**
36
- * Gets a deserialized value by key.
48
+ * Reads a deserialized value and resolves to `null` when the key is missing.
49
+ *
50
+ * @typeParam T - The expected value type; deserialization does not validate this type.
37
51
  */
38
52
  getItem: <T = unknown>(key: string) => Promise<null | T>;
39
53
  /**
40
- * Gets the TTL of a key in seconds.
54
+ * Reads a key's remaining TTL in seconds, or `-1` for no expiry and `-2` for a missing key.
41
55
  */
42
56
  getItemTtl: (key: string) => Promise<number>;
43
57
  /**
44
- * Checks if a key exists.
58
+ * Checks a key and resolves to whether it exists.
45
59
  */
46
60
  hasItem: (key: string) => Promise<boolean>;
47
61
  /**
48
- * Removes a key.
62
+ * Removes a key and resolves to whether a key was deleted.
49
63
  */
50
64
  removeItem: (key: string) => Promise<boolean>;
51
65
  /**
52
- * Sets a value for a key.
66
+ * Stores a value and resolves to whether the backend acknowledges the write.
53
67
  */
54
68
  setItem: (key: string, value: any) => Promise<boolean>;
55
69
  /**
56
- * Sets a value for a key with a TTL.
70
+ * Stores a value with an expiry and resolves to whether the backend acknowledges the write.
71
+ *
72
+ * @param key - The storage key.
73
+ * @param ttlSeconds - The expiry duration in seconds.
74
+ * @param value - The value to serialize and store.
57
75
  */
58
76
  setItemWithTtl: (key: string, ttlSeconds: number, value: any) => Promise<boolean>;
59
77
  }
60
78
  //#endregion
61
- export { RedisLikeAdapter, RedisLikeStorage };
62
79
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/storages/redis/types.ts"],"mappings":";;;;UAGiB;;;;EAIb,SAAS,gBAAgB;;;;EAKzB,YAAY,gBAAgB,eAAe;;;;EAK3C,MAAM,gBAAgB;;;;EAKtB,YAAY,aAAa,OAAO,eAAe;;;;EAK/C,cAAc,aAAa,oBAAoB,OAAO,eAAe;;;;EAKrE,MAAM,gBAAgB;;;;;UAMT;;;;EAIb,UAAU,aAAa,gBAAgB,eAAe;;;;EAKtD,aAAa,gBAAgB;;;;EAK7B,UAAU,gBAAgB;;;;EAK1B,aAAa,gBAAgB;;;;EAK7B,UAAU,aAAa,eAAe;;;;EAKtC,iBAAiB,aAAa,oBAAoB,eAAe"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/storages/redis/types.ts"],"mappings":";;;;;;;;iBAOiB;;;;EAIb,SAAS,gBAAgB;;;;EAKzB,YAAY,gBAAgB,eAAe;;;;EAK3C,MAAM,gBAAgB;;;;EAKtB,YAAY,aAAa,OAAO,eAAe;;;;;;;;EAS/C,cAAc,aAAa,oBAAoB,OAAO,eAAe;;;;EAKrE,MAAM,gBAAgB;;;;;;;;;iBAUT;;;;;;EAMb,UAAU,aAAa,gBAAgB,eAAe;;;;EAKtD,aAAa,gBAAgB;;;;EAK7B,UAAU,gBAAgB;;;;EAK1B,aAAa,gBAAgB;;;;EAK7B,UAAU,aAAa,eAAe;;;;;;;;EAStC,iBAAiB,aAAa,oBAAoB,eAAe"}
package/dist/string.d.ts CHANGED
@@ -2,30 +2,31 @@
2
2
  /**
3
3
  * Character-set presets supported by `randomString`.
4
4
  */
5
- type RandomStringMode = 'alphabetic' | 'alphanumeric' | 'lowercase' | 'lowercase-numeric' | 'numeric' | 'uppercase' | 'uppercase-numeric';
5
+ export type RandomStringMode = 'alphabetic' | 'alphanumeric' | 'lowercase' | 'lowercase-numeric' | 'numeric' | 'uppercase' | 'uppercase-numeric';
6
6
  /**
7
7
  * Generates a random string of a given length using a predefined character set.
8
8
  *
9
+ * @remarks
9
10
  * Uses `Math.random`, so this helper is suitable for display tokens, placeholders,
10
11
  * and test data, but not for passwords, API keys, or other cryptographic secrets.
11
12
  *
12
- * @param {number} length - The positive integer length of the string to generate
13
- * @param {RandomStringMode} [mode] - The character set to use (default: `'alphabetic'`)
13
+ * @param length - The positive integer length of the string to generate.
14
+ * @param mode - The character set to use (default: `'alphabetic'`).
14
15
  *
15
- * @returns {string} The generated random string
16
+ * @returns The generated random string.
16
17
  *
17
- * @throws {Error} If the length is not a positive integer or the mode is unsupported
18
+ * @throws Error if the length is not a positive integer or the mode is unsupported.
18
19
  *
19
20
  * @example
20
- * ```typescript
21
+ *
22
+ * ```ts
21
23
  * import { randomString } from '@kikiutils/shared/string';
22
24
  *
23
- * randomString(8); // e.g. 'aZbXwTyQ'
24
- * randomString(6, 'numeric'); // e.g. '402398'
25
- * randomString(10, 'alphanumeric'); // e.g. 'a9Z4pQ8xY2'
25
+ * randomString(8); // For example, 'aZbXwTyQ'.
26
+ * randomString(6, 'numeric'); // For example, '402398'.
27
+ * randomString(10, 'alphanumeric'); // For example, 'a9Z4pQ8xY2'.
26
28
  * ```
27
29
  */
28
- declare function randomString(length: number, mode?: RandomStringMode): string;
30
+ export declare function randomString(length: number, mode?: RandomStringMode): string;
29
31
  //#endregion
30
- export { RandomStringMode, randomString };
31
32
  //# sourceMappingURL=string.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"string.d.ts","names":[],"sources":["../src/string.ts"],"mappings":";;;;KAGY;;;;;;;;;;;;;;;;;;;;;;;iBA4CI,aAAa,gBAAgB,OAAM"}
1
+ {"version":3,"file":"string.d.ts","names":[],"sources":["../src/string.ts"],"mappings":";;;;YAGY;;;;;;;;;;;;;;;;;;;;;;;;;wBA8CI,aAAa,gBAAgB,OAAM"}
package/dist/string.js CHANGED
@@ -1,33 +1,38 @@
1
1
  //#region src/string.ts
2
+ const DIGITS = "0123456789";
3
+ const LOWERCASE = "abcdefghijklmnopqrstuvwxyz";
4
+ const UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
2
5
  const CHARSETS = {
3
- "alphabetic": "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
4
- "alphanumeric": "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
5
- "lowercase": "abcdefghijklmnopqrstuvwxyz",
6
- "lowercase-numeric": "0123456789abcdefghijklmnopqrstuvwxyz",
7
- "numeric": "0123456789",
8
- "uppercase": "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
9
- "uppercase-numeric": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
6
+ "alphabetic": LOWERCASE + UPPERCASE,
7
+ "alphanumeric": DIGITS + LOWERCASE + UPPERCASE,
8
+ "lowercase": LOWERCASE,
9
+ "lowercase-numeric": DIGITS + LOWERCASE,
10
+ "numeric": DIGITS,
11
+ "uppercase": UPPERCASE,
12
+ "uppercase-numeric": DIGITS + UPPERCASE
10
13
  };
11
14
  /**
12
15
  * Generates a random string of a given length using a predefined character set.
13
16
  *
17
+ * @remarks
14
18
  * Uses `Math.random`, so this helper is suitable for display tokens, placeholders,
15
19
  * and test data, but not for passwords, API keys, or other cryptographic secrets.
16
20
  *
17
- * @param {number} length - The positive integer length of the string to generate
18
- * @param {RandomStringMode} [mode] - The character set to use (default: `'alphabetic'`)
21
+ * @param length - The positive integer length of the string to generate.
22
+ * @param mode - The character set to use (default: `'alphabetic'`).
19
23
  *
20
- * @returns {string} The generated random string
24
+ * @returns The generated random string.
21
25
  *
22
- * @throws {Error} If the length is not a positive integer or the mode is unsupported
26
+ * @throws Error if the length is not a positive integer or the mode is unsupported.
23
27
  *
24
28
  * @example
25
- * ```typescript
29
+ *
30
+ * ```ts
26
31
  * import { randomString } from '@kikiutils/shared/string';
27
32
  *
28
- * randomString(8); // e.g. 'aZbXwTyQ'
29
- * randomString(6, 'numeric'); // e.g. '402398'
30
- * randomString(10, 'alphanumeric'); // e.g. 'a9Z4pQ8xY2'
33
+ * randomString(8); // For example, 'aZbXwTyQ'.
34
+ * randomString(6, 'numeric'); // For example, '402398'.
35
+ * randomString(10, 'alphanumeric'); // For example, 'a9Z4pQ8xY2'.
31
36
  * ```
32
37
  */
33
38
  function randomString(length, mode = "alphabetic") {
@@ -1 +1 @@
1
- {"version":3,"file":"string.js","names":[],"sources":["../src/string.ts"],"sourcesContent":["/**\n * Character-set presets supported by `randomString`.\n */\nexport type RandomStringMode =\n | 'alphabetic'\n | 'alphanumeric'\n | 'lowercase'\n | 'lowercase-numeric'\n | 'numeric'\n | 'uppercase'\n | 'uppercase-numeric';\n\nconst DIGITS = '0123456789';\nconst LOWERCASE = 'abcdefghijklmnopqrstuvwxyz';\nconst UPPERCASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';\nconst CHARSETS: Record<RandomStringMode, string> = {\n 'alphabetic': LOWERCASE + UPPERCASE,\n 'alphanumeric': DIGITS + LOWERCASE + UPPERCASE,\n 'lowercase': LOWERCASE,\n 'lowercase-numeric': DIGITS + LOWERCASE,\n 'numeric': DIGITS,\n 'uppercase': UPPERCASE,\n 'uppercase-numeric': DIGITS + UPPERCASE,\n};\n\n/**\n * Generates a random string of a given length using a predefined character set.\n *\n * Uses `Math.random`, so this helper is suitable for display tokens, placeholders,\n * and test data, but not for passwords, API keys, or other cryptographic secrets.\n *\n * @param {number} length - The positive integer length of the string to generate\n * @param {RandomStringMode} [mode] - The character set to use (default: `'alphabetic'`)\n *\n * @returns {string} The generated random string\n *\n * @throws {Error} If the length is not a positive integer or the mode is unsupported\n *\n * @example\n * ```typescript\n * import { randomString } from '@kikiutils/shared/string';\n *\n * randomString(8); // e.g. 'aZbXwTyQ'\n * randomString(6, 'numeric'); // e.g. '402398'\n * randomString(10, 'alphanumeric'); // e.g. 'a9Z4pQ8xY2'\n * ```\n */\nexport function randomString(length: number, mode: RandomStringMode = 'alphabetic') {\n if (!Number.isInteger(length) || length <= 0) {\n throw new Error(`Invalid length: ${length}. Must be a positive integer`);\n }\n\n const charset = CHARSETS[mode];\n if (!charset) throw new Error(`Unsupported mode: ${mode}`);\n return Array.from({ length }, () => charset[Math.floor(Math.random() * charset.length)]).join('');\n}\n"],"mappings":";AAeA,MAAM,WAA6C;CAC/C,cAAc;CACd,gBAAgB;CAChB,aAAa;CACb,qBAAqB;CACrB,WAAW;CACX,aAAa;CACb,qBAAqB;AACzB;;;;;;;;;;;;;;;;;;;;;;;AAwBA,SAAgB,aAAa,QAAgB,OAAyB,cAAc;CAChF,IAAI,CAAC,OAAO,UAAU,MAAM,KAAK,UAAU,GACvC,MAAM,IAAI,MAAM,mBAAmB,OAAO,6BAA6B;CAG3E,MAAM,UAAU,SAAS;CACzB,IAAI,CAAC,SAAS,MAAM,IAAI,MAAM,qBAAqB,MAAM;CACzD,OAAO,MAAM,KAAK,EAAE,OAAO,SAAS,QAAQ,KAAK,MAAM,KAAK,OAAO,IAAI,QAAQ,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE;AACpG"}
1
+ {"version":3,"file":"string.js","names":[],"sources":["../src/string.ts"],"sourcesContent":["/**\n * Character-set presets supported by `randomString`.\n */\nexport type RandomStringMode =\n | 'alphabetic'\n | 'alphanumeric'\n | 'lowercase'\n | 'lowercase-numeric'\n | 'numeric'\n | 'uppercase'\n | 'uppercase-numeric';\n\nconst DIGITS = '0123456789';\nconst LOWERCASE = 'abcdefghijklmnopqrstuvwxyz';\nconst UPPERCASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';\nconst CHARSETS: Record<RandomStringMode, string> = {\n 'alphabetic': LOWERCASE + UPPERCASE,\n 'alphanumeric': DIGITS + LOWERCASE + UPPERCASE,\n 'lowercase': LOWERCASE,\n 'lowercase-numeric': DIGITS + LOWERCASE,\n 'numeric': DIGITS,\n 'uppercase': UPPERCASE,\n 'uppercase-numeric': DIGITS + UPPERCASE,\n};\n\n/**\n * Generates a random string of a given length using a predefined character set.\n *\n * @remarks\n * Uses `Math.random`, so this helper is suitable for display tokens, placeholders,\n * and test data, but not for passwords, API keys, or other cryptographic secrets.\n *\n * @param length - The positive integer length of the string to generate.\n * @param mode - The character set to use (default: `'alphabetic'`).\n *\n * @returns The generated random string.\n *\n * @throws Error if the length is not a positive integer or the mode is unsupported.\n *\n * @example\n *\n * ```ts\n * import { randomString } from '@kikiutils/shared/string';\n *\n * randomString(8); // For example, 'aZbXwTyQ'.\n * randomString(6, 'numeric'); // For example, '402398'.\n * randomString(10, 'alphanumeric'); // For example, 'a9Z4pQ8xY2'.\n * ```\n */\nexport function randomString(length: number, mode: RandomStringMode = 'alphabetic') {\n if (!Number.isInteger(length) || length <= 0) {\n throw new Error(`Invalid length: ${length}. Must be a positive integer`);\n }\n\n const charset = CHARSETS[mode];\n if (!charset) throw new Error(`Unsupported mode: ${mode}`);\n return Array.from({ length }, () => charset[Math.floor(Math.random() * charset.length)]).join('');\n}\n"],"mappings":";AAYA,MAAM,SAAS;AACf,MAAM,YAAY;AAClB,MAAM,YAAY;AAClB,MAAM,WAA6C;CAC/C,cAAc,YAAY;CAC1B,gBAAgB,SAAS,YAAY;CACrC,aAAa;CACb,qBAAqB,SAAS;CAC9B,WAAW;CACX,aAAa;CACb,qBAAqB,SAAS;AAClC;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,aAAa,QAAgB,OAAyB,cAAc;CAChF,IAAI,CAAC,OAAO,UAAU,MAAM,KAAK,UAAU,GACvC,MAAM,IAAI,MAAM,mBAAmB,OAAO,6BAA6B;CAG3E,MAAM,UAAU,SAAS;CACzB,IAAI,CAAC,SAAS,MAAM,IAAI,MAAM,qBAAqB,MAAM;CACzD,OAAO,MAAM,KAAK,EAAE,OAAO,SAAS,QAAQ,KAAK,MAAM,KAAK,OAAO,IAAI,QAAQ,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE;AACpG"}
package/dist/time.d.ts CHANGED
@@ -1,24 +1,49 @@
1
1
  //#region src/time.d.ts
2
2
  /**
3
- * Delays execution until the specified duration elapses or the signal is aborted.
3
+ * Waits until a duration elapses or cancellation occurs without rejecting on cancellation.
4
4
  *
5
- * Aborting the signal rejects the promise with the signal's abort reason.
5
+ * @remarks
6
+ * The promise resolves without a value when the timer completes or the signal aborts.
7
+ * An already aborted signal resolves immediately; completion removes the abort listener and clears the timer.
6
8
  *
7
- * @param {number} ms - Delay duration in milliseconds
8
- * @param {AbortSignal} [signal] - Optional signal used to abort the delay
9
+ * @param ms - The delay duration in milliseconds, using native `setTimeout` timing rules.
10
+ * @param signal - The signal that ends the wait early.
9
11
  *
10
- * @returns {Promise<void>} Resolves when the delay completes or rejects when the signal is aborted
12
+ * @example
13
+ *
14
+ * ```ts
15
+ * import { delay } from '@kikiutils/shared/time';
16
+ *
17
+ * const controller = new AbortController();
18
+ * controller.abort();
19
+ * await delay(5000, controller.signal);
20
+ * ```
21
+ */
22
+ export declare function delay(ms: number, signal?: AbortSignal): Promise<void>;
23
+ /**
24
+ * Waits until a duration elapses and rejects on cancellation.
25
+ *
26
+ * @remarks
27
+ * The promise resolves without a value when the timer completes and rejects with `signal.reason` if aborted.
28
+ * An already aborted signal rejects immediately. Aborting clears the timer; timer completion removes the listener.
29
+ *
30
+ * @param ms - The delay duration in milliseconds, using native `setTimeout` timing rules.
31
+ * @param signal - The signal that cancels the wait.
11
32
  *
12
33
  * @example
13
- * ```typescript
34
+ *
35
+ * ```ts
14
36
  * import { delayOrThrow } from '@kikiutils/shared/time';
15
37
  *
16
38
  * const controller = new AbortController();
17
- * setTimeout(() => controller.abort(), 1000);
18
- * await delayOrThrow(5000, controller.signal); // rejects after ~1s
39
+ * controller.abort(new Error('Canceled'));
40
+ * try {
41
+ * await delayOrThrow(5000, controller.signal);
42
+ * } catch (error) {
43
+ * console.error(error);
44
+ * }
19
45
  * ```
20
46
  */
21
- declare function delayOrThrow(ms: number, signal?: AbortSignal): Promise<void>;
47
+ export declare function delayOrThrow(ms: number, signal?: AbortSignal): Promise<void>;
22
48
  //#endregion
23
- export { delayOrThrow };
24
49
  //# sourceMappingURL=time.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"time.d.ts","names":[],"sources":["../src/time.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;iBAmBgB,aAAa,YAAY,SAAS,cAAc"}
1
+ {"version":3,"file":"time.d.ts","names":[],"sources":["../src/time.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;wBAoBgB,MAAM,YAAY,SAAS,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;wBA2CzC,aAAa,YAAY,SAAS,cAAc"}
package/dist/time.js CHANGED
@@ -1,21 +1,61 @@
1
1
  //#region src/time.ts
2
2
  /**
3
- * Delays execution until the specified duration elapses or the signal is aborted.
3
+ * Waits until a duration elapses or cancellation occurs without rejecting on cancellation.
4
4
  *
5
- * Aborting the signal rejects the promise with the signal's abort reason.
5
+ * @remarks
6
+ * The promise resolves without a value when the timer completes or the signal aborts.
7
+ * An already aborted signal resolves immediately; completion removes the abort listener and clears the timer.
6
8
  *
7
- * @param {number} ms - Delay duration in milliseconds
8
- * @param {AbortSignal} [signal] - Optional signal used to abort the delay
9
+ * @param ms - The delay duration in milliseconds, using native `setTimeout` timing rules.
10
+ * @param signal - The signal that ends the wait early.
9
11
  *
10
- * @returns {Promise<void>} Resolves when the delay completes or rejects when the signal is aborted
12
+ * @example
13
+ *
14
+ * ```ts
15
+ * import { delay } from '@kikiutils/shared/time';
16
+ *
17
+ * const controller = new AbortController();
18
+ * controller.abort();
19
+ * await delay(5000, controller.signal);
20
+ * ```
21
+ */
22
+ function delay(ms, signal) {
23
+ return new Promise((resolve) => {
24
+ if (signal?.aborted) {
25
+ resolve();
26
+ return;
27
+ }
28
+ const done = () => {
29
+ clearTimeout(timeout);
30
+ signal?.removeEventListener("abort", done);
31
+ resolve();
32
+ };
33
+ const timeout = setTimeout(done, ms);
34
+ signal?.addEventListener("abort", done, { once: true });
35
+ });
36
+ }
37
+ /**
38
+ * Waits until a duration elapses and rejects on cancellation.
39
+ *
40
+ * @remarks
41
+ * The promise resolves without a value when the timer completes and rejects with `signal.reason` if aborted.
42
+ * An already aborted signal rejects immediately. Aborting clears the timer; timer completion removes the listener.
43
+ *
44
+ * @param ms - The delay duration in milliseconds, using native `setTimeout` timing rules.
45
+ * @param signal - The signal that cancels the wait.
11
46
  *
12
47
  * @example
13
- * ```typescript
48
+ *
49
+ * ```ts
14
50
  * import { delayOrThrow } from '@kikiutils/shared/time';
15
51
  *
16
52
  * const controller = new AbortController();
17
- * setTimeout(() => controller.abort(), 1000);
18
- * await delayOrThrow(5000, controller.signal); // rejects after ~1s
53
+ * controller.abort(new Error('Canceled'));
54
+ * try {
55
+ * await delayOrThrow(5000, controller.signal);
56
+ * } catch (error) {
57
+ * console.error(error);
58
+ * }
19
59
  * ```
20
60
  */
21
61
  function delayOrThrow(ms, signal) {
@@ -36,6 +76,6 @@ function delayOrThrow(ms, signal) {
36
76
  });
37
77
  }
38
78
  //#endregion
39
- export { delayOrThrow };
79
+ export { delay, delayOrThrow };
40
80
 
41
81
  //# sourceMappingURL=time.js.map
package/dist/time.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"time.js","names":[],"sources":["../src/time.ts"],"sourcesContent":["/**\n * Delays execution until the specified duration elapses or the signal is aborted.\n *\n * Aborting the signal rejects the promise with the signal's abort reason.\n *\n * @param {number} ms - Delay duration in milliseconds\n * @param {AbortSignal} [signal] - Optional signal used to abort the delay\n *\n * @returns {Promise<void>} Resolves when the delay completes or rejects when the signal is aborted\n *\n * @example\n * ```typescript\n * import { delayOrThrow } from '@kikiutils/shared/time';\n *\n * const controller = new AbortController();\n * setTimeout(() => controller.abort(), 1000);\n * await delayOrThrow(5000, controller.signal); // rejects after ~1s\n * ```\n */\nexport function delayOrThrow(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason);\n return;\n }\n\n const onAbort = () => {\n // eslint-disable-next-line ts/no-use-before-define\n clearTimeout(timeout);\n reject(signal!.reason);\n };\n\n const timeout = setTimeout(\n () => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n },\n ms,\n );\n\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,aAAa,IAAY,QAAqC;CAC1E,OAAO,IAAI,SAAS,SAAS,WAAW;EACpC,IAAI,QAAQ,SAAS;GACjB,OAAO,OAAO,MAAM;GACpB;EACJ;EAEA,MAAM,gBAAgB;GAElB,aAAa,OAAO;GACpB,OAAO,OAAQ,MAAM;EACzB;EAEA,MAAM,UAAU,iBACN;GACF,QAAQ,oBAAoB,SAAS,OAAO;GAC5C,QAAQ;EACZ,GACA,EACJ;EAEA,QAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;CAC7D,CAAC;AACL"}
1
+ {"version":3,"file":"time.js","names":[],"sources":["../src/time.ts"],"sourcesContent":["/**\n * Waits until a duration elapses or cancellation occurs without rejecting on cancellation.\n *\n * @remarks\n * The promise resolves without a value when the timer completes or the signal aborts.\n * An already aborted signal resolves immediately; completion removes the abort listener and clears the timer.\n *\n * @param ms - The delay duration in milliseconds, using native `setTimeout` timing rules.\n * @param signal - The signal that ends the wait early.\n *\n * @example\n *\n * ```ts\n * import { delay } from '@kikiutils/shared/time';\n *\n * const controller = new AbortController();\n * controller.abort();\n * await delay(5000, controller.signal);\n * ```\n */\nexport function delay(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n if (signal?.aborted) {\n resolve();\n return;\n }\n\n const done = () => {\n // eslint-disable-next-line ts/no-use-before-define\n clearTimeout(timeout);\n signal?.removeEventListener('abort', done);\n resolve();\n };\n\n const timeout = setTimeout(done, ms);\n signal?.addEventListener('abort', done, { once: true });\n });\n}\n\n/**\n * Waits until a duration elapses and rejects on cancellation.\n *\n * @remarks\n * The promise resolves without a value when the timer completes and rejects with `signal.reason` if aborted.\n * An already aborted signal rejects immediately. Aborting clears the timer; timer completion removes the listener.\n *\n * @param ms - The delay duration in milliseconds, using native `setTimeout` timing rules.\n * @param signal - The signal that cancels the wait.\n *\n * @example\n *\n * ```ts\n * import { delayOrThrow } from '@kikiutils/shared/time';\n *\n * const controller = new AbortController();\n * controller.abort(new Error('Canceled'));\n * try {\n * await delayOrThrow(5000, controller.signal);\n * } catch (error) {\n * console.error(error);\n * }\n * ```\n */\nexport function delayOrThrow(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason);\n return;\n }\n\n const onAbort = () => {\n // eslint-disable-next-line ts/no-use-before-define\n clearTimeout(timeout);\n reject(signal!.reason);\n };\n\n const timeout = setTimeout(\n () => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n },\n ms,\n );\n\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,MAAM,IAAY,QAAqC;CACnE,OAAO,IAAI,SAAS,YAAY;EAC5B,IAAI,QAAQ,SAAS;GACjB,QAAQ;GACR;EACJ;EAEA,MAAM,aAAa;GAEf,aAAa,OAAO;GACpB,QAAQ,oBAAoB,SAAS,IAAI;GACzC,QAAQ;EACZ;EAEA,MAAM,UAAU,WAAW,MAAM,EAAE;EACnC,QAAQ,iBAAiB,SAAS,MAAM,EAAE,MAAM,KAAK,CAAC;CAC1D,CAAC;AACL;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,aAAa,IAAY,QAAqC;CAC1E,OAAO,IAAI,SAAS,SAAS,WAAW;EACpC,IAAI,QAAQ,SAAS;GACjB,OAAO,OAAO,MAAM;GACpB;EACJ;EAEA,MAAM,gBAAgB;GAElB,aAAa,OAAO;GACpB,OAAO,OAAQ,MAAM;EACzB;EAEA,MAAM,UAAU,iBACN;GACF,QAAQ,oBAAoB,SAAS,OAAO;GAC5C,QAAQ;EACZ,GACA,EACJ;EAEA,QAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;CAC7D,CAAC;AACL"}
@@ -1,28 +1,17 @@
1
1
  import { ObjectId } from "bson";
2
2
  //#region src/types/filtered-key-path.d.ts
3
- /**
4
- * The following types are based on or inspired by types from the Element Plus project.
5
- * Source: https://github.com/element-plus/element-plus
6
- * License: MIT (https://opensource.org/licenses/MIT)
7
- *
8
- * Original types might have been modified to suit this project’s needs.
9
- */
10
- /***/
11
3
  type ConditionalPath<K extends number | string, V, U> = V extends U ? `${K}` : DefaultPath<K, V, U, never>;
12
4
  type DefaultPath<K extends number | string, V, U = never, RK = `${K}`> = V extends TerminalType ? RK : `${K}.${FilteredKeyPath<V, U>}`;
13
5
  /**
14
- * A utility type that generates a union of key paths from a given object type `T`,
15
- * filtered by a specific type `U`. If `U` is
16
- * not provided, it defaults to including all key paths.
6
+ * A union of nested object key paths optionally filtered by the matching value type.
17
7
  *
18
- * @template T - The object type to traverse.
19
- * @template U - The type used to filter key paths. Defaults to `never`, meaning no filtering.
8
+ * @typeParam T - The object type to traverse.
9
+ * @typeParam U - The value type to select; `never` disables filtering.
20
10
  */
21
- type FilteredKeyPath<T, U = never> = T extends ReadonlyArray<infer V> ? (IsTuple<T> extends true ? { [K in TupleKey<T>]-?: PathImpl<Exclude<K, symbol>, T[K], U>; }[TupleKey<T>] : PathImpl<number, V, U>) : { [K in keyof T]-?: PathImpl<Exclude<K, symbol>, T[K], U>; }[keyof T];
11
+ export type FilteredKeyPath<T, U = never> = T extends ReadonlyArray<infer V> ? (IsTuple<T> extends true ? { [K in TupleKey<T>]-?: PathImpl<Exclude<K, symbol>, T[K], U>; }[TupleKey<T>] : PathImpl<number, V, U>) : { [K in keyof T]-?: PathImpl<Exclude<K, symbol>, T[K], U>; }[keyof T];
22
12
  type IsTuple<T extends ReadonlyArray<any>> = number extends T['length'] ? false : true;
23
13
  type PathImpl<K extends number | string, V, U> = [U] extends [never] ? DefaultPath<K, V> : ConditionalPath<K, V, U>;
24
14
  type TerminalType = bigint | Blob | boolean | Date | File | null | number | ObjectId | RegExp | string | symbol | undefined;
25
15
  type TupleKey<T extends ReadonlyArray<any>> = Exclude<keyof T, keyof any[]>;
26
16
  //#endregion
27
- export { FilteredKeyPath };
28
17
  //# sourceMappingURL=filtered-key-path.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"filtered-key-path.d.ts","names":[],"sources":["../../src/types/filtered-key-path.ts"],"mappings":";;;;;;;;;;KAWK,gBAAgB,2BAA2B,GAAG,KAAK,UAAU,OAAO,MAAM,YAAY,GAAG,GAAG;KAC5F,YACD,2BACA,GACA,WACA,QAAQ,OACR,UAAU,eAAe,QAAQ,KAAK,gBAAgB,GAAG;;;;;;;;;KAWjD,gBAAgB,GAAG,aAAa,UAAU,oBAAoB,MAAM,QAAQ,qBAAqB,KAAK,SAAS,OAAO,SAAS,QAAQ,YAAY,EAAE,IAAI,MAAK,SAAS,MAAM,iBAAiB,GAAG,SAAS,WAAW,MAAM,SAAS,QAAQ,YAAY,EAAE,IAAI,YAAW;KAChR,QAAQ,UAAU,qCAAqC;KACvD,SAAS,2BAA2B,GAAG,MAAM,qBAAqB,YAAY,GAAG,KAAK,gBAAgB,GAAG,GAAG;KAC5G,wBAED,iBAEA,OACA,uBAGA,WACA;KAKC,SAAS,UAAU,sBAAsB,cAAc"}
1
+ {"version":3,"file":"filtered-key-path.d.ts","names":[],"sources":["../../src/types/filtered-key-path.ts"],"mappings":";;KAKK,gBAAgB,2BAA2B,GAAG,KAAK,UAAU,OAAO,MAAM,YAAY,GAAG,GAAG;KAC5F,YACD,2BACA,GACA,WACA,QAAQ,OACR,UAAU,eAAe,QAAQ,KAAK,gBAAgB,GAAG;;;;;;;YAUjD,gBAAgB,GAAG,aAAa,UAAU,oBAAoB,MAAM,QAAQ,qBAAqB,KAAK,SAAS,OAAO,SAAS,QAAQ,YAAY,EAAE,IAAI,MAAK,SAAS,MAAM,iBAAiB,GAAG,SAAS,WAAW,MAAM,SAAS,QAAQ,YAAY,EAAE,IAAI,YAAW;KAGhR,QAAQ,UAAU,qCAAqC;KACvD,SAAS,2BAA2B,GAAG,MAAM,qBAAqB,YAAY,GAAG,KAAK,gBAAgB,GAAG,GAAG;KAC5G,wBAED,iBAEA,OACA,uBAGA,WACA;KAKC,SAAS,UAAU,sBAAsB,cAAc"}