@kikiutils/shared 9.3.1 → 10.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/README.md +4 -0
- package/dist/clipboard.cjs +4 -0
- package/dist/clipboard.cjs.map +1 -1
- package/dist/clipboard.d.ts +4 -0
- package/dist/clipboard.d.ts.map +1 -1
- package/dist/clipboard.mjs +4 -0
- package/dist/clipboard.mjs.map +1 -1
- package/dist/element-plus.cjs +37 -0
- package/dist/element-plus.cjs.map +1 -0
- package/dist/element-plus.d.ts +28 -0
- package/dist/element-plus.d.ts.map +1 -0
- package/dist/element-plus.mjs +35 -0
- package/dist/element-plus.mjs.map +1 -0
- package/dist/storage/enhanced/local/core.cjs +2 -0
- package/dist/storage/enhanced/local/core.cjs.map +1 -1
- package/dist/storage/enhanced/local/core.d.ts +2 -0
- package/dist/storage/enhanced/local/core.d.ts.map +1 -1
- package/dist/storage/enhanced/local/core.mjs +2 -0
- package/dist/storage/enhanced/local/core.mjs.map +1 -1
- package/dist/storage/enhanced/local/keyed-store.cjs +2 -0
- package/dist/storage/enhanced/local/keyed-store.cjs.map +1 -1
- package/dist/storage/enhanced/local/keyed-store.d.ts +2 -0
- package/dist/storage/enhanced/local/keyed-store.d.ts.map +1 -1
- package/dist/storage/enhanced/local/keyed-store.mjs +2 -0
- package/dist/storage/enhanced/local/keyed-store.mjs.map +1 -1
- package/dist/storage/enhanced/redis/core.cjs +2 -0
- package/dist/storage/enhanced/redis/core.cjs.map +1 -1
- package/dist/storage/enhanced/redis/core.d.ts +2 -0
- package/dist/storage/enhanced/redis/core.d.ts.map +1 -1
- package/dist/storage/enhanced/redis/core.mjs +2 -0
- package/dist/storage/enhanced/redis/core.mjs.map +1 -1
- package/dist/storage/enhanced/redis/keyed-store.cjs +2 -0
- package/dist/storage/enhanced/redis/keyed-store.cjs.map +1 -1
- package/dist/storage/enhanced/redis/keyed-store.d.ts +2 -0
- package/dist/storage/enhanced/redis/keyed-store.d.ts.map +1 -1
- package/dist/storage/enhanced/redis/keyed-store.mjs +2 -0
- package/dist/storage/enhanced/redis/keyed-store.mjs.map +1 -1
- package/dist/storage/lru/keyed-store.cjs +7 -7
- package/dist/storage/lru/keyed-store.cjs.map +1 -1
- package/dist/storage/lru/keyed-store.d.ts +8 -9
- package/dist/storage/lru/keyed-store.d.ts.map +1 -1
- package/dist/storage/lru/keyed-store.mjs +7 -7
- package/dist/storage/lru/keyed-store.mjs.map +1 -1
- package/dist/web.cjs +17 -0
- package/dist/web.cjs.map +1 -1
- package/dist/web.d.ts +11 -0
- package/dist/web.d.ts.map +1 -1
- package/dist/web.mjs +17 -1
- package/dist/web.mjs.map +1 -1
- package/package.json +6 -3
- package/src/clipboard.ts +4 -0
- package/src/element-plus.ts +37 -0
- package/src/storage/enhanced/local/core.ts +2 -0
- package/src/storage/enhanced/local/keyed-store.ts +2 -0
- package/src/storage/enhanced/redis/core.ts +2 -0
- package/src/storage/enhanced/redis/keyed-store.ts +2 -0
- package/src/storage/lru/keyed-store.ts +10 -12
- package/src/web.ts +15 -0
package/README.md
CHANGED
package/dist/clipboard.cjs
CHANGED
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
*
|
|
18
18
|
* @example
|
|
19
19
|
* ```typescript
|
|
20
|
+
* import { copyBlobToClipboard } from '@kikiutils/shared/clipboard';
|
|
21
|
+
*
|
|
20
22
|
* const blob = new Blob(['Hello world'], { type: 'text/plain' });
|
|
21
23
|
* const result = await copyBlobToClipboard(blob);
|
|
22
24
|
* if (result.ok) {
|
|
@@ -61,6 +63,8 @@ async function copyBlobToClipboard(blob, options) {
|
|
|
61
63
|
*
|
|
62
64
|
* @example
|
|
63
65
|
* ```typescript
|
|
66
|
+
* import { copyTextToClipboard } from '@kikiutils/shared/clipboard';
|
|
67
|
+
*
|
|
64
68
|
* const result = await copyTextToClipboard('Hello!');
|
|
65
69
|
* if (result.ok) {
|
|
66
70
|
* console.log('Copied!');
|
package/dist/clipboard.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clipboard.cjs","sources":["../src/clipboard.ts"],"sourcesContent":["type CopyResult =\n | { error: unknown; ok: false }\n | { ok: true };\n\n/**\n * Attempts to copy a Blob (e.g. image, plain text, HTML) to the user's clipboard using the ClipboardItem API.\n *\n * ⚠️ Usage Notes:\n * - Must be called in a **secure context** (HTTPS or localhost).\n * - Must be called **in response to a user interaction** (e.g. click, input).\n * - Not supported in Safari and some older browsers.\n *\n * @param {Blob} blob - The Blob object to copy (e.g. from a File, image, or text content).\n * @param {ClipboardItemOptions} [options] - Optional options passed to the ClipboardItem constructor.\n *\n * @returns {Promise<CopyResult>} A promise resolving to a `CopyResult`:\n * - `{ ok: true }` if the copy succeeded\n * - `{ ok: false, error }` if the copy failed, with the error included\n *\n * @example\n * ```typescript\n * const blob = new Blob(['Hello world'], { type: 'text/plain' });\n * const result = await copyBlobToClipboard(blob);\n * if (result.ok) {\n * console.log('Copied blob!');\n * } else {\n * console.error('Copy failed:', result.error);\n * }\n * ```\n */\nexport async function copyBlobToClipboard(blob: Blob, options?: ClipboardItemOptions): Promise<CopyResult> {\n if (!navigator.clipboard?.write) {\n return {\n error: new Error('Clipboard.write is not supported in this browser.'),\n ok: false,\n };\n }\n\n try {\n const item = new ClipboardItem({ [blob.type]: blob }, options);\n await navigator.clipboard.write([item]);\n return { ok: true };\n } catch (error) {\n return {\n error,\n ok: false,\n };\n }\n}\n\n/**\n * Attempts to copy the given text to the user's clipboard using the modern Clipboard API.\n *\n * ⚠️ Usage Notes:\n * - Must be called in a **secure context** (HTTPS or localhost).\n * - Must be called **in response to a user interaction** (e.g. click, input).\n * - Not supported in some older browsers (especially legacy Safari).\n *\n * @param {string} text - The string to be copied to the clipboard.\n *\n * @returns {Promise<CopyResult>} A promise resolving to a `CopyResult`:\n * - `{ ok: true }` if the copy succeeded\n * - `{ ok: false, error }` if the copy failed, with the error included\n *\n * @example\n * ```typescript\n * const result = await copyTextToClipboard('Hello!');\n * if (result.ok) {\n * console.log('Copied!');\n * } else {\n * console.error('Copy failed:', result.error);\n * }\n * ```\n */\nexport async function copyTextToClipboard(text: string): Promise<CopyResult> {\n try {\n await navigator.clipboard.writeText(text);\n return { ok: true };\n } catch (error) {\n return {\n error,\n ok: false,\n };\n }\n}\n"],"names":[],"mappings":";;AAIA
|
|
1
|
+
{"version":3,"file":"clipboard.cjs","sources":["../src/clipboard.ts"],"sourcesContent":["type CopyResult =\n | { error: unknown; ok: false }\n | { ok: true };\n\n/**\n * Attempts to copy a Blob (e.g. image, plain text, HTML) to the user's clipboard using the ClipboardItem API.\n *\n * ⚠️ Usage Notes:\n * - Must be called in a **secure context** (HTTPS or localhost).\n * - Must be called **in response to a user interaction** (e.g. click, input).\n * - Not supported in Safari and some older browsers.\n *\n * @param {Blob} blob - The Blob object to copy (e.g. from a File, image, or text content).\n * @param {ClipboardItemOptions} [options] - Optional options passed to the ClipboardItem constructor.\n *\n * @returns {Promise<CopyResult>} A promise resolving to a `CopyResult`:\n * - `{ ok: true }` if the copy succeeded\n * - `{ ok: false, error }` if the copy failed, with the error included\n *\n * @example\n * ```typescript\n * import { copyBlobToClipboard } from '@kikiutils/shared/clipboard';\n *\n * const blob = new Blob(['Hello world'], { type: 'text/plain' });\n * const result = await copyBlobToClipboard(blob);\n * if (result.ok) {\n * console.log('Copied blob!');\n * } else {\n * console.error('Copy failed:', result.error);\n * }\n * ```\n */\nexport async function copyBlobToClipboard(blob: Blob, options?: ClipboardItemOptions): Promise<CopyResult> {\n if (!navigator.clipboard?.write) {\n return {\n error: new Error('Clipboard.write is not supported in this browser.'),\n ok: false,\n };\n }\n\n try {\n const item = new ClipboardItem({ [blob.type]: blob }, options);\n await navigator.clipboard.write([item]);\n return { ok: true };\n } catch (error) {\n return {\n error,\n ok: false,\n };\n }\n}\n\n/**\n * Attempts to copy the given text to the user's clipboard using the modern Clipboard API.\n *\n * ⚠️ Usage Notes:\n * - Must be called in a **secure context** (HTTPS or localhost).\n * - Must be called **in response to a user interaction** (e.g. click, input).\n * - Not supported in some older browsers (especially legacy Safari).\n *\n * @param {string} text - The string to be copied to the clipboard.\n *\n * @returns {Promise<CopyResult>} A promise resolving to a `CopyResult`:\n * - `{ ok: true }` if the copy succeeded\n * - `{ ok: false, error }` if the copy failed, with the error included\n *\n * @example\n * ```typescript\n * import { copyTextToClipboard } from '@kikiutils/shared/clipboard';\n *\n * const result = await copyTextToClipboard('Hello!');\n * if (result.ok) {\n * console.log('Copied!');\n * } else {\n * console.error('Copy failed:', result.error);\n * }\n * ```\n */\nexport async function copyTextToClipboard(text: string): Promise<CopyResult> {\n try {\n await navigator.clipboard.writeText(text);\n return { ok: true };\n } catch (error) {\n return {\n error,\n ok: false,\n };\n }\n}\n"],"names":[],"mappings":";;AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BG;AACI,eAAe,mBAAmB,CAAC,IAAU,EAAE,OAA8B,EAAA;AAChF,IAAA,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,KAAK,EAAE;QAC7B,OAAO;AACH,YAAA,KAAK,EAAE,IAAI,KAAK,CAAC,mDAAmD,CAAC;AACrE,YAAA,EAAE,EAAE,KAAK;SACZ;;AAGL,IAAA,IAAI;AACA,QAAA,MAAM,IAAI,GAAG,IAAI,aAAa,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,EAAE,EAAE,OAAO,CAAC;QAC9D,MAAM,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;AACvC,QAAA,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE;;IACrB,OAAO,KAAK,EAAE;QACZ,OAAO;YACH,KAAK;AACL,YAAA,EAAE,EAAE,KAAK;SACZ;;AAET;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;AAyBG;AACI,eAAe,mBAAmB,CAAC,IAAY,EAAA;AAClD,IAAA,IAAI;QACA,MAAM,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC;AACzC,QAAA,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE;;IACrB,OAAO,KAAK,EAAE;QACZ,OAAO;YACH,KAAK;AACL,YAAA,EAAE,EAAE,KAAK;SACZ;;AAET;;;;;"}
|
package/dist/clipboard.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ type CopyResult = {
|
|
|
21
21
|
*
|
|
22
22
|
* @example
|
|
23
23
|
* ```typescript
|
|
24
|
+
* import { copyBlobToClipboard } from '@kikiutils/shared/clipboard';
|
|
25
|
+
*
|
|
24
26
|
* const blob = new Blob(['Hello world'], { type: 'text/plain' });
|
|
25
27
|
* const result = await copyBlobToClipboard(blob);
|
|
26
28
|
* if (result.ok) {
|
|
@@ -47,6 +49,8 @@ export declare function copyBlobToClipboard(blob: Blob, options?: ClipboardItemO
|
|
|
47
49
|
*
|
|
48
50
|
* @example
|
|
49
51
|
* ```typescript
|
|
52
|
+
* import { copyTextToClipboard } from '@kikiutils/shared/clipboard';
|
|
53
|
+
*
|
|
50
54
|
* const result = await copyTextToClipboard('Hello!');
|
|
51
55
|
* if (result.ok) {
|
|
52
56
|
* console.log('Copied!');
|
package/dist/clipboard.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clipboard.d.ts","sourceRoot":"","sources":["../src/clipboard.ts"],"names":[],"mappings":"AAAA,KAAK,UAAU,GACX;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,KAAK,CAAA;CAAE,GAC7B;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,CAAC;AAEjB
|
|
1
|
+
{"version":3,"file":"clipboard.d.ts","sourceRoot":"","sources":["../src/clipboard.ts"],"names":[],"mappings":"AAAA,KAAK,UAAU,GACX;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,KAAK,CAAA;CAAE,GAC7B;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,CAAC;AAEjB;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,UAAU,CAAC,CAkBzG;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAU3E"}
|
package/dist/clipboard.mjs
CHANGED
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
*
|
|
16
16
|
* @example
|
|
17
17
|
* ```typescript
|
|
18
|
+
* import { copyBlobToClipboard } from '@kikiutils/shared/clipboard';
|
|
19
|
+
*
|
|
18
20
|
* const blob = new Blob(['Hello world'], { type: 'text/plain' });
|
|
19
21
|
* const result = await copyBlobToClipboard(blob);
|
|
20
22
|
* if (result.ok) {
|
|
@@ -59,6 +61,8 @@ async function copyBlobToClipboard(blob, options) {
|
|
|
59
61
|
*
|
|
60
62
|
* @example
|
|
61
63
|
* ```typescript
|
|
64
|
+
* import { copyTextToClipboard } from '@kikiutils/shared/clipboard';
|
|
65
|
+
*
|
|
62
66
|
* const result = await copyTextToClipboard('Hello!');
|
|
63
67
|
* if (result.ok) {
|
|
64
68
|
* console.log('Copied!');
|
package/dist/clipboard.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clipboard.mjs","sources":["../src/clipboard.ts"],"sourcesContent":["type CopyResult =\n | { error: unknown; ok: false }\n | { ok: true };\n\n/**\n * Attempts to copy a Blob (e.g. image, plain text, HTML) to the user's clipboard using the ClipboardItem API.\n *\n * ⚠️ Usage Notes:\n * - Must be called in a **secure context** (HTTPS or localhost).\n * - Must be called **in response to a user interaction** (e.g. click, input).\n * - Not supported in Safari and some older browsers.\n *\n * @param {Blob} blob - The Blob object to copy (e.g. from a File, image, or text content).\n * @param {ClipboardItemOptions} [options] - Optional options passed to the ClipboardItem constructor.\n *\n * @returns {Promise<CopyResult>} A promise resolving to a `CopyResult`:\n * - `{ ok: true }` if the copy succeeded\n * - `{ ok: false, error }` if the copy failed, with the error included\n *\n * @example\n * ```typescript\n * const blob = new Blob(['Hello world'], { type: 'text/plain' });\n * const result = await copyBlobToClipboard(blob);\n * if (result.ok) {\n * console.log('Copied blob!');\n * } else {\n * console.error('Copy failed:', result.error);\n * }\n * ```\n */\nexport async function copyBlobToClipboard(blob: Blob, options?: ClipboardItemOptions): Promise<CopyResult> {\n if (!navigator.clipboard?.write) {\n return {\n error: new Error('Clipboard.write is not supported in this browser.'),\n ok: false,\n };\n }\n\n try {\n const item = new ClipboardItem({ [blob.type]: blob }, options);\n await navigator.clipboard.write([item]);\n return { ok: true };\n } catch (error) {\n return {\n error,\n ok: false,\n };\n }\n}\n\n/**\n * Attempts to copy the given text to the user's clipboard using the modern Clipboard API.\n *\n * ⚠️ Usage Notes:\n * - Must be called in a **secure context** (HTTPS or localhost).\n * - Must be called **in response to a user interaction** (e.g. click, input).\n * - Not supported in some older browsers (especially legacy Safari).\n *\n * @param {string} text - The string to be copied to the clipboard.\n *\n * @returns {Promise<CopyResult>} A promise resolving to a `CopyResult`:\n * - `{ ok: true }` if the copy succeeded\n * - `{ ok: false, error }` if the copy failed, with the error included\n *\n * @example\n * ```typescript\n * const result = await copyTextToClipboard('Hello!');\n * if (result.ok) {\n * console.log('Copied!');\n * } else {\n * console.error('Copy failed:', result.error);\n * }\n * ```\n */\nexport async function copyTextToClipboard(text: string): Promise<CopyResult> {\n try {\n await navigator.clipboard.writeText(text);\n return { ok: true };\n } catch (error) {\n return {\n error,\n ok: false,\n };\n }\n}\n"],"names":[],"mappings":"AAIA
|
|
1
|
+
{"version":3,"file":"clipboard.mjs","sources":["../src/clipboard.ts"],"sourcesContent":["type CopyResult =\n | { error: unknown; ok: false }\n | { ok: true };\n\n/**\n * Attempts to copy a Blob (e.g. image, plain text, HTML) to the user's clipboard using the ClipboardItem API.\n *\n * ⚠️ Usage Notes:\n * - Must be called in a **secure context** (HTTPS or localhost).\n * - Must be called **in response to a user interaction** (e.g. click, input).\n * - Not supported in Safari and some older browsers.\n *\n * @param {Blob} blob - The Blob object to copy (e.g. from a File, image, or text content).\n * @param {ClipboardItemOptions} [options] - Optional options passed to the ClipboardItem constructor.\n *\n * @returns {Promise<CopyResult>} A promise resolving to a `CopyResult`:\n * - `{ ok: true }` if the copy succeeded\n * - `{ ok: false, error }` if the copy failed, with the error included\n *\n * @example\n * ```typescript\n * import { copyBlobToClipboard } from '@kikiutils/shared/clipboard';\n *\n * const blob = new Blob(['Hello world'], { type: 'text/plain' });\n * const result = await copyBlobToClipboard(blob);\n * if (result.ok) {\n * console.log('Copied blob!');\n * } else {\n * console.error('Copy failed:', result.error);\n * }\n * ```\n */\nexport async function copyBlobToClipboard(blob: Blob, options?: ClipboardItemOptions): Promise<CopyResult> {\n if (!navigator.clipboard?.write) {\n return {\n error: new Error('Clipboard.write is not supported in this browser.'),\n ok: false,\n };\n }\n\n try {\n const item = new ClipboardItem({ [blob.type]: blob }, options);\n await navigator.clipboard.write([item]);\n return { ok: true };\n } catch (error) {\n return {\n error,\n ok: false,\n };\n }\n}\n\n/**\n * Attempts to copy the given text to the user's clipboard using the modern Clipboard API.\n *\n * ⚠️ Usage Notes:\n * - Must be called in a **secure context** (HTTPS or localhost).\n * - Must be called **in response to a user interaction** (e.g. click, input).\n * - Not supported in some older browsers (especially legacy Safari).\n *\n * @param {string} text - The string to be copied to the clipboard.\n *\n * @returns {Promise<CopyResult>} A promise resolving to a `CopyResult`:\n * - `{ ok: true }` if the copy succeeded\n * - `{ ok: false, error }` if the copy failed, with the error included\n *\n * @example\n * ```typescript\n * import { copyTextToClipboard } from '@kikiutils/shared/clipboard';\n *\n * const result = await copyTextToClipboard('Hello!');\n * if (result.ok) {\n * console.log('Copied!');\n * } else {\n * console.error('Copy failed:', result.error);\n * }\n * ```\n */\nexport async function copyTextToClipboard(text: string): Promise<CopyResult> {\n try {\n await navigator.clipboard.writeText(text);\n return { ok: true };\n } catch (error) {\n return {\n error,\n ok: false,\n };\n }\n}\n"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BG;AACI,eAAe,mBAAmB,CAAC,IAAU,EAAE,OAA8B,EAAA;AAChF,IAAA,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,KAAK,EAAE;QAC7B,OAAO;AACH,YAAA,KAAK,EAAE,IAAI,KAAK,CAAC,mDAAmD,CAAC;AACrE,YAAA,EAAE,EAAE,KAAK;SACZ;;AAGL,IAAA,IAAI;AACA,QAAA,MAAM,IAAI,GAAG,IAAI,aAAa,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,EAAE,EAAE,OAAO,CAAC;QAC9D,MAAM,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;AACvC,QAAA,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE;;IACrB,OAAO,KAAK,EAAE;QACZ,OAAO;YACH,KAAK;AACL,YAAA,EAAE,EAAE,KAAK;SACZ;;AAET;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;AAyBG;AACI,eAAe,mBAAmB,CAAC,IAAY,EAAA;AAClD,IAAA,IAAI;QACA,MAAM,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC;AACzC,QAAA,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE;;IACrB,OAAO,KAAK,EAAE;QACZ,OAAO;YACH,KAAK;AACL,YAAA,EAAE,EAAE,KAAK;SACZ;;AAET;;;;"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates a reusable Element Plus `<el-form-item>` validation rule with sensible defaults.
|
|
5
|
+
*
|
|
6
|
+
* This utility provides default values for `required`, `trigger`, and `type`,
|
|
7
|
+
* while allowing overrides via the `options` parameter. It simplifies common
|
|
8
|
+
* form validation rule creation and ensures consistency across forms.
|
|
9
|
+
*
|
|
10
|
+
* @param {string} message - The validation message to display when the rule fails.
|
|
11
|
+
* @param {FormItemRule} [options] - Optional overrides for the rule fields.
|
|
12
|
+
* @param {boolean} [options.required] - Whether the field is required (default: `true`).
|
|
13
|
+
* @param {string | string[]} [options.trigger] - The event(s) that trigger validation (default: `'blur'`).
|
|
14
|
+
* @param {RuleType} [options.type] - The expected type of the field (default: `'string'`).
|
|
15
|
+
*
|
|
16
|
+
* @returns A `FormItemRule` object that can be used in Element Plus form validation.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { createElFormItemRuleWithDefaults } from '@kikiutils/shared/element-plus';
|
|
21
|
+
*
|
|
22
|
+
* const rule = createElFormItemRuleWithDefaults('This field is required');
|
|
23
|
+
* const optionalRule = createElFormItemRuleWithDefaults('Optional field', { required: false });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
function createElFormItemRuleWithDefaults(message, options = {}) {
|
|
27
|
+
return {
|
|
28
|
+
...options,
|
|
29
|
+
message,
|
|
30
|
+
required: options.required ?? true,
|
|
31
|
+
trigger: options.trigger ?? 'blur',
|
|
32
|
+
type: options.type ?? 'string',
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
exports.createElFormItemRuleWithDefaults = createElFormItemRuleWithDefaults;
|
|
37
|
+
//# sourceMappingURL=element-plus.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element-plus.cjs","sources":["../src/element-plus.ts"],"sourcesContent":["import type { RuleType } from 'async-validator';\nimport type { FormItemRule } from 'element-plus';\n\nexport type DoNotRemoveOrUseThisType = RuleType;\n\n/**\n * Creates a reusable Element Plus `<el-form-item>` validation rule with sensible defaults.\n *\n * This utility provides default values for `required`, `trigger`, and `type`,\n * while allowing overrides via the `options` parameter. It simplifies common\n * form validation rule creation and ensures consistency across forms.\n *\n * @param {string} message - The validation message to display when the rule fails.\n * @param {FormItemRule} [options] - Optional overrides for the rule fields.\n * @param {boolean} [options.required] - Whether the field is required (default: `true`).\n * @param {string | string[]} [options.trigger] - The event(s) that trigger validation (default: `'blur'`).\n * @param {RuleType} [options.type] - The expected type of the field (default: `'string'`).\n *\n * @returns A `FormItemRule` object that can be used in Element Plus form validation.\n *\n * @example\n * ```typescript\n * import { createElFormItemRuleWithDefaults } from '@kikiutils/shared/element-plus';\n *\n * const rule = createElFormItemRuleWithDefaults('This field is required');\n * const optionalRule = createElFormItemRuleWithDefaults('Optional field', { required: false });\n * ```\n */\nexport function createElFormItemRuleWithDefaults(message: string, options: FormItemRule = {}): FormItemRule {\n return {\n ...options,\n message,\n required: options.required ?? true,\n trigger: options.trigger ?? 'blur',\n type: options.type ?? 'string',\n };\n}\n"],"names":[],"mappings":";;AAKA;;;;;;;;;;;;;;;;;;;;;;AAsBG;SACa,gCAAgC,CAAC,OAAe,EAAE,UAAwB,EAAE,EAAA;IACxF,OAAO;AACH,QAAA,GAAG,OAAO;QACV,OAAO;AACP,QAAA,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,IAAI;AAClC,QAAA,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,MAAM;AAClC,QAAA,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,QAAQ;KACjC;AACL;;;;"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { RuleType } from 'async-validator';
|
|
2
|
+
import type { FormItemRule } from 'element-plus';
|
|
3
|
+
export type DoNotRemoveOrUseThisType = RuleType;
|
|
4
|
+
/**
|
|
5
|
+
* Creates a reusable Element Plus `<el-form-item>` validation rule with sensible defaults.
|
|
6
|
+
*
|
|
7
|
+
* This utility provides default values for `required`, `trigger`, and `type`,
|
|
8
|
+
* while allowing overrides via the `options` parameter. It simplifies common
|
|
9
|
+
* form validation rule creation and ensures consistency across forms.
|
|
10
|
+
*
|
|
11
|
+
* @param {string} message - The validation message to display when the rule fails.
|
|
12
|
+
* @param {FormItemRule} [options] - Optional overrides for the rule fields.
|
|
13
|
+
* @param {boolean} [options.required] - Whether the field is required (default: `true`).
|
|
14
|
+
* @param {string | string[]} [options.trigger] - The event(s) that trigger validation (default: `'blur'`).
|
|
15
|
+
* @param {RuleType} [options.type] - The expected type of the field (default: `'string'`).
|
|
16
|
+
*
|
|
17
|
+
* @returns A `FormItemRule` object that can be used in Element Plus form validation.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* import { createElFormItemRuleWithDefaults } from '@kikiutils/shared/element-plus';
|
|
22
|
+
*
|
|
23
|
+
* const rule = createElFormItemRuleWithDefaults('This field is required');
|
|
24
|
+
* const optionalRule = createElFormItemRuleWithDefaults('Optional field', { required: false });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function createElFormItemRuleWithDefaults(message: string, options?: FormItemRule): FormItemRule;
|
|
28
|
+
//# sourceMappingURL=element-plus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element-plus.d.ts","sourceRoot":"","sources":["../src/element-plus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,YAAY,CAQ1G"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a reusable Element Plus `<el-form-item>` validation rule with sensible defaults.
|
|
3
|
+
*
|
|
4
|
+
* This utility provides default values for `required`, `trigger`, and `type`,
|
|
5
|
+
* while allowing overrides via the `options` parameter. It simplifies common
|
|
6
|
+
* form validation rule creation and ensures consistency across forms.
|
|
7
|
+
*
|
|
8
|
+
* @param {string} message - The validation message to display when the rule fails.
|
|
9
|
+
* @param {FormItemRule} [options] - Optional overrides for the rule fields.
|
|
10
|
+
* @param {boolean} [options.required] - Whether the field is required (default: `true`).
|
|
11
|
+
* @param {string | string[]} [options.trigger] - The event(s) that trigger validation (default: `'blur'`).
|
|
12
|
+
* @param {RuleType} [options.type] - The expected type of the field (default: `'string'`).
|
|
13
|
+
*
|
|
14
|
+
* @returns A `FormItemRule` object that can be used in Element Plus form validation.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { createElFormItemRuleWithDefaults } from '@kikiutils/shared/element-plus';
|
|
19
|
+
*
|
|
20
|
+
* const rule = createElFormItemRuleWithDefaults('This field is required');
|
|
21
|
+
* const optionalRule = createElFormItemRuleWithDefaults('Optional field', { required: false });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
function createElFormItemRuleWithDefaults(message, options = {}) {
|
|
25
|
+
return {
|
|
26
|
+
...options,
|
|
27
|
+
message,
|
|
28
|
+
required: options.required ?? true,
|
|
29
|
+
trigger: options.trigger ?? 'blur',
|
|
30
|
+
type: options.type ?? 'string',
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export { createElFormItemRuleWithDefaults };
|
|
35
|
+
//# sourceMappingURL=element-plus.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element-plus.mjs","sources":["../src/element-plus.ts"],"sourcesContent":["import type { RuleType } from 'async-validator';\nimport type { FormItemRule } from 'element-plus';\n\nexport type DoNotRemoveOrUseThisType = RuleType;\n\n/**\n * Creates a reusable Element Plus `<el-form-item>` validation rule with sensible defaults.\n *\n * This utility provides default values for `required`, `trigger`, and `type`,\n * while allowing overrides via the `options` parameter. It simplifies common\n * form validation rule creation and ensures consistency across forms.\n *\n * @param {string} message - The validation message to display when the rule fails.\n * @param {FormItemRule} [options] - Optional overrides for the rule fields.\n * @param {boolean} [options.required] - Whether the field is required (default: `true`).\n * @param {string | string[]} [options.trigger] - The event(s) that trigger validation (default: `'blur'`).\n * @param {RuleType} [options.type] - The expected type of the field (default: `'string'`).\n *\n * @returns A `FormItemRule` object that can be used in Element Plus form validation.\n *\n * @example\n * ```typescript\n * import { createElFormItemRuleWithDefaults } from '@kikiutils/shared/element-plus';\n *\n * const rule = createElFormItemRuleWithDefaults('This field is required');\n * const optionalRule = createElFormItemRuleWithDefaults('Optional field', { required: false });\n * ```\n */\nexport function createElFormItemRuleWithDefaults(message: string, options: FormItemRule = {}): FormItemRule {\n return {\n ...options,\n message,\n required: options.required ?? true,\n trigger: options.trigger ?? 'blur',\n type: options.type ?? 'string',\n };\n}\n"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;AAsBG;SACa,gCAAgC,CAAC,OAAe,EAAE,UAAwB,EAAE,EAAA;IACxF,OAAO;AACH,QAAA,GAAG,OAAO;QACV,OAAO;AACP,QAAA,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,IAAI;AAClC,QAAA,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,MAAM;AAClC,QAAA,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,QAAQ;KACjC;AACL;;;;"}
|
|
@@ -18,6 +18,8 @@ const toCustomValue = (type, payload) => `${customValueHeader}${type}${payload}`
|
|
|
18
18
|
*
|
|
19
19
|
* @example
|
|
20
20
|
* ```typescript
|
|
21
|
+
* import { enhancedLocalStorage } from '@kikiutils/shared/storage/enhanced/local';
|
|
22
|
+
*
|
|
21
23
|
* enhancedLocalStorage.setItem('user', { name: 'user', createdAt: new Date() });
|
|
22
24
|
* const user = enhancedLocalStorage.getItem<{ name: string, createdAt: Date }>('user');
|
|
23
25
|
* ```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.cjs","sources":["../../../../src/storage/enhanced/local/core.ts"],"sourcesContent":["import {\n deserialize,\n serialize,\n} from 'superjson';\n\nenum StorageValueEncodingType {\n Json = '0',\n String = '1',\n}\n\nconst customValueHeader = '';\nconst customValueHeaderLength = customValueHeader.length + 1;\nconst toCustomValue = (type: StorageValueEncodingType, payload: string) => `${customValueHeader}${type}${payload}`;\n\n/**\n * An enhanced localStorage wrapper that supports storing\n * complex data types (e.g. Dates, Maps, Sets) using SuperJSON encoding.\n *\n * This utility preserves type structure when saving and retrieving values.\n *\n * @example\n * ```typescript\n * enhancedLocalStorage.setItem('user', { name: 'user', createdAt: new Date() });\n * const user = enhancedLocalStorage.getItem<{ name: string, createdAt: Date }>('user');\n * ```\n */\nexport const enhancedLocalStorage = Object.freeze({\n /**\n * Removes all items from localStorage.\n */\n clear: () => window.localStorage.clear(),\n /**\n * Retrieves a value by key and decodes it using SuperJSON or raw string.\n *\n * @template T - The expected type of the value.\n *\n * @param {string} key - The key of the value to retrieve.\n *\n * @returns {null | T} The decoded value or null if not found.\n */\n getItem<T = unknown>(key: string) {\n const rawValue = window.localStorage.getItem(key);\n return rawValue ? decodeStorageValue(rawValue) as T : null;\n },\n /**\n * Checks whether a key exists in localStorage.\n *\n * @param {string} key - The key to check.\n *\n * @returns {boolean} True if the key exists, false otherwise.\n */\n hasItem: (key: string) => window.localStorage.getItem(key) !== null,\n /**\n * Returns the number of items stored in localStorage.\n *\n * @returns {number} The number of items stored in localStorage.\n */\n get length() {\n return window.localStorage.length;\n },\n /**\n * Removes a specific key from localStorage.\n *\n * @param {string} key - The key to remove.\n */\n removeItem: (key: string) => window.localStorage.removeItem(key),\n /**\n * Stores a value in localStorage with automatic serialization.\n *\n * @param {string} key - The key to store the value under.\n * @param {any} value - The value to store.\n */\n setItem: (key: string, value: any) => window.localStorage.setItem(key, encodeToStorageValue(value)),\n});\n\nfunction decodeStorageValue(data: string) {\n if (!isCustomFormat(data)) return data;\n const payload = data.substring(customValueHeaderLength);\n const type = data.charAt(customValueHeader.length);\n switch (type) {\n case StorageValueEncodingType.Json:\n try {\n return deserialize(JSON.parse(payload));\n } catch {\n throw new Error('[EnhancedLocalStorage] Failed to parse JSON payload.');\n }\n case StorageValueEncodingType.String: return payload;\n default:\n throw new Error(`[EnhancedLocalStorage] Unknown encoding type: ${type}.`);\n }\n}\n\nfunction encodeToStorageValue(value: any) {\n if (typeof value === 'string') return toCustomValue(StorageValueEncodingType.String, value);\n return toCustomValue(StorageValueEncodingType.Json, JSON.stringify(serialize(value)));\n}\n\nfunction isCustomFormat(data: string) {\n return (\n data.length >= customValueHeaderLength\n && data[0] === customValueHeader[0]\n && data[1] === customValueHeader[1]\n );\n}\n"],"names":["deserialize","serialize"],"mappings":";;;;AAKA,IAAK,wBAGJ;AAHD,CAAA,UAAK,wBAAwB,EAAA;AACzB,IAAA,wBAAA,CAAA,MAAA,CAAA,GAAA,GAAU;AACV,IAAA,wBAAA,CAAA,QAAA,CAAA,GAAA,GAAY;AAChB,CAAC,EAHI,wBAAwB,KAAxB,wBAAwB,GAG5B,EAAA,CAAA,CAAA;AAED,MAAM,iBAAiB,GAAG,IAAI;AAC9B,MAAM,uBAAuB,GAAG,iBAAiB,CAAC,MAAM,GAAG,CAAC;AAC5D,MAAM,aAAa,GAAG,CAAC,IAA8B,EAAE,OAAe,KAAK,CAAA,EAAG,iBAAiB,CAAG,EAAA,IAAI,CAAG,EAAA,OAAO,EAAE;AAElH
|
|
1
|
+
{"version":3,"file":"core.cjs","sources":["../../../../src/storage/enhanced/local/core.ts"],"sourcesContent":["import {\n deserialize,\n serialize,\n} from 'superjson';\n\nenum StorageValueEncodingType {\n Json = '0',\n String = '1',\n}\n\nconst customValueHeader = '';\nconst customValueHeaderLength = customValueHeader.length + 1;\nconst toCustomValue = (type: StorageValueEncodingType, payload: string) => `${customValueHeader}${type}${payload}`;\n\n/**\n * An enhanced localStorage wrapper that supports storing\n * complex data types (e.g. Dates, Maps, Sets) using SuperJSON encoding.\n *\n * This utility preserves type structure when saving and retrieving values.\n *\n * @example\n * ```typescript\n * import { enhancedLocalStorage } from '@kikiutils/shared/storage/enhanced/local';\n *\n * enhancedLocalStorage.setItem('user', { name: 'user', createdAt: new Date() });\n * const user = enhancedLocalStorage.getItem<{ name: string, createdAt: Date }>('user');\n * ```\n */\nexport const enhancedLocalStorage = Object.freeze({\n /**\n * Removes all items from localStorage.\n */\n clear: () => window.localStorage.clear(),\n /**\n * Retrieves a value by key and decodes it using SuperJSON or raw string.\n *\n * @template T - The expected type of the value.\n *\n * @param {string} key - The key of the value to retrieve.\n *\n * @returns {null | T} The decoded value or null if not found.\n */\n getItem<T = unknown>(key: string) {\n const rawValue = window.localStorage.getItem(key);\n return rawValue ? decodeStorageValue(rawValue) as T : null;\n },\n /**\n * Checks whether a key exists in localStorage.\n *\n * @param {string} key - The key to check.\n *\n * @returns {boolean} True if the key exists, false otherwise.\n */\n hasItem: (key: string) => window.localStorage.getItem(key) !== null,\n /**\n * Returns the number of items stored in localStorage.\n *\n * @returns {number} The number of items stored in localStorage.\n */\n get length() {\n return window.localStorage.length;\n },\n /**\n * Removes a specific key from localStorage.\n *\n * @param {string} key - The key to remove.\n */\n removeItem: (key: string) => window.localStorage.removeItem(key),\n /**\n * Stores a value in localStorage with automatic serialization.\n *\n * @param {string} key - The key to store the value under.\n * @param {any} value - The value to store.\n */\n setItem: (key: string, value: any) => window.localStorage.setItem(key, encodeToStorageValue(value)),\n});\n\nfunction decodeStorageValue(data: string) {\n if (!isCustomFormat(data)) return data;\n const payload = data.substring(customValueHeaderLength);\n const type = data.charAt(customValueHeader.length);\n switch (type) {\n case StorageValueEncodingType.Json:\n try {\n return deserialize(JSON.parse(payload));\n } catch {\n throw new Error('[EnhancedLocalStorage] Failed to parse JSON payload.');\n }\n case StorageValueEncodingType.String: return payload;\n default:\n throw new Error(`[EnhancedLocalStorage] Unknown encoding type: ${type}.`);\n }\n}\n\nfunction encodeToStorageValue(value: any) {\n if (typeof value === 'string') return toCustomValue(StorageValueEncodingType.String, value);\n return toCustomValue(StorageValueEncodingType.Json, JSON.stringify(serialize(value)));\n}\n\nfunction isCustomFormat(data: string) {\n return (\n data.length >= customValueHeaderLength\n && data[0] === customValueHeader[0]\n && data[1] === customValueHeader[1]\n );\n}\n"],"names":["deserialize","serialize"],"mappings":";;;;AAKA,IAAK,wBAGJ;AAHD,CAAA,UAAK,wBAAwB,EAAA;AACzB,IAAA,wBAAA,CAAA,MAAA,CAAA,GAAA,GAAU;AACV,IAAA,wBAAA,CAAA,QAAA,CAAA,GAAA,GAAY;AAChB,CAAC,EAHI,wBAAwB,KAAxB,wBAAwB,GAG5B,EAAA,CAAA,CAAA;AAED,MAAM,iBAAiB,GAAG,IAAI;AAC9B,MAAM,uBAAuB,GAAG,iBAAiB,CAAC,MAAM,GAAG,CAAC;AAC5D,MAAM,aAAa,GAAG,CAAC,IAA8B,EAAE,OAAe,KAAK,CAAA,EAAG,iBAAiB,CAAG,EAAA,IAAI,CAAG,EAAA,OAAO,EAAE;AAElH;;;;;;;;;;;;;AAaG;AACU,MAAA,oBAAoB,GAAG,MAAM,CAAC,MAAM,CAAC;AAC9C;;AAEG;IACH,KAAK,EAAE,MAAM,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE;AACxC;;;;;;;;AAQG;AACH,IAAA,OAAO,CAAc,GAAW,EAAA;QAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC;AACjD,QAAA,OAAO,QAAQ,GAAG,kBAAkB,CAAC,QAAQ,CAAM,GAAG,IAAI;KAC7D;AACD;;;;;;AAMG;AACH,IAAA,OAAO,EAAE,CAAC,GAAW,KAAK,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI;AACnE;;;;AAIG;AACH,IAAA,IAAI,MAAM,GAAA;AACN,QAAA,OAAO,MAAM,CAAC,YAAY,CAAC,MAAM;KACpC;AACD;;;;AAIG;AACH,IAAA,UAAU,EAAE,CAAC,GAAW,KAAK,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC;AAChE;;;;;AAKG;IACH,OAAO,EAAE,CAAC,GAAW,EAAE,KAAU,KAAK,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,oBAAoB,CAAC,KAAK,CAAC,CAAC;AACtG,CAAA;AAED,SAAS,kBAAkB,CAAC,IAAY,EAAA;AACpC,IAAA,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC;AAAE,QAAA,OAAO,IAAI;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC;IACvD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC;IAClD,QAAQ,IAAI;QACR,KAAK,wBAAwB,CAAC,IAAI;AAC9B,YAAA,IAAI;gBACA,OAAOA,qBAAW,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;;AACzC,YAAA,MAAM;AACJ,gBAAA,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC;;AAE/E,QAAA,KAAK,wBAAwB,CAAC,MAAM,EAAE,OAAO,OAAO;AACpD,QAAA;AACI,YAAA,MAAM,IAAI,KAAK,CAAC,iDAAiD,IAAI,CAAA,CAAA,CAAG,CAAC;;AAErF;AAEA,SAAS,oBAAoB,CAAC,KAAU,EAAA;IACpC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,aAAa,CAAC,wBAAwB,CAAC,MAAM,EAAE,KAAK,CAAC;AAC3F,IAAA,OAAO,aAAa,CAAC,wBAAwB,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAACC,mBAAS,CAAC,KAAK,CAAC,CAAC,CAAC;AACzF;AAEA,SAAS,cAAc,CAAC,IAAY,EAAA;AAChC,IAAA,QACI,IAAI,CAAC,MAAM,IAAI;AACZ,WAAA,IAAI,CAAC,CAAC,CAAC,KAAK,iBAAiB,CAAC,CAAC;WAC/B,IAAI,CAAC,CAAC,CAAC,KAAK,iBAAiB,CAAC,CAAC,CAAC;AAE3C;;;;"}
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @example
|
|
8
8
|
* ```typescript
|
|
9
|
+
* import { enhancedLocalStorage } from '@kikiutils/shared/storage/enhanced/local';
|
|
10
|
+
*
|
|
9
11
|
* enhancedLocalStorage.setItem('user', { name: 'user', createdAt: new Date() });
|
|
10
12
|
* const user = enhancedLocalStorage.getItem<{ name: string, createdAt: Date }>('user');
|
|
11
13
|
* ```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../../src/storage/enhanced/local/core.ts"],"names":[],"mappings":"AAcA
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../../src/storage/enhanced/local/core.ts"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,oBAAoB;IAC7B;;OAEG;;IAEH;;;;;;;;OAQG;YACK,CAAC,iBAAiB,MAAM;IAIhC;;;;;;OAMG;mBACY,MAAM;IACrB;;;;OAIG;;IAIH;;;;OAIG;sBACe,MAAM;IACxB;;;;;OAKG;mBACY,MAAM,SAAS,GAAG;EACnC,CAAC"}
|
|
@@ -16,6 +16,8 @@ const toCustomValue = (type, payload) => `${customValueHeader}${type}${payload}`
|
|
|
16
16
|
*
|
|
17
17
|
* @example
|
|
18
18
|
* ```typescript
|
|
19
|
+
* import { enhancedLocalStorage } from '@kikiutils/shared/storage/enhanced/local';
|
|
20
|
+
*
|
|
19
21
|
* enhancedLocalStorage.setItem('user', { name: 'user', createdAt: new Date() });
|
|
20
22
|
* const user = enhancedLocalStorage.getItem<{ name: string, createdAt: Date }>('user');
|
|
21
23
|
* ```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.mjs","sources":["../../../../src/storage/enhanced/local/core.ts"],"sourcesContent":["import {\n deserialize,\n serialize,\n} from 'superjson';\n\nenum StorageValueEncodingType {\n Json = '0',\n String = '1',\n}\n\nconst customValueHeader = '';\nconst customValueHeaderLength = customValueHeader.length + 1;\nconst toCustomValue = (type: StorageValueEncodingType, payload: string) => `${customValueHeader}${type}${payload}`;\n\n/**\n * An enhanced localStorage wrapper that supports storing\n * complex data types (e.g. Dates, Maps, Sets) using SuperJSON encoding.\n *\n * This utility preserves type structure when saving and retrieving values.\n *\n * @example\n * ```typescript\n * enhancedLocalStorage.setItem('user', { name: 'user', createdAt: new Date() });\n * const user = enhancedLocalStorage.getItem<{ name: string, createdAt: Date }>('user');\n * ```\n */\nexport const enhancedLocalStorage = Object.freeze({\n /**\n * Removes all items from localStorage.\n */\n clear: () => window.localStorage.clear(),\n /**\n * Retrieves a value by key and decodes it using SuperJSON or raw string.\n *\n * @template T - The expected type of the value.\n *\n * @param {string} key - The key of the value to retrieve.\n *\n * @returns {null | T} The decoded value or null if not found.\n */\n getItem<T = unknown>(key: string) {\n const rawValue = window.localStorage.getItem(key);\n return rawValue ? decodeStorageValue(rawValue) as T : null;\n },\n /**\n * Checks whether a key exists in localStorage.\n *\n * @param {string} key - The key to check.\n *\n * @returns {boolean} True if the key exists, false otherwise.\n */\n hasItem: (key: string) => window.localStorage.getItem(key) !== null,\n /**\n * Returns the number of items stored in localStorage.\n *\n * @returns {number} The number of items stored in localStorage.\n */\n get length() {\n return window.localStorage.length;\n },\n /**\n * Removes a specific key from localStorage.\n *\n * @param {string} key - The key to remove.\n */\n removeItem: (key: string) => window.localStorage.removeItem(key),\n /**\n * Stores a value in localStorage with automatic serialization.\n *\n * @param {string} key - The key to store the value under.\n * @param {any} value - The value to store.\n */\n setItem: (key: string, value: any) => window.localStorage.setItem(key, encodeToStorageValue(value)),\n});\n\nfunction decodeStorageValue(data: string) {\n if (!isCustomFormat(data)) return data;\n const payload = data.substring(customValueHeaderLength);\n const type = data.charAt(customValueHeader.length);\n switch (type) {\n case StorageValueEncodingType.Json:\n try {\n return deserialize(JSON.parse(payload));\n } catch {\n throw new Error('[EnhancedLocalStorage] Failed to parse JSON payload.');\n }\n case StorageValueEncodingType.String: return payload;\n default:\n throw new Error(`[EnhancedLocalStorage] Unknown encoding type: ${type}.`);\n }\n}\n\nfunction encodeToStorageValue(value: any) {\n if (typeof value === 'string') return toCustomValue(StorageValueEncodingType.String, value);\n return toCustomValue(StorageValueEncodingType.Json, JSON.stringify(serialize(value)));\n}\n\nfunction isCustomFormat(data: string) {\n return (\n data.length >= customValueHeaderLength\n && data[0] === customValueHeader[0]\n && data[1] === customValueHeader[1]\n );\n}\n"],"names":[],"mappings":";;AAKA,IAAK,wBAGJ;AAHD,CAAA,UAAK,wBAAwB,EAAA;AACzB,IAAA,wBAAA,CAAA,MAAA,CAAA,GAAA,GAAU;AACV,IAAA,wBAAA,CAAA,QAAA,CAAA,GAAA,GAAY;AAChB,CAAC,EAHI,wBAAwB,KAAxB,wBAAwB,GAG5B,EAAA,CAAA,CAAA;AAED,MAAM,iBAAiB,GAAG,IAAI;AAC9B,MAAM,uBAAuB,GAAG,iBAAiB,CAAC,MAAM,GAAG,CAAC;AAC5D,MAAM,aAAa,GAAG,CAAC,IAA8B,EAAE,OAAe,KAAK,CAAA,EAAG,iBAAiB,CAAG,EAAA,IAAI,CAAG,EAAA,OAAO,EAAE;AAElH
|
|
1
|
+
{"version":3,"file":"core.mjs","sources":["../../../../src/storage/enhanced/local/core.ts"],"sourcesContent":["import {\n deserialize,\n serialize,\n} from 'superjson';\n\nenum StorageValueEncodingType {\n Json = '0',\n String = '1',\n}\n\nconst customValueHeader = '';\nconst customValueHeaderLength = customValueHeader.length + 1;\nconst toCustomValue = (type: StorageValueEncodingType, payload: string) => `${customValueHeader}${type}${payload}`;\n\n/**\n * An enhanced localStorage wrapper that supports storing\n * complex data types (e.g. Dates, Maps, Sets) using SuperJSON encoding.\n *\n * This utility preserves type structure when saving and retrieving values.\n *\n * @example\n * ```typescript\n * import { enhancedLocalStorage } from '@kikiutils/shared/storage/enhanced/local';\n *\n * enhancedLocalStorage.setItem('user', { name: 'user', createdAt: new Date() });\n * const user = enhancedLocalStorage.getItem<{ name: string, createdAt: Date }>('user');\n * ```\n */\nexport const enhancedLocalStorage = Object.freeze({\n /**\n * Removes all items from localStorage.\n */\n clear: () => window.localStorage.clear(),\n /**\n * Retrieves a value by key and decodes it using SuperJSON or raw string.\n *\n * @template T - The expected type of the value.\n *\n * @param {string} key - The key of the value to retrieve.\n *\n * @returns {null | T} The decoded value or null if not found.\n */\n getItem<T = unknown>(key: string) {\n const rawValue = window.localStorage.getItem(key);\n return rawValue ? decodeStorageValue(rawValue) as T : null;\n },\n /**\n * Checks whether a key exists in localStorage.\n *\n * @param {string} key - The key to check.\n *\n * @returns {boolean} True if the key exists, false otherwise.\n */\n hasItem: (key: string) => window.localStorage.getItem(key) !== null,\n /**\n * Returns the number of items stored in localStorage.\n *\n * @returns {number} The number of items stored in localStorage.\n */\n get length() {\n return window.localStorage.length;\n },\n /**\n * Removes a specific key from localStorage.\n *\n * @param {string} key - The key to remove.\n */\n removeItem: (key: string) => window.localStorage.removeItem(key),\n /**\n * Stores a value in localStorage with automatic serialization.\n *\n * @param {string} key - The key to store the value under.\n * @param {any} value - The value to store.\n */\n setItem: (key: string, value: any) => window.localStorage.setItem(key, encodeToStorageValue(value)),\n});\n\nfunction decodeStorageValue(data: string) {\n if (!isCustomFormat(data)) return data;\n const payload = data.substring(customValueHeaderLength);\n const type = data.charAt(customValueHeader.length);\n switch (type) {\n case StorageValueEncodingType.Json:\n try {\n return deserialize(JSON.parse(payload));\n } catch {\n throw new Error('[EnhancedLocalStorage] Failed to parse JSON payload.');\n }\n case StorageValueEncodingType.String: return payload;\n default:\n throw new Error(`[EnhancedLocalStorage] Unknown encoding type: ${type}.`);\n }\n}\n\nfunction encodeToStorageValue(value: any) {\n if (typeof value === 'string') return toCustomValue(StorageValueEncodingType.String, value);\n return toCustomValue(StorageValueEncodingType.Json, JSON.stringify(serialize(value)));\n}\n\nfunction isCustomFormat(data: string) {\n return (\n data.length >= customValueHeaderLength\n && data[0] === customValueHeader[0]\n && data[1] === customValueHeader[1]\n );\n}\n"],"names":[],"mappings":";;AAKA,IAAK,wBAGJ;AAHD,CAAA,UAAK,wBAAwB,EAAA;AACzB,IAAA,wBAAA,CAAA,MAAA,CAAA,GAAA,GAAU;AACV,IAAA,wBAAA,CAAA,QAAA,CAAA,GAAA,GAAY;AAChB,CAAC,EAHI,wBAAwB,KAAxB,wBAAwB,GAG5B,EAAA,CAAA,CAAA;AAED,MAAM,iBAAiB,GAAG,IAAI;AAC9B,MAAM,uBAAuB,GAAG,iBAAiB,CAAC,MAAM,GAAG,CAAC;AAC5D,MAAM,aAAa,GAAG,CAAC,IAA8B,EAAE,OAAe,KAAK,CAAA,EAAG,iBAAiB,CAAG,EAAA,IAAI,CAAG,EAAA,OAAO,EAAE;AAElH;;;;;;;;;;;;;AAaG;AACU,MAAA,oBAAoB,GAAG,MAAM,CAAC,MAAM,CAAC;AAC9C;;AAEG;IACH,KAAK,EAAE,MAAM,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE;AACxC;;;;;;;;AAQG;AACH,IAAA,OAAO,CAAc,GAAW,EAAA;QAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC;AACjD,QAAA,OAAO,QAAQ,GAAG,kBAAkB,CAAC,QAAQ,CAAM,GAAG,IAAI;KAC7D;AACD;;;;;;AAMG;AACH,IAAA,OAAO,EAAE,CAAC,GAAW,KAAK,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI;AACnE;;;;AAIG;AACH,IAAA,IAAI,MAAM,GAAA;AACN,QAAA,OAAO,MAAM,CAAC,YAAY,CAAC,MAAM;KACpC;AACD;;;;AAIG;AACH,IAAA,UAAU,EAAE,CAAC,GAAW,KAAK,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC;AAChE;;;;;AAKG;IACH,OAAO,EAAE,CAAC,GAAW,EAAE,KAAU,KAAK,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,oBAAoB,CAAC,KAAK,CAAC,CAAC;AACtG,CAAA;AAED,SAAS,kBAAkB,CAAC,IAAY,EAAA;AACpC,IAAA,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC;AAAE,QAAA,OAAO,IAAI;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC;IACvD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC;IAClD,QAAQ,IAAI;QACR,KAAK,wBAAwB,CAAC,IAAI;AAC9B,YAAA,IAAI;gBACA,OAAO,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;;AACzC,YAAA,MAAM;AACJ,gBAAA,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC;;AAE/E,QAAA,KAAK,wBAAwB,CAAC,MAAM,EAAE,OAAO,OAAO;AACpD,QAAA;AACI,YAAA,MAAM,IAAI,KAAK,CAAC,iDAAiD,IAAI,CAAA,CAAA,CAAG,CAAC;;AAErF;AAEA,SAAS,oBAAoB,CAAC,KAAU,EAAA;IACpC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,aAAa,CAAC,wBAAwB,CAAC,MAAM,EAAE,KAAK,CAAC;AAC3F,IAAA,OAAO,aAAa,CAAC,wBAAwB,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;AACzF;AAEA,SAAS,cAAc,CAAC,IAAY,EAAA;AAChC,IAAA,QACI,IAAI,CAAC,MAAM,IAAI;AACZ,WAAA,IAAI,CAAC,CAAC,CAAC,KAAK,iBAAiB,CAAC,CAAC;WAC/B,IAAI,CAAC,CAAC,CAAC,KAAK,iBAAiB,CAAC,CAAC,CAAC;AAE3C;;;;"}
|
|
@@ -15,6 +15,8 @@ const core = require('./core.cjs');
|
|
|
15
15
|
*
|
|
16
16
|
* @example
|
|
17
17
|
* ```typescript
|
|
18
|
+
* import { createKeyedEnhancedLocalStore } from '@kikiutils/shared/storage/enhanced/local';
|
|
19
|
+
*
|
|
18
20
|
* const userStore = createKeyedEnhancedLocalStore<User>()((id: number) => `user:${id}`);
|
|
19
21
|
* userStore.setItem({ id: 123, name: 'user' }, 123);
|
|
20
22
|
* const user = userStore.getItem(123);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyed-store.cjs","sources":["../../../../src/storage/enhanced/local/keyed-store.ts"],"sourcesContent":["import { enhancedLocalStorage } from './core';\n\n/**\n * Creates a reusable, type-safe storage interface based on `enhancedLocalStorage`\n * and a dynamic key-generation function.\n *\n * This utility allows you to abstract away key construction logic and work directly\n * with scoped key-value operations like `getItem`, `setItem`, and `removeItem`.\n *\n * @template D - The value type to store.\n *\n * @returns A factory that accepts a key generator function and returns a scoped storage interface.\n *\n * @example\n * ```typescript\n * const userStore = createKeyedEnhancedLocalStore<User>()((id: number) => `user:${id}`);\n * userStore.setItem({ id: 123, name: 'user' }, 123);\n * const user = userStore.getItem(123);\n * ```\n */\nexport function createKeyedEnhancedLocalStore<D = unknown>() {\n return <P extends any[]>(getKeyFunction: (...args: P) => string) => Object.freeze({\n getItem: (...args: P) => enhancedLocalStorage.getItem<D>(getKeyFunction(...args)),\n hasItem: (...args: P) => enhancedLocalStorage.hasItem(getKeyFunction(...args)),\n removeItem: (...args: P) => enhancedLocalStorage.removeItem(getKeyFunction(...args)),\n /**\n * Resolves the storage key from the given arguments.\n *\n * @returns {string} The final string key used internally.\n */\n resolveKey: (...args: P) => getKeyFunction(...args),\n setItem: (value: D, ...args: P) => enhancedLocalStorage.setItem(getKeyFunction(...args), value),\n });\n}\n"],"names":["enhancedLocalStorage"],"mappings":";;;;AAEA
|
|
1
|
+
{"version":3,"file":"keyed-store.cjs","sources":["../../../../src/storage/enhanced/local/keyed-store.ts"],"sourcesContent":["import { enhancedLocalStorage } from './core';\n\n/**\n * Creates a reusable, type-safe storage interface based on `enhancedLocalStorage`\n * and a dynamic key-generation function.\n *\n * This utility allows you to abstract away key construction logic and work directly\n * with scoped key-value operations like `getItem`, `setItem`, and `removeItem`.\n *\n * @template D - The value type to store.\n *\n * @returns A factory that accepts a key generator function and returns a scoped storage interface.\n *\n * @example\n * ```typescript\n * import { createKeyedEnhancedLocalStore } from '@kikiutils/shared/storage/enhanced/local';\n *\n * const userStore = createKeyedEnhancedLocalStore<User>()((id: number) => `user:${id}`);\n * userStore.setItem({ id: 123, name: 'user' }, 123);\n * const user = userStore.getItem(123);\n * ```\n */\nexport function createKeyedEnhancedLocalStore<D = unknown>() {\n return <P extends any[]>(getKeyFunction: (...args: P) => string) => Object.freeze({\n getItem: (...args: P) => enhancedLocalStorage.getItem<D>(getKeyFunction(...args)),\n hasItem: (...args: P) => enhancedLocalStorage.hasItem(getKeyFunction(...args)),\n removeItem: (...args: P) => enhancedLocalStorage.removeItem(getKeyFunction(...args)),\n /**\n * Resolves the storage key from the given arguments.\n *\n * @returns {string} The final string key used internally.\n */\n resolveKey: (...args: P) => getKeyFunction(...args),\n setItem: (value: D, ...args: P) => enhancedLocalStorage.setItem(getKeyFunction(...args), value),\n });\n}\n"],"names":["enhancedLocalStorage"],"mappings":";;;;AAEA;;;;;;;;;;;;;;;;;;;AAmBG;SACa,6BAA6B,GAAA;IACzC,OAAO,CAAkB,cAAsC,KAAK,MAAM,CAAC,MAAM,CAAC;AAC9E,QAAA,OAAO,EAAE,CAAC,GAAG,IAAO,KAAKA,yBAAoB,CAAC,OAAO,CAAI,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;AACjF,QAAA,OAAO,EAAE,CAAC,GAAG,IAAO,KAAKA,yBAAoB,CAAC,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;AAC9E,QAAA,UAAU,EAAE,CAAC,GAAG,IAAO,KAAKA,yBAAoB,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;AACpF;;;;AAIG;QACH,UAAU,EAAE,CAAC,GAAG,IAAO,KAAK,cAAc,CAAC,GAAG,IAAI,CAAC;QACnD,OAAO,EAAE,CAAC,KAAQ,EAAE,GAAG,IAAO,KAAKA,yBAAoB,CAAC,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,EAAE,KAAK,CAAC;AAClG,KAAA,CAAC;AACN;;;;"}
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
*
|
|
12
12
|
* @example
|
|
13
13
|
* ```typescript
|
|
14
|
+
* import { createKeyedEnhancedLocalStore } from '@kikiutils/shared/storage/enhanced/local';
|
|
15
|
+
*
|
|
14
16
|
* const userStore = createKeyedEnhancedLocalStore<User>()((id: number) => `user:${id}`);
|
|
15
17
|
* userStore.setItem({ id: 123, name: 'user' }, 123);
|
|
16
18
|
* const user = userStore.getItem(123);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyed-store.d.ts","sourceRoot":"","sources":["../../../../src/storage/enhanced/local/keyed-store.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"keyed-store.d.ts","sourceRoot":"","sources":["../../../../src/storage/enhanced/local/keyed-store.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,6BAA6B,CAAC,CAAC,GAAG,OAAO,MAC7C,CAAC,SAAS,GAAG,EAAE,EAAE,gBAAgB,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,MAAM;uBACxC,CAAC;uBACD,CAAC;0BACE,CAAC;IACvB;;;;OAIG;0BACmB,CAAC;qBACN,CAAC,WAAW,CAAC;GAErC"}
|
|
@@ -13,6 +13,8 @@ import { enhancedLocalStorage } from './core.mjs';
|
|
|
13
13
|
*
|
|
14
14
|
* @example
|
|
15
15
|
* ```typescript
|
|
16
|
+
* import { createKeyedEnhancedLocalStore } from '@kikiutils/shared/storage/enhanced/local';
|
|
17
|
+
*
|
|
16
18
|
* const userStore = createKeyedEnhancedLocalStore<User>()((id: number) => `user:${id}`);
|
|
17
19
|
* userStore.setItem({ id: 123, name: 'user' }, 123);
|
|
18
20
|
* const user = userStore.getItem(123);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyed-store.mjs","sources":["../../../../src/storage/enhanced/local/keyed-store.ts"],"sourcesContent":["import { enhancedLocalStorage } from './core';\n\n/**\n * Creates a reusable, type-safe storage interface based on `enhancedLocalStorage`\n * and a dynamic key-generation function.\n *\n * This utility allows you to abstract away key construction logic and work directly\n * with scoped key-value operations like `getItem`, `setItem`, and `removeItem`.\n *\n * @template D - The value type to store.\n *\n * @returns A factory that accepts a key generator function and returns a scoped storage interface.\n *\n * @example\n * ```typescript\n * const userStore = createKeyedEnhancedLocalStore<User>()((id: number) => `user:${id}`);\n * userStore.setItem({ id: 123, name: 'user' }, 123);\n * const user = userStore.getItem(123);\n * ```\n */\nexport function createKeyedEnhancedLocalStore<D = unknown>() {\n return <P extends any[]>(getKeyFunction: (...args: P) => string) => Object.freeze({\n getItem: (...args: P) => enhancedLocalStorage.getItem<D>(getKeyFunction(...args)),\n hasItem: (...args: P) => enhancedLocalStorage.hasItem(getKeyFunction(...args)),\n removeItem: (...args: P) => enhancedLocalStorage.removeItem(getKeyFunction(...args)),\n /**\n * Resolves the storage key from the given arguments.\n *\n * @returns {string} The final string key used internally.\n */\n resolveKey: (...args: P) => getKeyFunction(...args),\n setItem: (value: D, ...args: P) => enhancedLocalStorage.setItem(getKeyFunction(...args), value),\n });\n}\n"],"names":[],"mappings":";;AAEA
|
|
1
|
+
{"version":3,"file":"keyed-store.mjs","sources":["../../../../src/storage/enhanced/local/keyed-store.ts"],"sourcesContent":["import { enhancedLocalStorage } from './core';\n\n/**\n * Creates a reusable, type-safe storage interface based on `enhancedLocalStorage`\n * and a dynamic key-generation function.\n *\n * This utility allows you to abstract away key construction logic and work directly\n * with scoped key-value operations like `getItem`, `setItem`, and `removeItem`.\n *\n * @template D - The value type to store.\n *\n * @returns A factory that accepts a key generator function and returns a scoped storage interface.\n *\n * @example\n * ```typescript\n * import { createKeyedEnhancedLocalStore } from '@kikiutils/shared/storage/enhanced/local';\n *\n * const userStore = createKeyedEnhancedLocalStore<User>()((id: number) => `user:${id}`);\n * userStore.setItem({ id: 123, name: 'user' }, 123);\n * const user = userStore.getItem(123);\n * ```\n */\nexport function createKeyedEnhancedLocalStore<D = unknown>() {\n return <P extends any[]>(getKeyFunction: (...args: P) => string) => Object.freeze({\n getItem: (...args: P) => enhancedLocalStorage.getItem<D>(getKeyFunction(...args)),\n hasItem: (...args: P) => enhancedLocalStorage.hasItem(getKeyFunction(...args)),\n removeItem: (...args: P) => enhancedLocalStorage.removeItem(getKeyFunction(...args)),\n /**\n * Resolves the storage key from the given arguments.\n *\n * @returns {string} The final string key used internally.\n */\n resolveKey: (...args: P) => getKeyFunction(...args),\n setItem: (value: D, ...args: P) => enhancedLocalStorage.setItem(getKeyFunction(...args), value),\n });\n}\n"],"names":[],"mappings":";;AAEA;;;;;;;;;;;;;;;;;;;AAmBG;SACa,6BAA6B,GAAA;IACzC,OAAO,CAAkB,cAAsC,KAAK,MAAM,CAAC,MAAM,CAAC;AAC9E,QAAA,OAAO,EAAE,CAAC,GAAG,IAAO,KAAK,oBAAoB,CAAC,OAAO,CAAI,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;AACjF,QAAA,OAAO,EAAE,CAAC,GAAG,IAAO,KAAK,oBAAoB,CAAC,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;AAC9E,QAAA,UAAU,EAAE,CAAC,GAAG,IAAO,KAAK,oBAAoB,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;AACpF;;;;AAIG;QACH,UAAU,EAAE,CAAC,GAAG,IAAO,KAAK,cAAc,CAAC,GAAG,IAAI,CAAC;QACnD,OAAO,EAAE,CAAC,KAAQ,EAAE,GAAG,IAAO,KAAK,oBAAoB,CAAC,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,EAAE,KAAK,CAAC;AAClG,KAAA,CAAC;AACN;;;;"}
|
|
@@ -24,6 +24,8 @@ const customValueHeaderLength = customValueHeader.byteLength + 1;
|
|
|
24
24
|
*
|
|
25
25
|
* @example
|
|
26
26
|
* ```typescript
|
|
27
|
+
* import { createEnhancedRedisStorage } from '@kikiutils/shared/storage/enhanced/redis';
|
|
28
|
+
*
|
|
27
29
|
* const redisStorage = createEnhancedRedisStorage('redis://localhost');
|
|
28
30
|
* await redisStorage.setItem('user:1', { name: 'user' });
|
|
29
31
|
* const user = await redisStorage.getItem<{ name: string }>('user:1');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.cjs","sources":["../../../../src/storage/enhanced/redis/core.ts"],"sourcesContent":["import { Buffer } from 'node:buffer';\n\nimport { Redis } from 'ioredis';\nimport {\n deserialize,\n serialize,\n} from 'superjson';\n\nenum StorageValueEncodingType {\n Buffer = 0,\n Json = 1,\n String = 2,\n}\n\nconst customValueHeader = Buffer.of(\n 0xE2,\n 0x81,\n 0xA0,\n);\n\nconst customValueHeaderLength = customValueHeader.byteLength + 1;\n\n/**\n * Creates an enhanced Redis-based storage interface using SuperJSON encoding.\n *\n * This utility provides a typed, serializable key-value store backed by Redis,\n * supporting TTL operations and safe deserialization of complex types (e.g. Date, Map).\n *\n * @param {Redis | string} ioRedisInstanceOrUrl - Either an existing `ioredis` instance or a Redis connection string.\n *\n * @returns A frozen object that wraps Redis commands with typed get/set logic and encoding.\n *\n * @example\n * ```typescript\n * const redisStorage = createEnhancedRedisStorage('redis://localhost');\n * await redisStorage.setItem('user:1', { name: 'user' });\n * const user = await redisStorage.getItem<{ name: string }>('user:1');\n * ```\n */\nexport function createEnhancedRedisStorage(ioRedisInstanceOrUrl: Redis | string) {\n const instance = ioRedisInstanceOrUrl instanceof Redis ? ioRedisInstanceOrUrl : new Redis(ioRedisInstanceOrUrl);\n return Object.freeze({\n /**\n * Retrieves a value from Redis and decodes it.\n *\n * @template T - The expected return type.\n *\n * @param {string} key - The Redis key.\n *\n * @returns {Promise<null | T>} The decoded value or null if not found.\n */\n async getItem<T = unknown>(key: string) {\n const rawValue = await instance.getBuffer(key);\n return rawValue ? decodeStorageValue(rawValue) as T : null;\n },\n /**\n * Gets the remaining TTL (in seconds) for a given key.\n *\n * @param {string} key - The Redis key.\n *\n * @returns {Promise<number>} The number of seconds until the key expires, or -1 if no expiration is set.\n */\n getItemTtl: (key: string) => instance.ttl(key),\n /**\n * Checks whether a key exists in Redis.\n *\n * @param {string} key - The Redis key.\n *\n * @returns {Promise<boolean>} True if the key exists, false otherwise.\n */\n hasItem: async (key: string) => await instance.exists(key) === 1,\n /**\n * The underlying Redis instance, exposed for advanced operations.\n * Use with caution; most use cases should rely on the wrapper methods.\n *\n * @returns {Redis} The underlying Redis instance.\n */\n get instance() {\n return instance;\n },\n /**\n * Removes a key from Redis.\n *\n * @param {string} key - The Redis key to delete.\n *\n * @returns {Promise<boolean>} A Promise that resolves to `true` if the key was removed,\n * or `false` if it did not exist.\n */\n removeItem: async (key: string) => await instance.del(key) === 1,\n /**\n * Stores a value in Redis without expiration.\n *\n * @param {string} key - The Redis key.\n * @param {any} value - The value to store. Will be serialized.\n */\n setItem: (key: string, value: any) => instance.set(key, encodeToStorageValue(value)),\n /**\n * Stores a value in Redis with a time-to-live (TTL).\n *\n * @param {string} key - The Redis key.\n * @param {number} seconds - Expiration time in seconds.\n * @param {any} value - The value to store. Will be serialized.\n */\n setItemWithTtl(key: string, seconds: number, value: any) {\n return instance.setex(key, seconds, encodeToStorageValue(value));\n },\n });\n}\n\nfunction decodeStorageValue(data: Buffer) {\n if (!isCustomFormat(data)) return data;\n const payload = data.subarray(customValueHeaderLength);\n const type = data[customValueHeader.byteLength];\n switch (type) {\n case StorageValueEncodingType.Buffer: return payload;\n case StorageValueEncodingType.Json:\n try {\n return deserialize(JSON.parse(payload.toString()));\n } catch {\n throw new Error('[RedisStorage] Failed to parse JSON payload.');\n }\n case StorageValueEncodingType.String: return payload.toString();\n default:\n throw new Error(`[RedisStorage] Unknown encoding type: ${type}.`);\n }\n}\n\nfunction encodeToStorageValue(value: any) {\n if (Buffer.isBuffer(value)) return toCustomValue(StorageValueEncodingType.Buffer, value);\n if (typeof value === 'string') return toCustomValue(StorageValueEncodingType.String, Buffer.from(value));\n return toCustomValue(StorageValueEncodingType.Json, Buffer.from(JSON.stringify(serialize(value))));\n}\n\nfunction isCustomFormat(buffer: Buffer) {\n return (\n buffer.length >= customValueHeaderLength\n && buffer[0] === customValueHeader[0]\n && buffer[1] === customValueHeader[1]\n && buffer[2] === customValueHeader[2]\n );\n}\n\nfunction toCustomValue(type: StorageValueEncodingType, payload: Buffer) {\n return Buffer.concat([\n customValueHeader,\n Buffer.of(type),\n payload,\n ]);\n}\n"],"names":["Buffer","Redis","deserialize","serialize"],"mappings":";;;;;;AAQA,IAAK,wBAIJ;AAJD,CAAA,UAAK,wBAAwB,EAAA;AACzB,IAAA,wBAAA,CAAA,wBAAA,CAAA,QAAA,CAAA,GAAA,CAAA,CAAA,GAAA,QAAU;AACV,IAAA,wBAAA,CAAA,wBAAA,CAAA,MAAA,CAAA,GAAA,CAAA,CAAA,GAAA,MAAQ;AACR,IAAA,wBAAA,CAAA,wBAAA,CAAA,QAAA,CAAA,GAAA,CAAA,CAAA,GAAA,QAAU;AACd,CAAC,EAJI,wBAAwB,KAAxB,wBAAwB,GAI5B,EAAA,CAAA,CAAA;AAED,MAAM,iBAAiB,GAAGA,kBAAM,CAAC,EAAE,CAC/B,IAAI,EACJ,IAAI,EACJ,IAAI,CACP;AAED,MAAM,uBAAuB,GAAG,iBAAiB,CAAC,UAAU,GAAG,CAAC;AAEhE
|
|
1
|
+
{"version":3,"file":"core.cjs","sources":["../../../../src/storage/enhanced/redis/core.ts"],"sourcesContent":["import { Buffer } from 'node:buffer';\n\nimport { Redis } from 'ioredis';\nimport {\n deserialize,\n serialize,\n} from 'superjson';\n\nenum StorageValueEncodingType {\n Buffer = 0,\n Json = 1,\n String = 2,\n}\n\nconst customValueHeader = Buffer.of(\n 0xE2,\n 0x81,\n 0xA0,\n);\n\nconst customValueHeaderLength = customValueHeader.byteLength + 1;\n\n/**\n * Creates an enhanced Redis-based storage interface using SuperJSON encoding.\n *\n * This utility provides a typed, serializable key-value store backed by Redis,\n * supporting TTL operations and safe deserialization of complex types (e.g. Date, Map).\n *\n * @param {Redis | string} ioRedisInstanceOrUrl - Either an existing `ioredis` instance or a Redis connection string.\n *\n * @returns A frozen object that wraps Redis commands with typed get/set logic and encoding.\n *\n * @example\n * ```typescript\n * import { createEnhancedRedisStorage } from '@kikiutils/shared/storage/enhanced/redis';\n *\n * const redisStorage = createEnhancedRedisStorage('redis://localhost');\n * await redisStorage.setItem('user:1', { name: 'user' });\n * const user = await redisStorage.getItem<{ name: string }>('user:1');\n * ```\n */\nexport function createEnhancedRedisStorage(ioRedisInstanceOrUrl: Redis | string) {\n const instance = ioRedisInstanceOrUrl instanceof Redis ? ioRedisInstanceOrUrl : new Redis(ioRedisInstanceOrUrl);\n return Object.freeze({\n /**\n * Retrieves a value from Redis and decodes it.\n *\n * @template T - The expected return type.\n *\n * @param {string} key - The Redis key.\n *\n * @returns {Promise<null | T>} The decoded value or null if not found.\n */\n async getItem<T = unknown>(key: string) {\n const rawValue = await instance.getBuffer(key);\n return rawValue ? decodeStorageValue(rawValue) as T : null;\n },\n /**\n * Gets the remaining TTL (in seconds) for a given key.\n *\n * @param {string} key - The Redis key.\n *\n * @returns {Promise<number>} The number of seconds until the key expires, or -1 if no expiration is set.\n */\n getItemTtl: (key: string) => instance.ttl(key),\n /**\n * Checks whether a key exists in Redis.\n *\n * @param {string} key - The Redis key.\n *\n * @returns {Promise<boolean>} True if the key exists, false otherwise.\n */\n hasItem: async (key: string) => await instance.exists(key) === 1,\n /**\n * The underlying Redis instance, exposed for advanced operations.\n * Use with caution; most use cases should rely on the wrapper methods.\n *\n * @returns {Redis} The underlying Redis instance.\n */\n get instance() {\n return instance;\n },\n /**\n * Removes a key from Redis.\n *\n * @param {string} key - The Redis key to delete.\n *\n * @returns {Promise<boolean>} A Promise that resolves to `true` if the key was removed,\n * or `false` if it did not exist.\n */\n removeItem: async (key: string) => await instance.del(key) === 1,\n /**\n * Stores a value in Redis without expiration.\n *\n * @param {string} key - The Redis key.\n * @param {any} value - The value to store. Will be serialized.\n */\n setItem: (key: string, value: any) => instance.set(key, encodeToStorageValue(value)),\n /**\n * Stores a value in Redis with a time-to-live (TTL).\n *\n * @param {string} key - The Redis key.\n * @param {number} seconds - Expiration time in seconds.\n * @param {any} value - The value to store. Will be serialized.\n */\n setItemWithTtl(key: string, seconds: number, value: any) {\n return instance.setex(key, seconds, encodeToStorageValue(value));\n },\n });\n}\n\nfunction decodeStorageValue(data: Buffer) {\n if (!isCustomFormat(data)) return data;\n const payload = data.subarray(customValueHeaderLength);\n const type = data[customValueHeader.byteLength];\n switch (type) {\n case StorageValueEncodingType.Buffer: return payload;\n case StorageValueEncodingType.Json:\n try {\n return deserialize(JSON.parse(payload.toString()));\n } catch {\n throw new Error('[RedisStorage] Failed to parse JSON payload.');\n }\n case StorageValueEncodingType.String: return payload.toString();\n default:\n throw new Error(`[RedisStorage] Unknown encoding type: ${type}.`);\n }\n}\n\nfunction encodeToStorageValue(value: any) {\n if (Buffer.isBuffer(value)) return toCustomValue(StorageValueEncodingType.Buffer, value);\n if (typeof value === 'string') return toCustomValue(StorageValueEncodingType.String, Buffer.from(value));\n return toCustomValue(StorageValueEncodingType.Json, Buffer.from(JSON.stringify(serialize(value))));\n}\n\nfunction isCustomFormat(buffer: Buffer) {\n return (\n buffer.length >= customValueHeaderLength\n && buffer[0] === customValueHeader[0]\n && buffer[1] === customValueHeader[1]\n && buffer[2] === customValueHeader[2]\n );\n}\n\nfunction toCustomValue(type: StorageValueEncodingType, payload: Buffer) {\n return Buffer.concat([\n customValueHeader,\n Buffer.of(type),\n payload,\n ]);\n}\n"],"names":["Buffer","Redis","deserialize","serialize"],"mappings":"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"}
|
|
@@ -11,6 +11,8 @@ import { Redis } from 'ioredis';
|
|
|
11
11
|
*
|
|
12
12
|
* @example
|
|
13
13
|
* ```typescript
|
|
14
|
+
* import { createEnhancedRedisStorage } from '@kikiutils/shared/storage/enhanced/redis';
|
|
15
|
+
*
|
|
14
16
|
* const redisStorage = createEnhancedRedisStorage('redis://localhost');
|
|
15
17
|
* await redisStorage.setItem('user:1', { name: 'user' });
|
|
16
18
|
* const user = await redisStorage.getItem<{ name: string }>('user:1');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../../src/storage/enhanced/redis/core.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAoBhC
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../../src/storage/enhanced/redis/core.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAoBhC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,0BAA0B,CAAC,oBAAoB,EAAE,KAAK,GAAG,MAAM;IAGvE;;;;;;;;OAQG;YACW,CAAC,iBAAiB,MAAM;IAItC;;;;;;OAMG;sBACe,MAAM;IACxB;;;;;;OAMG;mBACkB,MAAM;IAC3B;;;;;OAKG;;IAIH;;;;;;;OAOG;sBACqB,MAAM;IAC9B;;;;;OAKG;mBACY,MAAM,SAAS,GAAG;IACjC;;;;;;OAMG;wBACiB,MAAM,WAAW,MAAM,SAAS,GAAG;GAI9D"}
|
|
@@ -22,6 +22,8 @@ const customValueHeaderLength = customValueHeader.byteLength + 1;
|
|
|
22
22
|
*
|
|
23
23
|
* @example
|
|
24
24
|
* ```typescript
|
|
25
|
+
* import { createEnhancedRedisStorage } from '@kikiutils/shared/storage/enhanced/redis';
|
|
26
|
+
*
|
|
25
27
|
* const redisStorage = createEnhancedRedisStorage('redis://localhost');
|
|
26
28
|
* await redisStorage.setItem('user:1', { name: 'user' });
|
|
27
29
|
* const user = await redisStorage.getItem<{ name: string }>('user:1');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.mjs","sources":["../../../../src/storage/enhanced/redis/core.ts"],"sourcesContent":["import { Buffer } from 'node:buffer';\n\nimport { Redis } from 'ioredis';\nimport {\n deserialize,\n serialize,\n} from 'superjson';\n\nenum StorageValueEncodingType {\n Buffer = 0,\n Json = 1,\n String = 2,\n}\n\nconst customValueHeader = Buffer.of(\n 0xE2,\n 0x81,\n 0xA0,\n);\n\nconst customValueHeaderLength = customValueHeader.byteLength + 1;\n\n/**\n * Creates an enhanced Redis-based storage interface using SuperJSON encoding.\n *\n * This utility provides a typed, serializable key-value store backed by Redis,\n * supporting TTL operations and safe deserialization of complex types (e.g. Date, Map).\n *\n * @param {Redis | string} ioRedisInstanceOrUrl - Either an existing `ioredis` instance or a Redis connection string.\n *\n * @returns A frozen object that wraps Redis commands with typed get/set logic and encoding.\n *\n * @example\n * ```typescript\n * const redisStorage = createEnhancedRedisStorage('redis://localhost');\n * await redisStorage.setItem('user:1', { name: 'user' });\n * const user = await redisStorage.getItem<{ name: string }>('user:1');\n * ```\n */\nexport function createEnhancedRedisStorage(ioRedisInstanceOrUrl: Redis | string) {\n const instance = ioRedisInstanceOrUrl instanceof Redis ? ioRedisInstanceOrUrl : new Redis(ioRedisInstanceOrUrl);\n return Object.freeze({\n /**\n * Retrieves a value from Redis and decodes it.\n *\n * @template T - The expected return type.\n *\n * @param {string} key - The Redis key.\n *\n * @returns {Promise<null | T>} The decoded value or null if not found.\n */\n async getItem<T = unknown>(key: string) {\n const rawValue = await instance.getBuffer(key);\n return rawValue ? decodeStorageValue(rawValue) as T : null;\n },\n /**\n * Gets the remaining TTL (in seconds) for a given key.\n *\n * @param {string} key - The Redis key.\n *\n * @returns {Promise<number>} The number of seconds until the key expires, or -1 if no expiration is set.\n */\n getItemTtl: (key: string) => instance.ttl(key),\n /**\n * Checks whether a key exists in Redis.\n *\n * @param {string} key - The Redis key.\n *\n * @returns {Promise<boolean>} True if the key exists, false otherwise.\n */\n hasItem: async (key: string) => await instance.exists(key) === 1,\n /**\n * The underlying Redis instance, exposed for advanced operations.\n * Use with caution; most use cases should rely on the wrapper methods.\n *\n * @returns {Redis} The underlying Redis instance.\n */\n get instance() {\n return instance;\n },\n /**\n * Removes a key from Redis.\n *\n * @param {string} key - The Redis key to delete.\n *\n * @returns {Promise<boolean>} A Promise that resolves to `true` if the key was removed,\n * or `false` if it did not exist.\n */\n removeItem: async (key: string) => await instance.del(key) === 1,\n /**\n * Stores a value in Redis without expiration.\n *\n * @param {string} key - The Redis key.\n * @param {any} value - The value to store. Will be serialized.\n */\n setItem: (key: string, value: any) => instance.set(key, encodeToStorageValue(value)),\n /**\n * Stores a value in Redis with a time-to-live (TTL).\n *\n * @param {string} key - The Redis key.\n * @param {number} seconds - Expiration time in seconds.\n * @param {any} value - The value to store. Will be serialized.\n */\n setItemWithTtl(key: string, seconds: number, value: any) {\n return instance.setex(key, seconds, encodeToStorageValue(value));\n },\n });\n}\n\nfunction decodeStorageValue(data: Buffer) {\n if (!isCustomFormat(data)) return data;\n const payload = data.subarray(customValueHeaderLength);\n const type = data[customValueHeader.byteLength];\n switch (type) {\n case StorageValueEncodingType.Buffer: return payload;\n case StorageValueEncodingType.Json:\n try {\n return deserialize(JSON.parse(payload.toString()));\n } catch {\n throw new Error('[RedisStorage] Failed to parse JSON payload.');\n }\n case StorageValueEncodingType.String: return payload.toString();\n default:\n throw new Error(`[RedisStorage] Unknown encoding type: ${type}.`);\n }\n}\n\nfunction encodeToStorageValue(value: any) {\n if (Buffer.isBuffer(value)) return toCustomValue(StorageValueEncodingType.Buffer, value);\n if (typeof value === 'string') return toCustomValue(StorageValueEncodingType.String, Buffer.from(value));\n return toCustomValue(StorageValueEncodingType.Json, Buffer.from(JSON.stringify(serialize(value))));\n}\n\nfunction isCustomFormat(buffer: Buffer) {\n return (\n buffer.length >= customValueHeaderLength\n && buffer[0] === customValueHeader[0]\n && buffer[1] === customValueHeader[1]\n && buffer[2] === customValueHeader[2]\n );\n}\n\nfunction toCustomValue(type: StorageValueEncodingType, payload: Buffer) {\n return Buffer.concat([\n customValueHeader,\n Buffer.of(type),\n payload,\n ]);\n}\n"],"names":[],"mappings":";;;;AAQA,IAAK,wBAIJ;AAJD,CAAA,UAAK,wBAAwB,EAAA;AACzB,IAAA,wBAAA,CAAA,wBAAA,CAAA,QAAA,CAAA,GAAA,CAAA,CAAA,GAAA,QAAU;AACV,IAAA,wBAAA,CAAA,wBAAA,CAAA,MAAA,CAAA,GAAA,CAAA,CAAA,GAAA,MAAQ;AACR,IAAA,wBAAA,CAAA,wBAAA,CAAA,QAAA,CAAA,GAAA,CAAA,CAAA,GAAA,QAAU;AACd,CAAC,EAJI,wBAAwB,KAAxB,wBAAwB,GAI5B,EAAA,CAAA,CAAA;AAED,MAAM,iBAAiB,GAAG,MAAM,CAAC,EAAE,CAC/B,IAAI,EACJ,IAAI,EACJ,IAAI,CACP;AAED,MAAM,uBAAuB,GAAG,iBAAiB,CAAC,UAAU,GAAG,CAAC;AAEhE
|
|
1
|
+
{"version":3,"file":"core.mjs","sources":["../../../../src/storage/enhanced/redis/core.ts"],"sourcesContent":["import { Buffer } from 'node:buffer';\n\nimport { Redis } from 'ioredis';\nimport {\n deserialize,\n serialize,\n} from 'superjson';\n\nenum StorageValueEncodingType {\n Buffer = 0,\n Json = 1,\n String = 2,\n}\n\nconst customValueHeader = Buffer.of(\n 0xE2,\n 0x81,\n 0xA0,\n);\n\nconst customValueHeaderLength = customValueHeader.byteLength + 1;\n\n/**\n * Creates an enhanced Redis-based storage interface using SuperJSON encoding.\n *\n * This utility provides a typed, serializable key-value store backed by Redis,\n * supporting TTL operations and safe deserialization of complex types (e.g. Date, Map).\n *\n * @param {Redis | string} ioRedisInstanceOrUrl - Either an existing `ioredis` instance or a Redis connection string.\n *\n * @returns A frozen object that wraps Redis commands with typed get/set logic and encoding.\n *\n * @example\n * ```typescript\n * import { createEnhancedRedisStorage } from '@kikiutils/shared/storage/enhanced/redis';\n *\n * const redisStorage = createEnhancedRedisStorage('redis://localhost');\n * await redisStorage.setItem('user:1', { name: 'user' });\n * const user = await redisStorage.getItem<{ name: string }>('user:1');\n * ```\n */\nexport function createEnhancedRedisStorage(ioRedisInstanceOrUrl: Redis | string) {\n const instance = ioRedisInstanceOrUrl instanceof Redis ? ioRedisInstanceOrUrl : new Redis(ioRedisInstanceOrUrl);\n return Object.freeze({\n /**\n * Retrieves a value from Redis and decodes it.\n *\n * @template T - The expected return type.\n *\n * @param {string} key - The Redis key.\n *\n * @returns {Promise<null | T>} The decoded value or null if not found.\n */\n async getItem<T = unknown>(key: string) {\n const rawValue = await instance.getBuffer(key);\n return rawValue ? decodeStorageValue(rawValue) as T : null;\n },\n /**\n * Gets the remaining TTL (in seconds) for a given key.\n *\n * @param {string} key - The Redis key.\n *\n * @returns {Promise<number>} The number of seconds until the key expires, or -1 if no expiration is set.\n */\n getItemTtl: (key: string) => instance.ttl(key),\n /**\n * Checks whether a key exists in Redis.\n *\n * @param {string} key - The Redis key.\n *\n * @returns {Promise<boolean>} True if the key exists, false otherwise.\n */\n hasItem: async (key: string) => await instance.exists(key) === 1,\n /**\n * The underlying Redis instance, exposed for advanced operations.\n * Use with caution; most use cases should rely on the wrapper methods.\n *\n * @returns {Redis} The underlying Redis instance.\n */\n get instance() {\n return instance;\n },\n /**\n * Removes a key from Redis.\n *\n * @param {string} key - The Redis key to delete.\n *\n * @returns {Promise<boolean>} A Promise that resolves to `true` if the key was removed,\n * or `false` if it did not exist.\n */\n removeItem: async (key: string) => await instance.del(key) === 1,\n /**\n * Stores a value in Redis without expiration.\n *\n * @param {string} key - The Redis key.\n * @param {any} value - The value to store. Will be serialized.\n */\n setItem: (key: string, value: any) => instance.set(key, encodeToStorageValue(value)),\n /**\n * Stores a value in Redis with a time-to-live (TTL).\n *\n * @param {string} key - The Redis key.\n * @param {number} seconds - Expiration time in seconds.\n * @param {any} value - The value to store. Will be serialized.\n */\n setItemWithTtl(key: string, seconds: number, value: any) {\n return instance.setex(key, seconds, encodeToStorageValue(value));\n },\n });\n}\n\nfunction decodeStorageValue(data: Buffer) {\n if (!isCustomFormat(data)) return data;\n const payload = data.subarray(customValueHeaderLength);\n const type = data[customValueHeader.byteLength];\n switch (type) {\n case StorageValueEncodingType.Buffer: return payload;\n case StorageValueEncodingType.Json:\n try {\n return deserialize(JSON.parse(payload.toString()));\n } catch {\n throw new Error('[RedisStorage] Failed to parse JSON payload.');\n }\n case StorageValueEncodingType.String: return payload.toString();\n default:\n throw new Error(`[RedisStorage] Unknown encoding type: ${type}.`);\n }\n}\n\nfunction encodeToStorageValue(value: any) {\n if (Buffer.isBuffer(value)) return toCustomValue(StorageValueEncodingType.Buffer, value);\n if (typeof value === 'string') return toCustomValue(StorageValueEncodingType.String, Buffer.from(value));\n return toCustomValue(StorageValueEncodingType.Json, Buffer.from(JSON.stringify(serialize(value))));\n}\n\nfunction isCustomFormat(buffer: Buffer) {\n return (\n buffer.length >= customValueHeaderLength\n && buffer[0] === customValueHeader[0]\n && buffer[1] === customValueHeader[1]\n && buffer[2] === customValueHeader[2]\n );\n}\n\nfunction toCustomValue(type: StorageValueEncodingType, payload: Buffer) {\n return Buffer.concat([\n customValueHeader,\n Buffer.of(type),\n payload,\n ]);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
*
|
|
17
17
|
* @example
|
|
18
18
|
* ```typescript
|
|
19
|
+
* import { createKeyedEnhancedRedisStore } from '@kikiutils/shared/storage/enhanced/redis';
|
|
20
|
+
*
|
|
19
21
|
* const userStore = createKeyedEnhancedRedisStore<User>(redisStorage)((id: number) => `user:${id}`);
|
|
20
22
|
* await userStore.setItem({ id: 123, name: 'user' }, 123);
|
|
21
23
|
* const user = await userStore.getItem(123);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyed-store.cjs","sources":["../../../../src/storage/enhanced/redis/keyed-store.ts"],"sourcesContent":["import type { createEnhancedRedisStorage } from './core';\n\n/**\n * Creates a reusable, type-safe Redis-backed storage interface based on `createEnhancedRedisStorage`\n * and a dynamic key-generation function.\n *\n * This utility abstracts away key construction and provides high-level access\n * to Redis operations such as `getItem`, `setItem`, `setItemWithTtl`, and `getItemTtl`.\n * It is ideal for namespaced data, caching, and session handling.\n *\n * @template D - The value type to store.\n *\n * @param {ReturnType<typeof createEnhancedRedisStorage>} storage - The enhanced Redis storage instance.\n *\n * @returns A factory that accepts a key generator function and returns a scoped Redis storage interface.\n *\n * @example\n * ```typescript\n * const userStore = createKeyedEnhancedRedisStore<User>(redisStorage)((id: number) => `user:${id}`);\n * await userStore.setItem({ id: 123, name: 'user' }, 123);\n * const user = await userStore.getItem(123);\n * ```\n */\nexport function createKeyedEnhancedRedisStore<D = unknown>(storage: ReturnType<typeof createEnhancedRedisStorage>) {\n return <P extends any[]>(getKeyFunction: (...args: P) => string) => Object.freeze({\n getItem: (...args: P) => storage.getItem<D>(getKeyFunction(...args)),\n getItemTtl: (...args: P) => storage.getItemTtl(getKeyFunction(...args)),\n hasItem: (...args: P) => storage.hasItem(getKeyFunction(...args)),\n removeItem: (...args: P) => storage.removeItem(getKeyFunction(...args)),\n /**\n * Resolves the storage key from the given arguments.\n *\n * @returns {string} The final string key used internally.\n */\n resolveKey: (...args: P) => getKeyFunction(...args),\n setItem: (value: D, ...args: P) => storage.setItem(getKeyFunction(...args), value),\n setItemWithTtl(seconds: number, value: D, ...args: P) {\n return storage.setItemWithTtl(getKeyFunction(...args), seconds, value);\n },\n });\n}\n"],"names":[],"mappings":";;AAEA
|
|
1
|
+
{"version":3,"file":"keyed-store.cjs","sources":["../../../../src/storage/enhanced/redis/keyed-store.ts"],"sourcesContent":["import type { createEnhancedRedisStorage } from './core';\n\n/**\n * Creates a reusable, type-safe Redis-backed storage interface based on `createEnhancedRedisStorage`\n * and a dynamic key-generation function.\n *\n * This utility abstracts away key construction and provides high-level access\n * to Redis operations such as `getItem`, `setItem`, `setItemWithTtl`, and `getItemTtl`.\n * It is ideal for namespaced data, caching, and session handling.\n *\n * @template D - The value type to store.\n *\n * @param {ReturnType<typeof createEnhancedRedisStorage>} storage - The enhanced Redis storage instance.\n *\n * @returns A factory that accepts a key generator function and returns a scoped Redis storage interface.\n *\n * @example\n * ```typescript\n * import { createKeyedEnhancedRedisStore } from '@kikiutils/shared/storage/enhanced/redis';\n *\n * const userStore = createKeyedEnhancedRedisStore<User>(redisStorage)((id: number) => `user:${id}`);\n * await userStore.setItem({ id: 123, name: 'user' }, 123);\n * const user = await userStore.getItem(123);\n * ```\n */\nexport function createKeyedEnhancedRedisStore<D = unknown>(storage: ReturnType<typeof createEnhancedRedisStorage>) {\n return <P extends any[]>(getKeyFunction: (...args: P) => string) => Object.freeze({\n getItem: (...args: P) => storage.getItem<D>(getKeyFunction(...args)),\n getItemTtl: (...args: P) => storage.getItemTtl(getKeyFunction(...args)),\n hasItem: (...args: P) => storage.hasItem(getKeyFunction(...args)),\n removeItem: (...args: P) => storage.removeItem(getKeyFunction(...args)),\n /**\n * Resolves the storage key from the given arguments.\n *\n * @returns {string} The final string key used internally.\n */\n resolveKey: (...args: P) => getKeyFunction(...args),\n setItem: (value: D, ...args: P) => storage.setItem(getKeyFunction(...args), value),\n setItemWithTtl(seconds: number, value: D, ...args: P) {\n return storage.setItemWithTtl(getKeyFunction(...args), seconds, value);\n },\n });\n}\n"],"names":[],"mappings":";;AAEA;;;;;;;;;;;;;;;;;;;;;;AAsBG;AACG,SAAU,6BAA6B,CAAc,OAAsD,EAAA;IAC7G,OAAO,CAAkB,cAAsC,KAAK,MAAM,CAAC,MAAM,CAAC;AAC9E,QAAA,OAAO,EAAE,CAAC,GAAG,IAAO,KAAK,OAAO,CAAC,OAAO,CAAI,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;AACpE,QAAA,UAAU,EAAE,CAAC,GAAG,IAAO,KAAK,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;AACvE,QAAA,OAAO,EAAE,CAAC,GAAG,IAAO,KAAK,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;AACjE,QAAA,UAAU,EAAE,CAAC,GAAG,IAAO,KAAK,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;AACvE;;;;AAIG;QACH,UAAU,EAAE,CAAC,GAAG,IAAO,KAAK,cAAc,CAAC,GAAG,IAAI,CAAC;QACnD,OAAO,EAAE,CAAC,KAAQ,EAAE,GAAG,IAAO,KAAK,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,EAAE,KAAK,CAAC;AAClF,QAAA,cAAc,CAAC,OAAe,EAAE,KAAQ,EAAE,GAAG,IAAO,EAAA;AAChD,YAAA,OAAO,OAAO,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC;SACzE;AACJ,KAAA,CAAC;AACN;;;;"}
|
|
@@ -15,6 +15,8 @@ import type { createEnhancedRedisStorage } from './core';
|
|
|
15
15
|
*
|
|
16
16
|
* @example
|
|
17
17
|
* ```typescript
|
|
18
|
+
* import { createKeyedEnhancedRedisStore } from '@kikiutils/shared/storage/enhanced/redis';
|
|
19
|
+
*
|
|
18
20
|
* const userStore = createKeyedEnhancedRedisStore<User>(redisStorage)((id: number) => `user:${id}`);
|
|
19
21
|
* await userStore.setItem({ id: 123, name: 'user' }, 123);
|
|
20
22
|
* const user = await userStore.getItem(123);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyed-store.d.ts","sourceRoot":"","sources":["../../../../src/storage/enhanced/redis/keyed-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,QAAQ,CAAC;AAEzD
|
|
1
|
+
{"version":3,"file":"keyed-store.d.ts","sourceRoot":"","sources":["../../../../src/storage/enhanced/redis/keyed-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,QAAQ,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,6BAA6B,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,0BAA0B,CAAC,IACrG,CAAC,SAAS,GAAG,EAAE,EAAE,gBAAgB,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,MAAM;uBACxC,CAAC;0BACE,CAAC;uBACJ,CAAC;0BACE,CAAC;IACvB;;;;OAIG;0BACmB,CAAC;qBACN,CAAC,WAAW,CAAC;4BACN,MAAM,SAAS,CAAC,WAAW,CAAC;GAI3D"}
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
*
|
|
15
15
|
* @example
|
|
16
16
|
* ```typescript
|
|
17
|
+
* import { createKeyedEnhancedRedisStore } from '@kikiutils/shared/storage/enhanced/redis';
|
|
18
|
+
*
|
|
17
19
|
* const userStore = createKeyedEnhancedRedisStore<User>(redisStorage)((id: number) => `user:${id}`);
|
|
18
20
|
* await userStore.setItem({ id: 123, name: 'user' }, 123);
|
|
19
21
|
* const user = await userStore.getItem(123);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyed-store.mjs","sources":["../../../../src/storage/enhanced/redis/keyed-store.ts"],"sourcesContent":["import type { createEnhancedRedisStorage } from './core';\n\n/**\n * Creates a reusable, type-safe Redis-backed storage interface based on `createEnhancedRedisStorage`\n * and a dynamic key-generation function.\n *\n * This utility abstracts away key construction and provides high-level access\n * to Redis operations such as `getItem`, `setItem`, `setItemWithTtl`, and `getItemTtl`.\n * It is ideal for namespaced data, caching, and session handling.\n *\n * @template D - The value type to store.\n *\n * @param {ReturnType<typeof createEnhancedRedisStorage>} storage - The enhanced Redis storage instance.\n *\n * @returns A factory that accepts a key generator function and returns a scoped Redis storage interface.\n *\n * @example\n * ```typescript\n * const userStore = createKeyedEnhancedRedisStore<User>(redisStorage)((id: number) => `user:${id}`);\n * await userStore.setItem({ id: 123, name: 'user' }, 123);\n * const user = await userStore.getItem(123);\n * ```\n */\nexport function createKeyedEnhancedRedisStore<D = unknown>(storage: ReturnType<typeof createEnhancedRedisStorage>) {\n return <P extends any[]>(getKeyFunction: (...args: P) => string) => Object.freeze({\n getItem: (...args: P) => storage.getItem<D>(getKeyFunction(...args)),\n getItemTtl: (...args: P) => storage.getItemTtl(getKeyFunction(...args)),\n hasItem: (...args: P) => storage.hasItem(getKeyFunction(...args)),\n removeItem: (...args: P) => storage.removeItem(getKeyFunction(...args)),\n /**\n * Resolves the storage key from the given arguments.\n *\n * @returns {string} The final string key used internally.\n */\n resolveKey: (...args: P) => getKeyFunction(...args),\n setItem: (value: D, ...args: P) => storage.setItem(getKeyFunction(...args), value),\n setItemWithTtl(seconds: number, value: D, ...args: P) {\n return storage.setItemWithTtl(getKeyFunction(...args), seconds, value);\n },\n });\n}\n"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"keyed-store.mjs","sources":["../../../../src/storage/enhanced/redis/keyed-store.ts"],"sourcesContent":["import type { createEnhancedRedisStorage } from './core';\n\n/**\n * Creates a reusable, type-safe Redis-backed storage interface based on `createEnhancedRedisStorage`\n * and a dynamic key-generation function.\n *\n * This utility abstracts away key construction and provides high-level access\n * to Redis operations such as `getItem`, `setItem`, `setItemWithTtl`, and `getItemTtl`.\n * It is ideal for namespaced data, caching, and session handling.\n *\n * @template D - The value type to store.\n *\n * @param {ReturnType<typeof createEnhancedRedisStorage>} storage - The enhanced Redis storage instance.\n *\n * @returns A factory that accepts a key generator function and returns a scoped Redis storage interface.\n *\n * @example\n * ```typescript\n * import { createKeyedEnhancedRedisStore } from '@kikiutils/shared/storage/enhanced/redis';\n *\n * const userStore = createKeyedEnhancedRedisStore<User>(redisStorage)((id: number) => `user:${id}`);\n * await userStore.setItem({ id: 123, name: 'user' }, 123);\n * const user = await userStore.getItem(123);\n * ```\n */\nexport function createKeyedEnhancedRedisStore<D = unknown>(storage: ReturnType<typeof createEnhancedRedisStorage>) {\n return <P extends any[]>(getKeyFunction: (...args: P) => string) => Object.freeze({\n getItem: (...args: P) => storage.getItem<D>(getKeyFunction(...args)),\n getItemTtl: (...args: P) => storage.getItemTtl(getKeyFunction(...args)),\n hasItem: (...args: P) => storage.hasItem(getKeyFunction(...args)),\n removeItem: (...args: P) => storage.removeItem(getKeyFunction(...args)),\n /**\n * Resolves the storage key from the given arguments.\n *\n * @returns {string} The final string key used internally.\n */\n resolveKey: (...args: P) => getKeyFunction(...args),\n setItem: (value: D, ...args: P) => storage.setItem(getKeyFunction(...args), value),\n setItemWithTtl(seconds: number, value: D, ...args: P) {\n return storage.setItemWithTtl(getKeyFunction(...args), seconds, value);\n },\n });\n}\n"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;AAsBG;AACG,SAAU,6BAA6B,CAAc,OAAsD,EAAA;IAC7G,OAAO,CAAkB,cAAsC,KAAK,MAAM,CAAC,MAAM,CAAC;AAC9E,QAAA,OAAO,EAAE,CAAC,GAAG,IAAO,KAAK,OAAO,CAAC,OAAO,CAAI,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;AACpE,QAAA,UAAU,EAAE,CAAC,GAAG,IAAO,KAAK,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;AACvE,QAAA,OAAO,EAAE,CAAC,GAAG,IAAO,KAAK,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;AACjE,QAAA,UAAU,EAAE,CAAC,GAAG,IAAO,KAAK,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;AACvE;;;;AAIG;QACH,UAAU,EAAE,CAAC,GAAG,IAAO,KAAK,cAAc,CAAC,GAAG,IAAI,CAAC;QACnD,OAAO,EAAE,CAAC,KAAQ,EAAE,GAAG,IAAO,KAAK,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,EAAE,KAAK,CAAC;AAClF,QAAA,cAAc,CAAC,OAAe,EAAE,KAAQ,EAAE,GAAG,IAAO,EAAA;AAChD,YAAA,OAAO,OAAO,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC;SACzE;AACJ,KAAA,CAAC;AACN;;;;"}
|
|
@@ -6,23 +6,21 @@
|
|
|
6
6
|
* This utility allows structured access to cache entries using a dynamic key-generation function.
|
|
7
7
|
*
|
|
8
8
|
* @template D - The specific value type exposed by this store (must extend `V`).
|
|
9
|
-
* @template K - The type of keys used in the LRU cache (default: string).
|
|
10
|
-
* @template V - The type of values stored in the LRU cache.
|
|
11
|
-
* @template FC - The value used by `lru-cache` fetch context (if any).
|
|
12
9
|
*
|
|
13
|
-
* @param {LRUCache<
|
|
10
|
+
* @param {LRUCache<any, any, any>} lruInstance - An instance of `lru-cache`.
|
|
14
11
|
*
|
|
15
12
|
* @returns A factory that accepts a key generator and returns a scoped, type-safe LRU-based store.
|
|
16
13
|
*
|
|
17
14
|
* @example
|
|
18
15
|
* ```typescript
|
|
19
|
-
*
|
|
16
|
+
* import { createKeyedLruStore } from '@kikiutils/shared/storage/lru/keyed-store';
|
|
17
|
+
*
|
|
18
|
+
* const lruCache = new LRUCache({ max: 5000 });
|
|
20
19
|
* const userStore = createKeyedLruStore<User>(lruCache)((id: number) => `user:${id}`);
|
|
21
20
|
* userStore.setItem({ id: 1 }, 1);
|
|
22
21
|
* const user = userStore.getItem(1);
|
|
23
22
|
* ```
|
|
24
23
|
*/
|
|
25
|
-
// eslint-disable-next-line ts/no-empty-object-type
|
|
26
24
|
function createKeyedLruStore(lruInstance) {
|
|
27
25
|
return (getKeyFunction) => Object.freeze({
|
|
28
26
|
/**
|
|
@@ -41,7 +39,9 @@ function createKeyedLruStore(lruInstance) {
|
|
|
41
39
|
* Resolves the full cache key from the given arguments.
|
|
42
40
|
*/
|
|
43
41
|
resolveKey: (...args) => getKeyFunction(...args),
|
|
44
|
-
setItem
|
|
42
|
+
setItem(value, ...args) {
|
|
43
|
+
lruInstance.set(getKeyFunction(...args), value);
|
|
44
|
+
},
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
47
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyed-store.cjs","sources":["../../../src/storage/lru/keyed-store.ts"],"sourcesContent":["import type { LRUCache } from 'lru-cache';\n\n/**\n * Creates a reusable, type-safe keyed store wrapper for an LRUCache instance.\n *\n * This utility allows structured access to cache entries using a dynamic key-generation function.\n *\n * @template D - The specific value type exposed by this store (must extend `V`).\n
|
|
1
|
+
{"version":3,"file":"keyed-store.cjs","sources":["../../../src/storage/lru/keyed-store.ts"],"sourcesContent":["import type { LRUCache } from 'lru-cache';\n\n/**\n * Creates a reusable, type-safe keyed store wrapper for an LRUCache instance.\n *\n * This utility allows structured access to cache entries using a dynamic key-generation function.\n *\n * @template D - The specific value type exposed by this store (must extend `V`).\n *\n * @param {LRUCache<any, any, any>} lruInstance - An instance of `lru-cache`.\n *\n * @returns A factory that accepts a key generator and returns a scoped, type-safe LRU-based store.\n *\n * @example\n * ```typescript\n * import { createKeyedLruStore } from '@kikiutils/shared/storage/lru/keyed-store';\n *\n * const lruCache = new LRUCache({ max: 5000 });\n * const userStore = createKeyedLruStore<User>(lruCache)((id: number) => `user:${id}`);\n * userStore.setItem({ id: 1 }, 1);\n * const user = userStore.getItem(1);\n * ```\n */\nexport function createKeyedLruStore<D = unknown>(lruInstance: LRUCache<any, any, any>) {\n return <P extends any[]>(getKeyFunction: (...args: P) => string) => Object.freeze({\n /**\n * Return a value from the cache. Will update the recency of the cache entry found.\n *\n * If the key is not found, returns `null`.\n */\n getItem(...args: P) {\n const rawValue = lruInstance.get(getKeyFunction(...args));\n return rawValue as D ?? null;\n },\n getItemTtl: (...args: P) => lruInstance.getRemainingTTL(getKeyFunction(...args)),\n hasItem: (...args: P) => lruInstance.has(getKeyFunction(...args)),\n removeItem: (...args: P) => lruInstance.delete(getKeyFunction(...args)),\n /**\n * Resolves the full cache key from the given arguments.\n */\n resolveKey: (...args: P) => getKeyFunction(...args),\n setItem(value: D, ...args: P) {\n lruInstance.set(getKeyFunction(...args), value);\n },\n });\n}\n"],"names":[],"mappings":";;AAEA;;;;;;;;;;;;;;;;;;;;AAoBG;AACG,SAAU,mBAAmB,CAAc,WAAoC,EAAA;IACjF,OAAO,CAAkB,cAAsC,KAAK,MAAM,CAAC,MAAM,CAAC;AAC9E;;;;AAIG;QACH,OAAO,CAAC,GAAG,IAAO,EAAA;AACd,YAAA,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;YACzD,OAAO,QAAa,IAAI,IAAI;SAC/B;AACD,QAAA,UAAU,EAAE,CAAC,GAAG,IAAO,KAAK,WAAW,CAAC,eAAe,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;AAChF,QAAA,OAAO,EAAE,CAAC,GAAG,IAAO,KAAK,WAAW,CAAC,GAAG,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;AACjE,QAAA,UAAU,EAAE,CAAC,GAAG,IAAO,KAAK,WAAW,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;AACvE;;AAEG;QACH,UAAU,EAAE,CAAC,GAAG,IAAO,KAAK,cAAc,CAAC,GAAG,IAAI,CAAC;AACnD,QAAA,OAAO,CAAC,KAAQ,EAAE,GAAG,IAAO,EAAA;YACxB,WAAW,CAAC,GAAG,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,EAAE,KAAK,CAAC;SAClD;AACJ,KAAA,CAAC;AACN;;;;"}
|
|
@@ -5,36 +5,35 @@ import type { LRUCache } from 'lru-cache';
|
|
|
5
5
|
* This utility allows structured access to cache entries using a dynamic key-generation function.
|
|
6
6
|
*
|
|
7
7
|
* @template D - The specific value type exposed by this store (must extend `V`).
|
|
8
|
-
* @template K - The type of keys used in the LRU cache (default: string).
|
|
9
|
-
* @template V - The type of values stored in the LRU cache.
|
|
10
|
-
* @template FC - The value used by `lru-cache` fetch context (if any).
|
|
11
8
|
*
|
|
12
|
-
* @param {LRUCache<
|
|
9
|
+
* @param {LRUCache<any, any, any>} lruInstance - An instance of `lru-cache`.
|
|
13
10
|
*
|
|
14
11
|
* @returns A factory that accepts a key generator and returns a scoped, type-safe LRU-based store.
|
|
15
12
|
*
|
|
16
13
|
* @example
|
|
17
14
|
* ```typescript
|
|
18
|
-
*
|
|
15
|
+
* import { createKeyedLruStore } from '@kikiutils/shared/storage/lru/keyed-store';
|
|
16
|
+
*
|
|
17
|
+
* const lruCache = new LRUCache({ max: 5000 });
|
|
19
18
|
* const userStore = createKeyedLruStore<User>(lruCache)((id: number) => `user:${id}`);
|
|
20
19
|
* userStore.setItem({ id: 1 }, 1);
|
|
21
20
|
* const user = userStore.getItem(1);
|
|
22
21
|
* ```
|
|
23
22
|
*/
|
|
24
|
-
export declare function createKeyedLruStore<D
|
|
23
|
+
export declare function createKeyedLruStore<D = unknown>(lruInstance: LRUCache<any, any, any>): <P extends any[]>(getKeyFunction: (...args: P) => string) => Readonly<{
|
|
25
24
|
/**
|
|
26
25
|
* Return a value from the cache. Will update the recency of the cache entry found.
|
|
27
26
|
*
|
|
28
27
|
* If the key is not found, returns `null`.
|
|
29
28
|
*/
|
|
30
|
-
getItem(...args: P):
|
|
29
|
+
getItem(...args: P): NonNullable<D> | null;
|
|
31
30
|
getItemTtl: (...args: P) => number;
|
|
32
31
|
hasItem: (...args: P) => boolean;
|
|
33
32
|
removeItem: (...args: P) => boolean;
|
|
34
33
|
/**
|
|
35
34
|
* Resolves the full cache key from the given arguments.
|
|
36
35
|
*/
|
|
37
|
-
resolveKey: (...args: P) =>
|
|
38
|
-
setItem
|
|
36
|
+
resolveKey: (...args: P) => string;
|
|
37
|
+
setItem(value: D, ...args: P): void;
|
|
39
38
|
}>;
|
|
40
39
|
//# sourceMappingURL=keyed-store.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyed-store.d.ts","sourceRoot":"","sources":["../../../src/storage/lru/keyed-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C
|
|
1
|
+
{"version":3,"file":"keyed-store.d.ts","sourceRoot":"","sources":["../../../src/storage/lru/keyed-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,GAAG,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,IACzE,CAAC,SAAS,GAAG,EAAE,EAAE,gBAAgB,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,MAAM;IAC3D;;;;OAIG;qBACc,CAAC;0BAII,CAAC;uBACJ,CAAC;0BACE,CAAC;IACvB;;OAEG;0BACmB,CAAC;mBACR,CAAC,WAAW,CAAC;GAInC"}
|
|
@@ -4,23 +4,21 @@
|
|
|
4
4
|
* This utility allows structured access to cache entries using a dynamic key-generation function.
|
|
5
5
|
*
|
|
6
6
|
* @template D - The specific value type exposed by this store (must extend `V`).
|
|
7
|
-
* @template K - The type of keys used in the LRU cache (default: string).
|
|
8
|
-
* @template V - The type of values stored in the LRU cache.
|
|
9
|
-
* @template FC - The value used by `lru-cache` fetch context (if any).
|
|
10
7
|
*
|
|
11
|
-
* @param {LRUCache<
|
|
8
|
+
* @param {LRUCache<any, any, any>} lruInstance - An instance of `lru-cache`.
|
|
12
9
|
*
|
|
13
10
|
* @returns A factory that accepts a key generator and returns a scoped, type-safe LRU-based store.
|
|
14
11
|
*
|
|
15
12
|
* @example
|
|
16
13
|
* ```typescript
|
|
17
|
-
*
|
|
14
|
+
* import { createKeyedLruStore } from '@kikiutils/shared/storage/lru/keyed-store';
|
|
15
|
+
*
|
|
16
|
+
* const lruCache = new LRUCache({ max: 5000 });
|
|
18
17
|
* const userStore = createKeyedLruStore<User>(lruCache)((id: number) => `user:${id}`);
|
|
19
18
|
* userStore.setItem({ id: 1 }, 1);
|
|
20
19
|
* const user = userStore.getItem(1);
|
|
21
20
|
* ```
|
|
22
21
|
*/
|
|
23
|
-
// eslint-disable-next-line ts/no-empty-object-type
|
|
24
22
|
function createKeyedLruStore(lruInstance) {
|
|
25
23
|
return (getKeyFunction) => Object.freeze({
|
|
26
24
|
/**
|
|
@@ -39,7 +37,9 @@ function createKeyedLruStore(lruInstance) {
|
|
|
39
37
|
* Resolves the full cache key from the given arguments.
|
|
40
38
|
*/
|
|
41
39
|
resolveKey: (...args) => getKeyFunction(...args),
|
|
42
|
-
setItem
|
|
40
|
+
setItem(value, ...args) {
|
|
41
|
+
lruInstance.set(getKeyFunction(...args), value);
|
|
42
|
+
},
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyed-store.mjs","sources":["../../../src/storage/lru/keyed-store.ts"],"sourcesContent":["import type { LRUCache } from 'lru-cache';\n\n/**\n * Creates a reusable, type-safe keyed store wrapper for an LRUCache instance.\n *\n * This utility allows structured access to cache entries using a dynamic key-generation function.\n *\n * @template D - The specific value type exposed by this store (must extend `V`).\n
|
|
1
|
+
{"version":3,"file":"keyed-store.mjs","sources":["../../../src/storage/lru/keyed-store.ts"],"sourcesContent":["import type { LRUCache } from 'lru-cache';\n\n/**\n * Creates a reusable, type-safe keyed store wrapper for an LRUCache instance.\n *\n * This utility allows structured access to cache entries using a dynamic key-generation function.\n *\n * @template D - The specific value type exposed by this store (must extend `V`).\n *\n * @param {LRUCache<any, any, any>} lruInstance - An instance of `lru-cache`.\n *\n * @returns A factory that accepts a key generator and returns a scoped, type-safe LRU-based store.\n *\n * @example\n * ```typescript\n * import { createKeyedLruStore } from '@kikiutils/shared/storage/lru/keyed-store';\n *\n * const lruCache = new LRUCache({ max: 5000 });\n * const userStore = createKeyedLruStore<User>(lruCache)((id: number) => `user:${id}`);\n * userStore.setItem({ id: 1 }, 1);\n * const user = userStore.getItem(1);\n * ```\n */\nexport function createKeyedLruStore<D = unknown>(lruInstance: LRUCache<any, any, any>) {\n return <P extends any[]>(getKeyFunction: (...args: P) => string) => Object.freeze({\n /**\n * Return a value from the cache. Will update the recency of the cache entry found.\n *\n * If the key is not found, returns `null`.\n */\n getItem(...args: P) {\n const rawValue = lruInstance.get(getKeyFunction(...args));\n return rawValue as D ?? null;\n },\n getItemTtl: (...args: P) => lruInstance.getRemainingTTL(getKeyFunction(...args)),\n hasItem: (...args: P) => lruInstance.has(getKeyFunction(...args)),\n removeItem: (...args: P) => lruInstance.delete(getKeyFunction(...args)),\n /**\n * Resolves the full cache key from the given arguments.\n */\n resolveKey: (...args: P) => getKeyFunction(...args),\n setItem(value: D, ...args: P) {\n lruInstance.set(getKeyFunction(...args), value);\n },\n });\n}\n"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;AAoBG;AACG,SAAU,mBAAmB,CAAc,WAAoC,EAAA;IACjF,OAAO,CAAkB,cAAsC,KAAK,MAAM,CAAC,MAAM,CAAC;AAC9E;;;;AAIG;QACH,OAAO,CAAC,GAAG,IAAO,EAAA;AACd,YAAA,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;YACzD,OAAO,QAAa,IAAI,IAAI;SAC/B;AACD,QAAA,UAAU,EAAE,CAAC,GAAG,IAAO,KAAK,WAAW,CAAC,eAAe,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;AAChF,QAAA,OAAO,EAAE,CAAC,GAAG,IAAO,KAAK,WAAW,CAAC,GAAG,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;AACjE,QAAA,UAAU,EAAE,CAAC,GAAG,IAAO,KAAK,WAAW,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;AACvE;;AAEG;QACH,UAAU,EAAE,CAAC,GAAG,IAAO,KAAK,cAAc,CAAC,GAAG,IAAI,CAAC;AACnD,QAAA,OAAO,CAAC,KAAQ,EAAE,GAAG,IAAO,EAAA;YACxB,WAAW,CAAC,GAAG,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,EAAE,KAAK,CAAC;SAClD;AACJ,KAAA,CAAC;AACN;;;;"}
|
package/dist/web.cjs
CHANGED
|
@@ -13,6 +13,23 @@ function appendRedirectParamFromCurrentLocationToUrl(url$1) {
|
|
|
13
13
|
const currentPath = `${window.location.pathname}${window.location.search}${window.location.hash}`;
|
|
14
14
|
return url.appendRedirectParamToUrl(url$1, currentPath);
|
|
15
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Navigates to the given URL, appending the current browser location
|
|
18
|
+
* (path, query, and hash) as the `redirect` query parameter.
|
|
19
|
+
*
|
|
20
|
+
* Useful for redirecting to login or other gateways while preserving
|
|
21
|
+
* the current location for post-auth navigation.
|
|
22
|
+
*
|
|
23
|
+
* @param {string} url - The destination URL to navigate to.
|
|
24
|
+
* @param {number} [delayMs] - Optional delay in milliseconds before navigation.
|
|
25
|
+
*/
|
|
26
|
+
function assignUrlWithRedirectParamFromCurrentLocation(url, delayMs) {
|
|
27
|
+
if (delayMs === undefined)
|
|
28
|
+
window.location.assign(appendRedirectParamFromCurrentLocationToUrl(url));
|
|
29
|
+
else
|
|
30
|
+
return setTimeout(() => window.location.assign(appendRedirectParamFromCurrentLocationToUrl(url)), delayMs);
|
|
31
|
+
}
|
|
16
32
|
|
|
17
33
|
exports.appendRedirectParamFromCurrentLocationToUrl = appendRedirectParamFromCurrentLocationToUrl;
|
|
34
|
+
exports.assignUrlWithRedirectParamFromCurrentLocation = assignUrlWithRedirectParamFromCurrentLocation;
|
|
18
35
|
//# sourceMappingURL=web.cjs.map
|
package/dist/web.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web.cjs","sources":["../src/web.ts"],"sourcesContent":["import { appendRedirectParamToUrl } from './url';\n\n/**\n * Appends the current browser URL (including path, query, and hash) as the `redirect` query parameter to the given URL.\n *\n * @param {string} url - The base URL to modify.\n *\n * @returns {string} A new URL with the current location as the `redirect` parameter.\n */\nexport function appendRedirectParamFromCurrentLocationToUrl(url: string) {\n const currentPath = `${window.location.pathname}${window.location.search}${window.location.hash}`;\n return appendRedirectParamToUrl(url, currentPath);\n}\n"],"names":["url","appendRedirectParamToUrl"],"mappings":";;;;AAEA;;;;;;AAMG;AACG,SAAU,2CAA2C,CAACA,KAAW,EAAA;IACnE,MAAM,WAAW,GAAG,CAAG,EAAA,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAG,EAAA,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAG,EAAA,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAA,CAAE;AACjG,IAAA,OAAOC,4BAAwB,CAACD,KAAG,EAAE,WAAW,CAAC;AACrD
|
|
1
|
+
{"version":3,"file":"web.cjs","sources":["../src/web.ts"],"sourcesContent":["import { appendRedirectParamToUrl } from './url';\n\n/**\n * Appends the current browser URL (including path, query, and hash) as the `redirect` query parameter to the given URL.\n *\n * @param {string} url - The base URL to modify.\n *\n * @returns {string} A new URL with the current location as the `redirect` parameter.\n */\nexport function appendRedirectParamFromCurrentLocationToUrl(url: string) {\n const currentPath = `${window.location.pathname}${window.location.search}${window.location.hash}`;\n return appendRedirectParamToUrl(url, currentPath);\n}\n\n/**\n * Navigates to the given URL, appending the current browser location\n * (path, query, and hash) as the `redirect` query parameter.\n *\n * Useful for redirecting to login or other gateways while preserving\n * the current location for post-auth navigation.\n *\n * @param {string} url - The destination URL to navigate to.\n * @param {number} [delayMs] - Optional delay in milliseconds before navigation.\n */\nexport function assignUrlWithRedirectParamFromCurrentLocation(url: string, delayMs?: number) {\n if (delayMs === undefined) window.location.assign(appendRedirectParamFromCurrentLocationToUrl(url));\n else return setTimeout(() => window.location.assign(appendRedirectParamFromCurrentLocationToUrl(url)), delayMs);\n}\n"],"names":["url","appendRedirectParamToUrl"],"mappings":";;;;AAEA;;;;;;AAMG;AACG,SAAU,2CAA2C,CAACA,KAAW,EAAA;IACnE,MAAM,WAAW,GAAG,CAAG,EAAA,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAG,EAAA,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAG,EAAA,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAA,CAAE;AACjG,IAAA,OAAOC,4BAAwB,CAACD,KAAG,EAAE,WAAW,CAAC;AACrD;AAEA;;;;;;;;;AASG;AACa,SAAA,6CAA6C,CAAC,GAAW,EAAE,OAAgB,EAAA;IACvF,IAAI,OAAO,KAAK,SAAS;QAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,2CAA2C,CAAC,GAAG,CAAC,CAAC;;AAC9F,QAAA,OAAO,UAAU,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,2CAA2C,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC;AACnH;;;;;"}
|
package/dist/web.d.ts
CHANGED
|
@@ -6,4 +6,15 @@
|
|
|
6
6
|
* @returns {string} A new URL with the current location as the `redirect` parameter.
|
|
7
7
|
*/
|
|
8
8
|
export declare function appendRedirectParamFromCurrentLocationToUrl(url: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Navigates to the given URL, appending the current browser location
|
|
11
|
+
* (path, query, and hash) as the `redirect` query parameter.
|
|
12
|
+
*
|
|
13
|
+
* Useful for redirecting to login or other gateways while preserving
|
|
14
|
+
* the current location for post-auth navigation.
|
|
15
|
+
*
|
|
16
|
+
* @param {string} url - The destination URL to navigate to.
|
|
17
|
+
* @param {number} [delayMs] - Optional delay in milliseconds before navigation.
|
|
18
|
+
*/
|
|
19
|
+
export declare function assignUrlWithRedirectParamFromCurrentLocation(url: string, delayMs?: number): NodeJS.Timeout | undefined;
|
|
9
20
|
//# sourceMappingURL=web.d.ts.map
|
package/dist/web.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,wBAAgB,2CAA2C,CAAC,GAAG,EAAE,MAAM,UAGtE"}
|
|
1
|
+
{"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,wBAAgB,2CAA2C,CAAC,GAAG,EAAE,MAAM,UAGtE;AAED;;;;;;;;;GASG;AACH,wBAAgB,6CAA6C,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,8BAG1F"}
|
package/dist/web.mjs
CHANGED
|
@@ -11,6 +11,22 @@ function appendRedirectParamFromCurrentLocationToUrl(url) {
|
|
|
11
11
|
const currentPath = `${window.location.pathname}${window.location.search}${window.location.hash}`;
|
|
12
12
|
return appendRedirectParamToUrl(url, currentPath);
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Navigates to the given URL, appending the current browser location
|
|
16
|
+
* (path, query, and hash) as the `redirect` query parameter.
|
|
17
|
+
*
|
|
18
|
+
* Useful for redirecting to login or other gateways while preserving
|
|
19
|
+
* the current location for post-auth navigation.
|
|
20
|
+
*
|
|
21
|
+
* @param {string} url - The destination URL to navigate to.
|
|
22
|
+
* @param {number} [delayMs] - Optional delay in milliseconds before navigation.
|
|
23
|
+
*/
|
|
24
|
+
function assignUrlWithRedirectParamFromCurrentLocation(url, delayMs) {
|
|
25
|
+
if (delayMs === undefined)
|
|
26
|
+
window.location.assign(appendRedirectParamFromCurrentLocationToUrl(url));
|
|
27
|
+
else
|
|
28
|
+
return setTimeout(() => window.location.assign(appendRedirectParamFromCurrentLocationToUrl(url)), delayMs);
|
|
29
|
+
}
|
|
14
30
|
|
|
15
|
-
export { appendRedirectParamFromCurrentLocationToUrl };
|
|
31
|
+
export { appendRedirectParamFromCurrentLocationToUrl, assignUrlWithRedirectParamFromCurrentLocation };
|
|
16
32
|
//# sourceMappingURL=web.mjs.map
|
package/dist/web.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web.mjs","sources":["../src/web.ts"],"sourcesContent":["import { appendRedirectParamToUrl } from './url';\n\n/**\n * Appends the current browser URL (including path, query, and hash) as the `redirect` query parameter to the given URL.\n *\n * @param {string} url - The base URL to modify.\n *\n * @returns {string} A new URL with the current location as the `redirect` parameter.\n */\nexport function appendRedirectParamFromCurrentLocationToUrl(url: string) {\n const currentPath = `${window.location.pathname}${window.location.search}${window.location.hash}`;\n return appendRedirectParamToUrl(url, currentPath);\n}\n"],"names":[],"mappings":";;AAEA;;;;;;AAMG;AACG,SAAU,2CAA2C,CAAC,GAAW,EAAA;IACnE,MAAM,WAAW,GAAG,CAAG,EAAA,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAG,EAAA,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAG,EAAA,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAA,CAAE;AACjG,IAAA,OAAO,wBAAwB,CAAC,GAAG,EAAE,WAAW,CAAC;AACrD;;;;"}
|
|
1
|
+
{"version":3,"file":"web.mjs","sources":["../src/web.ts"],"sourcesContent":["import { appendRedirectParamToUrl } from './url';\n\n/**\n * Appends the current browser URL (including path, query, and hash) as the `redirect` query parameter to the given URL.\n *\n * @param {string} url - The base URL to modify.\n *\n * @returns {string} A new URL with the current location as the `redirect` parameter.\n */\nexport function appendRedirectParamFromCurrentLocationToUrl(url: string) {\n const currentPath = `${window.location.pathname}${window.location.search}${window.location.hash}`;\n return appendRedirectParamToUrl(url, currentPath);\n}\n\n/**\n * Navigates to the given URL, appending the current browser location\n * (path, query, and hash) as the `redirect` query parameter.\n *\n * Useful for redirecting to login or other gateways while preserving\n * the current location for post-auth navigation.\n *\n * @param {string} url - The destination URL to navigate to.\n * @param {number} [delayMs] - Optional delay in milliseconds before navigation.\n */\nexport function assignUrlWithRedirectParamFromCurrentLocation(url: string, delayMs?: number) {\n if (delayMs === undefined) window.location.assign(appendRedirectParamFromCurrentLocationToUrl(url));\n else return setTimeout(() => window.location.assign(appendRedirectParamFromCurrentLocationToUrl(url)), delayMs);\n}\n"],"names":[],"mappings":";;AAEA;;;;;;AAMG;AACG,SAAU,2CAA2C,CAAC,GAAW,EAAA;IACnE,MAAM,WAAW,GAAG,CAAG,EAAA,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAG,EAAA,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAG,EAAA,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAA,CAAE;AACjG,IAAA,OAAO,wBAAwB,CAAC,GAAG,EAAE,WAAW,CAAC;AACrD;AAEA;;;;;;;;;AASG;AACa,SAAA,6CAA6C,CAAC,GAAW,EAAE,OAAgB,EAAA;IACvF,IAAI,OAAO,KAAK,SAAS;QAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,2CAA2C,CAAC,GAAG,CAAC,CAAC;;AAC9F,QAAA,OAAO,UAAU,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,2CAA2C,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC;AACnH;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kikiutils/shared",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.1.0",
|
|
4
4
|
"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.",
|
|
5
5
|
"author": "kiki-kanri",
|
|
6
6
|
"license": "MIT",
|
|
@@ -71,11 +71,13 @@
|
|
|
71
71
|
"@kikiutils/tsconfigs": "^5.0.1",
|
|
72
72
|
"@noble/hashes": "^1.8.0",
|
|
73
73
|
"@types/jest": "^29.5.14",
|
|
74
|
-
"@types/node": "^22.15.
|
|
74
|
+
"@types/node": "^22.15.16",
|
|
75
|
+
"async-validator": "^4.2.5",
|
|
75
76
|
"consola": "^3.4.2",
|
|
76
77
|
"cross-env": "^7.0.3",
|
|
77
78
|
"date-fns": "^4.1.0",
|
|
78
79
|
"decimal.js": "^10.5.0",
|
|
80
|
+
"element-plus": "^2.9.9",
|
|
79
81
|
"ioredis": "^5.6.1",
|
|
80
82
|
"jest": "^29.7.0",
|
|
81
83
|
"jest-environment-jsdom": "^29.7.0",
|
|
@@ -93,7 +95,8 @@
|
|
|
93
95
|
"pnpm": {
|
|
94
96
|
"onlyBuiltDependencies": [
|
|
95
97
|
"esbuild",
|
|
96
|
-
"unrs-resolver"
|
|
98
|
+
"unrs-resolver",
|
|
99
|
+
"vue-demi"
|
|
97
100
|
]
|
|
98
101
|
}
|
|
99
102
|
}
|
package/src/clipboard.ts
CHANGED
|
@@ -19,6 +19,8 @@ type CopyResult =
|
|
|
19
19
|
*
|
|
20
20
|
* @example
|
|
21
21
|
* ```typescript
|
|
22
|
+
* import { copyBlobToClipboard } from '@kikiutils/shared/clipboard';
|
|
23
|
+
*
|
|
22
24
|
* const blob = new Blob(['Hello world'], { type: 'text/plain' });
|
|
23
25
|
* const result = await copyBlobToClipboard(blob);
|
|
24
26
|
* if (result.ok) {
|
|
@@ -64,6 +66,8 @@ export async function copyBlobToClipboard(blob: Blob, options?: ClipboardItemOpt
|
|
|
64
66
|
*
|
|
65
67
|
* @example
|
|
66
68
|
* ```typescript
|
|
69
|
+
* import { copyTextToClipboard } from '@kikiutils/shared/clipboard';
|
|
70
|
+
*
|
|
67
71
|
* const result = await copyTextToClipboard('Hello!');
|
|
68
72
|
* if (result.ok) {
|
|
69
73
|
* console.log('Copied!');
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { RuleType } from 'async-validator';
|
|
2
|
+
import type { FormItemRule } from 'element-plus';
|
|
3
|
+
|
|
4
|
+
export type DoNotRemoveOrUseThisType = RuleType;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Creates a reusable Element Plus `<el-form-item>` validation rule with sensible defaults.
|
|
8
|
+
*
|
|
9
|
+
* This utility provides default values for `required`, `trigger`, and `type`,
|
|
10
|
+
* while allowing overrides via the `options` parameter. It simplifies common
|
|
11
|
+
* form validation rule creation and ensures consistency across forms.
|
|
12
|
+
*
|
|
13
|
+
* @param {string} message - The validation message to display when the rule fails.
|
|
14
|
+
* @param {FormItemRule} [options] - Optional overrides for the rule fields.
|
|
15
|
+
* @param {boolean} [options.required] - Whether the field is required (default: `true`).
|
|
16
|
+
* @param {string | string[]} [options.trigger] - The event(s) that trigger validation (default: `'blur'`).
|
|
17
|
+
* @param {RuleType} [options.type] - The expected type of the field (default: `'string'`).
|
|
18
|
+
*
|
|
19
|
+
* @returns A `FormItemRule` object that can be used in Element Plus form validation.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* import { createElFormItemRuleWithDefaults } from '@kikiutils/shared/element-plus';
|
|
24
|
+
*
|
|
25
|
+
* const rule = createElFormItemRuleWithDefaults('This field is required');
|
|
26
|
+
* const optionalRule = createElFormItemRuleWithDefaults('Optional field', { required: false });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export function createElFormItemRuleWithDefaults(message: string, options: FormItemRule = {}): FormItemRule {
|
|
30
|
+
return {
|
|
31
|
+
...options,
|
|
32
|
+
message,
|
|
33
|
+
required: options.required ?? true,
|
|
34
|
+
trigger: options.trigger ?? 'blur',
|
|
35
|
+
type: options.type ?? 'string',
|
|
36
|
+
};
|
|
37
|
+
}
|
|
@@ -20,6 +20,8 @@ const toCustomValue = (type: StorageValueEncodingType, payload: string) => `${cu
|
|
|
20
20
|
*
|
|
21
21
|
* @example
|
|
22
22
|
* ```typescript
|
|
23
|
+
* import { enhancedLocalStorage } from '@kikiutils/shared/storage/enhanced/local';
|
|
24
|
+
*
|
|
23
25
|
* enhancedLocalStorage.setItem('user', { name: 'user', createdAt: new Date() });
|
|
24
26
|
* const user = enhancedLocalStorage.getItem<{ name: string, createdAt: Date }>('user');
|
|
25
27
|
* ```
|
|
@@ -13,6 +13,8 @@ import { enhancedLocalStorage } from './core';
|
|
|
13
13
|
*
|
|
14
14
|
* @example
|
|
15
15
|
* ```typescript
|
|
16
|
+
* import { createKeyedEnhancedLocalStore } from '@kikiutils/shared/storage/enhanced/local';
|
|
17
|
+
*
|
|
16
18
|
* const userStore = createKeyedEnhancedLocalStore<User>()((id: number) => `user:${id}`);
|
|
17
19
|
* userStore.setItem({ id: 123, name: 'user' }, 123);
|
|
18
20
|
* const user = userStore.getItem(123);
|
|
@@ -32,6 +32,8 @@ const customValueHeaderLength = customValueHeader.byteLength + 1;
|
|
|
32
32
|
*
|
|
33
33
|
* @example
|
|
34
34
|
* ```typescript
|
|
35
|
+
* import { createEnhancedRedisStorage } from '@kikiutils/shared/storage/enhanced/redis';
|
|
36
|
+
*
|
|
35
37
|
* const redisStorage = createEnhancedRedisStorage('redis://localhost');
|
|
36
38
|
* await redisStorage.setItem('user:1', { name: 'user' });
|
|
37
39
|
* const user = await redisStorage.getItem<{ name: string }>('user:1');
|
|
@@ -16,6 +16,8 @@ import type { createEnhancedRedisStorage } from './core';
|
|
|
16
16
|
*
|
|
17
17
|
* @example
|
|
18
18
|
* ```typescript
|
|
19
|
+
* import { createKeyedEnhancedRedisStore } from '@kikiutils/shared/storage/enhanced/redis';
|
|
20
|
+
*
|
|
19
21
|
* const userStore = createKeyedEnhancedRedisStore<User>(redisStorage)((id: number) => `user:${id}`);
|
|
20
22
|
* await userStore.setItem({ id: 123, name: 'user' }, 123);
|
|
21
23
|
* const user = await userStore.getItem(123);
|
|
@@ -6,27 +6,23 @@ import type { LRUCache } from 'lru-cache';
|
|
|
6
6
|
* This utility allows structured access to cache entries using a dynamic key-generation function.
|
|
7
7
|
*
|
|
8
8
|
* @template D - The specific value type exposed by this store (must extend `V`).
|
|
9
|
-
* @template K - The type of keys used in the LRU cache (default: string).
|
|
10
|
-
* @template V - The type of values stored in the LRU cache.
|
|
11
|
-
* @template FC - The value used by `lru-cache` fetch context (if any).
|
|
12
9
|
*
|
|
13
|
-
* @param {LRUCache<
|
|
10
|
+
* @param {LRUCache<any, any, any>} lruInstance - An instance of `lru-cache`.
|
|
14
11
|
*
|
|
15
12
|
* @returns A factory that accepts a key generator and returns a scoped, type-safe LRU-based store.
|
|
16
13
|
*
|
|
17
14
|
* @example
|
|
18
15
|
* ```typescript
|
|
19
|
-
*
|
|
16
|
+
* import { createKeyedLruStore } from '@kikiutils/shared/storage/lru/keyed-store';
|
|
17
|
+
*
|
|
18
|
+
* const lruCache = new LRUCache({ max: 5000 });
|
|
20
19
|
* const userStore = createKeyedLruStore<User>(lruCache)((id: number) => `user:${id}`);
|
|
21
20
|
* userStore.setItem({ id: 1 }, 1);
|
|
22
21
|
* const user = userStore.getItem(1);
|
|
23
22
|
* ```
|
|
24
23
|
*/
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
lruInstance: LRUCache<K, V, FC>,
|
|
28
|
-
) {
|
|
29
|
-
return <P extends any[]>(getKeyFunction: (...args: P) => K) => Object.freeze({
|
|
24
|
+
export function createKeyedLruStore<D = unknown>(lruInstance: LRUCache<any, any, any>) {
|
|
25
|
+
return <P extends any[]>(getKeyFunction: (...args: P) => string) => Object.freeze({
|
|
30
26
|
/**
|
|
31
27
|
* Return a value from the cache. Will update the recency of the cache entry found.
|
|
32
28
|
*
|
|
@@ -34,7 +30,7 @@ export function createKeyedLruStore<D extends V, K extends {}, V extends {}, FC
|
|
|
34
30
|
*/
|
|
35
31
|
getItem(...args: P) {
|
|
36
32
|
const rawValue = lruInstance.get(getKeyFunction(...args));
|
|
37
|
-
return rawValue ?? null;
|
|
33
|
+
return rawValue as D ?? null;
|
|
38
34
|
},
|
|
39
35
|
getItemTtl: (...args: P) => lruInstance.getRemainingTTL(getKeyFunction(...args)),
|
|
40
36
|
hasItem: (...args: P) => lruInstance.has(getKeyFunction(...args)),
|
|
@@ -43,6 +39,8 @@ export function createKeyedLruStore<D extends V, K extends {}, V extends {}, FC
|
|
|
43
39
|
* Resolves the full cache key from the given arguments.
|
|
44
40
|
*/
|
|
45
41
|
resolveKey: (...args: P) => getKeyFunction(...args),
|
|
46
|
-
setItem
|
|
42
|
+
setItem(value: D, ...args: P) {
|
|
43
|
+
lruInstance.set(getKeyFunction(...args), value);
|
|
44
|
+
},
|
|
47
45
|
});
|
|
48
46
|
}
|
package/src/web.ts
CHANGED
|
@@ -11,3 +11,18 @@ export function appendRedirectParamFromCurrentLocationToUrl(url: string) {
|
|
|
11
11
|
const currentPath = `${window.location.pathname}${window.location.search}${window.location.hash}`;
|
|
12
12
|
return appendRedirectParamToUrl(url, currentPath);
|
|
13
13
|
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Navigates to the given URL, appending the current browser location
|
|
17
|
+
* (path, query, and hash) as the `redirect` query parameter.
|
|
18
|
+
*
|
|
19
|
+
* Useful for redirecting to login or other gateways while preserving
|
|
20
|
+
* the current location for post-auth navigation.
|
|
21
|
+
*
|
|
22
|
+
* @param {string} url - The destination URL to navigate to.
|
|
23
|
+
* @param {number} [delayMs] - Optional delay in milliseconds before navigation.
|
|
24
|
+
*/
|
|
25
|
+
export function assignUrlWithRedirectParamFromCurrentLocation(url: string, delayMs?: number) {
|
|
26
|
+
if (delayMs === undefined) window.location.assign(appendRedirectParamFromCurrentLocationToUrl(url));
|
|
27
|
+
else return setTimeout(() => window.location.assign(appendRedirectParamFromCurrentLocationToUrl(url)), delayMs);
|
|
28
|
+
}
|