@alwatr/local-storage 5.5.10 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.cjs.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/main.ts"],
4
- "sourcesContent": ["import {packageTracer} from '@alwatr/package-tracer';\n\n__dev_mode__: packageTracer.add(__package_name__, __package_version__);\n\n/**\n * Parse json string without throwing error.\n *\n * @param content - json string\n * @returns json object or null if json is invalid\n * @example\n * ```typescript\n * const json = parseJson('{\"a\":1,\"b\":2}');\n * console.log(json.a); // 1\n * ```\n */\nfunction parseJson<T extends JsonValue>(content: string): T | null {\n try {\n return JSON.parse(content);\n }\n catch (err) {\n console.error('parseJson', 'invalid_json', err);\n return null;\n }\n}\n\n// @TODO: localStorage polyfill (memory fallback)\n\n/**\n * A utility object for working with local storage and JSON data.\n */\nexport const localJsonStorage = {\n /**\n * Generate local storage key.\n *\n * @param name - Name of the item.\n * @param version - Version of the item (default: 1).\n * @returns The generated local storage key.\n * @example\n * ```typescript\n * localJsonStorage.key_('myItem', 1); // myItem.v1\n * ```\n */\n key_(name: string, version = 1): string {\n return `${name}.v${version}`;\n },\n\n /**\n * Get the local storage item and parse it as JSON.\n * If the item is not found, return the default value.\n * If the version is greater than 1, remove the previous version.\n * If the item is not a valid JSON object, return the default value.\n *\n * @param name - The name of the item.\n * @param defaultValue - The default value of the item.\n * @param version - The data structure version of the item (default: 1).\n * @returns The parsed JSON value or the default value if the item is not found.\n * @example\n * ```typescript\n * const value = localJsonStorage.getItem('myItem', {a: 1, b: 2});\n * ```\n */\n getItem<T extends JsonValue>(name: string, defaultValue: T, version = 1): T {\n if (version > 1) {\n this.removeItem(name, version - 1);\n }\n if (version > 1) {\n this.removeItem(name, version - 1);\n }\n const key = this.key_(name, version);\n const value = localStorage.getItem(key);\n if (value === null) {\n localStorage.setItem(key, JSON.stringify(defaultValue));\n return defaultValue;\n }\n const json = parseJson<T>(value);\n if (json === null) return defaultValue;\n return json;\n },\n\n /**\n * Check if an item exists in local storage.\n *\n * @param name - The name of the item.\n * @param version - The version of the item (default: 1).\n * @returns True if the item exists, false otherwise.\n * @example\n * ```typescript\n * const exists = localJsonStorage.hasItem('myItem');\n * ```\n */\n hasItem(name: string, version = 1): boolean {\n const key = this.key_(name, version);\n return localStorage.getItem(key) !== null;\n },\n\n /**\n * Set local storage item as JSON.\n *\n * @param name - Name of the item.\n * @param value - Value of the item.\n * @param version - Version of the item.\n * @example\n * ```typescript\n * localJsonStorage.setItem('myItem', {a: 1, b: 2});\n * ```\n */\n setItem<T extends JsonValue>(name: string, value: T, version = 1): void {\n const key = this.key_(name, version);\n localStorage.setItem(key, JSON.stringify(value));\n },\n\n /**\n * Removes an item from the local storage.\n *\n * @param name - The name of the item to remove.\n * @param version - The version of the item to remove. Default is 1.\n * @example\n * ```typescript\n * localJsonStorage.removeItem('myItem');\n * ```\n */\n removeItem(name: string, version = 1): void {\n const key = this.key_(name, version);\n localStorage.removeItem(key);\n },\n} as const;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAA4B;AAE5B,aAAc,qCAAc,IAAI,yBAAkB,QAAmB;AAarE,SAAS,UAA+B,SAA2B;AACjE,MAAI;AACF,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,SACO,KAAK;AACV,YAAQ,MAAM,aAAa,gBAAgB,GAAG;AAC9C,WAAO;AAAA,EACT;AACF;AAOO,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAY9B,KAAK,MAAc,UAAU,GAAW;AACtC,WAAO,GAAG,IAAI,KAAK,OAAO;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,QAA6B,MAAc,cAAiB,UAAU,GAAM;AAC1E,QAAI,UAAU,GAAG;AACf,WAAK,WAAW,MAAM,UAAU,CAAC;AAAA,IACnC;AACA,QAAI,UAAU,GAAG;AACf,WAAK,WAAW,MAAM,UAAU,CAAC;AAAA,IACnC;AACA,UAAM,MAAM,KAAK,KAAK,MAAM,OAAO;AACnC,UAAM,QAAQ,aAAa,QAAQ,GAAG;AACtC,QAAI,UAAU,MAAM;AAClB,mBAAa,QAAQ,KAAK,KAAK,UAAU,YAAY,CAAC;AACtD,aAAO;AAAA,IACT;AACA,UAAM,OAAO,UAAa,KAAK;AAC/B,QAAI,SAAS,KAAM,QAAO;AAC1B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,QAAQ,MAAc,UAAU,GAAY;AAC1C,UAAM,MAAM,KAAK,KAAK,MAAM,OAAO;AACnC,WAAO,aAAa,QAAQ,GAAG,MAAM;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,QAA6B,MAAc,OAAU,UAAU,GAAS;AACtE,UAAM,MAAM,KAAK,KAAK,MAAM,OAAO;AACnC,iBAAa,QAAQ,KAAK,KAAK,UAAU,KAAK,CAAC;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,WAAW,MAAc,UAAU,GAAS;AAC1C,UAAM,MAAM,KAAK,KAAK,MAAM,OAAO;AACnC,iBAAa,WAAW,GAAG;AAAA,EAC7B;AACF;",
3
+ "sources": ["../src/main.ts", "../src/local-storage.provider.ts"],
4
+ "sourcesContent": ["import {LocalStorageProvider} from './local-storage.provider.js';\n\nimport type {LocalStorageProviderConfig} from './type.js';\n\nexport * from './local-storage.provider.js';\nexport type * from './type.js';\n\n/**\n * Factory function to create a new LocalStorageProvider.\n *\n * @param config - The configuration for the provider.\n * @returns An instance of LocalStorageProvider.\n *\n * @example\n * ```typescript\n * const userSettings = createLocalStorageProvider({\n * name: 'user-settings',\n * version: 1,\n * defaultValue: { theme: 'light', notifications: true }\n * });\n *\n * // Write new settings\n * userSettings.write({ theme: 'dark', notifications: false });\n *\n * // Read the current settings\n * const currentSettings = userSettings.read();\n * console.log(currentSettings); // { theme: 'dark', notifications: false }\n * ```\n */\nexport function createLocalStorageProvider<T extends JsonValue>(config: LocalStorageProviderConfig<T>): LocalStorageProvider<T> {\n return new LocalStorageProvider<T>(config);\n}\n", "import {createLogger} from '@alwatr/logger';\n\nimport type {LocalStorageProviderConfig, StorageMeta} from './type.js';\n\n/**\n * A provider class for managing a specific, versioned item in localStorage.\n * It encapsulates the logic for key generation, serialization, and migration.\n *\n * @example\n * ```typescript\n * const userSettings = new LocalStorageProvider({\n * name: 'user-settings',\n * version: 1,\n * defaultValue: { theme: 'light', notifications: true }\n * });\n *\n * // Write new settings\n * userSettings.write({ theme: 'dark', notifications: false });\n *\n * // Read the current settings\n * const currentSettings = userSettings.read();\n * console.log(currentSettings); // { theme: 'dark', notifications: false }\n * ```\n */\nexport class LocalStorageProvider<T extends JsonValue> {\n public static readonly version = __package_version__;\n\n private readonly key__: string;\n protected readonly logger_ = createLogger(`local-storage-provider: ${this.config_.name}, v: ${this.config_.version}`);\n\n public constructor(protected readonly config_: LocalStorageProviderConfig<T>) {\n this.logger_.logMethodArgs?.('constructor', {config: this.config_});\n this.key__ = LocalStorageProvider.getKey(this.config_);\n this.migrate__();\n }\n\n /**\n * Generates the versioned storage key.\n * @param meta - An object containing the name and version.\n * @returns The versioned key string.\n */\n public static getKey(meta: StorageMeta): string {\n return `${meta.name}.v${meta.version}`;\n }\n\n /**\n * Statically checks if a versioned item exists in localStorage.\n * This method provides a high-performance way to check for data existence without the overhead of creating a full provider instance.\n *\n * @param meta - An object containing the name and version of the item to check.\n * @returns `true` if the item exists, otherwise `false`.\n *\n * @example\n * ```typescript\n * const formExists = LocalStorageProvider.has({ name: 'user-form', version: 1 });\n * if (formExists) {\n * // Show the \"Thank you\" message\n * } else {\n * // Show the form\n * }\n * ```\n */\n public static has(meta: StorageMeta): boolean {\n const key = LocalStorageProvider.getKey(meta);\n return localStorage.getItem(key) !== null;\n }\n\n /**\n * Writes the default value to localStorage and returns it.\n */\n private writeDefault__(): T {\n this.logger_.logMethodArgs?.('writeDefaultــ', this.config_.defaultValue);\n this.write(this.config_.defaultValue);\n return this.config_.defaultValue;\n }\n\n /**\n * Reads and parses the value from localStorage.\n * If the item doesn't exist, is invalid JSON, or doesn't match the expected type,\n * it writes and returns the default value.\n */\n public read(): T {\n try {\n const value = localStorage.getItem(this.key__);\n\n if (value === null) {\n this.logger_.logMethod?.('read//no_value');\n return this.writeDefault__();\n }\n\n const parsedValue = JSON.parse(value) as T;\n this.logger_.logMethodFull?.('read//value', undefined, {parsedValue});\n return parsedValue;\n }\n catch (err) {\n this.logger_.error('read', 'read_parse_error', {err});\n return this.writeDefault__();\n }\n }\n\n /**\n * Serializes and writes a value to localStorage.\n */\n public write(value: T): void {\n this.logger_.logMethodArgs?.('write', {value});\n try {\n localStorage.setItem(this.key__, JSON.stringify(value));\n }\n catch (err) {\n this.logger_.error('write', 'write_stringify_error', {err});\n }\n }\n\n /**\n * Removes the item from localStorage.\n */\n public remove(): void {\n localStorage.removeItem(this.key__);\n }\n\n /**\n * Manages data migration by removing all previous versions of the item.\n */\n private migrate__(): void {\n if (this.config_.version <= 1) return;\n\n // Iterate from v1 up to the version just before the current one and remove them.\n for (let i = 1; i < this.config_.version; i++) {\n const oldKey = LocalStorageProvider.getKey({name: this.config_.name, version: i});\n localStorage.removeItem(oldKey);\n }\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,oBAA2B;AAwBpB,IAAM,uBAAN,MAAM,sBAA0C;AAAA,EAM9C,YAA+B,SAAwC;AAAxC;AAFtC,SAAmB,cAAU,4BAAa,2BAA2B,KAAK,QAAQ,IAAI,QAAQ,KAAK,QAAQ,OAAO,EAAE;AAGlH,SAAK,QAAQ,gBAAgB,eAAe,EAAC,QAAQ,KAAK,QAAO,CAAC;AAClE,SAAK,QAAQ,sBAAqB,OAAO,KAAK,OAAO;AACrD,SAAK,UAAU;AAAA,EACjB;AAAA,EATA;AAAA,SAAuB,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBjC,OAAc,OAAO,MAA2B;AAC9C,WAAO,GAAG,KAAK,IAAI,KAAK,KAAK,OAAO;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,OAAc,IAAI,MAA4B;AAC5C,UAAM,MAAM,sBAAqB,OAAO,IAAI;AAC5C,WAAO,aAAa,QAAQ,GAAG,MAAM;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAoB;AAC1B,SAAK,QAAQ,gBAAgB,kBAAkB,KAAK,QAAQ,YAAY;AACxE,SAAK,MAAM,KAAK,QAAQ,YAAY;AACpC,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,OAAU;AACf,QAAI;AACF,YAAM,QAAQ,aAAa,QAAQ,KAAK,KAAK;AAE7C,UAAI,UAAU,MAAM;AAClB,aAAK,QAAQ,YAAY,gBAAgB;AACzC,eAAO,KAAK,eAAe;AAAA,MAC7B;AAEA,YAAM,cAAc,KAAK,MAAM,KAAK;AACpC,WAAK,QAAQ,gBAAgB,eAAe,QAAW,EAAC,YAAW,CAAC;AACpE,aAAO;AAAA,IACT,SACO,KAAK;AACV,WAAK,QAAQ,MAAM,QAAQ,oBAAoB,EAAC,IAAG,CAAC;AACpD,aAAO,KAAK,eAAe;AAAA,IAC7B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,MAAM,OAAgB;AAC3B,SAAK,QAAQ,gBAAgB,SAAS,EAAC,MAAK,CAAC;AAC7C,QAAI;AACF,mBAAa,QAAQ,KAAK,OAAO,KAAK,UAAU,KAAK,CAAC;AAAA,IACxD,SACO,KAAK;AACV,WAAK,QAAQ,MAAM,SAAS,yBAAyB,EAAC,IAAG,CAAC;AAAA,IAC5D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,SAAe;AACpB,iBAAa,WAAW,KAAK,KAAK;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAkB;AACxB,QAAI,KAAK,QAAQ,WAAW,EAAG;AAG/B,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,SAAS,KAAK;AAC7C,YAAM,SAAS,sBAAqB,OAAO,EAAC,MAAM,KAAK,QAAQ,MAAM,SAAS,EAAC,CAAC;AAChF,mBAAa,WAAW,MAAM;AAAA,IAChC;AAAA,EACF;AACF;;;ADvGO,SAAS,2BAAgD,QAAgE;AAC9H,SAAO,IAAI,qBAAwB,MAAM;AAC3C;",
6
6
  "names": []
7
7
  }
package/dist/main.d.ts CHANGED
@@ -1,69 +1,28 @@
1
+ import { LocalStorageProvider } from './local-storage.provider.js';
2
+ import type { LocalStorageProviderConfig } from './type.js';
3
+ export * from './local-storage.provider.js';
4
+ export type * from './type.js';
1
5
  /**
2
- * A utility object for working with local storage and JSON data.
6
+ * Factory function to create a new LocalStorageProvider.
7
+ *
8
+ * @param config - The configuration for the provider.
9
+ * @returns An instance of LocalStorageProvider.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const userSettings = createLocalStorageProvider({
14
+ * name: 'user-settings',
15
+ * version: 1,
16
+ * defaultValue: { theme: 'light', notifications: true }
17
+ * });
18
+ *
19
+ * // Write new settings
20
+ * userSettings.write({ theme: 'dark', notifications: false });
21
+ *
22
+ * // Read the current settings
23
+ * const currentSettings = userSettings.read();
24
+ * console.log(currentSettings); // { theme: 'dark', notifications: false }
25
+ * ```
3
26
  */
4
- export declare const localJsonStorage: {
5
- /**
6
- * Generate local storage key.
7
- *
8
- * @param name - Name of the item.
9
- * @param version - Version of the item (default: 1).
10
- * @returns The generated local storage key.
11
- * @example
12
- * ```typescript
13
- * localJsonStorage.key_('myItem', 1); // myItem.v1
14
- * ```
15
- */
16
- readonly key_: (name: string, version?: number) => string;
17
- /**
18
- * Get the local storage item and parse it as JSON.
19
- * If the item is not found, return the default value.
20
- * If the version is greater than 1, remove the previous version.
21
- * If the item is not a valid JSON object, return the default value.
22
- *
23
- * @param name - The name of the item.
24
- * @param defaultValue - The default value of the item.
25
- * @param version - The data structure version of the item (default: 1).
26
- * @returns The parsed JSON value or the default value if the item is not found.
27
- * @example
28
- * ```typescript
29
- * const value = localJsonStorage.getItem('myItem', {a: 1, b: 2});
30
- * ```
31
- */
32
- readonly getItem: <T extends JsonValue>(name: string, defaultValue: T, version?: number) => T;
33
- /**
34
- * Check if an item exists in local storage.
35
- *
36
- * @param name - The name of the item.
37
- * @param version - The version of the item (default: 1).
38
- * @returns True if the item exists, false otherwise.
39
- * @example
40
- * ```typescript
41
- * const exists = localJsonStorage.hasItem('myItem');
42
- * ```
43
- */
44
- readonly hasItem: (name: string, version?: number) => boolean;
45
- /**
46
- * Set local storage item as JSON.
47
- *
48
- * @param name - Name of the item.
49
- * @param value - Value of the item.
50
- * @param version - Version of the item.
51
- * @example
52
- * ```typescript
53
- * localJsonStorage.setItem('myItem', {a: 1, b: 2});
54
- * ```
55
- */
56
- readonly setItem: <T extends JsonValue>(name: string, value: T, version?: number) => void;
57
- /**
58
- * Removes an item from the local storage.
59
- *
60
- * @param name - The name of the item to remove.
61
- * @param version - The version of the item to remove. Default is 1.
62
- * @example
63
- * ```typescript
64
- * localJsonStorage.removeItem('myItem');
65
- * ```
66
- */
67
- readonly removeItem: (name: string, version?: number) => void;
68
- };
27
+ export declare function createLocalStorageProvider<T extends JsonValue>(config: LocalStorageProviderConfig<T>): LocalStorageProvider<T>;
69
28
  //# sourceMappingURL=main.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AA2BA;;GAEG;AACH,eAAO,MAAM,gBAAgB;IAC3B;;;;;;;;;;OAUG;0BACQ,MAAM,uBAAgB,MAAM;IAIvC;;;;;;;;;;;;;;OAcG;uBACK,CAAC,SAAS,SAAS,QAAQ,MAAM,gBAAgB,CAAC,uBAAgB,CAAC;IAkB3E;;;;;;;;;;OAUG;6BACW,MAAM,uBAAgB,OAAO;IAK3C;;;;;;;;;;OAUG;uBACK,CAAC,SAAS,SAAS,QAAQ,MAAM,SAAS,CAAC,uBAAgB,IAAI;IAKvE;;;;;;;;;OASG;gCACc,MAAM,uBAAgB,IAAI;CAInC,CAAC"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,oBAAoB,EAAC,MAAM,6BAA6B,CAAC;AAEjE,OAAO,KAAK,EAAC,0BAA0B,EAAC,MAAM,WAAW,CAAC;AAE1D,cAAc,6BAA6B,CAAC;AAC5C,mBAAmB,WAAW,CAAC;AAE/B;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,SAAS,EAAE,MAAM,EAAE,0BAA0B,CAAC,CAAC,CAAC,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAE9H"}
package/dist/main.mjs CHANGED
@@ -1,109 +1,110 @@
1
- /* @alwatr/local-storage v5.5.10 */
1
+ /* @alwatr/local-storage v6.1.0 */
2
2
 
3
- // src/main.ts
4
- import { packageTracer } from "@alwatr/package-tracer";
5
- __dev_mode__: packageTracer.add("@alwatr/local-storage", "5.5.10");
6
- function parseJson(content) {
7
- try {
8
- return JSON.parse(content);
9
- } catch (err) {
10
- console.error("parseJson", "invalid_json", err);
11
- return null;
3
+ // src/local-storage.provider.ts
4
+ import { createLogger } from "@alwatr/logger";
5
+ var LocalStorageProvider = class _LocalStorageProvider {
6
+ constructor(config_) {
7
+ this.config_ = config_;
8
+ this.logger_ = createLogger(`local-storage-provider: ${this.config_.name}, v: ${this.config_.version}`);
9
+ this.logger_.logMethodArgs?.("constructor", { config: this.config_ });
10
+ this.key__ = _LocalStorageProvider.getKey(this.config_);
11
+ this.migrate__();
12
+ }
13
+ static {
14
+ this.version = "6.1.0";
12
15
  }
13
- }
14
- var localJsonStorage = {
15
16
  /**
16
- * Generate local storage key.
17
- *
18
- * @param name - Name of the item.
19
- * @param version - Version of the item (default: 1).
20
- * @returns The generated local storage key.
21
- * @example
22
- * ```typescript
23
- * localJsonStorage.key_('myItem', 1); // myItem.v1
24
- * ```
17
+ * Generates the versioned storage key.
18
+ * @param meta - An object containing the name and version.
19
+ * @returns The versioned key string.
25
20
  */
26
- key_(name, version = 1) {
27
- return `${name}.v${version}`;
28
- },
21
+ static getKey(meta) {
22
+ return `${meta.name}.v${meta.version}`;
23
+ }
29
24
  /**
30
- * Get the local storage item and parse it as JSON.
31
- * If the item is not found, return the default value.
32
- * If the version is greater than 1, remove the previous version.
33
- * If the item is not a valid JSON object, return the default value.
25
+ * Statically checks if a versioned item exists in localStorage.
26
+ * This method provides a high-performance way to check for data existence without the overhead of creating a full provider instance.
27
+ *
28
+ * @param meta - An object containing the name and version of the item to check.
29
+ * @returns `true` if the item exists, otherwise `false`.
34
30
  *
35
- * @param name - The name of the item.
36
- * @param defaultValue - The default value of the item.
37
- * @param version - The data structure version of the item (default: 1).
38
- * @returns The parsed JSON value or the default value if the item is not found.
39
31
  * @example
40
32
  * ```typescript
41
- * const value = localJsonStorage.getItem('myItem', {a: 1, b: 2});
33
+ * const formExists = LocalStorageProvider.has({ name: 'user-form', version: 1 });
34
+ * if (formExists) {
35
+ * // Show the "Thank you" message
36
+ * } else {
37
+ * // Show the form
38
+ * }
42
39
  * ```
43
40
  */
44
- getItem(name, defaultValue, version = 1) {
45
- if (version > 1) {
46
- this.removeItem(name, version - 1);
47
- }
48
- if (version > 1) {
49
- this.removeItem(name, version - 1);
50
- }
51
- const key = this.key_(name, version);
52
- const value = localStorage.getItem(key);
53
- if (value === null) {
54
- localStorage.setItem(key, JSON.stringify(defaultValue));
55
- return defaultValue;
41
+ static has(meta) {
42
+ const key = _LocalStorageProvider.getKey(meta);
43
+ return localStorage.getItem(key) !== null;
44
+ }
45
+ /**
46
+ * Writes the default value to localStorage and returns it.
47
+ */
48
+ writeDefault__() {
49
+ this.logger_.logMethodArgs?.("writeDefaultــ", this.config_.defaultValue);
50
+ this.write(this.config_.defaultValue);
51
+ return this.config_.defaultValue;
52
+ }
53
+ /**
54
+ * Reads and parses the value from localStorage.
55
+ * If the item doesn't exist, is invalid JSON, or doesn't match the expected type,
56
+ * it writes and returns the default value.
57
+ */
58
+ read() {
59
+ try {
60
+ const value = localStorage.getItem(this.key__);
61
+ if (value === null) {
62
+ this.logger_.logMethod?.("read//no_value");
63
+ return this.writeDefault__();
64
+ }
65
+ const parsedValue = JSON.parse(value);
66
+ this.logger_.logMethodFull?.("read//value", void 0, { parsedValue });
67
+ return parsedValue;
68
+ } catch (err) {
69
+ this.logger_.error("read", "read_parse_error", { err });
70
+ return this.writeDefault__();
56
71
  }
57
- const json = parseJson(value);
58
- if (json === null) return defaultValue;
59
- return json;
60
- },
72
+ }
61
73
  /**
62
- * Check if an item exists in local storage.
63
- *
64
- * @param name - The name of the item.
65
- * @param version - The version of the item (default: 1).
66
- * @returns True if the item exists, false otherwise.
67
- * @example
68
- * ```typescript
69
- * const exists = localJsonStorage.hasItem('myItem');
70
- * ```
74
+ * Serializes and writes a value to localStorage.
71
75
  */
72
- hasItem(name, version = 1) {
73
- const key = this.key_(name, version);
74
- return localStorage.getItem(key) !== null;
75
- },
76
+ write(value) {
77
+ this.logger_.logMethodArgs?.("write", { value });
78
+ try {
79
+ localStorage.setItem(this.key__, JSON.stringify(value));
80
+ } catch (err) {
81
+ this.logger_.error("write", "write_stringify_error", { err });
82
+ }
83
+ }
76
84
  /**
77
- * Set local storage item as JSON.
78
- *
79
- * @param name - Name of the item.
80
- * @param value - Value of the item.
81
- * @param version - Version of the item.
82
- * @example
83
- * ```typescript
84
- * localJsonStorage.setItem('myItem', {a: 1, b: 2});
85
- * ```
85
+ * Removes the item from localStorage.
86
86
  */
87
- setItem(name, value, version = 1) {
88
- const key = this.key_(name, version);
89
- localStorage.setItem(key, JSON.stringify(value));
90
- },
87
+ remove() {
88
+ localStorage.removeItem(this.key__);
89
+ }
91
90
  /**
92
- * Removes an item from the local storage.
93
- *
94
- * @param name - The name of the item to remove.
95
- * @param version - The version of the item to remove. Default is 1.
96
- * @example
97
- * ```typescript
98
- * localJsonStorage.removeItem('myItem');
99
- * ```
91
+ * Manages data migration by removing all previous versions of the item.
100
92
  */
101
- removeItem(name, version = 1) {
102
- const key = this.key_(name, version);
103
- localStorage.removeItem(key);
93
+ migrate__() {
94
+ if (this.config_.version <= 1) return;
95
+ for (let i = 1; i < this.config_.version; i++) {
96
+ const oldKey = _LocalStorageProvider.getKey({ name: this.config_.name, version: i });
97
+ localStorage.removeItem(oldKey);
98
+ }
104
99
  }
105
100
  };
101
+
102
+ // src/main.ts
103
+ function createLocalStorageProvider(config) {
104
+ return new LocalStorageProvider(config);
105
+ }
106
106
  export {
107
- localJsonStorage
107
+ LocalStorageProvider,
108
+ createLocalStorageProvider
108
109
  };
109
110
  //# sourceMappingURL=main.mjs.map
package/dist/main.mjs.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/main.ts"],
4
- "sourcesContent": ["import {packageTracer} from '@alwatr/package-tracer';\n\n__dev_mode__: packageTracer.add(__package_name__, __package_version__);\n\n/**\n * Parse json string without throwing error.\n *\n * @param content - json string\n * @returns json object or null if json is invalid\n * @example\n * ```typescript\n * const json = parseJson('{\"a\":1,\"b\":2}');\n * console.log(json.a); // 1\n * ```\n */\nfunction parseJson<T extends JsonValue>(content: string): T | null {\n try {\n return JSON.parse(content);\n }\n catch (err) {\n console.error('parseJson', 'invalid_json', err);\n return null;\n }\n}\n\n// @TODO: localStorage polyfill (memory fallback)\n\n/**\n * A utility object for working with local storage and JSON data.\n */\nexport const localJsonStorage = {\n /**\n * Generate local storage key.\n *\n * @param name - Name of the item.\n * @param version - Version of the item (default: 1).\n * @returns The generated local storage key.\n * @example\n * ```typescript\n * localJsonStorage.key_('myItem', 1); // myItem.v1\n * ```\n */\n key_(name: string, version = 1): string {\n return `${name}.v${version}`;\n },\n\n /**\n * Get the local storage item and parse it as JSON.\n * If the item is not found, return the default value.\n * If the version is greater than 1, remove the previous version.\n * If the item is not a valid JSON object, return the default value.\n *\n * @param name - The name of the item.\n * @param defaultValue - The default value of the item.\n * @param version - The data structure version of the item (default: 1).\n * @returns The parsed JSON value or the default value if the item is not found.\n * @example\n * ```typescript\n * const value = localJsonStorage.getItem('myItem', {a: 1, b: 2});\n * ```\n */\n getItem<T extends JsonValue>(name: string, defaultValue: T, version = 1): T {\n if (version > 1) {\n this.removeItem(name, version - 1);\n }\n if (version > 1) {\n this.removeItem(name, version - 1);\n }\n const key = this.key_(name, version);\n const value = localStorage.getItem(key);\n if (value === null) {\n localStorage.setItem(key, JSON.stringify(defaultValue));\n return defaultValue;\n }\n const json = parseJson<T>(value);\n if (json === null) return defaultValue;\n return json;\n },\n\n /**\n * Check if an item exists in local storage.\n *\n * @param name - The name of the item.\n * @param version - The version of the item (default: 1).\n * @returns True if the item exists, false otherwise.\n * @example\n * ```typescript\n * const exists = localJsonStorage.hasItem('myItem');\n * ```\n */\n hasItem(name: string, version = 1): boolean {\n const key = this.key_(name, version);\n return localStorage.getItem(key) !== null;\n },\n\n /**\n * Set local storage item as JSON.\n *\n * @param name - Name of the item.\n * @param value - Value of the item.\n * @param version - Version of the item.\n * @example\n * ```typescript\n * localJsonStorage.setItem('myItem', {a: 1, b: 2});\n * ```\n */\n setItem<T extends JsonValue>(name: string, value: T, version = 1): void {\n const key = this.key_(name, version);\n localStorage.setItem(key, JSON.stringify(value));\n },\n\n /**\n * Removes an item from the local storage.\n *\n * @param name - The name of the item to remove.\n * @param version - The version of the item to remove. Default is 1.\n * @example\n * ```typescript\n * localJsonStorage.removeItem('myItem');\n * ```\n */\n removeItem(name: string, version = 1): void {\n const key = this.key_(name, version);\n localStorage.removeItem(key);\n },\n} as const;\n"],
5
- "mappings": ";;;AAAA,SAAQ,qBAAoB;AAE5B,aAAc,eAAc,IAAI,yBAAkB,QAAmB;AAarE,SAAS,UAA+B,SAA2B;AACjE,MAAI;AACF,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,SACO,KAAK;AACV,YAAQ,MAAM,aAAa,gBAAgB,GAAG;AAC9C,WAAO;AAAA,EACT;AACF;AAOO,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAY9B,KAAK,MAAc,UAAU,GAAW;AACtC,WAAO,GAAG,IAAI,KAAK,OAAO;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,QAA6B,MAAc,cAAiB,UAAU,GAAM;AAC1E,QAAI,UAAU,GAAG;AACf,WAAK,WAAW,MAAM,UAAU,CAAC;AAAA,IACnC;AACA,QAAI,UAAU,GAAG;AACf,WAAK,WAAW,MAAM,UAAU,CAAC;AAAA,IACnC;AACA,UAAM,MAAM,KAAK,KAAK,MAAM,OAAO;AACnC,UAAM,QAAQ,aAAa,QAAQ,GAAG;AACtC,QAAI,UAAU,MAAM;AAClB,mBAAa,QAAQ,KAAK,KAAK,UAAU,YAAY,CAAC;AACtD,aAAO;AAAA,IACT;AACA,UAAM,OAAO,UAAa,KAAK;AAC/B,QAAI,SAAS,KAAM,QAAO;AAC1B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,QAAQ,MAAc,UAAU,GAAY;AAC1C,UAAM,MAAM,KAAK,KAAK,MAAM,OAAO;AACnC,WAAO,aAAa,QAAQ,GAAG,MAAM;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,QAA6B,MAAc,OAAU,UAAU,GAAS;AACtE,UAAM,MAAM,KAAK,KAAK,MAAM,OAAO;AACnC,iBAAa,QAAQ,KAAK,KAAK,UAAU,KAAK,CAAC;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,WAAW,MAAc,UAAU,GAAS;AAC1C,UAAM,MAAM,KAAK,KAAK,MAAM,OAAO;AACnC,iBAAa,WAAW,GAAG;AAAA,EAC7B;AACF;",
3
+ "sources": ["../src/local-storage.provider.ts", "../src/main.ts"],
4
+ "sourcesContent": ["import {createLogger} from '@alwatr/logger';\n\nimport type {LocalStorageProviderConfig, StorageMeta} from './type.js';\n\n/**\n * A provider class for managing a specific, versioned item in localStorage.\n * It encapsulates the logic for key generation, serialization, and migration.\n *\n * @example\n * ```typescript\n * const userSettings = new LocalStorageProvider({\n * name: 'user-settings',\n * version: 1,\n * defaultValue: { theme: 'light', notifications: true }\n * });\n *\n * // Write new settings\n * userSettings.write({ theme: 'dark', notifications: false });\n *\n * // Read the current settings\n * const currentSettings = userSettings.read();\n * console.log(currentSettings); // { theme: 'dark', notifications: false }\n * ```\n */\nexport class LocalStorageProvider<T extends JsonValue> {\n public static readonly version = __package_version__;\n\n private readonly key__: string;\n protected readonly logger_ = createLogger(`local-storage-provider: ${this.config_.name}, v: ${this.config_.version}`);\n\n public constructor(protected readonly config_: LocalStorageProviderConfig<T>) {\n this.logger_.logMethodArgs?.('constructor', {config: this.config_});\n this.key__ = LocalStorageProvider.getKey(this.config_);\n this.migrate__();\n }\n\n /**\n * Generates the versioned storage key.\n * @param meta - An object containing the name and version.\n * @returns The versioned key string.\n */\n public static getKey(meta: StorageMeta): string {\n return `${meta.name}.v${meta.version}`;\n }\n\n /**\n * Statically checks if a versioned item exists in localStorage.\n * This method provides a high-performance way to check for data existence without the overhead of creating a full provider instance.\n *\n * @param meta - An object containing the name and version of the item to check.\n * @returns `true` if the item exists, otherwise `false`.\n *\n * @example\n * ```typescript\n * const formExists = LocalStorageProvider.has({ name: 'user-form', version: 1 });\n * if (formExists) {\n * // Show the \"Thank you\" message\n * } else {\n * // Show the form\n * }\n * ```\n */\n public static has(meta: StorageMeta): boolean {\n const key = LocalStorageProvider.getKey(meta);\n return localStorage.getItem(key) !== null;\n }\n\n /**\n * Writes the default value to localStorage and returns it.\n */\n private writeDefault__(): T {\n this.logger_.logMethodArgs?.('writeDefaultــ', this.config_.defaultValue);\n this.write(this.config_.defaultValue);\n return this.config_.defaultValue;\n }\n\n /**\n * Reads and parses the value from localStorage.\n * If the item doesn't exist, is invalid JSON, or doesn't match the expected type,\n * it writes and returns the default value.\n */\n public read(): T {\n try {\n const value = localStorage.getItem(this.key__);\n\n if (value === null) {\n this.logger_.logMethod?.('read//no_value');\n return this.writeDefault__();\n }\n\n const parsedValue = JSON.parse(value) as T;\n this.logger_.logMethodFull?.('read//value', undefined, {parsedValue});\n return parsedValue;\n }\n catch (err) {\n this.logger_.error('read', 'read_parse_error', {err});\n return this.writeDefault__();\n }\n }\n\n /**\n * Serializes and writes a value to localStorage.\n */\n public write(value: T): void {\n this.logger_.logMethodArgs?.('write', {value});\n try {\n localStorage.setItem(this.key__, JSON.stringify(value));\n }\n catch (err) {\n this.logger_.error('write', 'write_stringify_error', {err});\n }\n }\n\n /**\n * Removes the item from localStorage.\n */\n public remove(): void {\n localStorage.removeItem(this.key__);\n }\n\n /**\n * Manages data migration by removing all previous versions of the item.\n */\n private migrate__(): void {\n if (this.config_.version <= 1) return;\n\n // Iterate from v1 up to the version just before the current one and remove them.\n for (let i = 1; i < this.config_.version; i++) {\n const oldKey = LocalStorageProvider.getKey({name: this.config_.name, version: i});\n localStorage.removeItem(oldKey);\n }\n }\n}\n", "import {LocalStorageProvider} from './local-storage.provider.js';\n\nimport type {LocalStorageProviderConfig} from './type.js';\n\nexport * from './local-storage.provider.js';\nexport type * from './type.js';\n\n/**\n * Factory function to create a new LocalStorageProvider.\n *\n * @param config - The configuration for the provider.\n * @returns An instance of LocalStorageProvider.\n *\n * @example\n * ```typescript\n * const userSettings = createLocalStorageProvider({\n * name: 'user-settings',\n * version: 1,\n * defaultValue: { theme: 'light', notifications: true }\n * });\n *\n * // Write new settings\n * userSettings.write({ theme: 'dark', notifications: false });\n *\n * // Read the current settings\n * const currentSettings = userSettings.read();\n * console.log(currentSettings); // { theme: 'dark', notifications: false }\n * ```\n */\nexport function createLocalStorageProvider<T extends JsonValue>(config: LocalStorageProviderConfig<T>): LocalStorageProvider<T> {\n return new LocalStorageProvider<T>(config);\n}\n"],
5
+ "mappings": ";;;AAAA,SAAQ,oBAAmB;AAwBpB,IAAM,uBAAN,MAAM,sBAA0C;AAAA,EAM9C,YAA+B,SAAwC;AAAxC;AAFtC,SAAmB,UAAU,aAAa,2BAA2B,KAAK,QAAQ,IAAI,QAAQ,KAAK,QAAQ,OAAO,EAAE;AAGlH,SAAK,QAAQ,gBAAgB,eAAe,EAAC,QAAQ,KAAK,QAAO,CAAC;AAClE,SAAK,QAAQ,sBAAqB,OAAO,KAAK,OAAO;AACrD,SAAK,UAAU;AAAA,EACjB;AAAA,EATA;AAAA,SAAuB,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBjC,OAAc,OAAO,MAA2B;AAC9C,WAAO,GAAG,KAAK,IAAI,KAAK,KAAK,OAAO;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,OAAc,IAAI,MAA4B;AAC5C,UAAM,MAAM,sBAAqB,OAAO,IAAI;AAC5C,WAAO,aAAa,QAAQ,GAAG,MAAM;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAoB;AAC1B,SAAK,QAAQ,gBAAgB,kBAAkB,KAAK,QAAQ,YAAY;AACxE,SAAK,MAAM,KAAK,QAAQ,YAAY;AACpC,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,OAAU;AACf,QAAI;AACF,YAAM,QAAQ,aAAa,QAAQ,KAAK,KAAK;AAE7C,UAAI,UAAU,MAAM;AAClB,aAAK,QAAQ,YAAY,gBAAgB;AACzC,eAAO,KAAK,eAAe;AAAA,MAC7B;AAEA,YAAM,cAAc,KAAK,MAAM,KAAK;AACpC,WAAK,QAAQ,gBAAgB,eAAe,QAAW,EAAC,YAAW,CAAC;AACpE,aAAO;AAAA,IACT,SACO,KAAK;AACV,WAAK,QAAQ,MAAM,QAAQ,oBAAoB,EAAC,IAAG,CAAC;AACpD,aAAO,KAAK,eAAe;AAAA,IAC7B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,MAAM,OAAgB;AAC3B,SAAK,QAAQ,gBAAgB,SAAS,EAAC,MAAK,CAAC;AAC7C,QAAI;AACF,mBAAa,QAAQ,KAAK,OAAO,KAAK,UAAU,KAAK,CAAC;AAAA,IACxD,SACO,KAAK;AACV,WAAK,QAAQ,MAAM,SAAS,yBAAyB,EAAC,IAAG,CAAC;AAAA,IAC5D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,SAAe;AACpB,iBAAa,WAAW,KAAK,KAAK;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAkB;AACxB,QAAI,KAAK,QAAQ,WAAW,EAAG;AAG/B,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,SAAS,KAAK;AAC7C,YAAM,SAAS,sBAAqB,OAAO,EAAC,MAAM,KAAK,QAAQ,MAAM,SAAS,EAAC,CAAC;AAChF,mBAAa,WAAW,MAAM;AAAA,IAChC;AAAA,EACF;AACF;;;ACvGO,SAAS,2BAAgD,QAAgE;AAC9H,SAAO,IAAI,qBAAwB,MAAM;AAC3C;",
6
6
  "names": []
7
7
  }
package/dist/type.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ export interface StorageMeta {
2
+ /**
3
+ * The unique name for the storage item.
4
+ */
5
+ name: string;
6
+ /**
7
+ * The data structure version.
8
+ * starting from 1 and incrementing by 1 for each new version.
9
+ */
10
+ version: number;
11
+ }
12
+ export interface LocalStorageProviderConfig<T> extends StorageMeta {
13
+ /**
14
+ * The default value to use if no value is stored.
15
+ */
16
+ defaultValue: T;
17
+ }
18
+ //# sourceMappingURL=type.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,0BAA0B,CAAC,CAAC,CAAE,SAAQ,WAAW;IAChE;;OAEG;IACH,YAAY,EAAE,CAAC,CAAC;CACjB"}
package/package.json CHANGED
@@ -1,17 +1,18 @@
1
1
  {
2
2
  "name": "@alwatr/local-storage",
3
- "description": "`localJsonStorage` is a utility object in our TypeScript package that provides methods for interacting with the local storage in a structured and versioned manner.",
4
- "version": "5.5.10",
3
+ "description": "A modern, simple, and robust solution for managing versioned JSON objects in the browser's `localStorage`. This package provides a clean, class-based API with a factory function to ensure your application's data persistence is safe, maintainable, and future-proof.",
4
+ "version": "6.1.0",
5
5
  "author": "S. Ali Mihandoost <ali.mihandoost@gmail.com>",
6
6
  "bugs": "https://github.com/Alwatr/nanolib/issues",
7
7
  "dependencies": {
8
- "@alwatr/package-tracer": "5.5.10"
8
+ "@alwatr/logger": "5.6.1"
9
9
  },
10
10
  "devDependencies": {
11
11
  "@alwatr/nano-build": "6.1.1",
12
12
  "@alwatr/prettier-config": "5.0.3",
13
13
  "@alwatr/tsconfig-base": "6.0.1",
14
14
  "@alwatr/type-helper": "6.0.1",
15
+ "@jest/globals": "^30.1.2",
15
16
  "typescript": "^5.9.2"
16
17
  },
17
18
  "exports": {
@@ -75,5 +76,5 @@
75
76
  },
76
77
  "type": "module",
77
78
  "types": "./dist/main.d.ts",
78
- "gitHead": "cd02a1a9fa579930cd54291ba51ed86241313a6d"
79
+ "gitHead": "0555c6f5ac11e7a911deee9bc90cfa44b6fe0b48"
79
80
  }