@kikiutils/shared 18.0.0 → 18.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/buffer.d.ts +19 -21
- package/dist/buffer.d.ts.map +1 -1
- package/dist/buffer.js +18 -19
- package/dist/buffer.js.map +1 -1
- package/dist/classes/enhanced-date.d.ts +425 -0
- package/dist/classes/enhanced-date.d.ts.map +1 -0
- package/dist/classes/enhanced-date.js +591 -0
- package/dist/classes/enhanced-date.js.map +1 -0
- package/dist/classes/path.d.ts +211 -48
- package/dist/classes/path.d.ts.map +1 -1
- package/dist/classes/path.js +181 -52
- package/dist/classes/path.js.map +1 -1
- package/dist/classes/precision-number.d.ts +44 -39
- package/dist/classes/precision-number.d.ts.map +1 -1
- package/dist/classes/precision-number.js +51 -45
- package/dist/classes/precision-number.js.map +1 -1
- package/dist/classes/ssh-client.d.ts +3 -4
- package/dist/classes/ssh-client.d.ts.map +1 -1
- package/dist/classes/ssh-client.js +2 -2
- package/dist/classes/ssh-client.js.map +1 -1
- package/dist/clipboard.d.ts +25 -26
- package/dist/clipboard.d.ts.map +1 -1
- package/dist/clipboard.js +23 -23
- package/dist/clipboard.js.map +1 -1
- package/dist/consola.d.ts +12 -15
- package/dist/consola.d.ts.map +1 -1
- package/dist/consola.js +10 -12
- package/dist/consola.js.map +1 -1
- package/dist/crypto-hash.d.ts +65 -56
- package/dist/crypto-hash.d.ts.map +1 -1
- package/dist/crypto-hash.js +55 -45
- package/dist/crypto-hash.js.map +1 -1
- package/dist/datetime.d.ts +41 -53
- package/dist/datetime.d.ts.map +1 -1
- package/dist/datetime.js +53 -66
- package/dist/datetime.js.map +1 -1
- package/dist/element-plus.d.ts +13 -14
- package/dist/element-plus.d.ts.map +1 -1
- package/dist/element-plus.js +11 -11
- package/dist/element-plus.js.map +1 -1
- package/dist/enum.d.ts +39 -36
- package/dist/enum.d.ts.map +1 -1
- package/dist/enum.js +36 -32
- package/dist/enum.js.map +1 -1
- package/dist/env.d.ts +22 -15
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +20 -12
- package/dist/env.js.map +1 -1
- package/dist/event-awaiter.d.ts +47 -52
- package/dist/event-awaiter.d.ts.map +1 -1
- package/dist/event-awaiter.js +46 -50
- package/dist/event-awaiter.js.map +1 -1
- package/dist/general.d.ts +22 -17
- package/dist/general.d.ts.map +1 -1
- package/dist/general.js.map +1 -1
- package/dist/hash.d.ts +24 -21
- package/dist/hash.d.ts.map +1 -1
- package/dist/hash.js +20 -16
- package/dist/hash.js.map +1 -1
- package/dist/math.d.ts +20 -19
- package/dist/math.d.ts.map +1 -1
- package/dist/math.js +14 -12
- package/dist/math.js.map +1 -1
- package/dist/number.d.ts +10 -9
- package/dist/number.d.ts.map +1 -1
- package/dist/number.js +9 -7
- package/dist/number.js.map +1 -1
- package/dist/object.d.ts +22 -10
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +21 -8
- package/dist/object.js.map +1 -1
- package/dist/pino.d.ts +12 -15
- package/dist/pino.d.ts.map +1 -1
- package/dist/pino.js +10 -15
- package/dist/pino.js.map +1 -1
- package/dist/random.d.ts +17 -15
- package/dist/random.d.ts.map +1 -1
- package/dist/random.js +16 -13
- package/dist/random.js.map +1 -1
- package/dist/redis/script-runner.d.ts +57 -0
- package/dist/redis/script-runner.d.ts.map +1 -0
- package/dist/redis/script-runner.js +46 -0
- package/dist/redis/script-runner.js.map +1 -0
- package/dist/storages/lru/keyed-store.d.ts +18 -14
- package/dist/storages/lru/keyed-store.d.ts.map +1 -1
- package/dist/storages/lru/keyed-store.js +17 -12
- package/dist/storages/lru/keyed-store.js.map +1 -1
- package/dist/storages/redis/keyed-store.d.ts +11 -21
- package/dist/storages/redis/keyed-store.d.ts.map +1 -1
- package/dist/storages/redis/keyed-store.js +10 -19
- package/dist/storages/redis/keyed-store.js.map +1 -1
- package/dist/storages/redis/msgpack.d.ts +33 -13
- package/dist/storages/redis/msgpack.d.ts.map +1 -1
- package/dist/storages/redis/msgpack.js +32 -11
- package/dist/storages/redis/msgpack.js.map +1 -1
- package/dist/storages/redis/types.d.ts +34 -17
- package/dist/storages/redis/types.d.ts.map +1 -1
- package/dist/string.d.ts +12 -11
- package/dist/string.d.ts.map +1 -1
- package/dist/string.js +20 -15
- package/dist/string.js.map +1 -1
- package/dist/time.d.ts +35 -10
- package/dist/time.d.ts.map +1 -1
- package/dist/time.js +49 -9
- package/dist/time.js.map +1 -1
- package/dist/types/filtered-key-path.d.ts +4 -15
- package/dist/types/filtered-key-path.d.ts.map +1 -1
- package/dist/types/index.d.ts +10 -10
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/vue.d.ts +7 -7
- package/dist/types/vue.d.ts.map +1 -1
- package/dist/url.d.ts +15 -14
- package/dist/url.d.ts.map +1 -1
- package/dist/url.js +12 -10
- package/dist/url.js.map +1 -1
- package/dist/vue.d.ts +19 -21
- package/dist/vue.d.ts.map +1 -1
- package/dist/vue.js +15 -16
- package/dist/vue.js.map +1 -1
- package/dist/web.d.ts +14 -11
- package/dist/web.d.ts.map +1 -1
- package/dist/web.js +12 -8
- package/dist/web.js.map +1 -1
- package/package.json +20 -20
- package/src/buffer.ts +18 -19
- package/src/classes/enhanced-date.ts +665 -0
- package/src/classes/path.ts +232 -91
- package/src/classes/precision-number.ts +61 -53
- package/src/classes/ssh-client.ts +8 -5
- package/src/clipboard.ts +23 -23
- package/src/consola.ts +10 -12
- package/src/crypto-hash.ts +55 -45
- package/src/datetime.ts +65 -85
- package/src/element-plus.ts +11 -11
- package/src/enum.ts +36 -32
- package/src/env.ts +20 -12
- package/src/event-awaiter.ts +49 -50
- package/src/general.ts +20 -14
- package/src/hash.ts +20 -16
- package/src/math.ts +18 -16
- package/src/number.ts +9 -7
- package/src/object.ts +21 -8
- package/src/pino.ts +11 -15
- package/src/random.ts +16 -13
- package/src/redis/script-runner.ts +107 -0
- package/src/storages/lru/keyed-store.ts +17 -12
- package/src/storages/redis/keyed-store.ts +10 -19
- package/src/storages/redis/msgpack.ts +32 -11
- package/src/storages/redis/types.ts +32 -14
- package/src/string.ts +10 -8
- package/src/time.ts +52 -8
- package/src/types/filtered-key-path.ts +9 -14
- package/src/types/vue.ts +6 -5
- package/src/url.ts +12 -10
- package/src/vue.ts +15 -16
- 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
|
|
16
|
-
* @param
|
|
17
|
-
* @param
|
|
18
|
-
*
|
|
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
|
-
*
|
|
23
|
+
*
|
|
24
|
+
* ```ts
|
|
22
25
|
* import { stringifyObjectDeterministically } from '@kikiutils/shared/object';
|
|
23
26
|
*
|
|
24
|
-
* console.log(stringifyObjectDeterministically({
|
|
25
|
-
*
|
|
26
|
-
*
|
|
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 = "&") {
|
package/dist/object.js.map
CHANGED
|
@@ -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
|
|
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,24 @@
|
|
|
1
1
|
//#region src/pino.d.ts
|
|
2
2
|
/**
|
|
3
|
-
* A pino logger
|
|
3
|
+
* A pino logger with environment-controlled verbosity.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
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).
|
|
5
|
+
* @remarks
|
|
6
|
+
* `PINO_LOGGER_LEVEL` sets the log level when nonempty at module initialization;
|
|
7
|
+
* otherwise, `NODE_ENV=production` selects `error`, and other environments retain the logger's default level.
|
|
8
|
+
* Assign `logger.level` to change verbosity after initialization.
|
|
12
9
|
*
|
|
13
10
|
* @example
|
|
14
|
-
* ```typescript
|
|
15
|
-
* import { logger } from '@kikiutils/shared/pino';
|
|
16
11
|
*
|
|
17
|
-
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { logger } from '@kikiutils/shared/pino';
|
|
18
14
|
*
|
|
19
|
-
* // Manually change the level
|
|
20
15
|
* logger.level = 'info';
|
|
16
|
+
* logger.info('Application started');
|
|
21
17
|
* ```
|
|
18
|
+
*
|
|
19
|
+
* @see {@link https://getpino.io/#/docs/api?id=level-string | Pino log levels}
|
|
22
20
|
*/
|
|
23
|
-
declare const pinoLogger: import("pino").Logger<never, boolean>;
|
|
24
|
-
declare const logger: import("pino").Logger<never, boolean>;
|
|
21
|
+
export declare const pinoLogger: import("pino").Logger<never, boolean>;
|
|
22
|
+
export declare const logger: import("pino").Logger<never, boolean>;
|
|
25
23
|
//#endregion
|
|
26
|
-
export { logger, pinoLogger };
|
|
27
24
|
//# sourceMappingURL=pino.d.ts.map
|
package/dist/pino.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pino.d.ts","names":[],"sources":["../src/pino.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"pino.d.ts","names":[],"sources":["../src/pino.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;qBA6Ba,2BAAU;qBACV,uBAAM"}
|
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
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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
|
-
*
|
|
13
|
+
* @typeParam T - The generator's return value, preserved without awaiting or copying.
|
|
11
14
|
*
|
|
12
|
-
* @
|
|
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
|
-
* @
|
|
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
|
-
* @
|
|
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
|
package/dist/random.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"random.d.ts","names":[],"sources":["../src/random.ts"],"mappings":"
|
|
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
|
-
*
|
|
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
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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
|
-
*
|
|
13
|
+
* @typeParam T - The generator's return value, preserved without awaiting or copying.
|
|
11
14
|
*
|
|
12
|
-
* @
|
|
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
|
-
* @
|
|
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
|
-
* @
|
|
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})`);
|
package/dist/random.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"random.js","names":[],"sources":["../src/random.ts"],"sourcesContent":["/**\n *
|
|
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
|
|
4
|
+
* Creates a keyed cache factory sharing a caller-owned LRU cache.
|
|
5
5
|
*
|
|
6
|
-
* @
|
|
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
|
-
* @
|
|
12
|
+
* @typeParam D - The stored value type used by reads and writes.
|
|
9
13
|
*
|
|
10
|
-
* @
|
|
11
|
-
*
|
|
12
|
-
*
|
|
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
|
-
*
|
|
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
|
|
20
|
-
* const keyedStore = createLruKeyedStore(
|
|
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
|
-
*
|
|
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
|
-
*
|
|
32
|
+
* Returns the cached value and applies the underlying cache's read-recency policy.
|
|
28
33
|
*
|
|
29
|
-
*
|
|
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":"
|
|
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
|
|
3
|
+
* Creates a keyed cache factory sharing a caller-owned LRU cache.
|
|
4
4
|
*
|
|
5
|
-
* @
|
|
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
|
-
* @
|
|
11
|
+
* @typeParam D - The stored value type used by reads and writes.
|
|
8
12
|
*
|
|
9
|
-
* @
|
|
10
|
-
*
|
|
11
|
-
*
|
|
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
|
-
*
|
|
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
|
|
19
|
-
* const keyedStore = createLruKeyedStore(
|
|
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
|
-
*
|
|
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
|
-
*
|
|
32
|
+
* Returns the cached value and applies the underlying cache's read-recency policy.
|
|
28
33
|
*
|
|
29
|
-
*
|
|
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
|
|
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
|
|
5
|
+
* Creates a keyed store factory sharing a caller-owned Redis-like storage facade.
|
|
6
6
|
*
|
|
7
|
-
* @
|
|
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
|
-
* @
|
|
13
|
+
* @typeParam D - The stored value type used by reads and writes.
|
|
10
14
|
*
|
|
11
|
-
* @
|
|
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
|
-
* @
|
|
16
|
-
*
|
|
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":"
|
|
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"}
|