@kikiutils/shared 20.0.1 → 20.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/buffer.js.map +1 -1
- package/dist/classes/enhanced-date.d.ts +2 -2
- package/dist/classes/enhanced-date.d.ts.map +1 -1
- package/dist/classes/enhanced-date.js.map +1 -1
- package/dist/classes/path.d.ts +1 -1
- package/dist/classes/path.d.ts.map +1 -1
- package/dist/classes/path.js +30 -30
- package/dist/classes/path.js.map +1 -1
- package/dist/enum.d.ts +4 -3
- package/dist/enum.d.ts.map +1 -1
- package/dist/enum.js +3 -2
- package/dist/enum.js.map +1 -1
- package/dist/event-awaiter.d.ts.map +1 -1
- package/dist/event-awaiter.js +7 -6
- package/dist/event-awaiter.js.map +1 -1
- package/dist/general.d.ts +3 -2
- package/dist/general.d.ts.map +1 -1
- package/dist/general.js.map +1 -1
- package/dist/logger/_internals/formatter.d.ts +12 -4
- package/dist/logger/_internals/formatter.d.ts.map +1 -1
- package/dist/logger/_internals/formatter.js +12 -4
- package/dist/logger/_internals/formatter.js.map +1 -1
- package/dist/logger/_internals/logger.d.ts +6 -2
- package/dist/logger/_internals/logger.d.ts.map +1 -1
- package/dist/logger/_internals/logger.js +6 -3
- package/dist/logger/_internals/logger.js.map +1 -1
- package/dist/logger/node/_internals/file-writer.d.ts +3 -1
- package/dist/logger/node/_internals/file-writer.d.ts.map +1 -1
- package/dist/logger/node/_internals/file-writer.js +13 -9
- package/dist/logger/node/_internals/file-writer.js.map +1 -1
- package/dist/logger/node/_internals/formatter.d.ts +3 -1
- package/dist/logger/node/_internals/formatter.d.ts.map +1 -1
- package/dist/logger/node/_internals/formatter.js +3 -1
- package/dist/logger/node/_internals/formatter.js.map +1 -1
- package/dist/logger/node/index.js +11 -9
- package/dist/logger/node/index.js.map +1 -1
- package/dist/logger/node/types.d.ts +36 -12
- package/dist/logger/node/types.d.ts.map +1 -1
- package/dist/logger/types.d.ts +44 -19
- package/dist/logger/types.d.ts.map +1 -1
- package/dist/redis/script-runner.d.ts +1 -1
- package/dist/redis/script-runner.d.ts.map +1 -1
- package/dist/redis/script-runner.js.map +1 -1
- package/dist/storages/redis/keyed-store.d.ts.map +1 -1
- package/dist/storages/redis/keyed-store.js +10 -10
- package/dist/storages/redis/keyed-store.js.map +1 -1
- package/dist/storages/redis/msgpack.js +2 -2
- package/dist/storages/redis/msgpack.js.map +1 -1
- package/dist/time.d.ts.map +1 -1
- package/dist/time.js +4 -4
- package/dist/time.js.map +1 -1
- package/dist/types/filtered-key-path.d.ts +2 -2
- package/dist/types/filtered-key-path.d.ts.map +1 -1
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/url.d.ts.map +1 -1
- package/dist/url.js.map +1 -1
- package/package.json +15 -11
- package/src/buffer.ts +0 -1
- package/src/classes/enhanced-date.ts +2 -2
- package/src/classes/path.ts +31 -31
- package/src/enum.ts +11 -5
- package/src/event-awaiter.ts +9 -7
- package/src/general.ts +5 -3
- package/src/logger/_internals/formatter.ts +12 -4
- package/src/logger/_internals/logger.ts +13 -4
- package/src/logger/node/_internals/file-writer.ts +13 -9
- package/src/logger/node/_internals/formatter.ts +3 -1
- package/src/logger/node/index.ts +13 -10
- package/src/logger/node/types.ts +36 -12
- package/src/logger/types.ts +45 -19
- package/src/redis/script-runner.ts +1 -1
- package/src/storages/redis/keyed-store.ts +10 -10
- package/src/storages/redis/msgpack.ts +2 -2
- package/src/time.ts +4 -4
- package/src/types/filtered-key-path.ts +2 -2
- package/src/types/index.ts +6 -0
- package/src/url.ts +0 -1
package/dist/logger/types.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import { SafePromise } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Minimum severity to emit; `success` uses the same threshold as `info`.
|
|
4
|
+
*/
|
|
2
5
|
export type LoggerLevel = 'debug' | 'error' | 'fatal' | 'info' | 'silent' | 'trace' | 'warn';
|
|
3
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* A logging method, including the informational success presentation.
|
|
8
|
+
*/
|
|
4
9
|
export type LoggerMethod = 'success' | Exclude<LoggerLevel, 'silent'>;
|
|
5
10
|
/**
|
|
6
11
|
* A logger whose logging methods never throw or reject for recoverable failures.
|
|
@@ -11,40 +16,60 @@ export type LoggerMethod = 'success' | Exclude<LoggerLevel, 'silent'>;
|
|
|
11
16
|
*/
|
|
12
17
|
export interface Logger {
|
|
13
18
|
configure: (options: Pick<LoggerOptions, 'console' | 'icons' | 'prefix' | 'suffix' | 'timestamp'>) => void;
|
|
14
|
-
debug: (...args: unknown[]) =>
|
|
15
|
-
error: (...args: unknown[]) =>
|
|
16
|
-
fatal: (...args: unknown[]) =>
|
|
17
|
-
info: (...args: unknown[]) =>
|
|
18
|
-
/**
|
|
19
|
+
debug: (...args: unknown[]) => SafePromise<void>;
|
|
20
|
+
error: (...args: unknown[]) => SafePromise<void>;
|
|
21
|
+
fatal: (...args: unknown[]) => SafePromise<void>;
|
|
22
|
+
info: (...args: unknown[]) => SafePromise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Accepts success as an informational method; it is not a configurable threshold.
|
|
25
|
+
*/
|
|
19
26
|
isLevelEnabled: (level: LoggerLevel | LoggerMethod) => boolean;
|
|
20
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Sets a severity threshold (not success); env restores environment-driven filtering.
|
|
29
|
+
*/
|
|
21
30
|
setLevel: (level: 'env' | LoggerLevel) => void;
|
|
22
|
-
success: (...args: unknown[]) =>
|
|
23
|
-
trace: (...args: unknown[]) =>
|
|
24
|
-
warn: (...args: unknown[]) =>
|
|
31
|
+
success: (...args: unknown[]) => SafePromise<void>;
|
|
32
|
+
trace: (...args: unknown[]) => SafePromise<void>;
|
|
33
|
+
warn: (...args: unknown[]) => SafePromise<void>;
|
|
25
34
|
}
|
|
26
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* A shallow-frozen failure notification; nested error values retain their original ownership.
|
|
37
|
+
*/
|
|
27
38
|
export interface LoggerDiagnostic {
|
|
28
39
|
droppedCount?: number;
|
|
29
40
|
error?: unknown;
|
|
30
41
|
message: string;
|
|
31
|
-
/**
|
|
42
|
+
/**
|
|
43
|
+
* Same-type notifications suppressed since the previous emitted diagnostic.
|
|
44
|
+
*/
|
|
32
45
|
suppressedCount?: number;
|
|
33
46
|
type: 'closed' | 'console' | 'file' | 'format' | 'invalid-level' | 'overflow';
|
|
34
47
|
}
|
|
35
|
-
/**
|
|
48
|
+
/**
|
|
49
|
+
* Configuration shared by browser and server loggers.
|
|
50
|
+
*/
|
|
36
51
|
export interface LoggerOptions {
|
|
37
|
-
/**
|
|
52
|
+
/**
|
|
53
|
+
* Enables console output. Defaults to `true`.
|
|
54
|
+
*/
|
|
38
55
|
console?: boolean;
|
|
39
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* Enables Unicode level icons. Defaults to `true`.
|
|
58
|
+
*/
|
|
40
59
|
icons?: boolean;
|
|
41
|
-
/**
|
|
60
|
+
/**
|
|
61
|
+
* Overrides LOG_LEVEL; `env` restores the environment-driven threshold.
|
|
62
|
+
*/
|
|
42
63
|
level?: 'env' | LoggerLevel;
|
|
43
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* Best-effort, rate-limited notification; failures in this callback are contained.
|
|
66
|
+
*/
|
|
44
67
|
onError?: (event: Readonly<LoggerDiagnostic>) => void;
|
|
45
68
|
prefix?: string;
|
|
46
69
|
suffix?: string;
|
|
47
|
-
/**
|
|
70
|
+
/**
|
|
71
|
+
* Enables the fixed local-time millisecond prefix. Defaults to `true`.
|
|
72
|
+
*/
|
|
48
73
|
timestamp?: boolean;
|
|
49
74
|
}
|
|
50
75
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/logger/types.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/logger/types.ts"],"mappings":";;;;YAKY;;;;YAKA,2BAA2B,QAAQ;;;;;;;;iBAS9B;EACb,YAAY,SAAS,KAAK;EAC1B,WAAW,oBAAoB;EAC/B,WAAW,oBAAoB;EAC/B,WAAW,oBAAoB;EAC/B,UAAU,oBAAoB;;;;EAK9B,iBAAiB,OAAO,cAAc;;;;EAKtC,WAAW,eAAe;EAC1B,aAAa,oBAAoB;EACjC,WAAW,oBAAoB;EAC/B,UAAU,oBAAoB;;;;;iBAMjB;EACb;EACA;EACA;;;;EAKA;EACA;;;;;iBAMa;;;;EAIb;;;;EAKA;;;;EAKA,gBAAgB;;;;EAKhB,WAAW,OAAO,SAAS;EAC3B;EACA;;;;EAKA"}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*
|
|
13
13
|
* @returns A promise resolving to the Redis script result after execution completes.
|
|
14
14
|
*/
|
|
15
|
-
export type RedisScriptRunner<T = unknown> = (keys: readonly string[], args:
|
|
15
|
+
export type RedisScriptRunner<T = unknown> = (keys: readonly string[], args: ReadonlyArray<number | string>) => Promise<T>;
|
|
16
16
|
/**
|
|
17
17
|
* A caller-owned Redis client exposing raw command execution.
|
|
18
18
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"script-runner.d.ts","names":[],"sources":["../../src/redis/script-runner.ts"],"mappings":";;;;;;;;;;;;;;YAgBY,kBAAkB,gBAAgB,yBAAyB,
|
|
1
|
+
{"version":3,"file":"script-runner.d.ts","names":[],"sources":["../../src/redis/script-runner.ts"],"mappings":";;;;;;;;;;;;;;YAgBY,kBAAkB,gBAAgB,yBAAyB,MAAM,mCAAmC,QAC5G;;;;;;;;;iBAWa;;;;;;;EAOb,OAAO,iBAAiB,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;wBAwB/B,wBAAwB,aACpC,QAAQ,uBACR,gBACA,uBACD,kBAAkB"}
|
|
@@ -1 +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:
|
|
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: ReadonlyArray<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 +1 @@
|
|
|
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;
|
|
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;EAChB,sBAAA,MAAA,MAAC,QAAA;EACV,aAAA,MAAA,MAAC,QAAA;EACE,gBAAA,MAAA,MAAC;EACJ,aAAA,MAAA,MAAC;EACE,gBAAA,MAAA,MAAC;EACP,gBAAA,MAAA;EACC,UAAA,OAAA,MAAC,MAAW,MAAC;EACH,eAAA,oBAAM,OAAS,MAAC,MAAW,IAAC;EAGpB,uBAAA,oBAAM,OAAS,MAAC,MAAW,IAAC"}
|
|
@@ -17,18 +17,18 @@
|
|
|
17
17
|
*/
|
|
18
18
|
function createRedisKeyedStore(storage) {
|
|
19
19
|
return (keyFn) => Object.freeze({
|
|
20
|
-
getAndRemoveItem: (...args) => storage.getAndRemoveItem(keyFn(...args)),
|
|
21
|
-
getItem: (...args) => storage.getItem(keyFn(...args)),
|
|
22
|
-
getItemTtl: (...args) => storage.getItemTtl(keyFn(...args)),
|
|
23
|
-
hasItem: (...args) => storage.hasItem(keyFn(...args)),
|
|
24
|
-
removeItem: (...args) => storage.removeItem(keyFn(...args)),
|
|
20
|
+
getAndRemoveItem: async (...args) => await storage.getAndRemoveItem(keyFn(...args)),
|
|
21
|
+
getItem: async (...args) => await storage.getItem(keyFn(...args)),
|
|
22
|
+
getItemTtl: async (...args) => await storage.getItemTtl(keyFn(...args)),
|
|
23
|
+
hasItem: async (...args) => await storage.hasItem(keyFn(...args)),
|
|
24
|
+
removeItem: async (...args) => await storage.removeItem(keyFn(...args)),
|
|
25
25
|
resolveKey: (...args) => keyFn(...args),
|
|
26
|
-
setItem: (value, ...args) => storage.setItem(keyFn(...args), value),
|
|
27
|
-
setItemWithTtl(ttlSeconds, value, ...args) {
|
|
28
|
-
return storage.setItemWithTtl(keyFn(...args), ttlSeconds, value);
|
|
26
|
+
setItem: async (value, ...args) => await storage.setItem(keyFn(...args), value),
|
|
27
|
+
async setItemWithTtl(ttlSeconds, value, ...args) {
|
|
28
|
+
return await storage.setItemWithTtl(keyFn(...args), ttlSeconds, value);
|
|
29
29
|
},
|
|
30
|
-
setItemWithTtlIfAbsent(ttlSeconds, value, ...args) {
|
|
31
|
-
return storage.setItemWithTtlIfAbsent(keyFn(...args), ttlSeconds, value);
|
|
30
|
+
async setItemWithTtlIfAbsent(ttlSeconds, value, ...args) {
|
|
31
|
+
return await storage.setItemWithTtlIfAbsent(keyFn(...args), ttlSeconds, value);
|
|
32
32
|
}
|
|
33
33
|
});
|
|
34
34
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyed-store.js","names":[],"sources":["../../../src/storages/redis/keyed-store.ts"],"sourcesContent":["import type { MaybeReadonly } from '../../types';\n\nimport type { RedisLikeStorage } from './types';\n\n/**\n * Creates a keyed store factory sharing a caller-owned Redis-like storage facade.\n *\n * @remarks\n * The key resolver is called synchronously once per operation with the operation's key arguments.\n * Resolver exceptions propagate synchronously; asynchronous storage failures retain the underlying rejection.\n * `setItemWithTtl` and `setItemWithTtlIfAbsent` accept their TTL in seconds before the value and key arguments.\n * The factory does not open or close the underlying connection; cleanup remains the caller's responsibility.\n *\n * @typeParam D - The stored value type used by reads and writes.\n *\n * @param storage - The shared Redis-like storage instance.\n *\n * @returns A factory accepting a key resolver and returning a new frozen keyed facade sharing the storage.\n * Reads, atomic read-and-removals, writes, removals, and TTL results retain the underlying storage contract.\n */\nexport function createRedisKeyedStore<D = unknown>(storage: MaybeReadonly<RedisLikeStorage>) {\n return <P extends any[]>(keyFn: (...args: P) => string) => Object.freeze({\n getAndRemoveItem: (...args: P) => storage.getAndRemoveItem<D>(keyFn(...args)),\n getItem: (...args: P) => storage.getItem<D>(keyFn(...args)),\n getItemTtl: (...args: P) => storage.getItemTtl(keyFn(...args)),\n hasItem: (...args: P) => storage.hasItem(keyFn(...args)),\n removeItem: (...args: P) => storage.removeItem(keyFn(...args)),\n resolveKey: (...args: P) => keyFn(...args),\n setItem: (value: D, ...args: P) => storage.setItem(keyFn(...args), value),\n setItemWithTtl(ttlSeconds: number, value: D, ...args: P) {\n return storage.setItemWithTtl(keyFn(...args), ttlSeconds, value);\n },\n setItemWithTtlIfAbsent(ttlSeconds: number, value: D, ...args: P) {\n return storage.setItemWithTtlIfAbsent(keyFn(...args), ttlSeconds, value);\n },\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAoBA,SAAgB,sBAAmC,SAA0C;CACzF,QAAyB,UAAkC,OAAO,OAAO;EACrE,
|
|
1
|
+
{"version":3,"file":"keyed-store.js","names":[],"sources":["../../../src/storages/redis/keyed-store.ts"],"sourcesContent":["import type { MaybeReadonly } from '../../types';\n\nimport type { RedisLikeStorage } from './types';\n\n/**\n * Creates a keyed store factory sharing a caller-owned Redis-like storage facade.\n *\n * @remarks\n * The key resolver is called synchronously once per operation with the operation's key arguments.\n * Resolver exceptions propagate synchronously; asynchronous storage failures retain the underlying rejection.\n * `setItemWithTtl` and `setItemWithTtlIfAbsent` accept their TTL in seconds before the value and key arguments.\n * The factory does not open or close the underlying connection; cleanup remains the caller's responsibility.\n *\n * @typeParam D - The stored value type used by reads and writes.\n *\n * @param storage - The shared Redis-like storage instance.\n *\n * @returns A factory accepting a key resolver and returning a new frozen keyed facade sharing the storage.\n * Reads, atomic read-and-removals, writes, removals, and TTL results retain the underlying storage contract.\n */\nexport function createRedisKeyedStore<D = unknown>(storage: MaybeReadonly<RedisLikeStorage>) {\n return <P extends any[]>(keyFn: (...args: P) => string) => Object.freeze({\n getAndRemoveItem: async (...args: P) => await storage.getAndRemoveItem<D>(keyFn(...args)),\n getItem: async (...args: P) => await storage.getItem<D>(keyFn(...args)),\n getItemTtl: async (...args: P) => await storage.getItemTtl(keyFn(...args)),\n hasItem: async (...args: P) => await storage.hasItem(keyFn(...args)),\n removeItem: async (...args: P) => await storage.removeItem(keyFn(...args)),\n resolveKey: (...args: P) => keyFn(...args),\n setItem: async (value: D, ...args: P) => await storage.setItem(keyFn(...args), value),\n async setItemWithTtl(ttlSeconds: number, value: D, ...args: P) {\n return await storage.setItemWithTtl(keyFn(...args), ttlSeconds, value);\n },\n async setItemWithTtlIfAbsent(ttlSeconds: number, value: D, ...args: P) {\n return await storage.setItemWithTtlIfAbsent(keyFn(...args), ttlSeconds, value);\n },\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAoBA,SAAgB,sBAAmC,SAA0C;CACzF,QAAyB,UAAkC,OAAO,OAAO;EACrE,kBAAkB,OAAO,GAAG,SAAY,MAAM,QAAQ,iBAAoB,MAAM,GAAG,IAAI,CAAC;EACxF,SAAS,OAAO,GAAG,SAAY,MAAM,QAAQ,QAAW,MAAM,GAAG,IAAI,CAAC;EACtE,YAAY,OAAO,GAAG,SAAY,MAAM,QAAQ,WAAW,MAAM,GAAG,IAAI,CAAC;EACzE,SAAS,OAAO,GAAG,SAAY,MAAM,QAAQ,QAAQ,MAAM,GAAG,IAAI,CAAC;EACnE,YAAY,OAAO,GAAG,SAAY,MAAM,QAAQ,WAAW,MAAM,GAAG,IAAI,CAAC;EACzE,aAAa,GAAG,SAAY,MAAM,GAAG,IAAI;EACzC,SAAS,OAAO,OAAU,GAAG,SAAY,MAAM,QAAQ,QAAQ,MAAM,GAAG,IAAI,GAAG,KAAK;EACpF,MAAM,eAAe,YAAoB,OAAU,GAAG,MAAS;GAC3D,OAAO,MAAM,QAAQ,eAAe,MAAM,GAAG,IAAI,GAAG,YAAY,KAAK;EACzE;EACA,MAAM,uBAAuB,YAAoB,OAAU,GAAG,MAAS;GACnE,OAAO,MAAM,QAAQ,uBAAuB,MAAM,GAAG,IAAI,GAAG,YAAY,KAAK;EACjF;CACJ,CAAC;AACL"}
|
|
@@ -61,8 +61,8 @@ function createRedisMsgpackStorage(adapter) {
|
|
|
61
61
|
const rawValue = await adapter.getBuffer(key);
|
|
62
62
|
return rawValue ? decode(rawValue) : null;
|
|
63
63
|
},
|
|
64
|
-
getItemTtl: (key) => adapter.ttl(key),
|
|
65
|
-
hasItem: (key) => adapter.has(key),
|
|
64
|
+
getItemTtl: async (key) => await adapter.ttl(key),
|
|
65
|
+
hasItem: async (key) => await adapter.has(key),
|
|
66
66
|
removeItem: async (key) => await adapter.delete(key) === 1,
|
|
67
67
|
setItem: async (key, value) => await adapter.setBuffer(key, encode(value)) === "OK",
|
|
68
68
|
async setItemWithTtl(key, ttlSeconds, value) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"msgpack.js","names":[],"sources":["../../../src/storages/redis/msgpack.ts"],"sourcesContent":["import {\n decode,\n encode,\n isNativeAccelerationEnabled,\n} from 'msgpackr';\n\nimport type {\n RedisLikeAdapter,\n RedisLikeStorage,\n} from './types';\n\nif (!isNativeAccelerationEnabled) {\n console.warn('Native acceleration not enabled for msgpackr, verify that install finished properly');\n}\n\n/**\n * Creates a frozen Redis-like storage facade using MessagePack serialization.\n *\n * @remarks\n * Adapter rejections and MessagePack serialization errors propagate to the caller.\n * Reads resolve to `null` when no raw value exists; `getAndRemoveItem` reads and deletes in one atomic adapter call.\n * Writes resolve to `true` only when the adapter returns `OK`;\n * removal resolves to `true` only when exactly one key is deleted.\n * The adapter remains caller-owned; creating the facade does not open or close a connection.\n *\n * @param adapter - The caller-owned adapter for raw binary operations.\n *\n * @returns A new frozen facade sharing the supplied adapter.\n *\n * @example\n *\n * ```ts\n * import { createRedisMsgpackStorage } from '@kikiutils/shared/storages/redis/msgpack';\n * import type { RedisLikeAdapter } from '@kikiutils/shared/storages/redis/types';\n *\n * // This in-memory adapter demonstrates non-expiring operations without an external service.\n * const values = new Map<string, Uint8Array>();\n * const adapter: RedisLikeAdapter = {\n * delete: async (key) => values.delete(key) ? 1 : 0,\n * getBuffer: async (key) => values.get(key) ?? null,\n * getBufferAndDelete: async (key) => {\n * const value = values.get(key) ?? null;\n * values.delete(key);\n * return value;\n * },\n * has: async (key) => values.has(key),\n * setBuffer: async (key, value) => {\n * values.set(key, value);\n * return 'OK';\n * },\n * setBufferEx: async () => {\n * throw new Error('TTL writes are not supported by this example adapter');\n * },\n * setBufferExNx: async () => {\n * throw new Error('TTL writes are not supported by this example adapter');\n * },\n * ttl: async (key) => values.has(key) ? -1 : -2,\n * };\n *\n * const storage = createRedisMsgpackStorage(adapter);\n * await storage.setItem('profile', { name: 'Alice' });\n * const profile = await storage.getItem<{ name: string }>('profile');\n * console.log(profile); // => { name: 'Alice' }\n * ```\n */\nexport function createRedisMsgpackStorage(adapter: RedisLikeAdapter): Readonly<RedisLikeStorage> {\n return Object.freeze({\n async getAndRemoveItem<T = unknown>(key: string) {\n const rawValue = await adapter.getBufferAndDelete(key);\n return rawValue ? decode(rawValue) as T : null;\n },\n async getItem<T = unknown>(key: string) {\n const rawValue = await adapter.getBuffer(key);\n return rawValue ? decode(rawValue) as T : null;\n },\n getItemTtl: (key: string) => adapter.ttl(key),\n hasItem: (key: string) => adapter.has(key),\n removeItem: async (key: string) => await adapter.delete(key) === 1,\n setItem: async (key: string, value: any) => await adapter.setBuffer(key, encode(value)) === 'OK',\n async setItemWithTtl(key: string, ttlSeconds: number, value: any) {\n return await adapter.setBufferEx(key, ttlSeconds, encode(value)) === 'OK';\n },\n async setItemWithTtlIfAbsent(key: string, ttlSeconds: number, value: any) {\n return await adapter.setBufferExNx(key, ttlSeconds, encode(value)) === 'OK';\n },\n });\n}\n"],"mappings":";;AAWA,IAAI,CAAC,6BACD,QAAQ,KAAK,qFAAqF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqDtG,SAAgB,0BAA0B,SAAuD;CAC7F,OAAO,OAAO,OAAO;EACjB,MAAM,iBAA8B,KAAa;GAC7C,MAAM,WAAW,MAAM,QAAQ,mBAAmB,GAAG;GACrD,OAAO,WAAW,OAAO,QAAQ,IAAS;EAC9C;EACA,MAAM,QAAqB,KAAa;GACpC,MAAM,WAAW,MAAM,QAAQ,UAAU,GAAG;GAC5C,OAAO,WAAW,OAAO,QAAQ,IAAS;EAC9C;EACA,
|
|
1
|
+
{"version":3,"file":"msgpack.js","names":[],"sources":["../../../src/storages/redis/msgpack.ts"],"sourcesContent":["import {\n decode,\n encode,\n isNativeAccelerationEnabled,\n} from 'msgpackr';\n\nimport type {\n RedisLikeAdapter,\n RedisLikeStorage,\n} from './types';\n\nif (!isNativeAccelerationEnabled) {\n console.warn('Native acceleration not enabled for msgpackr, verify that install finished properly');\n}\n\n/**\n * Creates a frozen Redis-like storage facade using MessagePack serialization.\n *\n * @remarks\n * Adapter rejections and MessagePack serialization errors propagate to the caller.\n * Reads resolve to `null` when no raw value exists; `getAndRemoveItem` reads and deletes in one atomic adapter call.\n * Writes resolve to `true` only when the adapter returns `OK`;\n * removal resolves to `true` only when exactly one key is deleted.\n * The adapter remains caller-owned; creating the facade does not open or close a connection.\n *\n * @param adapter - The caller-owned adapter for raw binary operations.\n *\n * @returns A new frozen facade sharing the supplied adapter.\n *\n * @example\n *\n * ```ts\n * import { createRedisMsgpackStorage } from '@kikiutils/shared/storages/redis/msgpack';\n * import type { RedisLikeAdapter } from '@kikiutils/shared/storages/redis/types';\n *\n * // This in-memory adapter demonstrates non-expiring operations without an external service.\n * const values = new Map<string, Uint8Array>();\n * const adapter: RedisLikeAdapter = {\n * delete: async (key) => values.delete(key) ? 1 : 0,\n * getBuffer: async (key) => values.get(key) ?? null,\n * getBufferAndDelete: async (key) => {\n * const value = values.get(key) ?? null;\n * values.delete(key);\n * return value;\n * },\n * has: async (key) => values.has(key),\n * setBuffer: async (key, value) => {\n * values.set(key, value);\n * return 'OK';\n * },\n * setBufferEx: async () => {\n * throw new Error('TTL writes are not supported by this example adapter');\n * },\n * setBufferExNx: async () => {\n * throw new Error('TTL writes are not supported by this example adapter');\n * },\n * ttl: async (key) => values.has(key) ? -1 : -2,\n * };\n *\n * const storage = createRedisMsgpackStorage(adapter);\n * await storage.setItem('profile', { name: 'Alice' });\n * const profile = await storage.getItem<{ name: string }>('profile');\n * console.log(profile); // => { name: 'Alice' }\n * ```\n */\nexport function createRedisMsgpackStorage(adapter: RedisLikeAdapter): Readonly<RedisLikeStorage> {\n return Object.freeze({\n async getAndRemoveItem<T = unknown>(key: string) {\n const rawValue = await adapter.getBufferAndDelete(key);\n return rawValue ? decode(rawValue) as T : null;\n },\n async getItem<T = unknown>(key: string) {\n const rawValue = await adapter.getBuffer(key);\n return rawValue ? decode(rawValue) as T : null;\n },\n getItemTtl: async (key: string) => await adapter.ttl(key),\n hasItem: async (key: string) => await adapter.has(key),\n removeItem: async (key: string) => await adapter.delete(key) === 1,\n setItem: async (key: string, value: any) => await adapter.setBuffer(key, encode(value)) === 'OK',\n async setItemWithTtl(key: string, ttlSeconds: number, value: any) {\n return await adapter.setBufferEx(key, ttlSeconds, encode(value)) === 'OK';\n },\n async setItemWithTtlIfAbsent(key: string, ttlSeconds: number, value: any) {\n return await adapter.setBufferExNx(key, ttlSeconds, encode(value)) === 'OK';\n },\n });\n}\n"],"mappings":";;AAWA,IAAI,CAAC,6BACD,QAAQ,KAAK,qFAAqF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqDtG,SAAgB,0BAA0B,SAAuD;CAC7F,OAAO,OAAO,OAAO;EACjB,MAAM,iBAA8B,KAAa;GAC7C,MAAM,WAAW,MAAM,QAAQ,mBAAmB,GAAG;GACrD,OAAO,WAAW,OAAO,QAAQ,IAAS;EAC9C;EACA,MAAM,QAAqB,KAAa;GACpC,MAAM,WAAW,MAAM,QAAQ,UAAU,GAAG;GAC5C,OAAO,WAAW,OAAO,QAAQ,IAAS;EAC9C;EACA,YAAY,OAAO,QAAgB,MAAM,QAAQ,IAAI,GAAG;EACxD,SAAS,OAAO,QAAgB,MAAM,QAAQ,IAAI,GAAG;EACrD,YAAY,OAAO,QAAgB,MAAM,QAAQ,OAAO,GAAG,MAAM;EACjE,SAAS,OAAO,KAAa,UAAe,MAAM,QAAQ,UAAU,KAAK,OAAO,KAAK,CAAC,MAAM;EAC5F,MAAM,eAAe,KAAa,YAAoB,OAAY;GAC9D,OAAO,MAAM,QAAQ,YAAY,KAAK,YAAY,OAAO,KAAK,CAAC,MAAM;EACzE;EACA,MAAM,uBAAuB,KAAa,YAAoB,OAAY;GACtE,OAAO,MAAM,QAAQ,cAAc,KAAK,YAAY,OAAO,KAAK,CAAC,MAAM;EAC3E;CACJ,CAAC;AACL"}
|
package/dist/time.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time.d.ts","names":[],"sources":["../src/time.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"time.d.ts","names":[],"sources":["../src/time.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;wBAoBsB,MAAM,YAAY,SAAS,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;wBA2CzC,aAAa,YAAY,SAAS,cAAc"}
|
package/dist/time.js
CHANGED
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
* await delay(5000, controller.signal);
|
|
20
20
|
* ```
|
|
21
21
|
*/
|
|
22
|
-
function delay(ms, signal) {
|
|
23
|
-
return new Promise((resolve) => {
|
|
22
|
+
async function delay(ms, signal) {
|
|
23
|
+
return await new Promise((resolve) => {
|
|
24
24
|
if (signal?.aborted) {
|
|
25
25
|
resolve();
|
|
26
26
|
return;
|
|
@@ -58,8 +58,8 @@ function delay(ms, signal) {
|
|
|
58
58
|
* }
|
|
59
59
|
* ```
|
|
60
60
|
*/
|
|
61
|
-
function delayOrThrow(ms, signal) {
|
|
62
|
-
return new Promise((resolve, reject) => {
|
|
61
|
+
async function delayOrThrow(ms, signal) {
|
|
62
|
+
return await new Promise((resolve, reject) => {
|
|
63
63
|
if (signal?.aborted) {
|
|
64
64
|
reject(signal.reason);
|
|
65
65
|
return;
|
package/dist/time.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time.js","names":[],"sources":["../src/time.ts"],"sourcesContent":["/**\n * Waits until a duration elapses or cancellation occurs without rejecting on cancellation.\n *\n * @remarks\n * The promise resolves without a value when the timer completes or the signal aborts.\n * An already aborted signal resolves immediately; completion removes the abort listener and clears the timer.\n *\n * @param ms - The delay duration in milliseconds, using native `setTimeout` timing rules.\n * @param signal - The signal that ends the wait early.\n *\n * @example\n *\n * ```ts\n * import { delay } from '@kikiutils/shared/time';\n *\n * const controller = new AbortController();\n * controller.abort();\n * await delay(5000, controller.signal);\n * ```\n */\nexport function delay(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n if (signal?.aborted) {\n resolve();\n return;\n }\n\n const done = () => {\n // eslint-disable-next-line ts/no-use-before-define\n clearTimeout(timeout);\n signal?.removeEventListener('abort', done);\n resolve();\n };\n\n const timeout = setTimeout(done, ms);\n signal?.addEventListener('abort', done, { once: true });\n });\n}\n\n/**\n * Waits until a duration elapses and rejects on cancellation.\n *\n * @remarks\n * The promise resolves without a value when the timer completes and rejects with `signal.reason` if aborted.\n * An already aborted signal rejects immediately. Aborting clears the timer; timer completion removes the listener.\n *\n * @param ms - The delay duration in milliseconds, using native `setTimeout` timing rules.\n * @param signal - The signal that cancels the wait.\n *\n * @example\n *\n * ```ts\n * import { delayOrThrow } from '@kikiutils/shared/time';\n *\n * const controller = new AbortController();\n * controller.abort(new Error('Canceled'));\n * try {\n * await delayOrThrow(5000, controller.signal);\n * } catch (error) {\n * console.error(error);\n * }\n * ```\n */\nexport function delayOrThrow(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason);\n return;\n }\n\n const onAbort = () => {\n // eslint-disable-next-line ts/no-use-before-define\n clearTimeout(timeout);\n reject(signal!.reason);\n };\n\n const timeout = setTimeout(\n () => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n },\n ms,\n );\n\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAoBA,
|
|
1
|
+
{"version":3,"file":"time.js","names":[],"sources":["../src/time.ts"],"sourcesContent":["/**\n * Waits until a duration elapses or cancellation occurs without rejecting on cancellation.\n *\n * @remarks\n * The promise resolves without a value when the timer completes or the signal aborts.\n * An already aborted signal resolves immediately; completion removes the abort listener and clears the timer.\n *\n * @param ms - The delay duration in milliseconds, using native `setTimeout` timing rules.\n * @param signal - The signal that ends the wait early.\n *\n * @example\n *\n * ```ts\n * import { delay } from '@kikiutils/shared/time';\n *\n * const controller = new AbortController();\n * controller.abort();\n * await delay(5000, controller.signal);\n * ```\n */\nexport async function delay(ms: number, signal?: AbortSignal): Promise<void> {\n return await new Promise((resolve) => {\n if (signal?.aborted) {\n resolve();\n return;\n }\n\n const done = () => {\n // eslint-disable-next-line ts/no-use-before-define\n clearTimeout(timeout);\n signal?.removeEventListener('abort', done);\n resolve();\n };\n\n const timeout = setTimeout(done, ms);\n signal?.addEventListener('abort', done, { once: true });\n });\n}\n\n/**\n * Waits until a duration elapses and rejects on cancellation.\n *\n * @remarks\n * The promise resolves without a value when the timer completes and rejects with `signal.reason` if aborted.\n * An already aborted signal rejects immediately. Aborting clears the timer; timer completion removes the listener.\n *\n * @param ms - The delay duration in milliseconds, using native `setTimeout` timing rules.\n * @param signal - The signal that cancels the wait.\n *\n * @example\n *\n * ```ts\n * import { delayOrThrow } from '@kikiutils/shared/time';\n *\n * const controller = new AbortController();\n * controller.abort(new Error('Canceled'));\n * try {\n * await delayOrThrow(5000, controller.signal);\n * } catch (error) {\n * console.error(error);\n * }\n * ```\n */\nexport async function delayOrThrow(ms: number, signal?: AbortSignal): Promise<void> {\n return await new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason);\n return;\n }\n\n const onAbort = () => {\n // eslint-disable-next-line ts/no-use-before-define\n clearTimeout(timeout);\n reject(signal!.reason);\n };\n\n const timeout = setTimeout(\n () => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n },\n ms,\n );\n\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAoBA,eAAsB,MAAM,IAAY,QAAqC;CACzE,OAAO,MAAM,IAAI,SAAS,YAAY;EAClC,IAAI,QAAQ,SAAS;GACjB,QAAQ;GACR;EACJ;EAEA,MAAM,aAAa;GAEf,aAAa,OAAO;GACpB,QAAQ,oBAAoB,SAAS,IAAI;GACzC,QAAQ;EACZ;EAEA,MAAM,UAAU,WAAW,MAAM,EAAE;EACnC,QAAQ,iBAAiB,SAAS,MAAM,EAAE,MAAM,KAAK,CAAC;CAC1D,CAAC;AACL;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,eAAsB,aAAa,IAAY,QAAqC;CAChF,OAAO,MAAM,IAAI,SAAS,SAAS,WAAW;EAC1C,IAAI,QAAQ,SAAS;GACjB,OAAO,OAAO,MAAM;GACpB;EACJ;EAEA,MAAM,gBAAgB;GAElB,aAAa,OAAO;GACpB,OAAO,OAAQ,MAAM;EACzB;EAEA,MAAM,UAAU,iBACN;GACF,QAAQ,oBAAoB,SAAS,OAAO;GAC5C,QAAQ;EACZ,GACA,EACJ;EAEA,QAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;CAC7D,CAAC;AACL"}
|
|
@@ -8,9 +8,9 @@ type DefaultPath<K extends number | string, V, U = never, RK = `${K}`> = V exten
|
|
|
8
8
|
* @typeParam U - The value type to select; `never` disables filtering.
|
|
9
9
|
*/
|
|
10
10
|
export type FilteredKeyPath<T, U = never> = T extends ReadonlyArray<infer V> ? (IsTuple<T> extends true ? { [K in TupleKey<T>]-?: PathImpl<Exclude<K, symbol>, T[K], U>; }[TupleKey<T>] : PathImpl<number, V, U>) : { [K in keyof T]-?: PathImpl<Exclude<K, symbol>, T[K], U>; }[keyof T];
|
|
11
|
-
type IsTuple<T extends
|
|
11
|
+
type IsTuple<T extends readonly any[]> = number extends T['length'] ? false : true;
|
|
12
12
|
type PathImpl<K extends number | string, V, U> = [U] extends [never] ? DefaultPath<K, V> : ConditionalPath<K, V, U>;
|
|
13
13
|
type TerminalType = bigint | Blob | boolean | Date | File | null | number | ObjectId | RegExp | string | symbol | undefined;
|
|
14
|
-
type TupleKey<T extends
|
|
14
|
+
type TupleKey<T extends readonly any[]> = Exclude<keyof T, keyof any[]>;
|
|
15
15
|
export {};
|
|
16
16
|
//# sourceMappingURL=filtered-key-path.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filtered-key-path.d.ts","names":[],"sources":["../../src/types/filtered-key-path.ts"],"mappings":";KAKK,gBAAgB,2BAA2B,GAAG,KAAK,UAAU,OAAO,MAAM,YAAY,GAAG,GAAG;KAC5F,YACD,2BACA,GACA,WACA,QAAQ,OACR,UAAU,eAAe,QAAQ,KAAK,gBAAgB,GAAG;;;;;;;YAUjD,gBAAgB,GAAG,aAAa,UAAU,oBAAoB,MAAM,QAAQ,qBAAqB,KAAK,SAAS,OAAO,SAAS,QAAQ,YAAY,EAAE,IAAI,MAAK,SAAS,MAAM,iBAAiB,GAAG,SAAS,WAAW,MAAM,SAAS,QAAQ,YAAY,EAAE,IAAI,YAAW;KAGhR,QAAQ,
|
|
1
|
+
{"version":3,"file":"filtered-key-path.d.ts","names":[],"sources":["../../src/types/filtered-key-path.ts"],"mappings":";KAKK,gBAAgB,2BAA2B,GAAG,KAAK,UAAU,OAAO,MAAM,YAAY,GAAG,GAAG;KAC5F,YACD,2BACA,GACA,WACA,QAAQ,OACR,UAAU,eAAe,QAAQ,KAAK,gBAAgB,GAAG;;;;;;;YAUjD,gBAAgB,GAAG,aAAa,UAAU,oBAAoB,MAAM,QAAQ,qBAAqB,KAAK,SAAS,OAAO,SAAS,QAAQ,YAAY,EAAE,IAAI,MAAK,SAAS,MAAM,iBAAiB,GAAG,SAAS,WAAW,MAAM,SAAS,QAAQ,YAAY,EAAE,IAAI,YAAW;KAGhR,QAAQ,2CAA2C;KACnD,SAAS,2BAA2B,GAAG,MAAM,qBAAqB,YAAY,GAAG,KAAK,gBAAgB,GAAG,GAAG;KAC5G,wBAED,iBAEA,OACA,uBAGA,WACA;KAKC,SAAS,4BAA4B,cAAc"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -28,5 +28,12 @@ export type ReadonlyPartialRecord<K extends keyof any, T> = Readonly<PartialReco
|
|
|
28
28
|
* A readonly `Record`.
|
|
29
29
|
*/
|
|
30
30
|
export type ReadonlyRecord<K extends keyof any, T> = Readonly<Record<K, T>>;
|
|
31
|
+
/**
|
|
32
|
+
* A promise whose rejection is handled internally and can safely be left unawaited.
|
|
33
|
+
* This type only marks that contract; it does not add runtime rejection handling.
|
|
34
|
+
*/
|
|
35
|
+
export type SafePromise<T> = Promise<T> & {
|
|
36
|
+
readonly __safePromise?: true;
|
|
37
|
+
};
|
|
31
38
|
export type { FilteredKeyPath };
|
|
32
39
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":["NodeBlob","NodeFile"],"sources":["../../src/types/index.ts"],"mappings":";;;;;YAWY,cAAc,cAAc,OAAO,SAAS,OAAOA,SAAWC,SAAW;;;;YAKzE;;;;YAKA,aAAa,KAAK,QAAQ,KAAK;;;;YAK/B,cAAc,KAAK,SAAS,KAAK;;;;YAKjC,cAAc,qBAAqB,KAAK,QAAQ,OAAO,GAAG;;;;YAK1D,sBAAsB,qBAAqB,KAAK,SAAS,cAAc,GAAG;;;;YAK1E,eAAe,qBAAqB,KAAK,SAAS,OAAO,GAAG"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":["NodeBlob","NodeFile"],"sources":["../../src/types/index.ts"],"mappings":";;;;;YAWY,cAAc,cAAc,OAAO,SAAS,OAAOA,SAAWC,SAAW;;;;YAKzE;;;;YAKA,aAAa,KAAK,QAAQ,KAAK;;;;YAK/B,cAAc,KAAK,SAAS,KAAK;;;;YAKjC,cAAc,qBAAqB,KAAK,QAAQ,OAAO,GAAG;;;;YAK1D,sBAAsB,qBAAqB,KAAK,SAAS,cAAc,GAAG;;;;YAK1E,eAAe,qBAAqB,KAAK,SAAS,OAAO,GAAG;;;;;YAM5D,YAAY,KAAK,QAAQ;WAAgB"}
|
package/dist/url.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url.d.ts","names":[],"sources":["../src/url.ts"],"mappings":";;;;;;;;;;;;;wBAagB,yBAAyB,aAAa;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"url.d.ts","names":[],"sources":["../src/url.ts"],"mappings":";;;;;;;;;;;;;wBAagB,yBAAyB,aAAa;;;;;;;;;;;;;wBAuBtC,mBAAmB,iBAAiB;;;;;;;;;;;;;wBAoBpC,sBAAsB,gBAAgB"}
|
package/dist/url.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url.js","names":[],"sources":["../src/url.ts"],"sourcesContent":["/**\n * Appends or updates the `redirect` query parameter on a given URL.\n *\n * @remarks\n * Typically used to preserve the user's current path for post-login navigation.\n *\n * @param url - The target URL to modify.\n * @param redirectPath - The safe same-origin application path starting with `/` to use as the redirect destination.\n *\n * @returns A new URL string with the `redirect` query parameter.\n *\n * @throws Error if `redirectPath` is not a safe same-origin application path.\n */\nexport function appendRedirectParamToUrl(url: string, redirectPath: string) {\n
|
|
1
|
+
{"version":3,"file":"url.js","names":[],"sources":["../src/url.ts"],"sourcesContent":["/**\n * Appends or updates the `redirect` query parameter on a given URL.\n *\n * @remarks\n * Typically used to preserve the user's current path for post-login navigation.\n *\n * @param url - The target URL to modify.\n * @param redirectPath - The safe same-origin application path starting with `/` to use as the redirect destination.\n *\n * @returns A new URL string with the `redirect` query parameter.\n *\n * @throws Error if `redirectPath` is not a safe same-origin application path.\n */\nexport function appendRedirectParamToUrl(url: string, redirectPath: string) {\n if (!isSafeRedirectPath(redirectPath)) throw new Error(`Invalid redirect path: \"${redirectPath}\". Redirect paths must be safe same-origin paths starting with '/'.`);\n\n const [baseAndHash, rawQuery = ''] = url.split('?');\n const [base, hash] = (baseAndHash || '').split('#');\n const searchParams = new URLSearchParams(rawQuery);\n searchParams.set('redirect', redirectPath);\n const queryString = searchParams.toString();\n return hash ? `${base}?${queryString}#${hash}` : `${base}?${queryString}`;\n}\n\n/**\n * Returns whether a value is a safe same-origin redirect path.\n *\n * @remarks\n * Safe redirect paths are absolute application paths such as `/dashboard`.\n * Protocol-relative URLs (`//example.com`), absolute URLs, backslash paths,\n * and non-string values are rejected.\n *\n * @param value - The value to check.\n *\n * @returns Whether the value is safe to use as an application redirect path.\n */\nexport function isSafeRedirectPath(value: unknown): value is string {\n if (typeof value !== 'string') return false;\n if (!value.startsWith('/')) return false;\n if (value.startsWith('//')) return false;\n if (value.includes('\\\\')) return false;\n return true;\n}\n\n/**\n * Normalizes a redirect value into a safe same-origin application path.\n *\n * @remarks\n * If an array is provided, the first value is checked. Unsafe values fall back\n * to the provided fallback path.\n *\n * @param value - The redirect value to normalize.\n * @param fallback - The caller-supplied safe fallback path; it is returned unchanged and is not validated.\n *\n * @returns The validated input path, or the unvalidated fallback path.\n */\nexport function normalizeRedirectPath(value: unknown, fallback = '/') {\n const redirectPath = Array.isArray(value) ? value[0] : value;\n return isSafeRedirectPath(redirectPath) ? redirectPath : fallback;\n}\n"],"mappings":";;;;;;;;;;;;;;AAaA,SAAgB,yBAAyB,KAAa,cAAsB;CACxE,IAAI,CAAC,mBAAmB,YAAY,GAAG,MAAM,IAAI,MAAM,2BAA2B,aAAa,oEAAoE;CAEnK,MAAM,CAAC,aAAa,WAAW,MAAM,IAAI,MAAM,GAAG;CAClD,MAAM,CAAC,MAAM,SAAS,eAAe,GAAA,CAAI,MAAM,GAAG;CAClD,MAAM,eAAe,IAAI,gBAAgB,QAAQ;CACjD,aAAa,IAAI,YAAY,YAAY;CACzC,MAAM,cAAc,aAAa,SAAS;CAC1C,OAAO,OAAO,GAAG,KAAK,GAAG,YAAY,GAAG,SAAS,GAAG,KAAK,GAAG;AAChE;;;;;;;;;;;;;AAcA,SAAgB,mBAAmB,OAAiC;CAChE,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,IAAI,CAAC,MAAM,WAAW,GAAG,GAAG,OAAO;CACnC,IAAI,MAAM,WAAW,IAAI,GAAG,OAAO;CACnC,IAAI,MAAM,SAAS,IAAI,GAAG,OAAO;CACjC,OAAO;AACX;;;;;;;;;;;;;AAcA,SAAgB,sBAAsB,OAAgB,WAAW,KAAK;CAClE,MAAM,eAAe,MAAM,QAAQ,KAAK,IAAI,MAAM,KAAK;CACvD,OAAO,mBAAmB,YAAY,IAAI,eAAe;AAC7D"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kikiutils/shared",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "20.
|
|
4
|
+
"version": "20.1.1",
|
|
5
5
|
"description": "A lightweight and modular utility library for modern JavaScript and TypeScript — includes secure hashing, flexible logging, datetime tools, Vue/web helpers, storage abstraction, and more.",
|
|
6
6
|
"author": "kiki-kanri",
|
|
7
7
|
"license": "MIT",
|
|
@@ -143,35 +143,39 @@
|
|
|
143
143
|
"optional": true
|
|
144
144
|
}
|
|
145
145
|
},
|
|
146
|
+
"dependencies": {
|
|
147
|
+
"ts-extras": "^2.0.0",
|
|
148
|
+
"type-fest": "^5.10.0"
|
|
149
|
+
},
|
|
146
150
|
"devDependencies": {
|
|
147
151
|
"@antfu/eslint-config": "^10.0.0",
|
|
148
152
|
"@arethetypeswrong/core": "^0.18.5",
|
|
149
|
-
"@kikiutils/eslint-config": "^
|
|
153
|
+
"@kikiutils/eslint-config": "^11.0.0",
|
|
150
154
|
"@kikiutils/tsconfigs": "^7.0.0",
|
|
151
155
|
"@noble/hashes": "^2.4.0",
|
|
152
156
|
"@types/node": "^26.6.6",
|
|
153
|
-
"@vitest/coverage-v8": "^5.0
|
|
157
|
+
"@vitest/coverage-v8": "^5.1.0",
|
|
154
158
|
"async-validator": "^4.2.5",
|
|
155
|
-
"bson": "^7.3.
|
|
159
|
+
"bson": "^7.3.4",
|
|
156
160
|
"changelogen": "^0.6.2",
|
|
157
161
|
"cross-env": "^10.1.0",
|
|
158
162
|
"date-fns": "^4.4.0",
|
|
159
163
|
"decimal.js": "^10.6.0",
|
|
160
|
-
"element-plus": "^2.14.
|
|
164
|
+
"element-plus": "^2.14.8",
|
|
161
165
|
"eslint": "^10.14.0",
|
|
162
166
|
"file-type": "^22.3.0",
|
|
163
|
-
"jsdom": "^
|
|
164
|
-
"knip": "^6.44.
|
|
167
|
+
"jsdom": "^31.0.0",
|
|
168
|
+
"knip": "^6.44.2",
|
|
165
169
|
"lru-cache": "^11.5.3",
|
|
166
170
|
"millify": "^6.1.0",
|
|
167
|
-
"msgpackr": "^2.1.
|
|
171
|
+
"msgpackr": "^2.1.4",
|
|
168
172
|
"publint": "^0.3.25",
|
|
169
173
|
"rotating-file-stream": "^3.2.10",
|
|
170
|
-
"tsdown": "^0.23.
|
|
174
|
+
"tsdown": "^0.23.7",
|
|
171
175
|
"typescript": "^6.0.3",
|
|
172
176
|
"unplugin-unused": "^0.6.0",
|
|
173
|
-
"vitest": "^5.0
|
|
174
|
-
"vue": "^3.5.
|
|
177
|
+
"vitest": "^5.1.0",
|
|
178
|
+
"vue": "^3.5.45",
|
|
175
179
|
"vue-router": "^5.4.0"
|
|
176
180
|
}
|
|
177
181
|
}
|
package/src/buffer.ts
CHANGED
|
@@ -36,6 +36,5 @@ export async function toBuffer(input: BinaryInput) {
|
|
|
36
36
|
if (input instanceof ArrayBuffer) return Buffer.from(input);
|
|
37
37
|
if (input instanceof Uint8Array) return Buffer.from(input.buffer, input.byteOffset, input.byteLength);
|
|
38
38
|
if (typeof input.arrayBuffer === 'function') return Buffer.from(await input.arrayBuffer());
|
|
39
|
-
// eslint-disable-next-line style/max-len
|
|
40
39
|
throw new TypeError('The provided input is not a supported binary type (Blob, Buffer, File, ArrayBuffer, or Uint8Array).');
|
|
41
40
|
}
|
|
@@ -100,7 +100,7 @@ export class EnhancedDate extends Date {
|
|
|
100
100
|
*
|
|
101
101
|
* @returns A new `EnhancedDate`, or `Invalid Date` if the array is empty or contains an invalid date.
|
|
102
102
|
*/
|
|
103
|
-
static max(dates:
|
|
103
|
+
static max(dates: Array<Date | number>) {
|
|
104
104
|
return new EnhancedDate(dateFns.max(dates));
|
|
105
105
|
}
|
|
106
106
|
|
|
@@ -111,7 +111,7 @@ export class EnhancedDate extends Date {
|
|
|
111
111
|
*
|
|
112
112
|
* @returns A new `EnhancedDate`, or `Invalid Date` if the array is empty or contains an invalid date.
|
|
113
113
|
*/
|
|
114
|
-
static min(dates:
|
|
114
|
+
static min(dates: Array<Date | number>) {
|
|
115
115
|
return new EnhancedDate(dateFns.min(dates));
|
|
116
116
|
}
|
|
117
117
|
|
package/src/classes/path.ts
CHANGED
|
@@ -241,8 +241,8 @@ export class Path {
|
|
|
241
241
|
*
|
|
242
242
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.access}
|
|
243
243
|
*/
|
|
244
|
-
access(...args: DropFirstParameters<typeof fsp.access>) {
|
|
245
|
-
return fsp.access(this.#value, ...args);
|
|
244
|
+
async access(...args: DropFirstParameters<typeof fsp.access>) {
|
|
245
|
+
return await fsp.access(this.#value, ...args);
|
|
246
246
|
}
|
|
247
247
|
|
|
248
248
|
/**
|
|
@@ -253,8 +253,8 @@ export class Path {
|
|
|
253
253
|
*
|
|
254
254
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.appendFile}
|
|
255
255
|
*/
|
|
256
|
-
appendFile(...args: DropFirstParameters<typeof fsp.appendFile>) {
|
|
257
|
-
return fsp.appendFile(this.#value, ...args);
|
|
256
|
+
async appendFile(...args: DropFirstParameters<typeof fsp.appendFile>) {
|
|
257
|
+
return await fsp.appendFile(this.#value, ...args);
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
/**
|
|
@@ -265,8 +265,8 @@ export class Path {
|
|
|
265
265
|
*
|
|
266
266
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.chmod}
|
|
267
267
|
*/
|
|
268
|
-
chmod(...args: DropFirstParameters<typeof fsp.chmod>) {
|
|
269
|
-
return fsp.chmod(this.#value, ...args);
|
|
268
|
+
async chmod(...args: DropFirstParameters<typeof fsp.chmod>) {
|
|
269
|
+
return await fsp.chmod(this.#value, ...args);
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
/**
|
|
@@ -277,8 +277,8 @@ export class Path {
|
|
|
277
277
|
*
|
|
278
278
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.chown}
|
|
279
279
|
*/
|
|
280
|
-
chown(...args: DropFirstParameters<typeof fsp.chown>) {
|
|
281
|
-
return fsp.chown(this.#value, ...args);
|
|
280
|
+
async chown(...args: DropFirstParameters<typeof fsp.chown>) {
|
|
281
|
+
return await fsp.chown(this.#value, ...args);
|
|
282
282
|
}
|
|
283
283
|
|
|
284
284
|
/**
|
|
@@ -289,8 +289,8 @@ export class Path {
|
|
|
289
289
|
*
|
|
290
290
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.copyFile}
|
|
291
291
|
*/
|
|
292
|
-
copyFile(...args: DropFirstParameters<typeof fsp.copyFile>) {
|
|
293
|
-
return fsp.copyFile(this.#value, ...args);
|
|
292
|
+
async copyFile(...args: DropFirstParameters<typeof fsp.copyFile>) {
|
|
293
|
+
return await fsp.copyFile(this.#value, ...args);
|
|
294
294
|
}
|
|
295
295
|
|
|
296
296
|
/**
|
|
@@ -310,8 +310,8 @@ export class Path {
|
|
|
310
310
|
| null,
|
|
311
311
|
): Promise<void>;
|
|
312
312
|
mkdir(options?: fs.MakeDirectoryOptions | fs.Mode | null): Promise<string | undefined>;
|
|
313
|
-
mkdir(...args: any): any {
|
|
314
|
-
return fsp.mkdir(this.#value, ...args);
|
|
313
|
+
async mkdir(...args: any): Promise<any> {
|
|
314
|
+
return await fsp.mkdir(this.#value, ...args);
|
|
315
315
|
}
|
|
316
316
|
|
|
317
317
|
/**
|
|
@@ -322,8 +322,8 @@ export class Path {
|
|
|
322
322
|
*
|
|
323
323
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.open}
|
|
324
324
|
*/
|
|
325
|
-
open(...args: DropFirstParameters<typeof fsp.open>) {
|
|
326
|
-
return fsp.open(this.#value, ...args);
|
|
325
|
+
async open(...args: DropFirstParameters<typeof fsp.open>) {
|
|
326
|
+
return await fsp.open(this.#value, ...args);
|
|
327
327
|
}
|
|
328
328
|
|
|
329
329
|
/**
|
|
@@ -373,9 +373,9 @@ export class Path {
|
|
|
373
373
|
recursive?: boolean;
|
|
374
374
|
withFileTypes: true;
|
|
375
375
|
},
|
|
376
|
-
): Promise<fs.Dirent<Buffer
|
|
377
|
-
readdir(...args: any): any {
|
|
378
|
-
return fsp.readdir(this.#value, ...args);
|
|
376
|
+
): Promise<Array<fs.Dirent<Buffer>>>;
|
|
377
|
+
async readdir(...args: any): Promise<any> {
|
|
378
|
+
return await fsp.readdir(this.#value, ...args);
|
|
379
379
|
}
|
|
380
380
|
|
|
381
381
|
/**
|
|
@@ -412,8 +412,8 @@ export class Path {
|
|
|
412
412
|
| BufferEncoding
|
|
413
413
|
| null,
|
|
414
414
|
): Promise<Buffer | string>;
|
|
415
|
-
readFile(...args: any): any {
|
|
416
|
-
return fsp.readFile(this.#value, ...args);
|
|
415
|
+
async readFile(...args: any): Promise<any> {
|
|
416
|
+
return await fsp.readFile(this.#value, ...args);
|
|
417
417
|
}
|
|
418
418
|
|
|
419
419
|
/**
|
|
@@ -426,8 +426,8 @@ export class Path {
|
|
|
426
426
|
*
|
|
427
427
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.rename}
|
|
428
428
|
*/
|
|
429
|
-
rename(newPath: PathLike) {
|
|
430
|
-
return fsp.rename(this.#value, newPath.toString());
|
|
429
|
+
async rename(newPath: PathLike) {
|
|
430
|
+
return await fsp.rename(this.#value, newPath.toString());
|
|
431
431
|
}
|
|
432
432
|
|
|
433
433
|
/**
|
|
@@ -438,8 +438,8 @@ export class Path {
|
|
|
438
438
|
*
|
|
439
439
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.rm}
|
|
440
440
|
*/
|
|
441
|
-
rm(...args: DropFirstParameters<typeof fsp.rm>) {
|
|
442
|
-
return fsp.rm(this.#value, ...args);
|
|
441
|
+
async rm(...args: DropFirstParameters<typeof fsp.rm>) {
|
|
442
|
+
return await fsp.rm(this.#value, ...args);
|
|
443
443
|
}
|
|
444
444
|
|
|
445
445
|
/**
|
|
@@ -450,8 +450,8 @@ export class Path {
|
|
|
450
450
|
*
|
|
451
451
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.rmdir}
|
|
452
452
|
*/
|
|
453
|
-
rmdir(...args: DropFirstParameters<typeof fsp.rmdir>) {
|
|
454
|
-
return fsp.rmdir(this.#value, ...args);
|
|
453
|
+
async rmdir(...args: DropFirstParameters<typeof fsp.rmdir>) {
|
|
454
|
+
return await fsp.rmdir(this.#value, ...args);
|
|
455
455
|
}
|
|
456
456
|
|
|
457
457
|
/**
|
|
@@ -512,8 +512,8 @@ export class Path {
|
|
|
512
512
|
*
|
|
513
513
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.truncate}
|
|
514
514
|
*/
|
|
515
|
-
truncate(...args: DropFirstParameters<typeof fsp.truncate>) {
|
|
516
|
-
return fsp.truncate(this.#value, ...args);
|
|
515
|
+
async truncate(...args: DropFirstParameters<typeof fsp.truncate>) {
|
|
516
|
+
return await fsp.truncate(this.#value, ...args);
|
|
517
517
|
}
|
|
518
518
|
|
|
519
519
|
/**
|
|
@@ -524,8 +524,8 @@ export class Path {
|
|
|
524
524
|
*
|
|
525
525
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.unlink}
|
|
526
526
|
*/
|
|
527
|
-
unlink() {
|
|
528
|
-
return fsp.unlink(this.#value);
|
|
527
|
+
async unlink() {
|
|
528
|
+
return await fsp.unlink(this.#value);
|
|
529
529
|
}
|
|
530
530
|
|
|
531
531
|
/**
|
|
@@ -536,7 +536,7 @@ export class Path {
|
|
|
536
536
|
*
|
|
537
537
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.writeFile}
|
|
538
538
|
*/
|
|
539
|
-
writeFile(...args: DropFirstParameters<typeof fsp.writeFile>) {
|
|
540
|
-
return fsp.writeFile(this.#value, ...args);
|
|
539
|
+
async writeFile(...args: DropFirstParameters<typeof fsp.writeFile>) {
|
|
540
|
+
return await fsp.writeFile(this.#value, ...args);
|
|
541
541
|
}
|
|
542
542
|
}
|