litle-indexeddb 0.0.0-stage → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,39 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
1
+ # Little Indexed DB
2
+ Standard indexeddb on browsers store data in plain text. Attackers can steal your tokens or other PIN (personally identifiable information) from your browser.
3
+
4
+ little-IndexedDB is just a wrapper around indexedDB, it encrypts JSON-serializable with AES-GCM-256 encryption.
5
+
6
+ **Note:** Keys are not encrypted for indexing purposes.
7
+
8
+ Also, your application does not become immmune to client-side data-leaks from this. Due to the mutable qurik (curse) of JavaScript, any kind of XSS (Cross-Site-Scripting) is more than enough to steal the data. Though it depends on how you handle the crypto key.
9
+
10
+ # Usage
11
+ Use directly through esm.sh cdn:
12
+ ```js
13
+ <script type="module">
14
+ import LittleIndexedDB from 'https://esm.sh/little-indexeddb';
15
+
16
+ const db = new LittleIndexedDB('AppDB', 'auth_store');
17
+
18
+ const pin = prompt('Enter your security PIN:');
19
+ if (!pin) throw new Error('PIN is required to unlock storage.');
20
+
21
+ await db.init(pin);
22
+
23
+ try {
24
+ // For this example, I'm storing the user's auth tokens.
25
+ await db.setItem('session', {
26
+ name: 'Alex Mercer',
27
+ accessToken: 'eyJh...token',
28
+ refreshToken: 'rt_9823...secret'
29
+ });
30
+
31
+ const session = await db.getItem('session');
32
+ console.log('Decrypted user:', session.name);
33
+ } catch (err) {
34
+ console.error('Decryption failed: ', err);
35
+ } finally {
36
+ db.close(); // Closing is good.
37
+ }
38
+ </script>
39
+ ```
@@ -0,0 +1,69 @@
1
+ export interface EncryptedPayload {
2
+ iv: Uint8Array;
3
+ ciphertext: Uint8Array;
4
+ }
5
+ export interface StoredEntry<T = unknown> {
6
+ key: IDBValidKey;
7
+ value: T;
8
+ }
9
+ /**
10
+ * Basically IndexedDB with built-in AES-GCM encryption.
11
+ */
12
+ export default class LittleIndexedDB {
13
+ readonly dbName: string;
14
+ readonly storeName: string;
15
+ readonly version: number;
16
+ private db;
17
+ private cryptoKey;
18
+ /**
19
+ * @param dbName Database name.
20
+ * @param storeName Primary object store name.
21
+ * @param version Database schema version. Defaults to 1.
22
+ */
23
+ constructor(dbName: string, storeName: string, version?: number);
24
+ /**
25
+ * Derives an AES-GCM-256 key from a passphrase and a salt using PBKDF2.
26
+ */
27
+ private _deriveKey;
28
+ /**
29
+ * Encrypts any JSON serializable val ue.
30
+ */
31
+ private _encrypt;
32
+ /**
33
+ * Decrypts an encrypted payload back into its original parsed data structure.
34
+ */
35
+ private _decrypt;
36
+ /**
37
+ * Reads or creates the database PBKDF2 salt in the `__meta__` store.
38
+ */
39
+ private _getOrCreateSalt;
40
+ /**
41
+ * Initializes the IndexedDB instance.
42
+ * @param passphrase Passphrase used to derive encryption keys.
43
+ */
44
+ init(passphrase: string): Promise<this>;
45
+ /**
46
+ * Encrypts and persists a value by key.
47
+ */
48
+ setItem<T>(key: IDBValidKey, value: T): Promise<boolean>;
49
+ /**
50
+ * Retrieves and decrypts a value by key. Returns `null` if not found.
51
+ */
52
+ getItem<T>(key: IDBValidKey): Promise<T | null>;
53
+ /**
54
+ * Deletes an item by key.
55
+ */
56
+ removeItem(key: IDBValidKey): Promise<boolean>;
57
+ /**
58
+ * Clear all encrypted entries in the current object store.
59
+ */
60
+ clear(): Promise<boolean>;
61
+ /**
62
+ * Get all key-value entries from the store.
63
+ */
64
+ getAll<T>(): Promise<StoredEntry<T>[]>;
65
+ /**
66
+ * Close the connection. Please use it.
67
+ */
68
+ close(): void;
69
+ }
@@ -0,0 +1,169 @@
1
+ // \0@oxc-project+runtime@0.156.0/helpers/esm/typeof.js
2
+ function e(t) {
3
+ "@babel/helpers - typeof";
4
+ return e = typeof Symbol == "function" && typeof Symbol.iterator == "symbol" ? function(e) {
5
+ return typeof e;
6
+ } : function(e) {
7
+ return e && typeof Symbol == "function" && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e;
8
+ }, e(t);
9
+ }
10
+ // \0@oxc-project+runtime@0.156.0/helpers/esm/toPrimitive.js
11
+ function t(t, n) {
12
+ if (e(t) != "object" || !t) return t;
13
+ var r = t[Symbol.toPrimitive];
14
+ if (r !== void 0) {
15
+ var i = r.call(t, n || "default");
16
+ if (e(i) != "object") return i;
17
+ throw TypeError("@@toPrimitive must return a primitive value.");
18
+ }
19
+ return (n === "string" ? String : Number)(t);
20
+ }
21
+ // \0@oxc-project+runtime@0.156.0/helpers/esm/toPropertyKey.js
22
+ function n(n) {
23
+ var r = t(n, "string");
24
+ return e(r) == "symbol" ? r : r + "";
25
+ }
26
+ // \0@oxc-project+runtime@0.156.0/helpers/esm/defineProperty.js
27
+ function r(e, t, r) {
28
+ return (t = n(t)) in e ? Object.defineProperty(e, t, {
29
+ value: r,
30
+ enumerable: !0,
31
+ configurable: !0,
32
+ writable: !0
33
+ }) : e[t] = r, e;
34
+ }
35
+ // src/index.ts
36
+ var i = class {
37
+ constructor(e, t, n = 1) {
38
+ r(this, "dbName", void 0), r(this, "storeName", void 0), r(this, "version", void 0), r(this, "db", null), r(this, "cryptoKey", null), this.dbName = e, this.storeName = t, this.version = n;
39
+ }
40
+ async _deriveKey(e, t) {
41
+ let n = new TextEncoder(), r = await crypto.subtle.importKey("raw", n.encode(e), { name: "PBKDF2" }, !1, ["deriveKey"]);
42
+ return crypto.subtle.deriveKey({
43
+ name: "PBKDF2",
44
+ salt: t,
45
+ iterations: 1e5,
46
+ hash: "SHA-256"
47
+ }, r, {
48
+ name: "AES-GCM",
49
+ length: 256
50
+ }, !1, ["encrypt", "decrypt"]);
51
+ }
52
+ async _encrypt(e) {
53
+ if (!this.cryptoKey) throw Error("Key not initialized. Call init() first.");
54
+ let t = crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(12)), n = new TextEncoder().encode(JSON.stringify(e)), r = await crypto.subtle.encrypt({
55
+ name: "AES-GCM",
56
+ iv: t
57
+ }, this.cryptoKey, n);
58
+ return {
59
+ iv: t,
60
+ ciphertext: new Uint8Array(r)
61
+ };
62
+ }
63
+ async _decrypt(e) {
64
+ if (!this.cryptoKey) throw Error("Key not initialized. Call init() first.");
65
+ let t = await crypto.subtle.decrypt({
66
+ name: "AES-GCM",
67
+ iv: e.iv
68
+ }, this.cryptoKey, e.ciphertext), n = new TextDecoder().decode(t);
69
+ return JSON.parse(n);
70
+ }
71
+ async _getOrCreateSalt() {
72
+ if (!this.db) throw Error("Database not connected.");
73
+ return new Promise((e, t) => {
74
+ let n = this.db.transaction("__meta__", "readwrite").objectStore("__meta__"), r = n.get("db_salt");
75
+ r.onsuccess = () => {
76
+ let t = r.result;
77
+ if (t?.value) e(new Uint8Array(t.value));
78
+ else {
79
+ let t = crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(16));
80
+ n.put({
81
+ id: "db_salt",
82
+ value: t
83
+ }), e(t);
84
+ }
85
+ }, r.onerror = () => t(r.error);
86
+ });
87
+ }
88
+ async init(e) {
89
+ return new Promise((t, n) => {
90
+ let r = indexedDB.open(this.dbName, this.version);
91
+ r.onupgradeneeded = (e) => {
92
+ let t = e.target.result;
93
+ t.objectStoreNames.contains("__meta__") || t.createObjectStore("__meta__", { keyPath: "id" }), t.objectStoreNames.contains(this.storeName) || t.createObjectStore(this.storeName);
94
+ }, r.onsuccess = async (r) => {
95
+ this.db = r.target.result;
96
+ try {
97
+ let n = await this._getOrCreateSalt();
98
+ this.cryptoKey = await this._deriveKey(e, n), t(this);
99
+ } catch (e) {
100
+ n(e);
101
+ }
102
+ }, r.onerror = (e) => {
103
+ n(e.target.error);
104
+ };
105
+ });
106
+ }
107
+ async setItem(e, t) {
108
+ if (!this.db) throw Error("Database not initialized.");
109
+ let n = await this._encrypt(t);
110
+ return new Promise((t, r) => {
111
+ let i = this.db.transaction(this.storeName, "readwrite").objectStore(this.storeName).put(n, e);
112
+ i.onsuccess = () => t(!0), i.onerror = () => r(i.error);
113
+ });
114
+ }
115
+ async getItem(e) {
116
+ if (!this.db) throw Error("Database not initialized.");
117
+ return new Promise((t, n) => {
118
+ let r = this.db.transaction(this.storeName, "readonly").objectStore(this.storeName).get(e);
119
+ r.onsuccess = async () => {
120
+ if (!r.result) return t(null);
121
+ try {
122
+ t(await this._decrypt(r.result));
123
+ } catch {
124
+ n(/* @__PURE__ */ Error("Decryption failed. Invalid passphrase or corrupted data."));
125
+ }
126
+ }, r.onerror = () => n(r.error);
127
+ });
128
+ }
129
+ async removeItem(e) {
130
+ if (!this.db) throw Error("Database not initialized.");
131
+ return new Promise((t, n) => {
132
+ let r = this.db.transaction(this.storeName, "readwrite").objectStore(this.storeName).delete(e);
133
+ r.onsuccess = () => t(!0), r.onerror = () => n(r.error);
134
+ });
135
+ }
136
+ async clear() {
137
+ if (!this.db) throw Error("Database not initialized.");
138
+ return new Promise((e, t) => {
139
+ let n = this.db.transaction(this.storeName, "readwrite").objectStore(this.storeName).clear();
140
+ n.onsuccess = () => e(!0), n.onerror = () => t(n.error);
141
+ });
142
+ }
143
+ async getAll() {
144
+ if (!this.db) throw Error("Database not initialized.");
145
+ return new Promise((e, t) => {
146
+ let n = this.db.transaction(this.storeName, "readonly").objectStore(this.storeName).openCursor(), r = [];
147
+ n.onsuccess = async (n) => {
148
+ let i = n.target.result;
149
+ if (i) try {
150
+ let e = await this._decrypt(i.value);
151
+ r.push({
152
+ key: i.key,
153
+ value: e
154
+ }), i.continue();
155
+ } catch (e) {
156
+ let n = e instanceof Error ? e.message : String(e);
157
+ t(/* @__PURE__ */ Error(`Failed to decrypt record under key '${String(i.key)}': ${n}`));
158
+ }
159
+ else e(r);
160
+ }, n.onerror = () => t(n.error);
161
+ });
162
+ }
163
+ close() {
164
+ this.db && (this.db.close(), this.db = null, this.cryptoKey = null);
165
+ }
166
+ };
167
+ export { i as default };
168
+
169
+ //# sourceMappingURL=little-indexeddb.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"little-indexeddb.es.js","names":["_typeof","o","toPrimitive","e","r","toPropertyKey","i","t","_defineProperty","LittleIndexedDB","dbName","storeName","version","enc","keyMaterial","passphrase","iv","encodedData","data","ciphertextBuffer","decryptedBuffer","encryptedRecord","jsonString","store","req","record","newSalt","resolve","reject","request","db","event","salt","err","value","key","results","cursor","decryptedValue","msg"],"sources":["../src/index.ts"],"sourcesContent":["export interface EncryptedPayload {\r\n iv: Uint8Array;\r\n ciphertext: Uint8Array;\r\n}\r\n\r\nexport interface StoredEntry<T = unknown> {\r\n key: IDBValidKey;\r\n value: T;\r\n}\r\n\r\ninterface MetaRecord {\r\n id: string;\r\n value: Uint8Array;\r\n}\r\n\r\n/**\r\n * Basically IndexedDB with built-in AES-GCM encryption.\r\n */\r\nexport default class LittleIndexedDB {\r\n private db: IDBDatabase | null = null;\r\n private cryptoKey: CryptoKey | null = null;\r\n\r\n /**\r\n * @param dbName Database name.\r\n * @param storeName Primary object store name.\r\n * @param version Database schema version. Defaults to 1.\r\n */\r\n constructor(\r\n public readonly dbName: string,\r\n public readonly storeName: string,\r\n public readonly version: number = 1\r\n ) {}\r\n\r\n /**\r\n * Derives an AES-GCM-256 key from a passphrase and a salt using PBKDF2.\r\n */\r\n private async _deriveKey(passphrase: string, salt: Uint8Array): Promise<CryptoKey> {\r\n const enc = new TextEncoder();\r\n const keyMaterial = await crypto.subtle.importKey(\r\n \"raw\",\r\n enc.encode(passphrase),\r\n { name: \"PBKDF2\" },\r\n false,\r\n [\"deriveKey\"]\r\n );\r\n\r\n return crypto.subtle.deriveKey(\r\n {\r\n name: \"PBKDF2\",\r\n salt: salt as BufferSource,\r\n iterations: 100_000,\r\n hash: \"SHA-256\",\r\n },\r\n keyMaterial,\r\n { name: \"AES-GCM\", length: 256 },\r\n false,\r\n [\"encrypt\", \"decrypt\"]\r\n );\r\n }\r\n\r\n /**\r\n * Encrypts any JSON serializable val ue.\r\n */\r\n private async _encrypt<T>(data: T): Promise<EncryptedPayload> {\r\n if (!this.cryptoKey) throw new Error(\"Key not initialized. Call init() first.\");\r\n\r\n const iv = crypto.getRandomValues(new Uint8Array(12));\r\n const encodedData = new TextEncoder().encode(JSON.stringify(data));\r\n\r\n const ciphertextBuffer = await crypto.subtle.encrypt(\r\n { name: \"AES-GCM\", iv },\r\n this.cryptoKey,\r\n encodedData\r\n );\r\n\r\n return {\r\n iv,\r\n ciphertext: new Uint8Array(ciphertextBuffer),\r\n };\r\n }\r\n\r\n /**\r\n * Decrypts an encrypted payload back into its original parsed data structure.\r\n */\r\n private async _decrypt<T>(encryptedRecord: EncryptedPayload): Promise<T> {\r\n if (!this.cryptoKey) throw new Error(\"Key not initialized. Call init() first.\");\r\n\r\n const decryptedBuffer = await crypto.subtle.decrypt(\r\n { name: \"AES-GCM\", iv: encryptedRecord.iv as BufferSource },\r\n this.cryptoKey,\r\n encryptedRecord.ciphertext as BufferSource\r\n );\r\n\r\n const jsonString = new TextDecoder().decode(decryptedBuffer);\r\n return JSON.parse(jsonString) as T;\r\n }\r\n\r\n /**\r\n * Reads or creates the database PBKDF2 salt in the `__meta__` store.\r\n */\r\n private async _getOrCreateSalt(): Promise<Uint8Array> {\r\n if (!this.db) throw new Error(\"Database not connected.\");\r\n\r\n return new Promise((resolve, reject) => {\r\n const tx = this.db!.transaction(\"__meta__\", \"readwrite\");\r\n const store = tx.objectStore(\"__meta__\");\r\n const req = store.get(\"db_salt\");\r\n\r\n req.onsuccess = () => {\r\n const record = req.result as MetaRecord | undefined;\r\n if (record?.value) {\r\n resolve(new Uint8Array(record.value));\r\n } else {\r\n const newSalt = crypto.getRandomValues(new Uint8Array(16));\r\n store.put({ id: \"db_salt\", value: newSalt });\r\n resolve(newSalt);\r\n }\r\n };\r\n\r\n req.onerror = () => reject(req.error);\r\n });\r\n }\r\n\r\n /**\r\n * Initializes the IndexedDB instance.\r\n * @param passphrase Passphrase used to derive encryption keys.\r\n */\r\n public async init(passphrase: string): Promise<this> {\r\n return new Promise((resolve, reject) => {\r\n const request = indexedDB.open(this.dbName, this.version);\r\n\r\n request.onupgradeneeded = (event: IDBVersionChangeEvent) => {\r\n const db = (event.target as IDBOpenDBRequest).result;\r\n if (!db.objectStoreNames.contains(\"__meta__\")) {\r\n db.createObjectStore(\"__meta__\", { keyPath: \"id\" });\r\n }\r\n if (!db.objectStoreNames.contains(this.storeName)) {\r\n db.createObjectStore(this.storeName);\r\n }\r\n };\r\n\r\n request.onsuccess = async (event: Event) => {\r\n this.db = (event.target as IDBOpenDBRequest).result;\r\n try {\r\n const salt = await this._getOrCreateSalt();\r\n this.cryptoKey = await this._deriveKey(passphrase, salt);\r\n resolve(this);\r\n } catch (err) {\r\n reject(err);\r\n }\r\n };\r\n\r\n request.onerror = (event: Event) => {\r\n reject((event.target as IDBOpenDBRequest).error);\r\n };\r\n });\r\n }\r\n\r\n /**\r\n * Encrypts and persists a value by key.\r\n */\r\n public async setItem<T>(key: IDBValidKey, value: T): Promise<boolean> {\r\n if (!this.db) throw new Error(\"Database not initialized.\");\r\n const encryptedRecord = await this._encrypt(value);\r\n\r\n return new Promise((resolve, reject) => {\r\n const tx = this.db!.transaction(this.storeName, \"readwrite\");\r\n const store = tx.objectStore(this.storeName);\r\n const req = store.put(encryptedRecord, key);\r\n\r\n req.onsuccess = () => resolve(true);\r\n req.onerror = () => reject(req.error);\r\n });\r\n }\r\n\r\n /**\r\n * Retrieves and decrypts a value by key. Returns `null` if not found.\r\n */\r\n public async getItem<T>(key: IDBValidKey): Promise<T | null> {\r\n if (!this.db) throw new Error(\"Database not initialized.\");\r\n\r\n return new Promise((resolve, reject) => {\r\n const tx = this.db!.transaction(this.storeName, \"readonly\");\r\n const store = tx.objectStore(this.storeName);\r\n const req = store.get(key);\r\n\r\n req.onsuccess = async () => {\r\n if (!req.result) return resolve(null);\r\n try {\r\n const decrypted = await this._decrypt<T>(req.result as EncryptedPayload);\r\n resolve(decrypted);\r\n } catch {\r\n reject(new Error(\"Decryption failed. Invalid passphrase or corrupted data.\"));\r\n }\r\n };\r\n\r\n req.onerror = () => reject(req.error);\r\n });\r\n }\r\n\r\n /**\r\n * Deletes an item by key.\r\n */\r\n public async removeItem(key: IDBValidKey): Promise<boolean> {\r\n if (!this.db) throw new Error(\"Database not initialized.\");\r\n\r\n return new Promise((resolve, reject) => {\r\n const tx = this.db!.transaction(this.storeName, \"readwrite\");\r\n const store = tx.objectStore(this.storeName);\r\n const req = store.delete(key);\r\n\r\n req.onsuccess = () => resolve(true);\r\n req.onerror = () => reject(req.error);\r\n });\r\n }\r\n\r\n /**\r\n * Clear all encrypted entries in the current object store.\r\n */\r\n public async clear(): Promise<boolean> {\r\n if (!this.db) throw new Error(\"Database not initialized.\");\r\n\r\n return new Promise((resolve, reject) => {\r\n const tx = this.db!.transaction(this.storeName, \"readwrite\");\r\n const store = tx.objectStore(this.storeName);\r\n const req = store.clear();\r\n\r\n req.onsuccess = () => resolve(true);\r\n req.onerror = () => reject(req.error);\r\n });\r\n }\r\n\r\n /**\r\n * Get all key-value entries from the store.\r\n */\r\n public async getAll<T>(): Promise<StoredEntry<T>[]> {\r\n if (!this.db) throw new Error(\"Database not initialized.\");\r\n\r\n return new Promise((resolve, reject) => {\r\n const tx = this.db!.transaction(this.storeName, \"readonly\");\r\n const store = tx.objectStore(this.storeName);\r\n const req = store.openCursor();\r\n const results: StoredEntry<T>[] = [];\r\n\r\n req.onsuccess = async (event: Event) => {\r\n const cursor = (event.target as IDBRequest<IDBCursorWithValue | null>).result;\r\n if (cursor) {\r\n try {\r\n const decryptedValue = await this._decrypt<T>(cursor.value as EncryptedPayload);\r\n results.push({ key: cursor.key, value: decryptedValue });\r\n cursor.continue();\r\n } catch (err) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n reject(new Error(`Failed to decrypt record under key '${String(cursor.key)}': ${msg}`));\r\n }\r\n } else {\r\n resolve(results);\r\n }\r\n };\r\n\r\n req.onerror = () => reject(req.error);\r\n });\r\n }\r\n\r\n /**\r\n * Close the connection. Please use it.\r\n */\r\n public close(): void {\r\n if (this.db) {\r\n this.db.close();\r\n this.db = null;\r\n this.cryptoKey = null;\r\n }\r\n }\r\n}"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?module.exports=t():typeof define==`function`&&define.amd?define([],t):(e=typeof globalThis<`u`?globalThis:e||self,e.LittleIndexedDB=t())})(this,function(){function e(t){"@babel/helpers - typeof";return e=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},e(t)}function t(t,n){if(e(t)!=`object`||!t)return t;var r=t[Symbol.toPrimitive];if(r!==void 0){var i=r.call(t,n||`default`);if(e(i)!=`object`)return i;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(n===`string`?String:Number)(t)}function n(n){var r=t(n,`string`);return e(r)==`symbol`?r:r+``}function r(e,t,r){return(t=n(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}return class{constructor(e,t,n=1){r(this,`dbName`,void 0),r(this,`storeName`,void 0),r(this,`version`,void 0),r(this,`db`,null),r(this,`cryptoKey`,null),this.dbName=e,this.storeName=t,this.version=n}async _deriveKey(e,t){let n=new TextEncoder,r=await crypto.subtle.importKey(`raw`,n.encode(e),{name:`PBKDF2`},!1,[`deriveKey`]);return crypto.subtle.deriveKey({name:`PBKDF2`,salt:t,iterations:1e5,hash:`SHA-256`},r,{name:`AES-GCM`,length:256},!1,[`encrypt`,`decrypt`])}async _encrypt(e){if(!this.cryptoKey)throw Error(`Key not initialized. Call init() first.`);let t=crypto.getRandomValues(new Uint8Array(12)),n=new TextEncoder().encode(JSON.stringify(e)),r=await crypto.subtle.encrypt({name:`AES-GCM`,iv:t},this.cryptoKey,n);return{iv:t,ciphertext:new Uint8Array(r)}}async _decrypt(e){if(!this.cryptoKey)throw Error(`Key not initialized. Call init() first.`);let t=await crypto.subtle.decrypt({name:`AES-GCM`,iv:e.iv},this.cryptoKey,e.ciphertext),n=new TextDecoder().decode(t);return JSON.parse(n)}async _getOrCreateSalt(){if(!this.db)throw Error(`Database not connected.`);return new Promise((e,t)=>{let n=this.db.transaction(`__meta__`,`readwrite`).objectStore(`__meta__`),r=n.get(`db_salt`);r.onsuccess=()=>{let t=r.result;if(t?.value)e(new Uint8Array(t.value));else{let t=crypto.getRandomValues(new Uint8Array(16));n.put({id:`db_salt`,value:t}),e(t)}},r.onerror=()=>t(r.error)})}async init(e){return new Promise((t,n)=>{let r=indexedDB.open(this.dbName,this.version);r.onupgradeneeded=e=>{let t=e.target.result;t.objectStoreNames.contains(`__meta__`)||t.createObjectStore(`__meta__`,{keyPath:`id`}),t.objectStoreNames.contains(this.storeName)||t.createObjectStore(this.storeName)},r.onsuccess=async r=>{this.db=r.target.result;try{let n=await this._getOrCreateSalt();this.cryptoKey=await this._deriveKey(e,n),t(this)}catch(e){n(e)}},r.onerror=e=>{n(e.target.error)}})}async setItem(e,t){if(!this.db)throw Error(`Database not initialized.`);let n=await this._encrypt(t);return new Promise((t,r)=>{let i=this.db.transaction(this.storeName,`readwrite`).objectStore(this.storeName).put(n,e);i.onsuccess=()=>t(!0),i.onerror=()=>r(i.error)})}async getItem(e){if(!this.db)throw Error(`Database not initialized.`);return new Promise((t,n)=>{let r=this.db.transaction(this.storeName,`readonly`).objectStore(this.storeName).get(e);r.onsuccess=async()=>{if(!r.result)return t(null);try{t(await this._decrypt(r.result))}catch{n(Error(`Decryption failed. Invalid passphrase or corrupted data.`))}},r.onerror=()=>n(r.error)})}async removeItem(e){if(!this.db)throw Error(`Database not initialized.`);return new Promise((t,n)=>{let r=this.db.transaction(this.storeName,`readwrite`).objectStore(this.storeName).delete(e);r.onsuccess=()=>t(!0),r.onerror=()=>n(r.error)})}async clear(){if(!this.db)throw Error(`Database not initialized.`);return new Promise((e,t)=>{let n=this.db.transaction(this.storeName,`readwrite`).objectStore(this.storeName).clear();n.onsuccess=()=>e(!0),n.onerror=()=>t(n.error)})}async getAll(){if(!this.db)throw Error(`Database not initialized.`);return new Promise((e,t)=>{let n=this.db.transaction(this.storeName,`readonly`).objectStore(this.storeName).openCursor(),r=[];n.onsuccess=async n=>{let i=n.target.result;if(i)try{let e=await this._decrypt(i.value);r.push({key:i.key,value:e}),i.continue()}catch(e){let n=e instanceof Error?e.message:String(e);t(Error(`Failed to decrypt record under key '${String(i.key)}': ${n}`))}else e(r)},n.onerror=()=>t(n.error)})}close(){this.db&&(this.db.close(),this.db=null,this.cryptoKey=null)}}});
2
+ //# sourceMappingURL=little-indexeddb.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"little-indexeddb.umd.js","names":["factory","global","_typeof","o","toPrimitive","e","r","toPropertyKey","i","t","_defineProperty","dbName","storeName","version","enc","keyMaterial","passphrase","iv","encodedData","data","ciphertextBuffer","decryptedBuffer","encryptedRecord","jsonString","store","req","record","resolve","newSalt","reject","request","db","event","salt","err","value","key","results","cursor","decryptedValue","msg"],"sources":["../src/index.ts"],"sourcesContent":["export interface EncryptedPayload {\r\n iv: Uint8Array;\r\n ciphertext: Uint8Array;\r\n}\r\n\r\nexport interface StoredEntry<T = unknown> {\r\n key: IDBValidKey;\r\n value: T;\r\n}\r\n\r\ninterface MetaRecord {\r\n id: string;\r\n value: Uint8Array;\r\n}\r\n\r\n/**\r\n * Basically IndexedDB with built-in AES-GCM encryption.\r\n */\r\nexport default class LittleIndexedDB {\r\n private db: IDBDatabase | null = null;\r\n private cryptoKey: CryptoKey | null = null;\r\n\r\n /**\r\n * @param dbName Database name.\r\n * @param storeName Primary object store name.\r\n * @param version Database schema version. Defaults to 1.\r\n */\r\n constructor(\r\n public readonly dbName: string,\r\n public readonly storeName: string,\r\n public readonly version: number = 1\r\n ) {}\r\n\r\n /**\r\n * Derives an AES-GCM-256 key from a passphrase and a salt using PBKDF2.\r\n */\r\n private async _deriveKey(passphrase: string, salt: Uint8Array): Promise<CryptoKey> {\r\n const enc = new TextEncoder();\r\n const keyMaterial = await crypto.subtle.importKey(\r\n \"raw\",\r\n enc.encode(passphrase),\r\n { name: \"PBKDF2\" },\r\n false,\r\n [\"deriveKey\"]\r\n );\r\n\r\n return crypto.subtle.deriveKey(\r\n {\r\n name: \"PBKDF2\",\r\n salt: salt as BufferSource,\r\n iterations: 100_000,\r\n hash: \"SHA-256\",\r\n },\r\n keyMaterial,\r\n { name: \"AES-GCM\", length: 256 },\r\n false,\r\n [\"encrypt\", \"decrypt\"]\r\n );\r\n }\r\n\r\n /**\r\n * Encrypts any JSON serializable val ue.\r\n */\r\n private async _encrypt<T>(data: T): Promise<EncryptedPayload> {\r\n if (!this.cryptoKey) throw new Error(\"Key not initialized. Call init() first.\");\r\n\r\n const iv = crypto.getRandomValues(new Uint8Array(12));\r\n const encodedData = new TextEncoder().encode(JSON.stringify(data));\r\n\r\n const ciphertextBuffer = await crypto.subtle.encrypt(\r\n { name: \"AES-GCM\", iv },\r\n this.cryptoKey,\r\n encodedData\r\n );\r\n\r\n return {\r\n iv,\r\n ciphertext: new Uint8Array(ciphertextBuffer),\r\n };\r\n }\r\n\r\n /**\r\n * Decrypts an encrypted payload back into its original parsed data structure.\r\n */\r\n private async _decrypt<T>(encryptedRecord: EncryptedPayload): Promise<T> {\r\n if (!this.cryptoKey) throw new Error(\"Key not initialized. Call init() first.\");\r\n\r\n const decryptedBuffer = await crypto.subtle.decrypt(\r\n { name: \"AES-GCM\", iv: encryptedRecord.iv as BufferSource },\r\n this.cryptoKey,\r\n encryptedRecord.ciphertext as BufferSource\r\n );\r\n\r\n const jsonString = new TextDecoder().decode(decryptedBuffer);\r\n return JSON.parse(jsonString) as T;\r\n }\r\n\r\n /**\r\n * Reads or creates the database PBKDF2 salt in the `__meta__` store.\r\n */\r\n private async _getOrCreateSalt(): Promise<Uint8Array> {\r\n if (!this.db) throw new Error(\"Database not connected.\");\r\n\r\n return new Promise((resolve, reject) => {\r\n const tx = this.db!.transaction(\"__meta__\", \"readwrite\");\r\n const store = tx.objectStore(\"__meta__\");\r\n const req = store.get(\"db_salt\");\r\n\r\n req.onsuccess = () => {\r\n const record = req.result as MetaRecord | undefined;\r\n if (record?.value) {\r\n resolve(new Uint8Array(record.value));\r\n } else {\r\n const newSalt = crypto.getRandomValues(new Uint8Array(16));\r\n store.put({ id: \"db_salt\", value: newSalt });\r\n resolve(newSalt);\r\n }\r\n };\r\n\r\n req.onerror = () => reject(req.error);\r\n });\r\n }\r\n\r\n /**\r\n * Initializes the IndexedDB instance.\r\n * @param passphrase Passphrase used to derive encryption keys.\r\n */\r\n public async init(passphrase: string): Promise<this> {\r\n return new Promise((resolve, reject) => {\r\n const request = indexedDB.open(this.dbName, this.version);\r\n\r\n request.onupgradeneeded = (event: IDBVersionChangeEvent) => {\r\n const db = (event.target as IDBOpenDBRequest).result;\r\n if (!db.objectStoreNames.contains(\"__meta__\")) {\r\n db.createObjectStore(\"__meta__\", { keyPath: \"id\" });\r\n }\r\n if (!db.objectStoreNames.contains(this.storeName)) {\r\n db.createObjectStore(this.storeName);\r\n }\r\n };\r\n\r\n request.onsuccess = async (event: Event) => {\r\n this.db = (event.target as IDBOpenDBRequest).result;\r\n try {\r\n const salt = await this._getOrCreateSalt();\r\n this.cryptoKey = await this._deriveKey(passphrase, salt);\r\n resolve(this);\r\n } catch (err) {\r\n reject(err);\r\n }\r\n };\r\n\r\n request.onerror = (event: Event) => {\r\n reject((event.target as IDBOpenDBRequest).error);\r\n };\r\n });\r\n }\r\n\r\n /**\r\n * Encrypts and persists a value by key.\r\n */\r\n public async setItem<T>(key: IDBValidKey, value: T): Promise<boolean> {\r\n if (!this.db) throw new Error(\"Database not initialized.\");\r\n const encryptedRecord = await this._encrypt(value);\r\n\r\n return new Promise((resolve, reject) => {\r\n const tx = this.db!.transaction(this.storeName, \"readwrite\");\r\n const store = tx.objectStore(this.storeName);\r\n const req = store.put(encryptedRecord, key);\r\n\r\n req.onsuccess = () => resolve(true);\r\n req.onerror = () => reject(req.error);\r\n });\r\n }\r\n\r\n /**\r\n * Retrieves and decrypts a value by key. Returns `null` if not found.\r\n */\r\n public async getItem<T>(key: IDBValidKey): Promise<T | null> {\r\n if (!this.db) throw new Error(\"Database not initialized.\");\r\n\r\n return new Promise((resolve, reject) => {\r\n const tx = this.db!.transaction(this.storeName, \"readonly\");\r\n const store = tx.objectStore(this.storeName);\r\n const req = store.get(key);\r\n\r\n req.onsuccess = async () => {\r\n if (!req.result) return resolve(null);\r\n try {\r\n const decrypted = await this._decrypt<T>(req.result as EncryptedPayload);\r\n resolve(decrypted);\r\n } catch {\r\n reject(new Error(\"Decryption failed. Invalid passphrase or corrupted data.\"));\r\n }\r\n };\r\n\r\n req.onerror = () => reject(req.error);\r\n });\r\n }\r\n\r\n /**\r\n * Deletes an item by key.\r\n */\r\n public async removeItem(key: IDBValidKey): Promise<boolean> {\r\n if (!this.db) throw new Error(\"Database not initialized.\");\r\n\r\n return new Promise((resolve, reject) => {\r\n const tx = this.db!.transaction(this.storeName, \"readwrite\");\r\n const store = tx.objectStore(this.storeName);\r\n const req = store.delete(key);\r\n\r\n req.onsuccess = () => resolve(true);\r\n req.onerror = () => reject(req.error);\r\n });\r\n }\r\n\r\n /**\r\n * Clear all encrypted entries in the current object store.\r\n */\r\n public async clear(): Promise<boolean> {\r\n if (!this.db) throw new Error(\"Database not initialized.\");\r\n\r\n return new Promise((resolve, reject) => {\r\n const tx = this.db!.transaction(this.storeName, \"readwrite\");\r\n const store = tx.objectStore(this.storeName);\r\n const req = store.clear();\r\n\r\n req.onsuccess = () => resolve(true);\r\n req.onerror = () => reject(req.error);\r\n });\r\n }\r\n\r\n /**\r\n * Get all key-value entries from the store.\r\n */\r\n public async getAll<T>(): Promise<StoredEntry<T>[]> {\r\n if (!this.db) throw new Error(\"Database not initialized.\");\r\n\r\n return new Promise((resolve, reject) => {\r\n const tx = this.db!.transaction(this.storeName, \"readonly\");\r\n const store = tx.objectStore(this.storeName);\r\n const req = store.openCursor();\r\n const results: StoredEntry<T>[] = [];\r\n\r\n req.onsuccess = async (event: Event) => {\r\n const cursor = (event.target as IDBRequest<IDBCursorWithValue | null>).result;\r\n if (cursor) {\r\n try {\r\n const decryptedValue = await this._decrypt<T>(cursor.value as EncryptedPayload);\r\n results.push({ key: cursor.key, value: decryptedValue });\r\n cursor.continue();\r\n } catch (err) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n reject(new Error(`Failed to decrypt record under key '${String(cursor.key)}': ${msg}`));\r\n }\r\n } else {\r\n resolve(results);\r\n }\r\n };\r\n\r\n req.onerror = () => reject(req.error);\r\n });\r\n }\r\n\r\n /**\r\n * Close the connection. Please use it.\r\n */\r\n public close(): void {\r\n if (this.db) {\r\n this.db.close();\r\n this.db = null;\r\n this.cryptoKey = null;\r\n }\r\n }\r\n}"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,38 @@
1
1
  {
2
2
  "name": "litle-indexeddb",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "description": "IndexedDb with AES-GCM encryption",
4
+ "private": false,
5
+ "version": "1.0.1",
6
+ "type": "module",
7
+ "main": "./dist/little-indexeddb.umd.js",
8
+ "module": "./dist/little-indexeddb.umd.js",
9
+ "types": "./dist/index.d.ts",
10
+ "unpkg": "./dist/little-indexeddb.umd.js",
11
+ "jsdeliver": "./dist/little-indexeddb.umd.js",
12
+ "exports": {
13
+ ".": {
14
+ "import": "./dist/little-indexeddb.es.js",
15
+ "require": "./dist/little-indexeddb.umd.js",
16
+ "types": "./dist/index.d.ts"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "scripts": {
23
+ "dev": "vite",
24
+ "build": "tsc --noEmit && vite build",
25
+ "preview": "vite preview",
26
+ "prepublishOnly": "yarn build"
27
+ },
28
+ "devDependencies": {
29
+ "@microsoft/api-extractor": "^7.60.1",
30
+ "@typescript/typescript6": "^6.0.2",
31
+ "typescript": "~7.0.2",
32
+ "vite": "^8.3.5"
33
+ },
34
+ "dependencies": {
35
+ "@types/node": "^26.6.6",
36
+ "vite-plugin-dts": "^5.1.2"
37
+ }
38
+ }