@kikiutils/shared 18.0.1 → 18.2.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 +457 -0
  6. package/dist/classes/enhanced-date.d.ts.map +1 -0
  7. package/dist/classes/enhanced-date.js +635 -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 +188 -54
  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 +13 -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 +26 -21
  103. package/dist/time.d.ts.map +1 -1
  104. package/dist/time.js +24 -18
  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 +21 -21
  125. package/src/buffer.ts +18 -19
  126. package/src/classes/enhanced-date.ts +715 -0
  127. package/src/classes/path.ts +248 -96
  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 +24 -18
  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
package/dist/object.js CHANGED
@@ -2,6 +2,7 @@
2
2
  /**
3
3
  * Serializes a nested object into a deterministic, flat string format.
4
4
  *
5
+ * @remarks
5
6
  * This function recursively traverses the input object (including nested objects and arrays),
6
7
  * flattens it into key paths using dot notation (e.g. "a.b.0.c"), sorts all keys,
7
8
  * and joins each key-value pair into a string with customizable separators.
@@ -12,18 +13,30 @@
12
13
  * Note: Empty objects and arrays produce an empty string, which is useful for
13
14
  * generating deterministic signature payloads.
14
15
  *
15
- * @param {Record<string, any>} input - The object to serialize. Can contain nested objects and arrays
16
- * @param {string} kvSeparator - The string used to separate each key from its value (default: '=')
17
- * @param {string} pairSeparator - The string used to separate each key-value pair (default: '&')
18
- * @returns {string} A deterministic string representation of the input object
16
+ * @param input - The object to serialize. Can contain nested objects and arrays.
17
+ * @param kvSeparator - The string used to separate each key from its value (default: '=').
18
+ * @param pairSeparator - The string used to separate each key-value pair (default: '&').
19
+ *
20
+ * @returns A deterministic string representation of the input object.
19
21
  *
20
22
  * @example
21
- * ```typescript
23
+ *
24
+ * ```ts
22
25
  * import { stringifyObjectDeterministically } from '@kikiutils/shared/object';
23
26
  *
24
- * console.log(stringifyObjectDeterministically({ b: 2, a: { x: 1, y: [3, 4] } })); // a.x=1&a.y.0=3&a.y.1=4&b=2
25
- * console.log(stringifyObjectDeterministically({ foo: 'bar' }, ':', '|')); // foo:bar
26
- * console.log(stringifyObjectDeterministically({})); // ''
27
+ * console.log(stringifyObjectDeterministically({
28
+ * b: 2,
29
+ * a: {
30
+ * x: 1,
31
+ * y: [
32
+ * 3,
33
+ * 4,
34
+ * ],
35
+ * },
36
+ * })); // => a.x=1&a.y.0=3&a.y.1=4&b=2
37
+ *
38
+ * console.log(stringifyObjectDeterministically({ foo: 'bar' }, ':', '|')); // => foo:bar
39
+ * console.log(stringifyObjectDeterministically({})); // => ''
27
40
  * ```
28
41
  */
29
42
  function stringifyObjectDeterministically(input, kvSeparator = "=", pairSeparator = "&") {
@@ -1 +1 @@
1
- {"version":3,"file":"object.js","names":[],"sources":["../src/object.ts"],"sourcesContent":["/**\n * Serializes a nested object into a deterministic, flat string format.\n *\n * This function recursively traverses the input object (including nested objects and arrays),\n * flattens it into key paths using dot notation (e.g. \"a.b.0.c\"), sorts all keys,\n * and joins each key-value pair into a string with customizable separators.\n *\n * It is designed for use cases such as signature generation, cache key construction,\n * or any context requiring consistent and predictable object serialization.\n *\n * Note: Empty objects and arrays produce an empty string, which is useful for\n * generating deterministic signature payloads.\n *\n * @param {Record<string, any>} input - The object to serialize. Can contain nested objects and arrays\n * @param {string} kvSeparator - The string used to separate each key from its value (default: '=')\n * @param {string} pairSeparator - The string used to separate each key-value pair (default: '&')\n * @returns {string} A deterministic string representation of the input object\n *\n * @example\n * ```typescript\n * import { stringifyObjectDeterministically } from '@kikiutils/shared/object';\n *\n * console.log(stringifyObjectDeterministically({ b: 2, a: { x: 1, y: [3, 4] } })); // a.x=1&a.y.0=3&a.y.1=4&b=2\n * console.log(stringifyObjectDeterministically({ foo: 'bar' }, ':', '|')); // foo:bar\n * console.log(stringifyObjectDeterministically({})); // ''\n * ```\n */\nexport function stringifyObjectDeterministically(\n input: Record<string, any>,\n kvSeparator: string = '=',\n pairSeparator: string = '&',\n) {\n const entries: string[] = [];\n\n function walk(object: any, path: string[] = []) {\n if (Array.isArray(object)) {\n object.forEach((value, i) => {\n walk(\n value,\n [\n ...path,\n i.toString(),\n ],\n );\n });\n } else if (\n object !== null\n && typeof object === 'object'\n && Object.prototype.toString.call(object) === '[object Object]'\n ) {\n Object.keys(object).sort().forEach((key) => {\n walk(\n object[key],\n [\n ...path,\n key,\n ],\n );\n });\n } else entries.push(`${path.join('.')}${kvSeparator}${String(object)}`);\n }\n\n walk(input);\n return entries.sort().join(pairSeparator);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,SAAgB,iCACZ,OACA,cAAsB,KACtB,gBAAwB,KAC1B;CACE,MAAM,UAAoB,CAAC;CAE3B,SAAS,KAAK,QAAa,OAAiB,CAAC,GAAG;EAC5C,IAAI,MAAM,QAAQ,MAAM,GACpB,OAAO,SAAS,OAAO,MAAM;GACzB,KACI,OACA,CACI,GAAG,MACH,EAAE,SAAS,CACf,CACJ;EACJ,CAAC;OACE,IACH,WAAW,QACR,OAAO,WAAW,YAClB,OAAO,UAAU,SAAS,KAAK,MAAM,MAAM,mBAE9C,OAAO,KAAK,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,QAAQ;GACxC,KACI,OAAO,MACP,CACI,GAAG,MACH,GACJ,CACJ;EACJ,CAAC;OACE,QAAQ,KAAK,GAAG,KAAK,KAAK,GAAG,IAAI,cAAc,OAAO,MAAM,GAAG;CAC1E;CAEA,KAAK,KAAK;CACV,OAAO,QAAQ,KAAK,CAAC,CAAC,KAAK,aAAa;AAC5C"}
1
+ {"version":3,"file":"object.js","names":[],"sources":["../src/object.ts"],"sourcesContent":["/**\n * Serializes a nested object into a deterministic, flat string format.\n *\n * @remarks\n * This function recursively traverses the input object (including nested objects and arrays),\n * flattens it into key paths using dot notation (e.g. \"a.b.0.c\"), sorts all keys,\n * and joins each key-value pair into a string with customizable separators.\n *\n * It is designed for use cases such as signature generation, cache key construction,\n * or any context requiring consistent and predictable object serialization.\n *\n * Note: Empty objects and arrays produce an empty string, which is useful for\n * generating deterministic signature payloads.\n *\n * @param input - The object to serialize. Can contain nested objects and arrays.\n * @param kvSeparator - The string used to separate each key from its value (default: '=').\n * @param pairSeparator - The string used to separate each key-value pair (default: '&').\n *\n * @returns A deterministic string representation of the input object.\n *\n * @example\n *\n * ```ts\n * import { stringifyObjectDeterministically } from '@kikiutils/shared/object';\n *\n * console.log(stringifyObjectDeterministically({\n * b: 2,\n * a: {\n * x: 1,\n * y: [\n * 3,\n * 4,\n * ],\n * },\n * })); // => a.x=1&a.y.0=3&a.y.1=4&b=2\n *\n * console.log(stringifyObjectDeterministically({ foo: 'bar' }, ':', '|')); // => foo:bar\n * console.log(stringifyObjectDeterministically({})); // => ''\n * ```\n */\nexport function stringifyObjectDeterministically(\n input: Record<string, any>,\n kvSeparator: string = '=',\n pairSeparator: string = '&',\n) {\n const entries: string[] = [];\n\n function walk(object: any, path: string[] = []) {\n if (Array.isArray(object)) {\n object.forEach((value, i) => {\n walk(\n value,\n [\n ...path,\n i.toString(),\n ],\n );\n });\n } else if (\n object !== null\n && typeof object === 'object'\n && Object.prototype.toString.call(object) === '[object Object]'\n ) {\n Object.keys(object).sort().forEach((key) => {\n walk(\n object[key],\n [\n ...path,\n key,\n ],\n );\n });\n } else entries.push(`${path.join('.')}${kvSeparator}${String(object)}`);\n }\n\n walk(input);\n return entries.sort().join(pairSeparator);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,SAAgB,iCACZ,OACA,cAAsB,KACtB,gBAAwB,KAC1B;CACE,MAAM,UAAoB,CAAC;CAE3B,SAAS,KAAK,QAAa,OAAiB,CAAC,GAAG;EAC5C,IAAI,MAAM,QAAQ,MAAM,GACpB,OAAO,SAAS,OAAO,MAAM;GACzB,KACI,OACA,CACI,GAAG,MACH,EAAE,SAAS,CACf,CACJ;EACJ,CAAC;OACE,IACH,WAAW,QACR,OAAO,WAAW,YAClB,OAAO,UAAU,SAAS,KAAK,MAAM,MAAM,mBAE9C,OAAO,KAAK,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,QAAQ;GACxC,KACI,OAAO,MACP,CACI,GAAG,MACH,GACJ,CACJ;EACJ,CAAC;OACE,QAAQ,KAAK,GAAG,KAAK,KAAK,GAAG,IAAI,cAAc,OAAO,MAAM,GAAG;CAC1E;CAEA,KAAK,KAAK;CACV,OAAO,QAAQ,KAAK,CAAC,CAAC,KAAK,aAAa;AAC5C"}
package/dist/pino.d.ts CHANGED
@@ -1,27 +1,25 @@
1
+ import { pino } from "pino";
1
2
  //#region src/pino.d.ts
2
3
  /**
3
- * A pino logger instance with the configured stream.
4
+ * A pino logger with environment-controlled verbosity.
4
5
  *
5
- * The logger's level is determined based on the `PINO_LOGGER_LEVEL` and `NODE_ENV` environment variables.
6
- * If `PINO_LOGGER_LEVEL` is set, it will be used; otherwise, if `NODE_ENV` is `production`,
7
- * the level will be set to `error`.
8
- *
9
- * To manually change the level, assign the desired level to `logger.level`.
10
- *
11
- * See available levels [here](https://getpino.io/#/docs/api?id=level-string).
6
+ * @remarks
7
+ * `PINO_LOGGER_LEVEL` sets the log level when nonempty at module initialization;
8
+ * otherwise, `NODE_ENV=production` selects `error`, and other environments retain the logger's default level.
9
+ * Assign `logger.level` to change verbosity after initialization.
12
10
  *
13
11
  * @example
14
- * ```typescript
15
- * import { logger } from '@kikiutils/shared/pino';
16
12
  *
17
- * logger.info('test'); // [2024-07-11 12:12:30.085] INFO: test
13
+ * ```ts
14
+ * import { logger } from '@kikiutils/shared/pino';
18
15
  *
19
- * // Manually change the level
20
16
  * logger.level = 'info';
17
+ * logger.info('Application started');
21
18
  * ```
19
+ *
20
+ * @see {@link https://getpino.io/#/docs/api?id=level-string | Pino log levels}
22
21
  */
23
- declare const pinoLogger: import("pino").Logger<never, boolean>;
24
- declare const logger: import("pino").Logger<never, boolean>;
22
+ export declare const pinoLogger: pino.Logger<never, boolean>;
23
+ export declare const logger: pino.Logger<never, boolean>;
25
24
  //#endregion
26
- export { logger, pinoLogger };
27
25
  //# sourceMappingURL=pino.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pino.d.ts","names":[],"sources":["../src/pino.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;cAiCa,2BAAU;cACV,uBAAM"}
1
+ {"version":3,"file":"pino.d.ts","names":[],"sources":["../src/pino.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;qBA6Ba,YAAU,KAAA;qBACV,QAAM,KAAA"}
package/dist/pino.js CHANGED
@@ -1,34 +1,29 @@
1
1
  import { pino } from "pino";
2
2
  import { PinoPretty } from "pino-pretty";
3
3
  //#region src/pino.ts
4
- /**
5
- * Configure pinoPretty to enhance the log output.
6
- */
7
4
  const stream = PinoPretty({
8
5
  colorize: true,
9
6
  ignore: "hostname,pid",
10
7
  translateTime: "SYS:yyyy-mm-dd HH:MM:ss.l"
11
8
  });
12
9
  /**
13
- * A pino logger instance with the configured stream.
14
- *
15
- * The logger's level is determined based on the `PINO_LOGGER_LEVEL` and `NODE_ENV` environment variables.
16
- * If `PINO_LOGGER_LEVEL` is set, it will be used; otherwise, if `NODE_ENV` is `production`,
17
- * the level will be set to `error`.
18
- *
19
- * To manually change the level, assign the desired level to `logger.level`.
10
+ * A pino logger with environment-controlled verbosity.
20
11
  *
21
- * See available levels [here](https://getpino.io/#/docs/api?id=level-string).
12
+ * @remarks
13
+ * `PINO_LOGGER_LEVEL` sets the log level when nonempty at module initialization;
14
+ * otherwise, `NODE_ENV=production` selects `error`, and other environments retain the logger's default level.
15
+ * Assign `logger.level` to change verbosity after initialization.
22
16
  *
23
17
  * @example
24
- * ```typescript
25
- * import { logger } from '@kikiutils/shared/pino';
26
18
  *
27
- * logger.info('test'); // [2024-07-11 12:12:30.085] INFO: test
19
+ * ```ts
20
+ * import { logger } from '@kikiutils/shared/pino';
28
21
  *
29
- * // Manually change the level
30
22
  * logger.level = 'info';
23
+ * logger.info('Application started');
31
24
  * ```
25
+ *
26
+ * @see {@link https://getpino.io/#/docs/api?id=level-string | Pino log levels}
32
27
  */
33
28
  const pinoLogger = pino({}, stream);
34
29
  const logger = pinoLogger;
package/dist/pino.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"pino.js","names":[],"sources":["../src/pino.ts"],"sourcesContent":["import { pino } from 'pino';\nimport { PinoPretty } from 'pino-pretty';\n\n/**\n * Configure pinoPretty to enhance the log output.\n */\nconst stream = PinoPretty({\n colorize: true, // Enable colored output for better readability\n ignore: 'hostname,pid', // Exclude 'hostname' and 'pid' fields from the logs\n translateTime: 'SYS:yyyy-mm-dd HH:MM:ss.l', // Format the timestamp in 'yyyy-mm-dd HH:MM:ss.l' format\n});\n\n/**\n * A pino logger instance with the configured stream.\n *\n * The logger's level is determined based on the `PINO_LOGGER_LEVEL` and `NODE_ENV` environment variables.\n * If `PINO_LOGGER_LEVEL` is set, it will be used; otherwise, if `NODE_ENV` is `production`,\n * the level will be set to `error`.\n *\n * To manually change the level, assign the desired level to `logger.level`.\n *\n * See available levels [here](https://getpino.io/#/docs/api?id=level-string).\n *\n * @example\n * ```typescript\n * import { logger } from '@kikiutils/shared/pino';\n *\n * logger.info('test'); // [2024-07-11 12:12:30.085] INFO: test\n *\n * // Manually change the level\n * logger.level = 'info';\n * ```\n */\nexport const pinoLogger = pino({}, stream);\nexport const logger = pinoLogger;\n// eslint-disable-next-line style/max-len\npinoLogger.level = process.env.PINO_LOGGER_LEVEL || (process.env.NODE_ENV === 'production' ? 'error' : pinoLogger.level);\n"],"mappings":";;;;;;AAMA,MAAM,SAAS,WAAW;CACtB,UAAU;CACV,QAAQ;CACR,eAAe;AACnB,CAAC;;;;;;;;;;;;;;;;;;;;;;AAuBD,MAAa,aAAa,KAAK,CAAC,GAAG,MAAM;AACzC,MAAa,SAAS;AAEtB,WAAW,QAAQ,QAAQ,IAAI,sBAAsB,QAAQ,IAAI,aAAa,eAAe,UAAU,WAAW"}
1
+ {"version":3,"file":"pino.js","names":[],"sources":["../src/pino.ts"],"sourcesContent":["import { pino } from 'pino';\nimport { PinoPretty } from 'pino-pretty';\n\n// Configure pretty-printed log output.\nconst stream = PinoPretty({\n colorize: true, // Enable colored output for better readability\n ignore: 'hostname,pid', // Exclude 'hostname' and 'pid' fields from the logs\n translateTime: 'SYS:yyyy-mm-dd HH:MM:ss.l', // Format the timestamp in 'yyyy-mm-dd HH:MM:ss.l' format\n});\n\n/**\n * A pino logger with environment-controlled verbosity.\n *\n * @remarks\n * `PINO_LOGGER_LEVEL` sets the log level when nonempty at module initialization;\n * otherwise, `NODE_ENV=production` selects `error`, and other environments retain the logger's default level.\n * Assign `logger.level` to change verbosity after initialization.\n *\n * @example\n *\n * ```ts\n * import { logger } from '@kikiutils/shared/pino';\n *\n * logger.level = 'info';\n * logger.info('Application started');\n * ```\n *\n * @see {@link https://getpino.io/#/docs/api?id=level-string | Pino log levels}\n */\nexport const pinoLogger = pino({}, stream);\nexport const logger = pinoLogger;\n// eslint-disable-next-line style/max-len\npinoLogger.level = process.env.PINO_LOGGER_LEVEL || (process.env.NODE_ENV === 'production' ? 'error' : pinoLogger.level);\n"],"mappings":";;;AAIA,MAAM,SAAS,WAAW;CACtB,UAAU;CACV,QAAQ;CACR,eAAe;AACnB,CAAC;;;;;;;;;;;;;;;;;;;;AAqBD,MAAa,aAAa,KAAK,CAAC,GAAG,MAAM;AACzC,MAAa,SAAS;AAEtB,WAAW,QAAQ,QAAQ,IAAI,sBAAsB,QAAQ,IAAI,aAAa,eAAe,UAAU,WAAW"}
package/dist/random.d.ts CHANGED
@@ -1,25 +1,27 @@
1
1
  //#region src/random.d.ts
2
2
  /**
3
- * Generates a value using a provided generator function, where the input length
4
- * is determined by two levels of nested random ranges:
3
+ * Calls a generator once with a length sampled from two nested random ranges.
5
4
  *
6
- * 1. First, a random number (`innerMin`) is chosen between `minMin` and `minMax`.
7
- * 2. Then, a final length is chosen between `Math.max(innerMin, maxMin)` and `maxMax`.
8
- * 3. The generator is called with the final length and its result is returned.
5
+ * @remarks
6
+ * Integer bounds are inclusive. First, a lower bound is sampled between `minMin` and `minMax`;
7
+ * the final length is sampled between the larger of that value and `maxMin`, and `maxMax`.
8
+ * Inputs must be finite integers and `minMax` must not exceed `maxMax` for valid nested ranges;
9
+ * these requirements are not checked beyond the two individual bound-order checks.
10
+ * The callback is called synchronously once after sampling. Its return value, including a promise,
11
+ * is returned unchanged, and any synchronous exception propagates.
9
12
  *
10
- * This function supports any return type by using a generic type parameter.
13
+ * @typeParam T - The generator's return value, preserved without awaiting or copying.
11
14
  *
12
- * @template T - The return type of the generator function
15
+ * @param generator - The callback that receives the sampled length.
16
+ * @param minMin - The inclusive lower bound for the first sample.
17
+ * @param minMax - The inclusive upper bound for the first sample.
18
+ * @param maxMin - The minimum inclusive lower bound for the final sample.
19
+ * @param maxMax - The inclusive upper bound for the final sample.
13
20
  *
14
- * @param {(length: number) => T} generator - A function that accepts a length and returns a value of type T
15
- * @param {number} minMin - Lower bound of the first random range
16
- * @param {number} minMax - Upper bound of the first random range
17
- * @param {number} maxMin - Lower bound of the second random range
18
- * @param {number} maxMax - Upper bound of the second random range
21
+ * @returns The generator's result for the sampled length.
19
22
  *
20
- * @returns {T} The result of the generator function using the computed final length
23
+ * @throws Error if `minMin` exceeds `minMax` or `maxMin` exceeds `maxMax`.
21
24
  */
22
- declare function generateWithNestedRandomLength<T = string>(generator: (length: number) => T, minMin: number, minMax: number, maxMin: number, maxMax: number): T;
25
+ export declare function generateWithNestedRandomLength<T = string>(generator: (length: number) => T, minMin: number, minMax: number, maxMin: number, maxMax: number): T;
23
26
  //#endregion
24
- export { generateWithNestedRandomLength };
25
27
  //# sourceMappingURL=random.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"random.d.ts","names":[],"sources":["../src/random.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;iBAoBgB,+BAA+B,YAC3C,YAAY,mBAAmB,GAC/B,gBACA,gBACA,gBACA,iBAAc"}
1
+ {"version":3,"file":"random.d.ts","names":[],"sources":["../src/random.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;wBAuBgB,+BAA+B,YAC3C,YAAY,mBAAmB,GAC/B,gBACA,gBACA,gBACA,iBAAc"}
package/dist/random.js CHANGED
@@ -1,23 +1,26 @@
1
1
  //#region src/random.ts
2
2
  /**
3
- * Generates a value using a provided generator function, where the input length
4
- * is determined by two levels of nested random ranges:
3
+ * Calls a generator once with a length sampled from two nested random ranges.
5
4
  *
6
- * 1. First, a random number (`innerMin`) is chosen between `minMin` and `minMax`.
7
- * 2. Then, a final length is chosen between `Math.max(innerMin, maxMin)` and `maxMax`.
8
- * 3. The generator is called with the final length and its result is returned.
5
+ * @remarks
6
+ * Integer bounds are inclusive. First, a lower bound is sampled between `minMin` and `minMax`;
7
+ * the final length is sampled between the larger of that value and `maxMin`, and `maxMax`.
8
+ * Inputs must be finite integers and `minMax` must not exceed `maxMax` for valid nested ranges;
9
+ * these requirements are not checked beyond the two individual bound-order checks.
10
+ * The callback is called synchronously once after sampling. Its return value, including a promise,
11
+ * is returned unchanged, and any synchronous exception propagates.
9
12
  *
10
- * This function supports any return type by using a generic type parameter.
13
+ * @typeParam T - The generator's return value, preserved without awaiting or copying.
11
14
  *
12
- * @template T - The return type of the generator function
15
+ * @param generator - The callback that receives the sampled length.
16
+ * @param minMin - The inclusive lower bound for the first sample.
17
+ * @param minMax - The inclusive upper bound for the first sample.
18
+ * @param maxMin - The minimum inclusive lower bound for the final sample.
19
+ * @param maxMax - The inclusive upper bound for the final sample.
13
20
  *
14
- * @param {(length: number) => T} generator - A function that accepts a length and returns a value of type T
15
- * @param {number} minMin - Lower bound of the first random range
16
- * @param {number} minMax - Upper bound of the first random range
17
- * @param {number} maxMin - Lower bound of the second random range
18
- * @param {number} maxMax - Upper bound of the second random range
21
+ * @returns The generator's result for the sampled length.
19
22
  *
20
- * @returns {T} The result of the generator function using the computed final length
23
+ * @throws Error if `minMin` exceeds `minMax` or `maxMin` exceeds `maxMax`.
21
24
  */
22
25
  function generateWithNestedRandomLength(generator, minMin, minMax, maxMin, maxMax) {
23
26
  if (minMin > minMax) throw new Error(`Invalid range: minMin (${minMin}) cannot be greater than minMax (${minMax})`);
@@ -1 +1 @@
1
- {"version":3,"file":"random.js","names":[],"sources":["../src/random.ts"],"sourcesContent":["/**\n * Generates a value using a provided generator function, where the input length\n * is determined by two levels of nested random ranges:\n *\n * 1. First, a random number (`innerMin`) is chosen between `minMin` and `minMax`.\n * 2. Then, a final length is chosen between `Math.max(innerMin, maxMin)` and `maxMax`.\n * 3. The generator is called with the final length and its result is returned.\n *\n * This function supports any return type by using a generic type parameter.\n *\n * @template T - The return type of the generator function\n *\n * @param {(length: number) => T} generator - A function that accepts a length and returns a value of type T\n * @param {number} minMin - Lower bound of the first random range\n * @param {number} minMax - Upper bound of the first random range\n * @param {number} maxMin - Lower bound of the second random range\n * @param {number} maxMax - Upper bound of the second random range\n *\n * @returns {T} The result of the generator function using the computed final length\n */\nexport function generateWithNestedRandomLength<T = string>(\n generator: (length: number) => T,\n minMin: number,\n minMax: number,\n maxMin: number,\n maxMax: number,\n) {\n if (minMin > minMax) throw new Error(`Invalid range: minMin (${minMin}) cannot be greater than minMax (${minMax})`);\n if (maxMin > maxMax) throw new Error(`Invalid range: maxMin (${maxMin}) cannot be greater than maxMax (${maxMax})`);\n\n const random = (min: number, max: number) => Math.floor(Math.random() * (max - min + 1)) + min;\n const innerMin = random(minMin, minMax);\n const finalLength = random(Math.max(innerMin, maxMin), maxMax);\n return generator(finalLength);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,+BACZ,WACA,QACA,QACA,QACA,QACF;CACE,IAAI,SAAS,QAAQ,MAAM,IAAI,MAAM,0BAA0B,OAAO,mCAAmC,OAAO,EAAE;CAClH,IAAI,SAAS,QAAQ,MAAM,IAAI,MAAM,0BAA0B,OAAO,mCAAmC,OAAO,EAAE;CAElH,MAAM,UAAU,KAAa,QAAgB,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,MAAM,EAAE,IAAI;CAC3F,MAAM,WAAW,OAAO,QAAQ,MAAM;CAEtC,OAAO,UADa,OAAO,KAAK,IAAI,UAAU,MAAM,GAAG,MAC5B,CAAC;AAChC"}
1
+ {"version":3,"file":"random.js","names":[],"sources":["../src/random.ts"],"sourcesContent":["/**\n * Calls a generator once with a length sampled from two nested random ranges.\n *\n * @remarks\n * Integer bounds are inclusive. First, a lower bound is sampled between `minMin` and `minMax`;\n * the final length is sampled between the larger of that value and `maxMin`, and `maxMax`.\n * Inputs must be finite integers and `minMax` must not exceed `maxMax` for valid nested ranges;\n * these requirements are not checked beyond the two individual bound-order checks.\n * The callback is called synchronously once after sampling. Its return value, including a promise,\n * is returned unchanged, and any synchronous exception propagates.\n *\n * @typeParam T - The generator's return value, preserved without awaiting or copying.\n *\n * @param generator - The callback that receives the sampled length.\n * @param minMin - The inclusive lower bound for the first sample.\n * @param minMax - The inclusive upper bound for the first sample.\n * @param maxMin - The minimum inclusive lower bound for the final sample.\n * @param maxMax - The inclusive upper bound for the final sample.\n *\n * @returns The generator's result for the sampled length.\n *\n * @throws Error if `minMin` exceeds `minMax` or `maxMin` exceeds `maxMax`.\n */\nexport function generateWithNestedRandomLength<T = string>(\n generator: (length: number) => T,\n minMin: number,\n minMax: number,\n maxMin: number,\n maxMax: number,\n) {\n if (minMin > minMax) throw new Error(`Invalid range: minMin (${minMin}) cannot be greater than minMax (${minMax})`);\n if (maxMin > maxMax) throw new Error(`Invalid range: maxMin (${maxMin}) cannot be greater than maxMax (${maxMax})`);\n\n const random = (min: number, max: number) => Math.floor(Math.random() * (max - min + 1)) + min;\n const innerMin = random(minMin, minMax);\n const finalLength = random(Math.max(innerMin, maxMin), maxMax);\n return generator(finalLength);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,+BACZ,WACA,QACA,QACA,QACA,QACF;CACE,IAAI,SAAS,QAAQ,MAAM,IAAI,MAAM,0BAA0B,OAAO,mCAAmC,OAAO,EAAE;CAClH,IAAI,SAAS,QAAQ,MAAM,IAAI,MAAM,0BAA0B,OAAO,mCAAmC,OAAO,EAAE;CAElH,MAAM,UAAU,KAAa,QAAgB,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,MAAM,EAAE,IAAI;CAC3F,MAAM,WAAW,OAAO,QAAQ,MAAM;CAEtC,OAAO,UADa,OAAO,KAAK,IAAI,UAAU,MAAM,GAAG,MAC5B,CAAC;AAChC"}
@@ -0,0 +1,57 @@
1
+ //#region src/redis/script-runner.d.ts
2
+ /**
3
+ * An asynchronous Lua script runner with caller-declared results.
4
+ *
5
+ * @remarks
6
+ * Input arrays are unchanged, and numeric arguments are converted to strings before execution.
7
+ * Results are not cached or validated against the declared type.
8
+ *
9
+ * @typeParam T - The expected Lua result type, without runtime validation.
10
+ *
11
+ * @param keys - The script's Redis keys, in `KEYS` order.
12
+ * @param args - The script's arguments, in `ARGV` order.
13
+ *
14
+ * @returns A promise resolving to the Redis script result after execution completes.
15
+ */
16
+ export type RedisScriptRunner<T = unknown> = (keys: readonly string[], args: readonly (number | string)[]) => Promise<T>;
17
+ /**
18
+ * A caller-owned Redis client exposing raw command execution.
19
+ *
20
+ * @remarks
21
+ * The client manages connections and command routing. `SCRIPT LOAD` and `EVALSHA` must target the same server
22
+ * for script-cache recovery to succeed. Missing-script rejections must be `Error` instances whose messages
23
+ * begin with the Redis error code `NOSCRIPT`, followed by whitespace or the end of the message.
24
+ */
25
+ export interface RedisLikeScriptClient {
26
+ /**
27
+ * Sends a raw Redis command and resolves to its reply, or rejects on failure.
28
+ *
29
+ * @param command - The Redis command name.
30
+ * @param args - The command arguments in protocol order.
31
+ */
32
+ send: (command: string, args: string[]) => Promise<unknown>;
33
+ }
34
+ /**
35
+ * Creates a Lua script runner that reloads missing cached scripts before retrying execution.
36
+ *
37
+ * @remarks
38
+ * Calls use `EVALSHA` with the SHA-1 digest of the source. A `NOSCRIPT` rejection loads the script with
39
+ * `SCRIPT LOAD` before another execution attempt, provided the attempt limit has not been reached.
40
+ * Concurrent cache misses on the same runner share an in-flight load; reuse the runner to share that load.
41
+ * Load failures and errors other than `NOSCRIPT` propagate without retries. The final execution error is
42
+ * preserved when the attempt limit is reached. The runner does not cache results or close the client.
43
+ *
44
+ * @typeParam T - The expected Lua result type, without runtime validation.
45
+ *
46
+ * @param client - The caller-owned client used for raw Redis commands.
47
+ * @param source - The Lua source loaded when the script is absent from the server's cache.
48
+ * @param maxAttempts - The maximum `EVALSHA` attempts per invocation, including the initial attempt.
49
+ * Must be a positive safe integer. Defaults to `3`; `1` disables script loading and retries.
50
+ *
51
+ * @returns A reusable runner sharing the client and any in-flight script load.
52
+ *
53
+ * @throws RangeError if `maxAttempts` is not a positive safe integer.
54
+ */
55
+ export declare function createRedisScriptRunner<T = unknown>(client: RedisLikeScriptClient, source: string, maxAttempts?: number): RedisScriptRunner<T>;
56
+ //#endregion
57
+ //# sourceMappingURL=script-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"script-runner.d.ts","names":[],"sources":["../../src/redis/script-runner.ts"],"mappings":";;;;;;;;;;;;;;;YAgBY,kBAAkB,gBAAgB,yBAAyB,uCAAuC,QAC1G;;;;;;;;;iBAWa;;;;;;;EAOb,OAAO,iBAAiB,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;wBAwB/B,wBAAwB,aACpC,QAAQ,uBACR,gBACA,uBACD,kBAAkB"}
@@ -0,0 +1,46 @@
1
+ import { createHash } from "node:crypto";
2
+ //#region src/redis/script-runner.ts
3
+ /**
4
+ * Creates a Lua script runner that reloads missing cached scripts before retrying execution.
5
+ *
6
+ * @remarks
7
+ * Calls use `EVALSHA` with the SHA-1 digest of the source. A `NOSCRIPT` rejection loads the script with
8
+ * `SCRIPT LOAD` before another execution attempt, provided the attempt limit has not been reached.
9
+ * Concurrent cache misses on the same runner share an in-flight load; reuse the runner to share that load.
10
+ * Load failures and errors other than `NOSCRIPT` propagate without retries. The final execution error is
11
+ * preserved when the attempt limit is reached. The runner does not cache results or close the client.
12
+ *
13
+ * @typeParam T - The expected Lua result type, without runtime validation.
14
+ *
15
+ * @param client - The caller-owned client used for raw Redis commands.
16
+ * @param source - The Lua source loaded when the script is absent from the server's cache.
17
+ * @param maxAttempts - The maximum `EVALSHA` attempts per invocation, including the initial attempt.
18
+ * Must be a positive safe integer. Defaults to `3`; `1` disables script loading and retries.
19
+ *
20
+ * @returns A reusable runner sharing the client and any in-flight script load.
21
+ *
22
+ * @throws RangeError if `maxAttempts` is not a positive safe integer.
23
+ */
24
+ function createRedisScriptRunner(client, source, maxAttempts = 3) {
25
+ if (!Number.isSafeInteger(maxAttempts) || maxAttempts < 1) throw new RangeError("maxAttempts must be a positive safe integer");
26
+ const digest = createHash("sha1").update(source).digest("hex");
27
+ let loadingPromise;
28
+ return async (keys, args) => {
29
+ for (let attempt = 1;; attempt += 1) try {
30
+ return await client.send("EVALSHA", [
31
+ digest,
32
+ String(keys.length),
33
+ ...keys,
34
+ ...args.map(String)
35
+ ]);
36
+ } catch (error) {
37
+ if (!(error instanceof Error) || !/^NOSCRIPT(?:\s|$)/.test(error.message) || attempt >= maxAttempts) throw error;
38
+ if (loadingPromise === void 0) loadingPromise = client.send("SCRIPT", ["LOAD", source]).finally(() => loadingPromise = void 0);
39
+ await loadingPromise;
40
+ }
41
+ };
42
+ }
43
+ //#endregion
44
+ export { createRedisScriptRunner };
45
+
46
+ //# sourceMappingURL=script-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"script-runner.js","names":[],"sources":["../../src/redis/script-runner.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\n\n/**\n * An asynchronous Lua script runner with caller-declared results.\n *\n * @remarks\n * Input arrays are unchanged, and numeric arguments are converted to strings before execution.\n * Results are not cached or validated against the declared type.\n *\n * @typeParam T - The expected Lua result type, without runtime validation.\n *\n * @param keys - The script's Redis keys, in `KEYS` order.\n * @param args - The script's arguments, in `ARGV` order.\n *\n * @returns A promise resolving to the Redis script result after execution completes.\n */\nexport type RedisScriptRunner<T = unknown> = (keys: readonly string[], args: readonly (number | string)[]) => Promise<\n T\n>;\n\n/**\n * A caller-owned Redis client exposing raw command execution.\n *\n * @remarks\n * The client manages connections and command routing. `SCRIPT LOAD` and `EVALSHA` must target the same server\n * for script-cache recovery to succeed. Missing-script rejections must be `Error` instances whose messages\n * begin with the Redis error code `NOSCRIPT`, followed by whitespace or the end of the message.\n */\nexport interface RedisLikeScriptClient {\n /**\n * Sends a raw Redis command and resolves to its reply, or rejects on failure.\n *\n * @param command - The Redis command name.\n * @param args - The command arguments in protocol order.\n */\n send: (command: string, args: string[]) => Promise<unknown>;\n}\n\n/**\n * Creates a Lua script runner that reloads missing cached scripts before retrying execution.\n *\n * @remarks\n * Calls use `EVALSHA` with the SHA-1 digest of the source. A `NOSCRIPT` rejection loads the script with\n * `SCRIPT LOAD` before another execution attempt, provided the attempt limit has not been reached.\n * Concurrent cache misses on the same runner share an in-flight load; reuse the runner to share that load.\n * Load failures and errors other than `NOSCRIPT` propagate without retries. The final execution error is\n * preserved when the attempt limit is reached. The runner does not cache results or close the client.\n *\n * @typeParam T - The expected Lua result type, without runtime validation.\n *\n * @param client - The caller-owned client used for raw Redis commands.\n * @param source - The Lua source loaded when the script is absent from the server's cache.\n * @param maxAttempts - The maximum `EVALSHA` attempts per invocation, including the initial attempt.\n * Must be a positive safe integer. Defaults to `3`; `1` disables script loading and retries.\n *\n * @returns A reusable runner sharing the client and any in-flight script load.\n *\n * @throws RangeError if `maxAttempts` is not a positive safe integer.\n */\nexport function createRedisScriptRunner<T = unknown>(\n client: RedisLikeScriptClient,\n source: string,\n maxAttempts: number = 3,\n): RedisScriptRunner<T> {\n if (!Number.isSafeInteger(maxAttempts) || maxAttempts < 1) {\n throw new RangeError('maxAttempts must be a positive safe integer');\n }\n\n const digest = createHash('sha1').update(source).digest('hex');\n let loadingPromise: Promise<unknown> | undefined;\n\n return async (keys, args) => {\n for (let attempt = 1; ; attempt += 1) {\n try {\n return await client.send(\n 'EVALSHA',\n [\n digest,\n String(keys.length),\n ...keys,\n ...args.map(String),\n ],\n ) as T;\n } catch (error) {\n if (\n !(error instanceof Error)\n || !/^NOSCRIPT(?:\\s|$)/.test(error.message)\n || attempt >= maxAttempts\n ) throw error;\n\n if (loadingPromise === undefined) {\n loadingPromise = client\n .send(\n 'SCRIPT',\n [\n 'LOAD',\n source,\n ],\n )\n .finally(() => loadingPromise = undefined);\n }\n\n await loadingPromise;\n }\n }\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA2DA,SAAgB,wBACZ,QACA,QACA,cAAsB,GACF;CACpB,IAAI,CAAC,OAAO,cAAc,WAAW,KAAK,cAAc,GACpD,MAAM,IAAI,WAAW,6CAA6C;CAGtE,MAAM,SAAS,WAAW,MAAM,CAAC,CAAC,OAAO,MAAM,CAAC,CAAC,OAAO,KAAK;CAC7D,IAAI;CAEJ,OAAO,OAAO,MAAM,SAAS;EACzB,KAAK,IAAI,UAAU,IAAK,WAAW,GAC/B,IAAI;GACA,OAAO,MAAM,OAAO,KAChB,WACA;IACI;IACA,OAAO,KAAK,MAAM;IAClB,GAAG;IACH,GAAG,KAAK,IAAI,MAAM;GACtB,CACJ;EACJ,SAAS,OAAO;GACZ,IACI,EAAE,iBAAiB,UAChB,CAAC,oBAAoB,KAAK,MAAM,OAAO,KACvC,WAAW,aAChB,MAAM;GAER,IAAI,mBAAmB,KAAA,GACnB,iBAAiB,OACZ,KACG,UACA,CACI,QACA,MACJ,CACJ,CAAC,CACA,cAAc,iBAAiB,KAAA,CAAS;GAGjD,MAAM;EACV;CAER;AACJ"}
@@ -1,32 +1,37 @@
1
1
  import { LRUCache } from "lru-cache";
2
2
  //#region src/storages/lru/keyed-store.d.ts
3
3
  /**
4
- * Creates a keyed store wrapper around an LRU cache instance.
4
+ * Creates a keyed cache factory sharing a caller-owned LRU cache.
5
5
  *
6
- * @template D - The data type stored in the keyed store
6
+ * @remarks
7
+ * The key resolver is called synchronously once per operation, and its exceptions propagate.
8
+ * Reads return the cached value without copying it, or `null` for missing or nullish values.
9
+ * `getItemTtl` exposes the underlying remaining TTL in milliseconds; `setItem` returns the underlying cache.
10
+ * The facade does not dispose the supplied cache, and LRU defaults remain those of the supplied instance.
7
11
  *
8
- * @param {LRUCache<any, any, any>} lruInstance - The underlying lru-cache instance
12
+ * @typeParam D - The stored value type used by reads and writes.
9
13
  *
10
- * @returns {(keyFn: (...args: P) => string) => Readonly<{
11
- * getItem, getItemTtl, hasItem, removeItem, resolveKey, setItem
12
- * }>} A factory that accepts a key resolver and returns a frozen keyed cache facade
14
+ * @param lruInstance - The shared LRU cache instance.
15
+ *
16
+ * @returns A factory accepting a key resolver and returning a new frozen keyed facade sharing the cache.
13
17
  *
14
18
  * @example
15
- * ```typescript
19
+ *
20
+ * ```ts
16
21
  * import { createLruKeyedStore } from '@kikiutils/shared/storages/lru/keyed-store';
17
22
  * import { LRUCache } from 'lru-cache';
18
23
  *
19
- * const lru = new LRUCache({ max: 100 });
20
- * const keyedStore = createLruKeyedStore(lru)((userId: string) => `user:${userId}`);
24
+ * const cache = new LRUCache<string, { name: string }>({ max: 100 });
25
+ * const keyedStore = createLruKeyedStore<{ name: string }>(cache)((userId: string) => `user:${userId}`);
21
26
  * keyedStore.setItem({ name: 'Alice' }, 'user-123');
22
- * const user = keyedStore.getItem('user-123'); // { name: 'Alice' }
27
+ * console.log(keyedStore.getItem('user-123')); // => { name: 'Alice' }
23
28
  * ```
24
29
  */
25
- declare function createLruKeyedStore<D = unknown>(lruInstance: LRUCache<any, any, any>): <P extends any[]>(keyFn: (...args: P) => string) => Readonly<{
30
+ export declare function createLruKeyedStore<D = unknown>(lruInstance: LRUCache<any, any, any>): <P extends any[]>(keyFn: (...args: P) => string) => Readonly<{
26
31
  /**
27
- * Return a value from the cache. Will update the recency of the cache entry found.
32
+ * Returns the cached value and applies the underlying cache's read-recency policy.
28
33
  *
29
- * If the key is not found, returns `null`.
34
+ * @returns The cached value without copying it, or `null` when absent or nullish.
30
35
  */
31
36
  getItem(...args: P): NonNullable<D> | null;
32
37
  getItemTtl: (...args: P) => number;
@@ -39,5 +44,4 @@ declare function createLruKeyedStore<D = unknown>(lruInstance: LRUCache<any, any
39
44
  setItem: (value: D, ...args: P) => LRUCache<any, any, any>;
40
45
  }>;
41
46
  //#endregion
42
- export { createLruKeyedStore };
43
47
  //# sourceMappingURL=keyed-store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"keyed-store.d.ts","names":[],"sources":["../../../src/storages/lru/keyed-store.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;iBAwBgB,oBAAoB,aAAa,aAAa,2BAClD,iBAAiB,WAAW,MAAM,iBAAY;;;;;;EAMjC,WAAA,MAAA,IAAC,YAAA;EAII,gBAAA,MAAA;EACH,aAAA,MAAA;EACG,gBAAA,MAAA;;;;EAIA,gBAAA,MAAA;EACL,UAAA,OAAA,MAAC,MAAW,MAAC"}
1
+ {"version":3,"file":"keyed-store.d.ts","names":[],"sources":["../../../src/storages/lru/keyed-store.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBA6BgB,oBAAoB,aAAa,aAAa,2BAClD,iBAAiB,WAAW,MAAM,iBAAY;;;;;;EAMjC,WAAA,MAAA,IAAC,YAAA;EAII,gBAAA,MAAA;EACH,aAAA,MAAA;EACG,gBAAA,MAAA;;;;EAIA,gBAAA,MAAA;EACL,UAAA,OAAA,MAAC,MAAW,MAAC"}
@@ -1,32 +1,37 @@
1
1
  //#region src/storages/lru/keyed-store.ts
2
2
  /**
3
- * Creates a keyed store wrapper around an LRU cache instance.
3
+ * Creates a keyed cache factory sharing a caller-owned LRU cache.
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, and its exceptions propagate.
7
+ * Reads return the cached value without copying it, or `null` for missing or nullish values.
8
+ * `getItemTtl` exposes the underlying remaining TTL in milliseconds; `setItem` returns the underlying cache.
9
+ * The facade does not dispose the supplied cache, and LRU defaults remain those of the supplied instance.
6
10
  *
7
- * @param {LRUCache<any, any, any>} lruInstance - The underlying lru-cache 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
11
- * }>} A factory that accepts a key resolver and returns a frozen keyed cache facade
13
+ * @param lruInstance - The shared LRU cache instance.
14
+ *
15
+ * @returns A factory accepting a key resolver and returning a new frozen keyed facade sharing the cache.
12
16
  *
13
17
  * @example
14
- * ```typescript
18
+ *
19
+ * ```ts
15
20
  * import { createLruKeyedStore } from '@kikiutils/shared/storages/lru/keyed-store';
16
21
  * import { LRUCache } from 'lru-cache';
17
22
  *
18
- * const lru = new LRUCache({ max: 100 });
19
- * const keyedStore = createLruKeyedStore(lru)((userId: string) => `user:${userId}`);
23
+ * const cache = new LRUCache<string, { name: string }>({ max: 100 });
24
+ * const keyedStore = createLruKeyedStore<{ name: string }>(cache)((userId: string) => `user:${userId}`);
20
25
  * keyedStore.setItem({ name: 'Alice' }, 'user-123');
21
- * const user = keyedStore.getItem('user-123'); // { name: 'Alice' }
26
+ * console.log(keyedStore.getItem('user-123')); // => { name: 'Alice' }
22
27
  * ```
23
28
  */
24
29
  function createLruKeyedStore(lruInstance) {
25
30
  return (keyFn) => Object.freeze({
26
31
  /**
27
- * Return a value from the cache. Will update the recency of the cache entry found.
32
+ * Returns the cached value and applies the underlying cache's read-recency policy.
28
33
  *
29
- * If the key is not found, returns `null`.
34
+ * @returns The cached value without copying it, or `null` when absent or nullish.
30
35
  */
31
36
  getItem(...args) {
32
37
  return lruInstance.get(keyFn(...args)) ?? null;
@@ -1 +1 @@
1
- {"version":3,"file":"keyed-store.js","names":[],"sources":["../../../src/storages/lru/keyed-store.ts"],"sourcesContent":["import type { LRUCache } from 'lru-cache';\n\n/**\n * Creates a keyed store wrapper around an LRU cache instance.\n *\n * @template D - The data type stored in the keyed store\n *\n * @param {LRUCache<any, any, any>} lruInstance - The underlying lru-cache instance\n *\n * @returns {(keyFn: (...args: P) => string) => Readonly<{\n * getItem, getItemTtl, hasItem, removeItem, resolveKey, setItem\n * }>} A factory that accepts a key resolver and returns a frozen keyed cache facade\n *\n * @example\n * ```typescript\n * import { createLruKeyedStore } from '@kikiutils/shared/storages/lru/keyed-store';\n * import { LRUCache } from 'lru-cache';\n *\n * const lru = new LRUCache({ max: 100 });\n * const keyedStore = createLruKeyedStore(lru)((userId: string) => `user:${userId}`);\n * keyedStore.setItem({ name: 'Alice' }, 'user-123');\n * const user = keyedStore.getItem('user-123'); // { name: 'Alice' }\n * ```\n */\nexport function createLruKeyedStore<D = unknown>(lruInstance: LRUCache<any, any, any>) {\n return <P extends any[]>(keyFn: (...args: P) => string) => Object.freeze({\n /**\n * Return a value from the cache. Will update the recency of the cache entry found.\n *\n * If the key is not found, returns `null`.\n */\n getItem(...args: P) {\n const rawValue = lruInstance.get(keyFn(...args));\n return rawValue as D ?? null;\n },\n getItemTtl: (...args: P) => lruInstance.getRemainingTTL(keyFn(...args)),\n hasItem: (...args: P) => lruInstance.has(keyFn(...args)),\n removeItem: (...args: P) => lruInstance.delete(keyFn(...args)),\n /**\n * Resolves the full cache key from the given arguments.\n */\n resolveKey: (...args: P) => keyFn(...args),\n setItem: (value: D, ...args: P) => lruInstance.set(keyFn(...args), value),\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAwBA,SAAgB,oBAAiC,aAAsC;CACnF,QAAyB,UAAkC,OAAO,OAAO;;;;;;EAMrE,QAAQ,GAAG,MAAS;GAEhB,OADiB,YAAY,IAAI,MAAM,GAAG,IAAI,CAChC,KAAU;EAC5B;EACA,aAAa,GAAG,SAAY,YAAY,gBAAgB,MAAM,GAAG,IAAI,CAAC;EACtE,UAAU,GAAG,SAAY,YAAY,IAAI,MAAM,GAAG,IAAI,CAAC;EACvD,aAAa,GAAG,SAAY,YAAY,OAAO,MAAM,GAAG,IAAI,CAAC;;;;EAI7D,aAAa,GAAG,SAAY,MAAM,GAAG,IAAI;EACzC,UAAU,OAAU,GAAG,SAAY,YAAY,IAAI,MAAM,GAAG,IAAI,GAAG,KAAK;CAC5E,CAAC;AACL"}
1
+ {"version":3,"file":"keyed-store.js","names":[],"sources":["../../../src/storages/lru/keyed-store.ts"],"sourcesContent":["import type { LRUCache } from 'lru-cache';\n\n/**\n * Creates a keyed cache factory sharing a caller-owned LRU cache.\n *\n * @remarks\n * The key resolver is called synchronously once per operation, and its exceptions propagate.\n * Reads return the cached value without copying it, or `null` for missing or nullish values.\n * `getItemTtl` exposes the underlying remaining TTL in milliseconds; `setItem` returns the underlying cache.\n * The facade does not dispose the supplied cache, and LRU defaults remain those of the supplied instance.\n *\n * @typeParam D - The stored value type used by reads and writes.\n *\n * @param lruInstance - The shared LRU cache instance.\n *\n * @returns A factory accepting a key resolver and returning a new frozen keyed facade sharing the cache.\n *\n * @example\n *\n * ```ts\n * import { createLruKeyedStore } from '@kikiutils/shared/storages/lru/keyed-store';\n * import { LRUCache } from 'lru-cache';\n *\n * const cache = new LRUCache<string, { name: string }>({ max: 100 });\n * const keyedStore = createLruKeyedStore<{ name: string }>(cache)((userId: string) => `user:${userId}`);\n * keyedStore.setItem({ name: 'Alice' }, 'user-123');\n * console.log(keyedStore.getItem('user-123')); // => { name: 'Alice' }\n * ```\n */\nexport function createLruKeyedStore<D = unknown>(lruInstance: LRUCache<any, any, any>) {\n return <P extends any[]>(keyFn: (...args: P) => string) => Object.freeze({\n /**\n * Returns the cached value and applies the underlying cache's read-recency policy.\n *\n * @returns The cached value without copying it, or `null` when absent or nullish.\n */\n getItem(...args: P) {\n const rawValue = lruInstance.get(keyFn(...args));\n return rawValue as D ?? null;\n },\n getItemTtl: (...args: P) => lruInstance.getRemainingTTL(keyFn(...args)),\n hasItem: (...args: P) => lruInstance.has(keyFn(...args)),\n removeItem: (...args: P) => lruInstance.delete(keyFn(...args)),\n /**\n * Resolves the full cache key from the given arguments.\n */\n resolveKey: (...args: P) => keyFn(...args),\n setItem: (value: D, ...args: P) => lruInstance.set(keyFn(...args), value),\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,SAAgB,oBAAiC,aAAsC;CACnF,QAAyB,UAAkC,OAAO,OAAO;;;;;;EAMrE,QAAQ,GAAG,MAAS;GAEhB,OADiB,YAAY,IAAI,MAAM,GAAG,IAAI,CAChC,KAAU;EAC5B;EACA,aAAa,GAAG,SAAY,YAAY,gBAAgB,MAAM,GAAG,IAAI,CAAC;EACtE,UAAU,GAAG,SAAY,YAAY,IAAI,MAAM,GAAG,IAAI,CAAC;EACvD,aAAa,GAAG,SAAY,YAAY,OAAO,MAAM,GAAG,IAAI,CAAC;;;;EAI7D,aAAa,GAAG,SAAY,MAAM,GAAG,IAAI;EACzC,UAAU,OAAU,GAAG,SAAY,YAAY,IAAI,MAAM,GAAG,IAAI,GAAG,KAAK;CAC5E,CAAC;AACL"}
@@ -2,31 +2,22 @@ import { MaybeReadonly } from "../../types/index.js";
2
2
  import { RedisLikeStorage } from "./types.js";
3
3
  //#region src/storages/redis/keyed-store.d.ts
4
4
  /**
5
- * Creates a keyed store wrapper around a Redis-like storage.
5
+ * Creates a keyed store factory sharing a caller-owned Redis-like storage facade.
6
6
  *
7
- * @template D - The data type stored in the keyed store
7
+ * @remarks
8
+ * The key resolver is called synchronously once per operation with the operation's key arguments.
9
+ * Resolver exceptions propagate synchronously; asynchronous storage failures retain the underlying rejection.
10
+ * `setItemWithTtl` accepts its TTL in seconds before the value and key arguments.
11
+ * The factory does not open or close the underlying connection; cleanup remains the caller's responsibility.
8
12
  *
9
- * @param {MaybeReadonly<RedisLikeStorage>} storage - The underlying Redis-like storage instance
13
+ * @typeParam D - The stored value type used by reads and writes.
10
14
  *
11
- * @returns {(keyFn: (...args: P) => string) => Readonly<{
12
- * getItem, getItemTtl, hasItem, removeItem, resolveKey, setItem, setItemWithTtl
13
- * }>} A factory that accepts a key resolver and returns a frozen Redis keyed-store facade
15
+ * @param storage - The shared Redis-like storage instance.
14
16
  *
15
- * @example
16
- * ```typescript
17
- * import { createRedisKeyedStore } from '@kikiutils/shared/storages/redis/keyed-store';
18
- * import { createRedisMsgpackStorage } from '@kikiutils/shared/storages/redis/msgpack';
19
- * import { createClient } from 'redis';
20
- *
21
- * const client = createClient();
22
- * await client.connect();
23
- * const storage = createRedisMsgpackStorage(client as unknown as RedisLikeAdapter);
24
- * const keyedStore = createRedisKeyedStore(storage)((userId: string) => `user:${userId}`);
25
- * await keyedStore.setItem({ name: 'Alice' }, 'user-123');
26
- * const user = await keyedStore.getItem('user-123'); // { name: 'Alice' }
27
- * ```
17
+ * @returns A factory accepting a key resolver and returning a new frozen keyed facade sharing the storage.
18
+ * Reads, writes, removals, and TTL results retain the underlying storage contract.
28
19
  */
29
- declare function createRedisKeyedStore<D = unknown>(storage: MaybeReadonly<RedisLikeStorage>): <P extends any[]>(keyFn: (...args: P) => string) => Readonly<{
20
+ export declare function createRedisKeyedStore<D = unknown>(storage: MaybeReadonly<RedisLikeStorage>): <P extends any[]>(keyFn: (...args: P) => string) => Readonly<{
30
21
  getItem: (...args: P) => Promise<D | null>;
31
22
  getItemTtl: (...args: P) => Promise<number>;
32
23
  hasItem: (...args: P) => Promise<boolean>;
@@ -36,5 +27,4 @@ declare function createRedisKeyedStore<D = unknown>(storage: MaybeReadonly<Redis
36
27
  setItemWithTtl(ttlSeconds: number, value: D, ...args: P): Promise<boolean>;
37
28
  }>;
38
29
  //#endregion
39
- export { createRedisKeyedStore };
40
30
  //# sourceMappingURL=keyed-store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"keyed-store.d.ts","names":[],"sources":["../../../src/storages/redis/keyed-store.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6BgB,sBAAsB,aAAa,SAAS,cAAc,qBAC9D,iBAAiB,WAAW,MAAM,iBAAY;EAC/B,aAAA,MAAA,MAAC,QAAA;EACE,gBAAA,MAAA,MAAC;EACJ,aAAA,MAAA,MAAC;EACE,gBAAA,MAAA,MAAC;EACD,gBAAA,MAAA;EACL,UAAA,OAAA,MAAC,MAAW,MAAC;EACH,eAAA,oBAAM,OAAS,MAAC,MAAW,IAAC"}
1
+ {"version":3,"file":"keyed-store.d.ts","names":[],"sources":["../../../src/storages/redis/keyed-store.ts"],"mappings":";;;;;;;;;;;;;;;;;;;wBAoBgB,sBAAsB,aAAa,SAAS,cAAc,qBAC9D,iBAAiB,WAAW,MAAM,iBAAY;EAC/B,aAAA,MAAA,MAAC,QAAA;EACE,gBAAA,MAAA,MAAC;EACJ,aAAA,MAAA,MAAC;EACE,gBAAA,MAAA,MAAC;EACD,gBAAA,MAAA;EACL,UAAA,OAAA,MAAC,MAAW,MAAC;EACH,eAAA,oBAAM,OAAS,MAAC,MAAW,IAAC"}