Skip to content

Commit 4922768

Browse files
authored
Merge pull request #1 from mqxym/docs-add-jsdoc
Docs add jsdoc: 0.6.1
2 parents 974ccb4 + a87114e commit 4922768

12 files changed

+404
-69
lines changed

dist/cjs/sls.browser.min.cjs

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

dist/cjs/sls.browser.min.js.map

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/esm/sls.browser.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/esm/sls.browser.min.js.map

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/types/api/SecureLocalStorage.d.ts

Lines changed: 169 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,67 @@
11
import { SecureDataView } from "../utils/secureDataView";
22
import type { IdbConfig } from "../crypto/DeviceKeyProvider";
3+
/**
4+
* Configuration options for initializing SecureLocalStorage.
5+
*/
36
export interface SecureLocalStorageOptions {
4-
/** Override the localStorage key (for multi-tenant apps or tests). */
7+
/**
8+
* Overrides the default key used for storing encrypted data in `localStorage`.
9+
* This is useful for multi-tenant applications or for isolating data in tests.
10+
* @default "secure-local-storage"
11+
*/
512
storageKey?: string;
6-
/** Override IndexedDB configuration (for multi-tenant apps or tests). */
13+
/**
14+
* Overrides the default IndexedDB configuration for storing the device-specific key.
15+
* This is useful for multi-tenant applications or for isolating data in tests.
16+
*/
717
idbConfig?: Partial<IdbConfig>;
818
}
19+
/**
20+
* Provides a secure, client-side storage solution that encrypts data before persisting it.
21+
*
22+
* `SecureLocalStorage` offers two primary modes of operation:
23+
* 1. **Device-bound Mode**: (Default) Data is encrypted with a key that is stored in
24+
* the browser's IndexedDB. This key is unique to the device and profile, making it
25+
* difficult to access from other devices. Data is automatically unlocked when the
26+
* class is instantiated.
27+
* 2. **Master Password Mode**: Data is encrypted with a key derived from a user-provided
28+
* master password. The data can only be accessed by providing the correct password,
29+
* allowing for portability across devices but requiring user interaction to unlock.
30+
*
31+
* The class handles key management, encryption, and data serialization, providing a
32+
* simple `getData`/`setData` interface for application use. It also supports features
33+
* like key rotation, data export/import, and changing or removing the master password.
34+
*
35+
* @example
36+
* ```typescript
37+
* // Initialize in device-bound mode
38+
* const sls = new SecureLocalStorage();
39+
*
40+
* // Set some data
41+
* await sls.setData({ mySecret: "hello world" });
42+
*
43+
* // Get the data back
44+
* const dataView = await sls.getData();
45+
* console.log(dataView.value.mySecret); // "hello world"
46+
*
47+
* // Wipe the plaintext from memory
48+
* dataView.wipe();
49+
* ```
50+
*
51+
* @example
52+
* ```typescript
53+
* // Initialize and set a master password
54+
* const sls = new SecureLocalStorage();
55+
* await sls.setMasterPassword("my-strong-password-123");
56+
*
57+
* // Later, in a new session
58+
* const sls2 = new SecureLocalStorage();
59+
* await sls2.unlock("my-strong-password-123");
60+
* const data = await sls2.getData();
61+
* // ... use data
62+
* sls2.lock(); // clear session keys
63+
* ```
64+
*/
965
export declare class SecureLocalStorage {
1066
private readonly store;
1167
private readonly enc;
@@ -14,39 +70,134 @@ export declare class SecureLocalStorage {
1470
private dek;
1571
private ready;
1672
private readonly idbConfig;
73+
/**
74+
* The current version of the data structure format.
75+
*/
1776
readonly DATA_VERSION: number;
77+
/**
78+
* Initializes a new instance of SecureLocalStorage.
79+
*
80+
* The constructor immediately begins an asynchronous initialization process.
81+
* Public methods will await this process, so you don't need to manually wait
82+
* for it to complete.
83+
*
84+
* @param opts - Optional configuration to customize storage keys.
85+
*/
1886
constructor(opts?: SecureLocalStorageOptions);
87+
/**
88+
* Checks if the storage is currently protected by a master password.
89+
* @returns `true` if a master password is set, `false` otherwise.
90+
*/
1991
isUsingMasterPassword(): boolean;
20-
/** Unlock session with master password (no-op in device mode / no data available ). */
92+
/**
93+
* Unlocks the data encryption key (DEK) using the provided master password.
94+
* This is required to access data when in master password mode.
95+
* If the store is in device-bound mode or is already unlocked, this method does nothing.
96+
*
97+
* @param masterPassword - The user's master password.
98+
* @throws {ValidationError} If the master password is an empty string or invalid.
99+
*/
21100
unlock(masterPassword: string): Promise<void>;
22-
/** Set a master password (switch from device mode to master mode). */
101+
/**
102+
* Sets a master password, switching from device-bound mode to master password mode.
103+
* This re-encrypts the data encryption key (DEK) with a new key derived from the password.
104+
*
105+
* @param masterPassword - The new master password to set. Must be a non-empty string.
106+
* @throws {ModeError} If a master password is already set.
107+
* @throws {ValidationError} If the master password is an empty string.
108+
*/
23109
setMasterPassword(masterPassword: string): Promise<void>;
24-
/** Remove master password, re-wrapping DEK with device-bound KEK. Requires unlocked session. */
110+
/**
111+
* Removes the master password, switching back to device-bound mode.
112+
* The DEK is re-encrypted using the device-specific key.
113+
* Requires the session to be unlocked.
114+
*
115+
* @throws {ModeError} If no master password is set.
116+
* @throws {LockedError} If the session is locked.
117+
*/
25118
removeMasterPassword(): Promise<void>;
26-
/** Rotate master password atomically. */
119+
/**
120+
* Atomically changes the master password.
121+
* If not in master password mode, it will set the new password.
122+
*
123+
* @param oldMasterPassword - The current master password.
124+
* @param newMasterPassword - The new master password. Must be a non-empty string.
125+
* @throws {ValidationError} If the new password is empty or if the old password is incorrect.
126+
* @throws {LockedError} If the session is locked.
127+
*/
27128
rotateMasterPassword(oldMasterPassword: string, newMasterPassword: string): Promise<void>;
28-
/** Lock the session (clears derived KEK & DEK from memory). */
129+
/**
130+
* Locks the session by clearing the cached Key Encryption Key (KEK) and
131+
* Data Encryption Key (DEK) from memory.
132+
* After locking, `unlock()` must be called to perform further operations.
133+
*/
29134
lock(): void;
30-
/** Rotate DEK and device KEK. Allowed only in password-less mode. */
135+
/**
136+
* Rotates the Data Encryption Key (DEK) and the device-specific Key Encryption Key (KEK).
137+
* This enhances security by replacing the keys used to protect the data.
138+
* This operation is only allowed in device-bound mode.
139+
*
140+
* @throws {ModeError} If a master password is set.
141+
*/
31142
rotateKeys(): Promise<void>;
32-
/** Get decrypted data as a wipeable view object. */
143+
/**
144+
* Retrieves the decrypted data.
145+
*
146+
* @returns A promise that resolves to a `SecureDataView`, a wrapper around the
147+
* decrypted data object that includes a `wipe()` method to securely
148+
* clear the plaintext data from memory.
149+
* @throws {LockedError} If the session is locked.
150+
* @throws {ValidationError} If the stored data is not a plain object.
151+
* @template T The expected type of the stored data object.
152+
*/
33153
getData<T extends Record<string, unknown> = Record<string, unknown>>(): Promise<SecureDataView<T>>;
34-
/** Replace data with the provided plain object. */
154+
/**
155+
* Encrypts and persists the provided data object, replacing any existing data.
156+
*
157+
* @param value The plain JavaScript object to store. It must be serializable.
158+
* @throws {LockedError} If the session is locked.
159+
* @throws {ValidationError} If the provided value is not a plain object.
160+
*/
35161
setData<T extends Record<string, unknown>>(value: T): Promise<void>;
36162
/**
37-
* Export the encrypted bundle as JSON string.
38-
* - If `customExportPassword` provided: derive export KEK (Argon2id) and rewrap DEK accordingly (mPw=false).
39-
* - If absent and in master mode: exports current config wrapped with master password (mPw=true).
163+
* Exports the encrypted data bundle as a JSON string.
164+
*
165+
* There are two export modes:
166+
* 1. **Master Password Mode**: If no `customExportPassword` is provided and a master
167+
* password is set, the bundle is exported using the existing master password.
168+
* 2. **Custom Password Mode**: If a `customExportPassword` is provided, the bundle
169+
* is re-encrypted with a key derived from this password. This is required when
170+
* in device-bound mode.
171+
*
172+
* @param customExportPassword - An optional password to protect the exported data.
173+
* Required if not in master password mode.
174+
* @returns A JSON string representing the encrypted data bundle.
175+
* @throws {ExportError} If a password is required but not provided, or if the
176+
* provided password is invalid.
40177
*/
41178
exportData(customExportPassword?: string): Promise<string>;
42179
/**
43-
* Import previously exported JSON.
44-
* - If bundle.mPw===true OR header.rounds>1 and no mPw flag: expects master password.
45-
* - Else expects export password.
46-
* After import, rewrap to device mode if using export password.
180+
* Imports a previously exported data bundle.
181+
*
182+
* The method determines whether to use a master password or an export password
183+
* based on the bundle's metadata. After a successful import using an export
184+
* password, the data is re-encrypted into device-bound mode. If imported with a
185+
* master password, it remains in master password mode.
186+
*
187+
* @param serialized - The JSON string of the exported data bundle.
188+
* @param password - The password required to decrypt the bundle (master or export).
189+
* @returns A promise that resolves to 'masterPassword' or 'customExportPassword'
190+
* indicating which type of password was used for the import.
191+
* @throws {ImportError} If the JSON is invalid, the bundle is corrupted, the
192+
* password is required but missing, or the password is incorrect.
47193
*/
48194
importData(serialized: string, password?: string): Promise<string>;
49-
/** Clear all data (localStorage + IndexedDB KEK) and reinitialize fresh empty store in device mode. */
195+
/**
196+
* Clears all stored data, including the encrypted bundle from `localStorage` and
197+
* the device key from `IndexedDB`.
198+
* After clearing, the instance is reinitialized to a fresh, empty state in
199+
* device-bound mode.
200+
*/
50201
clear(): Promise<void>;
51202
private initialize;
52203
private persist;

dist/types/index.d.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,28 @@ import { SecureLocalStorage, type SecureLocalStorageOptions } from "./api/Secure
22
export type { SecureLocalStorageOptions } from "./api/SecureLocalStorage";
33
export { SecureLocalStorage } from "./api/SecureLocalStorage";
44
/**
5-
* Factory per your API:
5+
* Creates and initializes a new `SecureLocalStorage` instance.
66
*
7-
* ```ts
8-
* const sls = secureLocalStorage(); // init
9-
* await sls.setData({ value1: 123 });
7+
* This factory function is the recommended way to get started with the library.
8+
* It provides a convenient shorthand for `new SecureLocalStorage(opts)`.
9+
*
10+
* @param {SecureLocalStorageOptions} [opts] - Optional configuration to customize storage keys and other behavior.
11+
* @returns {SecureLocalStorage} A new instance of the `SecureLocalStorage` class.
12+
* @example
13+
* ```typescript
14+
* import secureLocalStorage from 'secure-local-storage';
15+
*
16+
* // Initialize with default options
17+
* const sls = secureLocalStorage();
18+
*
19+
* async function main() {
20+
* await sls.setData({ secret: 'This is a secret' });
21+
* const data = await sls.getData();
22+
* console.log(data.value.secret); // "This is a secret"
23+
* data.wipe();
24+
* }
25+
*
26+
* main();
1027
* ```
1128
*/
1229
export default function secureLocalStorage(opts?: SecureLocalStorageOptions): SecureLocalStorage;

examples/dist/sls.browser.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/dist/sls.browser.min.js.map

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@mqxym/secure-local-storage",
3-
"version": "0.6.0",
3+
"version": "0.6.1",
44
"description": "Secure arbitrary objects in localStorage using AES-GCM envelope encryption with device-bound KEK (IndexedDB) or Argon2id-derived KEK (master password).",
55
"license": "MIT",
66
"author": "mqxym",

0 commit comments

Comments
 (0)