@kikiutils/shared 15.0.0 → 15.0.2

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 (77) hide show
  1. package/README.md +46 -119
  2. package/dist/classes/ssh-client.d.ts +3 -3
  3. package/dist/classes/ssh-client.d.ts.map +1 -1
  4. package/dist/consola.d.ts +3 -3
  5. package/dist/consola.d.ts.map +1 -1
  6. package/dist/crypto-hash.d.ts +145 -0
  7. package/dist/crypto-hash.d.ts.map +1 -1
  8. package/dist/crypto-hash.js +137 -7
  9. package/dist/crypto-hash.js.map +1 -1
  10. package/dist/datetime.d.ts +0 -2
  11. package/dist/datetime.d.ts.map +1 -1
  12. package/dist/datetime.js +0 -2
  13. package/dist/datetime.js.map +1 -1
  14. package/dist/env.d.ts +2 -0
  15. package/dist/env.d.ts.map +1 -1
  16. package/dist/env.js +2 -0
  17. package/dist/env.js.map +1 -1
  18. package/dist/event-awaiter.js +1 -1
  19. package/dist/event-awaiter.js.map +1 -1
  20. package/dist/hash.d.ts +48 -5
  21. package/dist/hash.d.ts.map +1 -1
  22. package/dist/hash.js +49 -6
  23. package/dist/hash.js.map +1 -1
  24. package/dist/math.js +1 -1
  25. package/dist/math.js.map +1 -1
  26. package/dist/object.d.ts +4 -0
  27. package/dist/object.d.ts.map +1 -1
  28. package/dist/object.js +4 -0
  29. package/dist/object.js.map +1 -1
  30. package/dist/pino.d.ts +3 -3
  31. package/dist/random.js +2 -0
  32. package/dist/random.js.map +1 -1
  33. package/dist/storages/lru/keyed-store.d.ts +22 -0
  34. package/dist/storages/lru/keyed-store.d.ts.map +1 -1
  35. package/dist/storages/lru/keyed-store.js +22 -0
  36. package/dist/storages/lru/keyed-store.js.map +1 -1
  37. package/dist/storages/redis/keyed-store.d.ts +25 -0
  38. package/dist/storages/redis/keyed-store.d.ts.map +1 -1
  39. package/dist/storages/redis/keyed-store.js +25 -0
  40. package/dist/storages/redis/keyed-store.js.map +1 -1
  41. package/dist/storages/redis/msgpack.d.ts +20 -0
  42. package/dist/storages/redis/msgpack.d.ts.map +1 -1
  43. package/dist/storages/redis/msgpack.js +20 -0
  44. package/dist/storages/redis/msgpack.js.map +1 -1
  45. package/dist/storages/redis/types.d.ts +42 -0
  46. package/dist/storages/redis/types.d.ts.map +1 -1
  47. package/dist/string.js +1 -1
  48. package/dist/string.js.map +1 -1
  49. package/dist/time.d.ts +17 -0
  50. package/dist/time.d.ts.map +1 -1
  51. package/dist/time.js +17 -0
  52. package/dist/time.js.map +1 -1
  53. package/dist/url.d.ts +3 -0
  54. package/dist/url.d.ts.map +1 -1
  55. package/dist/url.js +8 -2
  56. package/dist/url.js.map +1 -1
  57. package/dist/vue.d.ts +6 -0
  58. package/dist/vue.d.ts.map +1 -1
  59. package/dist/vue.js +6 -0
  60. package/dist/vue.js.map +1 -1
  61. package/package.json +22 -22
  62. package/src/crypto-hash.ts +143 -14
  63. package/src/datetime.ts +0 -2
  64. package/src/env.ts +2 -0
  65. package/src/event-awaiter.ts +1 -1
  66. package/src/hash.ts +56 -14
  67. package/src/math.ts +2 -1
  68. package/src/object.ts +4 -0
  69. package/src/random.ts +3 -0
  70. package/src/storages/lru/keyed-store.ts +22 -0
  71. package/src/storages/redis/keyed-store.ts +25 -0
  72. package/src/storages/redis/msgpack.ts +20 -0
  73. package/src/storages/redis/types.ts +52 -0
  74. package/src/string.ts +1 -1
  75. package/src/time.ts +17 -0
  76. package/src/url.ts +13 -2
  77. package/src/vue.ts +6 -0
@@ -1,6 +1,26 @@
1
1
  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
+ /**
5
+ * Creates a Redis-like storage using msgpack serialization.
6
+ *
7
+ * @param {RedisLikeAdapter} adapter - The Redis-like adapter to use for raw buffer operations
8
+ *
9
+ * @returns {Readonly<RedisLikeStorage>} A readonly storage instance
10
+ * with getItem, setItem, hasItem, removeItem, getItemTtl, setItemWithTtl
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { createRedisMsgpackStorage } from '@kikiutils/shared/storages/redis/msgpack';
15
+ * import { createClient } from 'redis';
16
+ *
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' }
22
+ * ```
23
+ */
4
24
  function createRedisMsgpackStorage(adapter) {
5
25
  return Object.freeze({
6
26
  async getItem(key) {
@@ -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\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,4BACD,SAAQ,KAAK,sFAAsF;AAGvG,SAAgB,0BAA0B,SAAuD;AAC7F,QAAO,OAAO,OAAO;EACjB,MAAM,QAAqB,KAAa;GACpC,MAAM,WAAW,MAAM,QAAQ,UAAU,IAAI;AAC7C,UAAO,WAAW,OAAO,SAAS,GAAQ;;EAE9C,aAAa,QAAgB,QAAQ,IAAI,IAAI;EAC7C,UAAU,QAAgB,QAAQ,IAAI,IAAI;EAC1C,YAAY,OAAO,QAAgB,MAAM,QAAQ,OAAO,IAAI,KAAK;EACjE,SAAS,OAAO,KAAa,UAAe,MAAM,QAAQ,UAAU,KAAK,OAAO,MAAM,CAAC,KAAK;EAC5F,MAAM,eAAe,KAAa,YAAoB,OAAY;AAC9D,UAAO,MAAM,QAAQ,YAAY,KAAK,YAAY,OAAO,MAAM,CAAC,KAAK;;EAE5E,CAAC"}
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,4BACD,SAAQ,KAAK,sFAAsF;;;;;;;;;;;;;;;;;;;;;AAuBvG,SAAgB,0BAA0B,SAAuD;AAC7F,QAAO,OAAO,OAAO;EACjB,MAAM,QAAqB,KAAa;GACpC,MAAM,WAAW,MAAM,QAAQ,UAAU,IAAI;AAC7C,UAAO,WAAW,OAAO,SAAS,GAAQ;;EAE9C,aAAa,QAAgB,QAAQ,IAAI,IAAI;EAC7C,UAAU,QAAgB,QAAQ,IAAI,IAAI;EAC1C,YAAY,OAAO,QAAgB,MAAM,QAAQ,OAAO,IAAI,KAAK;EACjE,SAAS,OAAO,KAAa,UAAe,MAAM,QAAQ,UAAU,KAAK,OAAO,MAAM,CAAC,KAAK;EAC5F,MAAM,eAAe,KAAa,YAAoB,OAAY;AAC9D,UAAO,MAAM,QAAQ,YAAY,KAAK,YAAY,OAAO,MAAM,CAAC,KAAK;;EAE5E,CAAC"}
@@ -1,20 +1,62 @@
1
1
  import { Nullable } from "../../types/index.js";
2
2
 
3
3
  //#region src/storages/redis/types.d.ts
4
+ /**
5
+ * Low-level Redis-like adapter interface for raw buffer operations.
6
+ */
4
7
  interface RedisLikeAdapter {
8
+ /**
9
+ * Deletes a key and returns the number of keys deleted.
10
+ */
5
11
  delete: (key: string) => Promise<number>;
12
+ /**
13
+ * Gets the raw buffer value for a key.
14
+ */
6
15
  getBuffer: (key: string) => Promise<Nullable<Uint8Array>>;
16
+ /**
17
+ * Checks if a key exists.
18
+ */
7
19
  has: (key: string) => Promise<boolean>;
20
+ /**
21
+ * Sets a raw buffer value for a key.
22
+ */
8
23
  setBuffer: (key: string, value: Uint8Array) => Promise<'OK' | void>;
24
+ /**
25
+ * Sets a raw buffer value for a key with a TTL.
26
+ */
9
27
  setBufferEx: (key: string, ttlSeconds: number, value: Uint8Array) => Promise<'OK' | void>;
28
+ /**
29
+ * Gets the TTL of a key in seconds.
30
+ */
10
31
  ttl: (key: string) => Promise<number>;
11
32
  }
33
+ /**
34
+ * High-level Redis-like storage interface with typed get/set operations.
35
+ */
12
36
  interface RedisLikeStorage {
37
+ /**
38
+ * Gets a deserialized value by key.
39
+ */
13
40
  getItem: <T = unknown>(key: string) => Promise<Nullable<T>>;
41
+ /**
42
+ * Gets the TTL of a key in seconds.
43
+ */
14
44
  getItemTtl: (key: string) => Promise<number>;
45
+ /**
46
+ * Checks if a key exists.
47
+ */
15
48
  hasItem: (key: string) => Promise<boolean>;
49
+ /**
50
+ * Removes a key.
51
+ */
16
52
  removeItem: (key: string) => Promise<boolean>;
53
+ /**
54
+ * Sets a value for a key.
55
+ */
17
56
  setItem: (key: string, value: any) => Promise<boolean>;
57
+ /**
58
+ * Sets a value for a key with a TTL.
59
+ */
18
60
  setItemWithTtl: (key: string, ttlSeconds: number, value: any) => Promise<boolean>;
19
61
  }
20
62
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/storages/redis/types.ts"],"mappings":";;;UAEiB,gBAAA;EACb,MAAA,GAAS,GAAA,aAAgB,OAAA;EACzB,SAAA,GAAY,GAAA,aAAgB,OAAA,CAAQ,QAAA,CAAS,UAAA;EAC7C,GAAA,GAAM,GAAA,aAAgB,OAAA;EACtB,SAAA,GAAY,GAAA,UAAa,KAAA,EAAO,UAAA,KAAe,OAAA;EAC/C,WAAA,GAAc,GAAA,UAAa,UAAA,UAAoB,KAAA,EAAO,UAAA,KAAe,OAAA;EACrE,GAAA,GAAM,GAAA,aAAgB,OAAA;AAAA;AAAA,UAGT,gBAAA;EACb,OAAA,gBAAuB,GAAA,aAAgB,OAAA,CAAQ,QAAA,CAAS,CAAA;EACxD,UAAA,GAAa,GAAA,aAAgB,OAAA;EAC7B,OAAA,GAAU,GAAA,aAAgB,OAAA;EAC1B,UAAA,GAAa,GAAA,aAAgB,OAAA;EAC7B,OAAA,GAAU,GAAA,UAAa,KAAA,UAAe,OAAA;EACtC,cAAA,GAAiB,GAAA,UAAa,UAAA,UAAoB,KAAA,UAAe,OAAA;AAAA"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/storages/redis/types.ts"],"mappings":";;;;;AAKA;UAAiB,gBAAA;;;;EAIb,MAAA,GAAS,GAAA,aAAgB,OAAA;EAKG;;;EAA5B,SAAA,GAAY,GAAA,aAAgB,OAAA,CAAQ,QAAA,CAAS,UAAA;EAeS;;;EAVtD,GAAA,GAAM,GAAA,aAAgB,OAAA;EAeO;;;EAV7B,SAAA,GAAY,GAAA,UAAa,KAAA,EAAO,UAAA,KAAe,OAAA;EAV/C;;;EAeA,WAAA,GAAc,GAAA,UAAa,UAAA,UAAoB,KAAA,EAAO,UAAA,KAAe,OAAA;EAfxB;;;EAoB7C,GAAA,GAAM,GAAA,aAAgB,OAAA;AAAA;;;;UAMT,gBAAA;EAXb;;;EAeA,OAAA,gBAAuB,GAAA,aAAgB,OAAA,CAAQ,QAAA,CAAS,CAAA;EAfT;;;EAoB/C,UAAA,GAAa,GAAA,aAAgB,OAAA;EAfP;;;EAoBtB,OAAA,GAAU,GAAA,aAAgB,OAAA;EAdG;;;EAmB7B,UAAA,GAAa,GAAA,aAAgB,OAAA;EAfU;;;EAoBvC,OAAA,GAAU,GAAA,UAAa,KAAA,UAAe,OAAA;EAAA;;;EAKtC,cAAA,GAAiB,GAAA,UAAa,UAAA,UAAoB,KAAA,UAAe,OAAA;AAAA"}
package/dist/string.js CHANGED
@@ -34,7 +34,7 @@ function randomString(length, mode = "alphabetic") {
34
34
  if (!Number.isInteger(length) || length <= 0) throw new Error(`Invalid length: ${length}. Must be a positive integer`);
35
35
  const charset = CHARSETS[mode];
36
36
  if (!charset) throw new Error(`Unsupported mode: ${mode}`);
37
- return Array.from({ length }).fill(charset[Math.floor(Math.random() * charset.length)]).join("");
37
+ return Array.from({ length }, () => charset[Math.floor(Math.random() * charset.length)]).join("");
38
38
  }
39
39
  //#endregion
40
40
  export { randomString };
@@ -1 +1 @@
1
- {"version":3,"file":"string.js","names":[],"sources":["../src/string.ts"],"sourcesContent":["export 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 specified character set.\n *\n * @param {number} length - The length of the string to generate. Must be a positive integer\n * @param {RandomStringMode} [mode] - The character set to use\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 * console.log(randomString(8)); // e.g. 'aZbXwTyQ' (alphabetic)\n * console.log(randomString(6, 'numeric')); // e.g. '402398'\n * console.log(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 }).fill(charset[Math.floor(Math.random() * charset.length)]).join('');\n}\n"],"mappings":";AASA,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;CACjC;;;;;;;;;;;;;;;;;;;;AAqBD,SAAgB,aAAa,QAAgB,OAAyB,cAAc;AAChF,KAAI,CAAC,OAAO,UAAU,OAAO,IAAI,UAAU,EACvC,OAAM,IAAI,MAAM,mBAAmB,OAAO,8BAA8B;CAG5E,MAAM,UAAU,SAAS;AACzB,KAAI,CAAC,QAAS,OAAM,IAAI,MAAM,qBAAqB,OAAO;AAC1D,QAAO,MAAM,KAAK,EAAE,QAAQ,CAAC,CAAC,KAAK,QAAQ,KAAK,MAAM,KAAK,QAAQ,GAAG,QAAQ,OAAO,EAAE,CAAC,KAAK,GAAG"}
1
+ {"version":3,"file":"string.js","names":[],"sources":["../src/string.ts"],"sourcesContent":["export 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 specified character set.\n *\n * @param {number} length - The length of the string to generate. Must be a positive integer\n * @param {RandomStringMode} [mode] - The character set to use\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 * console.log(randomString(8)); // e.g. 'aZbXwTyQ' (alphabetic)\n * console.log(randomString(6, 'numeric')); // e.g. '402398'\n * console.log(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":";AASA,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;CACjC;;;;;;;;;;;;;;;;;;;;AAqBD,SAAgB,aAAa,QAAgB,OAAyB,cAAc;AAChF,KAAI,CAAC,OAAO,UAAU,OAAO,IAAI,UAAU,EACvC,OAAM,IAAI,MAAM,mBAAmB,OAAO,8BAA8B;CAG5E,MAAM,UAAU,SAAS;AACzB,KAAI,CAAC,QAAS,OAAM,IAAI,MAAM,qBAAqB,OAAO;AAC1D,QAAO,MAAM,KAAK,EAAE,QAAQ,QAAQ,QAAQ,KAAK,MAAM,KAAK,QAAQ,GAAG,QAAQ,OAAO,EAAE,CAAC,KAAK,GAAG"}
package/dist/time.d.ts CHANGED
@@ -1,4 +1,21 @@
1
1
  //#region src/time.d.ts
2
+ /**
3
+ * Creates a delay that can be aborted via AbortSignal.
4
+ *
5
+ * @param {number} ms - Delay duration in milliseconds
6
+ * @param {AbortSignal} [signal] - Optional AbortSignal to cancel the delay
7
+ *
8
+ * @returns {Promise<undefined>} A promise that resolves after ms or resolves immediately on abort
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { abortableDelay } from '@kikiutils/shared/time';
13
+ *
14
+ * const controller = new AbortController();
15
+ * setTimeout(() => controller.abort(), 1000);
16
+ * await abortableDelay(5000, controller.signal); // resolves after ~1s when aborted
17
+ * ```
18
+ */
2
19
  declare function abortableDelay(ms: number, signal?: AbortSignal): Promise<unknown>;
3
20
  //#endregion
4
21
  export { abortableDelay };
@@ -1 +1 @@
1
- {"version":3,"file":"time.d.ts","names":[],"sources":["../src/time.ts"],"mappings":";iBAAgB,cAAA,CAAe,EAAA,UAAY,MAAA,GAAS,WAAA,GAAW,OAAA"}
1
+ {"version":3,"file":"time.d.ts","names":[],"sources":["../src/time.ts"],"mappings":";;AAiBA;;;;;;;;;;;;;;;;iBAAgB,cAAA,CAAe,EAAA,UAAY,MAAA,GAAS,WAAA,GAAW,OAAA"}
package/dist/time.js CHANGED
@@ -1,4 +1,21 @@
1
1
  //#region src/time.ts
2
+ /**
3
+ * Creates a delay that can be aborted via AbortSignal.
4
+ *
5
+ * @param {number} ms - Delay duration in milliseconds
6
+ * @param {AbortSignal} [signal] - Optional AbortSignal to cancel the delay
7
+ *
8
+ * @returns {Promise<undefined>} A promise that resolves after ms or resolves immediately on abort
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { abortableDelay } from '@kikiutils/shared/time';
13
+ *
14
+ * const controller = new AbortController();
15
+ * setTimeout(() => controller.abort(), 1000);
16
+ * await abortableDelay(5000, controller.signal); // resolves after ~1s when aborted
17
+ * ```
18
+ */
2
19
  function abortableDelay(ms, signal) {
3
20
  return new Promise((resolve) => {
4
21
  const timeout = setTimeout(resolve, ms);
package/dist/time.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"time.js","names":[],"sources":["../src/time.ts"],"sourcesContent":["export function abortableDelay(ms: number, signal?: AbortSignal) {\n return new Promise((resolve) => {\n const timeout = setTimeout(resolve, ms);\n if (signal) {\n signal.addEventListener(\n 'abort',\n () => {\n clearTimeout(timeout);\n resolve(undefined);\n },\n );\n }\n });\n}\n"],"mappings":";AAAA,SAAgB,eAAe,IAAY,QAAsB;AAC7D,QAAO,IAAI,SAAS,YAAY;EAC5B,MAAM,UAAU,WAAW,SAAS,GAAG;AACvC,MAAI,OACA,QAAO,iBACH,eACM;AACF,gBAAa,QAAQ;AACrB,WAAQ,KAAA,EAAU;IAEzB;GAEP"}
1
+ {"version":3,"file":"time.js","names":[],"sources":["../src/time.ts"],"sourcesContent":["/**\n * Creates a delay that can be aborted via AbortSignal.\n *\n * @param {number} ms - Delay duration in milliseconds\n * @param {AbortSignal} [signal] - Optional AbortSignal to cancel the delay\n *\n * @returns {Promise<undefined>} A promise that resolves after ms or resolves immediately on abort\n *\n * @example\n * ```typescript\n * import { abortableDelay } from '@kikiutils/shared/time';\n *\n * const controller = new AbortController();\n * setTimeout(() => controller.abort(), 1000);\n * await abortableDelay(5000, controller.signal); // resolves after ~1s when aborted\n * ```\n */\nexport function abortableDelay(ms: number, signal?: AbortSignal) {\n return new Promise((resolve) => {\n const timeout = setTimeout(resolve, ms);\n if (signal) {\n signal.addEventListener(\n 'abort',\n () => {\n clearTimeout(timeout);\n resolve(undefined);\n },\n );\n }\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAiBA,SAAgB,eAAe,IAAY,QAAsB;AAC7D,QAAO,IAAI,SAAS,YAAY;EAC5B,MAAM,UAAU,WAAW,SAAS,GAAG;AACvC,MAAI,OACA,QAAO,iBACH,eACM;AACF,gBAAa,QAAQ;AACrB,WAAQ,KAAA,EAAU;IAEzB;GAEP"}
package/dist/url.d.ts CHANGED
@@ -6,8 +6,11 @@
6
6
  *
7
7
  * @param {string} url - The target URL to modify
8
8
  * @param {string} redirectPath - The path to use as the redirect destination
9
+ * (must be an absolute path starting with '/')
9
10
  *
10
11
  * @returns {string} A new URL string with the `redirect` query parameter
12
+ *
13
+ * @throws {Error} If redirectPath is not a valid relative path (must start with '/')
11
14
  */
12
15
  declare function appendRedirectParamToUrl(url: string, redirectPath: string): string;
13
16
  //#endregion
package/dist/url.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"url.d.ts","names":[],"sources":["../src/url.ts"],"mappings":";;AAUA;;;;;;;;;iBAAgB,wBAAA,CAAyB,GAAA,UAAa,YAAA"}
1
+ {"version":3,"file":"url.d.ts","names":[],"sources":["../src/url.ts"],"mappings":";;AAaA;;;;;;;;;;;;iBAAgB,wBAAA,CAAyB,GAAA,UAAa,YAAA"}
package/dist/url.js CHANGED
@@ -6,14 +6,20 @@
6
6
  *
7
7
  * @param {string} url - The target URL to modify
8
8
  * @param {string} redirectPath - The path to use as the redirect destination
9
+ * (must be an absolute path starting with '/')
9
10
  *
10
11
  * @returns {string} A new URL string with the `redirect` query parameter
12
+ *
13
+ * @throws {Error} If redirectPath is not a valid relative path (must start with '/')
11
14
  */
12
15
  function appendRedirectParamToUrl(url, redirectPath) {
13
- const [base, rawQuery = ""] = url.split("?");
16
+ if (!redirectPath.startsWith("/")) throw new Error(`Invalid redirect path: "${redirectPath}". Redirect paths must be absolute paths starting with '/'.`);
17
+ const [baseAndHash, rawQuery = ""] = url.split("?");
18
+ const [base, hash] = (baseAndHash || "").split("#");
14
19
  const searchParams = new URLSearchParams(rawQuery);
15
20
  searchParams.set("redirect", redirectPath);
16
- return `${base}?${searchParams.toString()}`;
21
+ const queryString = searchParams.toString();
22
+ return hash ? `${base}?${queryString}#${hash}` : `${base}?${queryString}`;
17
23
  }
18
24
  //#endregion
19
25
  export { appendRedirectParamToUrl };
package/dist/url.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"url.js","names":[],"sources":["../src/url.ts"],"sourcesContent":["/**\n * Appends or updates the `redirect` query parameter on a given URL.\n *\n * Typically used to preserve the user's current path for post-login navigation.\n *\n * @param {string} url - The target URL to modify\n * @param {string} redirectPath - The path to use as the redirect destination\n *\n * @returns {string} A new URL string with the `redirect` query parameter\n */\nexport function appendRedirectParamToUrl(url: string, redirectPath: string) {\n const [base, rawQuery = ''] = url.split('?');\n const searchParams = new URLSearchParams(rawQuery);\n searchParams.set('redirect', redirectPath);\n return `${base}?${searchParams.toString()}`;\n}\n"],"mappings":";;;;;;;;;;;AAUA,SAAgB,yBAAyB,KAAa,cAAsB;CACxE,MAAM,CAAC,MAAM,WAAW,MAAM,IAAI,MAAM,IAAI;CAC5C,MAAM,eAAe,IAAI,gBAAgB,SAAS;AAClD,cAAa,IAAI,YAAY,aAAa;AAC1C,QAAO,GAAG,KAAK,GAAG,aAAa,UAAU"}
1
+ {"version":3,"file":"url.js","names":[],"sources":["../src/url.ts"],"sourcesContent":["/**\n * Appends or updates the `redirect` query parameter on a given URL.\n *\n * Typically used to preserve the user's current path for post-login navigation.\n *\n * @param {string} url - The target URL to modify\n * @param {string} redirectPath - The path to use as the redirect destination\n * (must be an absolute path starting with '/')\n *\n * @returns {string} A new URL string with the `redirect` query parameter\n *\n * @throws {Error} If redirectPath is not a valid relative path (must start with '/')\n */\nexport function appendRedirectParamToUrl(url: string, redirectPath: string) {\n if (!redirectPath.startsWith('/')) {\n throw new Error(\n `Invalid redirect path: \"${redirectPath}\". Redirect paths must be absolute paths starting with '/'.`,\n );\n }\n\n const [baseAndHash, rawQuery = ''] = url.split('?');\n const [base, hash] = (baseAndHash || '').split('#');\n const searchParams = new URLSearchParams(rawQuery);\n searchParams.set('redirect', redirectPath);\n const queryString = searchParams.toString();\n return hash ? `${base}?${queryString}#${hash}` : `${base}?${queryString}`;\n}\n"],"mappings":";;;;;;;;;;;;;;AAaA,SAAgB,yBAAyB,KAAa,cAAsB;AACxE,KAAI,CAAC,aAAa,WAAW,IAAI,CAC7B,OAAM,IAAI,MACN,2BAA2B,aAAa,6DAC3C;CAGL,MAAM,CAAC,aAAa,WAAW,MAAM,IAAI,MAAM,IAAI;CACnD,MAAM,CAAC,MAAM,SAAS,eAAe,IAAI,MAAM,IAAI;CACnD,MAAM,eAAe,IAAI,gBAAgB,SAAS;AAClD,cAAa,IAAI,YAAY,aAAa;CAC1C,MAAM,cAAc,aAAa,UAAU;AAC3C,QAAO,OAAO,GAAG,KAAK,GAAG,YAAY,GAAG,SAAS,GAAG,KAAK,GAAG"}
package/dist/vue.d.ts CHANGED
@@ -26,6 +26,12 @@ declare function clearTimeoutRef(timeoutRef: Ref<Nullable<ReturnType<typeof setT
26
26
  * A Vue composition function that remembers and restores scroll position
27
27
  * of a scrollable container across route changes and keep-alive activation.
28
28
  *
29
+ * Designed for use with `<KeepAlive>` components. Scroll state is saved on
30
+ * route leave and restored when the component is activated again.
31
+ *
32
+ * Note: Without `<KeepAlive>`, the component state is destroyed on unmount,
33
+ * so scroll position will not be preserved.
34
+ *
29
35
  * @template T - The type of the scrollable element (defaults to HTMLElement)
30
36
  *
31
37
  * @param {Ref<Nullable<T>>} containerRef - A ref to the scrollable HTML element
package/dist/vue.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"vue.d.ts","names":[],"sources":["../src/vue.ts"],"mappings":";;;;;;AAiBA;;;;;iBAAgB,wCAAA,CAAyC,GAAA;;;;;;iBASzC,gBAAA,CAAiB,WAAA,EAAa,GAAA,CAAI,QAAA,CAAS,UAAA,QAAkB,WAAA;;;;;;iBAU7D,eAAA,CAAgB,UAAA,EAAY,GAAA,CAAI,QAAA,CAAS,UAAA,QAAkB,UAAA;;;;AAA3E;;;;;iBAagB,iBAAA,WAA4B,OAAA,GAAU,WAAA,CAAA,CAAa,YAAA,EAAc,GAAA,CAAI,QAAA,CAAS,CAAA"}
1
+ {"version":3,"file":"vue.d.ts","names":[],"sources":["../src/vue.ts"],"mappings":";;;;;;AAiBA;;;;;iBAAgB,wCAAA,CAAyC,GAAA;;;;;;iBASzC,gBAAA,CAAiB,WAAA,EAAa,GAAA,CAAI,QAAA,CAAS,UAAA,QAAkB,WAAA;;;;;;iBAU7D,eAAA,CAAgB,UAAA,EAAY,GAAA,CAAI,QAAA,CAAS,UAAA,QAAkB,UAAA;;;;AAA3E;;;;;;;;;;;iBAmBgB,iBAAA,WAA4B,OAAA,GAAU,WAAA,CAAA,CAAa,YAAA,EAAc,GAAA,CAAI,QAAA,CAAS,CAAA"}
package/dist/vue.js CHANGED
@@ -34,6 +34,12 @@ function clearTimeoutRef(timeoutRef) {
34
34
  * A Vue composition function that remembers and restores scroll position
35
35
  * of a scrollable container across route changes and keep-alive activation.
36
36
  *
37
+ * Designed for use with `<KeepAlive>` components. Scroll state is saved on
38
+ * route leave and restored when the component is activated again.
39
+ *
40
+ * Note: Without `<KeepAlive>`, the component state is destroyed on unmount,
41
+ * so scroll position will not be preserved.
42
+ *
37
43
  * @template T - The type of the scrollable element (defaults to HTMLElement)
38
44
  *
39
45
  * @param {Ref<Nullable<T>>} containerRef - A ref to the scrollable HTML element
package/dist/vue.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"vue.js","names":[],"sources":["../src/vue.ts"],"sourcesContent":["import { onActivated } from 'vue';\nimport type { Ref } from 'vue';\nimport {\n onBeforeRouteLeave,\n useRoute,\n} from 'vue-router';\n\nimport type { Nullable } from './types';\nimport { appendRedirectParamToUrl } from './url';\n\n/**\n * Appends the current Vue Router route's fullPath as the `redirect` query parameter to the given URL.\n *\n * @param {string} url - The base URL to modify\n *\n * @returns {string} A new URL with the current route fullPath as the `redirect` parameter\n */\nexport function appendRedirectParamFromCurrentRouteToUrl(url: string) {\n return appendRedirectParamToUrl(url, useRoute().fullPath);\n}\n\n/**\n * Clears an interval referenced by a Vue ref and sets it to null.\n *\n * @param {Ref<Nullable<ReturnType<typeof setInterval>>>} intervalRef - A Vue ref holding a NodeJS.Timeout or null\n */\nexport function clearIntervalRef(intervalRef: Ref<Nullable<ReturnType<typeof setInterval>>>) {\n if (intervalRef.value) clearInterval(intervalRef.value);\n intervalRef.value = null;\n}\n\n/**\n * Clears a timeout referenced by a Vue ref and sets it to null.\n *\n * @param {Ref<Nullable<ReturnType<typeof setTimeout>>>} timeoutRef - A Vue ref holding a NodeJS.Timeout or null\n */\nexport function clearTimeoutRef(timeoutRef: Ref<Nullable<ReturnType<typeof setTimeout>>>) {\n if (timeoutRef.value) clearTimeout(timeoutRef.value);\n timeoutRef.value = null;\n}\n\n/**\n * A Vue composition function that remembers and restores scroll position\n * of a scrollable container across route changes and keep-alive activation.\n *\n * @template T - The type of the scrollable element (defaults to HTMLElement)\n *\n * @param {Ref<Nullable<T>>} containerRef - A ref to the scrollable HTML element\n */\nexport function usePreserveScroll<T extends Element = HTMLElement>(containerRef: Ref<Nullable<T>>) {\n let scrollLeft = 0;\n let scrollTop = 0;\n onActivated(() => {\n if (!containerRef.value) return;\n containerRef.value.scrollLeft = scrollLeft;\n containerRef.value.scrollTop = scrollTop;\n });\n\n onBeforeRouteLeave(() => {\n scrollLeft = containerRef.value?.scrollLeft || 0;\n scrollTop = containerRef.value?.scrollTop || 0;\n });\n}\n"],"mappings":";;;;;;;;;;;AAiBA,SAAgB,yCAAyC,KAAa;AAClE,QAAO,yBAAyB,KAAK,UAAU,CAAC,SAAS;;;;;;;AAQ7D,SAAgB,iBAAiB,aAA4D;AACzF,KAAI,YAAY,MAAO,eAAc,YAAY,MAAM;AACvD,aAAY,QAAQ;;;;;;;AAQxB,SAAgB,gBAAgB,YAA0D;AACtF,KAAI,WAAW,MAAO,cAAa,WAAW,MAAM;AACpD,YAAW,QAAQ;;;;;;;;;;AAWvB,SAAgB,kBAAmD,cAAgC;CAC/F,IAAI,aAAa;CACjB,IAAI,YAAY;AAChB,mBAAkB;AACd,MAAI,CAAC,aAAa,MAAO;AACzB,eAAa,MAAM,aAAa;AAChC,eAAa,MAAM,YAAY;GACjC;AAEF,0BAAyB;AACrB,eAAa,aAAa,OAAO,cAAc;AAC/C,cAAY,aAAa,OAAO,aAAa;GAC/C"}
1
+ {"version":3,"file":"vue.js","names":[],"sources":["../src/vue.ts"],"sourcesContent":["import { onActivated } from 'vue';\nimport type { Ref } from 'vue';\nimport {\n onBeforeRouteLeave,\n useRoute,\n} from 'vue-router';\n\nimport type { Nullable } from './types';\nimport { appendRedirectParamToUrl } from './url';\n\n/**\n * Appends the current Vue Router route's fullPath as the `redirect` query parameter to the given URL.\n *\n * @param {string} url - The base URL to modify\n *\n * @returns {string} A new URL with the current route fullPath as the `redirect` parameter\n */\nexport function appendRedirectParamFromCurrentRouteToUrl(url: string) {\n return appendRedirectParamToUrl(url, useRoute().fullPath);\n}\n\n/**\n * Clears an interval referenced by a Vue ref and sets it to null.\n *\n * @param {Ref<Nullable<ReturnType<typeof setInterval>>>} intervalRef - A Vue ref holding a NodeJS.Timeout or null\n */\nexport function clearIntervalRef(intervalRef: Ref<Nullable<ReturnType<typeof setInterval>>>) {\n if (intervalRef.value) clearInterval(intervalRef.value);\n intervalRef.value = null;\n}\n\n/**\n * Clears a timeout referenced by a Vue ref and sets it to null.\n *\n * @param {Ref<Nullable<ReturnType<typeof setTimeout>>>} timeoutRef - A Vue ref holding a NodeJS.Timeout or null\n */\nexport function clearTimeoutRef(timeoutRef: Ref<Nullable<ReturnType<typeof setTimeout>>>) {\n if (timeoutRef.value) clearTimeout(timeoutRef.value);\n timeoutRef.value = null;\n}\n\n/**\n * A Vue composition function that remembers and restores scroll position\n * of a scrollable container across route changes and keep-alive activation.\n *\n * Designed for use with `<KeepAlive>` components. Scroll state is saved on\n * route leave and restored when the component is activated again.\n *\n * Note: Without `<KeepAlive>`, the component state is destroyed on unmount,\n * so scroll position will not be preserved.\n *\n * @template T - The type of the scrollable element (defaults to HTMLElement)\n *\n * @param {Ref<Nullable<T>>} containerRef - A ref to the scrollable HTML element\n */\nexport function usePreserveScroll<T extends Element = HTMLElement>(containerRef: Ref<Nullable<T>>) {\n let scrollLeft = 0;\n let scrollTop = 0;\n onActivated(() => {\n if (!containerRef.value) return;\n containerRef.value.scrollLeft = scrollLeft;\n containerRef.value.scrollTop = scrollTop;\n });\n\n onBeforeRouteLeave(() => {\n scrollLeft = containerRef.value?.scrollLeft || 0;\n scrollTop = containerRef.value?.scrollTop || 0;\n });\n}\n"],"mappings":";;;;;;;;;;;AAiBA,SAAgB,yCAAyC,KAAa;AAClE,QAAO,yBAAyB,KAAK,UAAU,CAAC,SAAS;;;;;;;AAQ7D,SAAgB,iBAAiB,aAA4D;AACzF,KAAI,YAAY,MAAO,eAAc,YAAY,MAAM;AACvD,aAAY,QAAQ;;;;;;;AAQxB,SAAgB,gBAAgB,YAA0D;AACtF,KAAI,WAAW,MAAO,cAAa,WAAW,MAAM;AACpD,YAAW,QAAQ;;;;;;;;;;;;;;;;AAiBvB,SAAgB,kBAAmD,cAAgC;CAC/F,IAAI,aAAa;CACjB,IAAI,YAAY;AAChB,mBAAkB;AACd,MAAI,CAAC,aAAa,MAAO;AACzB,eAAa,MAAM,aAAa;AAChC,eAAa,MAAM,YAAY;GACjC;AAEF,0BAAyB;AACrB,eAAa,aAAa,OAAO,cAAc;AAC/C,cAAY,aAAa,OAAO,aAAa;GAC/C"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kikiutils/shared",
3
3
  "type": "module",
4
- "version": "15.0.0",
4
+ "version": "15.0.2",
5
5
  "description": "A lightweight and modular utility library for modern JavaScript and TypeScript — includes secure hashing, flexible logging, datetime tools, Vue/web helpers, storage abstraction, and more.",
6
6
  "author": "kiki-kanri",
7
7
  "license": "MIT",
@@ -67,21 +67,21 @@
67
67
  "typecheck": "tsc -b --noEmit"
68
68
  },
69
69
  "peerDependencies": {
70
- "@noble/hashes": "^2.0.1",
70
+ "@noble/hashes": "^2.2.0",
71
71
  "@types/ssh2": "^1.15.5",
72
72
  "async-validator": "^4.2.5",
73
73
  "bson": "^7.2.0",
74
74
  "consola": "^3.4.2",
75
75
  "date-fns": "^4.1.0",
76
76
  "decimal.js": "^10.6.0",
77
- "element-plus": "^2.13.5",
78
- "lru-cache": "^11.2.6",
77
+ "element-plus": "^2.13.7",
78
+ "lru-cache": "^11.3.5",
79
79
  "millify": "^6.1.0",
80
- "msgpackr": "^1.11.8",
80
+ "msgpackr": "^1.11.9",
81
81
  "node-ssh": "^13.2.1",
82
82
  "pino": "^10.3.1",
83
83
  "pino-pretty": "^13.1.3",
84
- "vue": "^3.5.30",
84
+ "vue": "^3.5.32",
85
85
  "vue-router": ">= 4.6.4"
86
86
  },
87
87
  "peerDependenciesMeta": {
@@ -135,13 +135,13 @@
135
135
  }
136
136
  },
137
137
  "devDependencies": {
138
- "@antfu/eslint-config": "^7.7.0",
139
- "@kikiutils/eslint-config": "^7.0.2",
140
- "@kikiutils/tsconfigs": "^5.1.0",
141
- "@noble/hashes": "^2.0.1",
142
- "@types/node": "^25.4.0",
138
+ "@antfu/eslint-config": "^8.2.0",
139
+ "@kikiutils/eslint-config": "^9.0.1",
140
+ "@kikiutils/tsconfigs": "^6.0.0",
141
+ "@noble/hashes": "^2.2.0",
142
+ "@types/node": "^25.6.0",
143
143
  "@types/ssh2": "^1.15.5",
144
- "@vitest/coverage-v8": "^4.0.18",
144
+ "@vitest/coverage-v8": "^4.1.4",
145
145
  "async-validator": "^4.2.5",
146
146
  "bson": "^7.2.0",
147
147
  "changelogen": "^0.6.2",
@@ -149,22 +149,22 @@
149
149
  "cross-env": "^10.1.0",
150
150
  "date-fns": "^4.1.0",
151
151
  "decimal.js": "^10.6.0",
152
- "element-plus": "^2.13.5",
153
- "jsdom": "^28.1.0",
154
- "knip": "^5.86.0",
155
- "lru-cache": "^11.2.6",
152
+ "element-plus": "^2.13.7",
153
+ "jsdom": "^29.0.2",
154
+ "knip": "^6.5.0",
155
+ "lru-cache": "^11.3.5",
156
156
  "millify": "^6.1.0",
157
- "msgpackr": "^1.11.8",
157
+ "msgpackr": "^1.11.10",
158
158
  "node-ssh": "^13.2.1",
159
159
  "pino": "^10.3.1",
160
160
  "pino-pretty": "^13.1.3",
161
161
  "publint": "^0.3.18",
162
- "tsdown": "^0.21.1",
163
- "typescript": "^5.9.3",
162
+ "tsdown": "^0.21.9",
163
+ "typescript": "^6.0.3",
164
164
  "unplugin-unused": "^0.5.7",
165
- "vitest": "^4.0.18",
166
- "vue": "^3.5.30",
167
- "vue-router": "^5.0.3"
165
+ "vitest": "^4.1.4",
166
+ "vue": "^3.5.32",
167
+ "vue-router": "^5.0.4"
168
168
  },
169
169
  "pnpm": {
170
170
  "onlyBuiltDependencies": [
@@ -1,61 +1,190 @@
1
+ import { createHash } from 'node:crypto';
2
+ import type {
3
+ BinaryLike,
4
+ BinaryToTextEncoding,
5
+ } from 'node:crypto';
6
+
1
7
  /**
2
- * This file provides a set of functions for creating hash digests using different algorithms and bit lengths.
3
- * It includes functions for generating SHA-3 hash digests with bit lengths of 224, 256, 384, and 512,
4
- * as well as a function for generating MD5 hash digests.
8
+ * Computes the MD5 hash of the given data.
9
+ *
10
+ * @param {BinaryLike} data - The input data to hash
11
+ * @param {BinaryToTextEncoding} [outputEncoding] - The output encoding (default: `'hex'`)
5
12
  *
6
- * These functions use the Node.js crypto module to generate the hashes.
7
- * Can only be used in Node.js/Deno/Bun runtimes.
13
+ * @returns {string | Buffer} The hash digest in the specified encoding
8
14
  *
9
15
  * @example
10
16
  * ```typescript
11
- * import { cryptoSha3256 } from '@kikiutils/shared/crypto-hash';
17
+ * import { cryptoMd5 } from '@kikiutils/shared/crypto-hash';
12
18
  *
13
- * console.log(cryptoSha3256('test')); // 36f028580bb02cc8272a9a020f4200e346e276ae664e45ee80745574e2f5ab80
19
+ * console.log(cryptoMd5('test')); // 33ed9a05a10b21f0...
14
20
  * ```
15
21
  */
16
-
17
- import { createHash } from 'node:crypto';
18
- import type {
19
- BinaryLike,
20
- BinaryToTextEncoding,
21
- } from 'node:crypto';
22
-
23
22
  export function cryptoMd5(data: BinaryLike, outputEncoding: BinaryToTextEncoding = 'hex') {
24
23
  return createHash('md5').update(data).digest(outputEncoding);
25
24
  }
26
25
 
26
+ /**
27
+ * Computes the MD5 hash of the given data and returns the raw buffer.
28
+ *
29
+ * @param {BinaryLike} data - The input data to hash
30
+ *
31
+ * @returns {Buffer} The raw hash digest as a Buffer
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * import { cryptoMd5ToBuffer } from '@kikiutils/shared/crypto-hash';
36
+ *
37
+ * console.log(cryptoMd5ToBuffer('test')); // <Buffer 33 ed 9a ...>
38
+ * ```
39
+ */
27
40
  export function cryptoMd5ToBuffer(data: BinaryLike) {
28
41
  return createHash('md5').update(data).digest();
29
42
  }
30
43
 
44
+ /**
45
+ * Computes the SHA-3 hash of the given data using the 224-bit digest.
46
+ *
47
+ * @param {BinaryLike} data - The input data to hash
48
+ * @param {BinaryToTextEncoding} [outputEncoding] - The output encoding (default: `'hex'`)
49
+ *
50
+ * @returns {string | Buffer} The hash digest in the specified encoding
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * import { cryptoSha3224 } from '@kikiutils/shared/crypto-hash';
55
+ *
56
+ * console.log(cryptoSha3224('test')); // 0qW8FoqDcFmkpuqR9J3uT8YX...
57
+ * ```
58
+ */
31
59
  export function cryptoSha3224(data: BinaryLike, outputEncoding: BinaryToTextEncoding = 'hex') {
32
60
  return createHash('sha3-224').update(data).digest(outputEncoding);
33
61
  }
34
62
 
63
+ /**
64
+ * Computes the SHA-3 hash of the given data using the 224-bit digest and returns the raw buffer.
65
+ *
66
+ * @param {BinaryLike} data - The input data to hash
67
+ *
68
+ * @returns {Buffer} The raw hash digest as a Buffer
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * import { cryptoSha3224ToBuffer } from '@kikiutils/shared/crypto-hash';
73
+ *
74
+ * console.log(cryptoSha3224ToBuffer('test')); // <Buffer 0q W8 Fo ...>
75
+ * ```
76
+ */
35
77
  export function cryptoSha3224ToBuffer(data: BinaryLike) {
36
78
  return createHash('sha3-224').update(data).digest();
37
79
  }
38
80
 
81
+ /**
82
+ * Computes the SHA-3 hash of the given data using the 256-bit digest.
83
+ *
84
+ * @param {BinaryLike} data - The input data to hash
85
+ * @param {BinaryToTextEncoding} [outputEncoding] - The output encoding (default: `'hex'`)
86
+ *
87
+ * @returns {string | Buffer} The hash digest in the specified encoding
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * import { cryptoSha3256 } from '@kikiutils/shared/crypto-hash';
92
+ *
93
+ * console.log(cryptoSha3256('test')); // 36f028580bb02cc8272a9a020f4200e346e276ae664e45ee80745574e2f5ab80
94
+ * ```
95
+ */
39
96
  export function cryptoSha3256(data: BinaryLike, outputEncoding: BinaryToTextEncoding = 'hex') {
40
97
  return createHash('sha3-256').update(data).digest(outputEncoding);
41
98
  }
42
99
 
100
+ /**
101
+ * Computes the SHA-3 hash of the given data using the 256-bit digest and returns the raw buffer.
102
+ *
103
+ * @param {BinaryLike} data - The input data to hash
104
+ *
105
+ * @returns {Buffer} The raw hash digest as a Buffer
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * import { cryptoSha3256ToBuffer } from '@kikiutils/shared/crypto-hash';
110
+ *
111
+ * console.log(cryptoSha3256ToBuffer('test')); // <Buffer 36 f0 28 ...>
112
+ * ```
113
+ */
43
114
  export function cryptoSha3256ToBuffer(data: BinaryLike) {
44
115
  return createHash('sha3-256').update(data).digest();
45
116
  }
46
117
 
118
+ /**
119
+ * Computes the SHA-3 hash of the given data using the 384-bit digest.
120
+ *
121
+ * @param {BinaryLike} data - The input data to hash
122
+ * @param {BinaryToTextEncoding} [outputEncoding] - The output encoding (default: `'hex'`)
123
+ *
124
+ * @returns {string | Buffer} The hash digest in the specified encoding
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * import { cryptoSha3384 } from '@kikiutils/shared/crypto-hash';
129
+ *
130
+ * console.log(cryptoSha3384('test')); // 1Q2wQAYaZ4o8vWX5bEB2n3Y...
131
+ * ```
132
+ */
47
133
  export function cryptoSha3384(data: BinaryLike, outputEncoding: BinaryToTextEncoding = 'hex') {
48
134
  return createHash('sha3-384').update(data).digest(outputEncoding);
49
135
  }
50
136
 
137
+ /**
138
+ * Computes the SHA-3 hash of the given data using the 384-bit digest and returns the raw buffer.
139
+ *
140
+ * @param {BinaryLike} data - The input data to hash
141
+ *
142
+ * @returns {Buffer} The raw hash digest as a Buffer
143
+ *
144
+ * @example
145
+ * ```typescript
146
+ * import { cryptoSha3384ToBuffer } from '@kikiutils/shared/crypto-hash';
147
+ *
148
+ * console.log(cryptoSha3384ToBuffer('test')); // <Buffer 1Q 2w QZ ...>
149
+ * ```
150
+ */
51
151
  export function cryptoSha3384ToBuffer(data: BinaryLike) {
52
152
  return createHash('sha3-384').update(data).digest();
53
153
  }
54
154
 
155
+ /**
156
+ * Computes the SHA-3 hash of the given data using the 512-bit digest.
157
+ *
158
+ * @param {BinaryLike} data - The input data to hash
159
+ * @param {BinaryToTextEncoding} [outputEncoding] - The output encoding (default: `'hex'`)
160
+ *
161
+ * @returns {string | Buffer} The hash digest in the specified encoding
162
+ *
163
+ * @example
164
+ * ```typescript
165
+ * import { cryptoSha3512 } from '@kikiutils/shared/crypto-hash';
166
+ *
167
+ * console.log(cryptoSha3512('test')); // b_NQJ8FJBY9dIjm1q7...
168
+ * ```
169
+ */
55
170
  export function cryptoSha3512(data: BinaryLike, outputEncoding: BinaryToTextEncoding = 'hex') {
56
171
  return createHash('sha3-512').update(data).digest(outputEncoding);
57
172
  }
58
173
 
174
+ /**
175
+ * Computes the SHA-3 hash of the given data using the 512-bit digest and returns the raw buffer.
176
+ *
177
+ * @param {BinaryLike} data - The input data to hash
178
+ *
179
+ * @returns {Buffer} The raw hash digest as a Buffer
180
+ *
181
+ * @example
182
+ * ```typescript
183
+ * import { cryptoSha3512ToBuffer } from '@kikiutils/shared/crypto-hash';
184
+ *
185
+ * console.log(cryptoSha3512ToBuffer('test')); // <Buffer b_ NQ ...>
186
+ * ```
187
+ */
59
188
  export function cryptoSha3512ToBuffer(data: BinaryLike) {
60
189
  return createHash('sha3-512').update(data).digest();
61
190
  }
package/src/datetime.ts CHANGED
@@ -42,8 +42,6 @@ export type DateRangeType = 'lastMonth' | 'lastWeek' | 'thisMonth' | 'thisWeek'
42
42
  * // Format a date string
43
43
  * console.log(formatDate('2024-07-10T00:00:00Z', 'yyyy-MM-dd')); // 2024-07-10
44
44
  * ```
45
- *
46
- * @see https://date-fns.org/docs/format
47
45
  */
48
46
  export function formatDate(date: DateArg<Date> & {}, format: string = 'yyyy-MM-dd HH:mm:ss', options?: FormatOptions) {
49
47
  return dateFnsFormat(date, format, options);
package/src/env.ts CHANGED
@@ -35,6 +35,8 @@ export class EnvironmentNotFoundError extends Error {
35
35
  *
36
36
  * @example
37
37
  * ```typescript
38
+ * import { checkAndGetEnvValue } from '@kikiutils/shared/env';
39
+ *
38
40
  * process.env.API_KEY = '';
39
41
  * checkAndGetEnvValue('API_KEY'); // ✅ Returns '' (still considered "defined")
40
42
  *
@@ -82,7 +82,7 @@ export class EventAwaiter<T> {
82
82
 
83
83
  resolvers.push(resolve);
84
84
  this.#promiseResolvers.set(key, resolvers);
85
- if (timeoutMs) {
85
+ if (timeoutMs != null) {
86
86
  setTimeout(
87
87
  () => {
88
88
  const resolvers = this.#promiseResolvers.get(key);