tiny-idb 1.2.0 → 1.3.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 CHANGED
@@ -2,12 +2,23 @@
2
2
 
3
3
  **A minimalist, high-performance IndexedDB wrapper for modern web applications.**
4
4
 
5
- `tiny-idb` provides a non-blocking, asynchronous alternative to `localStorage`. It is designed for developers who require the durability and capacity of IndexedDB without the complexity of its native API. By focusing on a single-store, key-value architecture, it eliminates the need for database versioning and boilerplate configuration.
5
+ `tiny-idb` provides a non-blocking, asynchronous alternative to `localStorage`. While `localStorage` is capped at ~5-10MB and can be cleared by the browser under memory pressure, `tiny-idb` leverages IndexedDB to offer virtually unlimited storage (up to 80% of disk space) with much higher durability.
6
+
7
+ It is designed for developers who require the reliability and capacity of IndexedDB without the complexity of its native API. By focusing on a single-store, key-value architecture, it eliminates the need for database versioning and boilerplate configuration.
6
8
 
7
9
  [![NPM Version](https://img.shields.io/npm/v/tiny-idb.svg)](https://www.npmjs.com/package/tiny-idb)
8
10
  [![License](https://img.shields.io/npm/l/tiny-idb.svg)](LICENSE)
9
11
  [![Size](https://img.shields.io/bundlephobia/minzip/tiny-idb)](https://bundlephobia.com/package/tiny-idb)
10
12
 
13
+ ## Why tiny-idb?
14
+
15
+ There are many IndexedDB wrappers, but `tiny-idb` is built with a specific philosophy: **Smallest possible footprint without sacrificing data integrity.**
16
+
17
+ - **Smaller than most icons**: At less than 1KB (gzipped), it's lighter than a 16x16 PNG.
18
+ - **Atomic Operations**: Built-in `update`, `push`, and `merge` are ACID-compliant and race-condition safe. No more partial updates or data loss.
19
+ - **Zero dependencies**: Built on pure vanilla JS. No external bloat.
20
+ - **Drop-in localStorage replacement**: Use the same `getItem`, `setItem`, `removeItem` calls, but with `await`.
21
+
11
22
  ## Core Advantages
12
23
 
13
24
  ### Architectural Simplicity
@@ -44,13 +55,14 @@ npm install tiny-idb
44
55
 
45
56
  ## Technical Comparison
46
57
 
47
- | Feature | localStorage | tiny-idb |
58
+ | Feature | `localStorage` | `tiny-idb` |
48
59
  |---------|--------------|----------|
49
60
  | **Execution** | Synchronous (Blocks UI) | Asynchronous (Non-blocking) |
50
- | **Storage Limit** | ~5-10MB | Virtually unlimited (until disk is full) |
51
- | **Data Types** | Strings only | Objects, Blobs, Arrays, Numbers |
61
+ | **Storage Limit** | ~5-10MB (Fixed) | Virtually unlimited (80%+ of disk) |
62
+ | **Data Types** | Strings only (Requires `JSON.parse`) | Objects, Blobs, Arrays, Numbers, Files |
52
63
  | **Data Integrity** | Basic | ACID Compliant |
53
64
  | **Race Condition Safety** | None | Atomic `update`/`push`/`merge` |
65
+ | **Tab Sync** | No | Automatic |
54
66
 
55
67
  ## API Reference
56
68
 
@@ -63,13 +75,24 @@ npm install tiny-idb
63
75
  | `clear()` | Removes all data from the store. |
64
76
  | `keys()` | Returns an array of all keys. |
65
77
  | `values()` | Returns an array of all values. |
78
+ | `entries()` | Returns an array of `[key, value]` pairs. |
66
79
  | `count()` | Returns the total number of entries. |
67
- | `update(key, fn)` | Performs an atomic read-modify-write operation. |
68
- | `push(key, value)` | Atomically appends a value to an array. |
69
- | `merge(key, patch)` | Atomically shallow-merges an object. |
80
+ | `update(key, fn)` | Performs an **atomic** read-modify-write. |
81
+ | `push(key, value)` | **Atomically** appends to an array. |
82
+ | `merge(key, patch)` | **Atomically** shallow-merges an object. |
70
83
 
71
84
  ## Example Use Cases
72
85
 
86
+ ### Iterating over Data
87
+ Use `entries()` to easily process all stored key-value pairs.
88
+ ```javascript
89
+ const allEntries = await tinyIDB.entries();
90
+
91
+ for (const [key, value] of allEntries) {
92
+ console.log(`${key}:`, value);
93
+ }
94
+ ```
95
+
73
96
  ### User Settings Management
74
97
  Easily manage and update partial user preferences without worrying about race conditions.
75
98
  ```javascript
@@ -84,6 +107,19 @@ await tinyIDB.merge('settings', { notifications: false, language: 'en' });
84
107
  // Result: { theme: 'dark', notifications: false, language: 'en' }
85
108
  ```
86
109
 
110
+ ### Storing Binary Data (Blobs/Files)
111
+ Unlike `localStorage`, `tiny-idb` can store binary data directly.
112
+ ```javascript
113
+ const response = await fetch('/profile-picture.jpg');
114
+ const blob = await response.blob();
115
+
116
+ await tinyIDB.set('user_avatar', blob);
117
+
118
+ // Later...
119
+ const avatar = await tinyIDB.get('user_avatar');
120
+ document.querySelector('img').src = URL.createObjectURL(avatar);
121
+ ```
122
+
87
123
  ### Persistent Shopping Cart
88
124
  Atomically add items to a list, ensuring no items are lost during concurrent updates.
89
125
  ```javascript
@@ -100,7 +136,7 @@ Safely increment values using the `update` method.
100
136
  ```javascript
101
137
  await tinyIDB.set('page_views', 0);
102
138
 
103
- // Increment safely
139
+ // Increment safely - even if multiple tabs do it at once
104
140
  await tinyIDB.update('page_views', count => (count || 0) + 1);
105
141
  ```
106
142
 
@@ -134,6 +170,15 @@ await settings.set('theme', 'dark');
134
170
  await cache.set('temp_data', { id: 1 });
135
171
  ```
136
172
 
173
+ ## Browser Support
174
+
175
+ `tiny-idb` targets modern browsers that support:
176
+ - [IndexedDB](https://caniuse.com/indexeddb) (98%+)
177
+ - [ES Modules](https://caniuse.com/es6-module)
178
+ - [Async/Await](https://caniuse.com/async-functions)
179
+
180
+ If you need to support legacy browsers (IE11), you will need to transpile and polyfill.
181
+
137
182
  ## Development
138
183
 
139
184
  `tiny-idb` is written in pure vanilla JavaScript. No compilation is required for development.
@@ -148,10 +193,10 @@ npm test
148
193
  npm run test:min
149
194
  ```
150
195
 
151
- ### Minification
196
+ ### Building & Minification
152
197
  Generate the production-ready minified file:
153
198
  ```bash
154
- npm run minify
199
+ npm run build
155
200
  ```
156
201
 
157
202
  ## License
package/index.d.ts ADDED
@@ -0,0 +1,78 @@
1
+ /** tiny-idb - MIT © Jelodar */
2
+
3
+ export interface TinyIDBInstance {
4
+ /**
5
+ * Creates or retrieves a cached instance of a database and store.
6
+ * @param dbName Name of the IndexedDB database.
7
+ * @param storeName Name of the object store (defaults to dbName).
8
+ */
9
+ open(dbName: string, storeName?: string): TinyIDBInstance;
10
+
11
+ /**
12
+ * Persists a value to the store.
13
+ */
14
+ set(key: any, value: any): Promise<void>;
15
+ /** Alias for set() */
16
+ setItem(key: any, value: any): Promise<void>;
17
+
18
+ /**
19
+ * Retrieves a value; returns undefined if not found.
20
+ */
21
+ get<T = any>(key: any): Promise<T | undefined>;
22
+ /** Alias for get() */
23
+ getItem<T = any>(key: any): Promise<T | undefined>;
24
+
25
+ /**
26
+ * Deletes a specific key.
27
+ */
28
+ remove(key: any): Promise<void>;
29
+ /** Alias for remove() */
30
+ removeItem(key: any): Promise<void>;
31
+
32
+ /**
33
+ * Removes all data from the store.
34
+ */
35
+ clear(): Promise<void>;
36
+
37
+ /**
38
+ * Returns an array of all keys.
39
+ */
40
+ keys(): Promise<any[]>;
41
+
42
+ /**
43
+ * Returns an array of all values.
44
+ */
45
+ values<T = any>(): Promise<T[]>;
46
+
47
+ /**
48
+ * Returns an array of [key, value] pairs.
49
+ */
50
+ entries<K = any, V = any>(): Promise<[K, V][]>;
51
+
52
+ /**
53
+ * Returns the total number of entries.
54
+ */
55
+ count(): Promise<number>;
56
+
57
+ /**
58
+ * Performs an atomic read-modify-write operation within a single transaction.
59
+ * Note: The function 'fn' must be synchronous or microtask-only (no await on fetch/setTimeout)
60
+ * to prevent the IndexedDB transaction from auto-committing.
61
+ * @param key The key to update.
62
+ * @param fn A function that receives the current value and returns the new value.
63
+ */
64
+ update<T = any>(key: any, fn: (currentValue: T | undefined) => T | Promise<T>): Promise<void>;
65
+
66
+ /**
67
+ * Atomically appends a value to an array. Initializes as [value] if key doesn't exist.
68
+ */
69
+ push(key: any, value: any): Promise<void>;
70
+
71
+ /**
72
+ * Atomically shallow-merges an object. Initializes as patch if key doesn't exist.
73
+ */
74
+ merge(key: any, patch: object): Promise<void>;
75
+ }
76
+
77
+ export const tinyIDB: TinyIDBInstance;
78
+ export default tinyIDB;
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "tiny-idb",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "An extremely fast, super simple, and dependency-free IndexedDB wrapper. A drop-in replacement for localStorage with reliability and durability.",
5
5
  "main": "tiny-idb.js",
6
6
  "module": "tiny-idb.js",
7
+ "types": "index.d.ts",
7
8
  "type": "module",
8
9
  "repository": {
9
10
  "type": "git",
@@ -19,7 +20,8 @@
19
20
  "browser",
20
21
  "persistent",
21
22
  "nosql",
22
- "key-value"
23
+ "key-value",
24
+ "typescript"
23
25
  ],
24
26
  "author": "Jelodar",
25
27
  "license": "MIT",
@@ -30,6 +32,7 @@
30
32
  "files": [
31
33
  "tiny-idb.js",
32
34
  "tiny-idb.min.js",
35
+ "index.d.ts",
33
36
  "LICENSE",
34
37
  "README.md"
35
38
  ],
@@ -40,6 +43,7 @@
40
43
  "scripts": {
41
44
  "test": "node test.js",
42
45
  "test:min": "TEST_MIN=1 node test.js",
43
- "minify": "terser tiny-idb.js -o tiny-idb.min.js -c toplevel,unsafe -m toplevel --comments false"
46
+ "build": "npm run minify",
47
+ "minify": "terser tiny-idb.js -o tiny-idb.min.js -c toplevel,unsafe -m toplevel --comments '/tiny-idb/'"
44
48
  }
45
49
  }
package/tiny-idb.js CHANGED
@@ -1,10 +1,4 @@
1
- /**
2
- * tiny-idb - A super simple, fast, and dependency-free IndexedDB wrapper.
3
- * Designed as a drop-in replacement for localStorage with durability and performance.
4
- *
5
- * @author Jelodar
6
- * @license MIT
7
- */
1
+ /** tiny-idb - MIT © Jelodar */
8
2
 
9
3
  const instances = new Map();
10
4
  const prom = (req) => new Promise((res, rej) => {
@@ -43,23 +37,24 @@ const getAPI = (dbName = 'tiny-idb', storeName = undefined) => {
43
37
  });
44
38
  };
45
39
 
46
- const update = async (key, fn) => tx(RW, async s => {
47
- const n = await fn(await prom(s.get(key)));
48
- return prom(s.put(n, key));
49
- });
40
+ const update = (key, fn) => tx(RW, async s => prom(s.put(await fn(await prom(s.get(key))), key)));
50
41
 
51
42
  const api = {
52
43
  open: getAPI,
53
44
  set: (key, value) => tx(RW, s => prom(s.put(value, key))),
54
45
  get: key => tx(RO, s => prom(s.get(key))),
55
- remove: k => tx(RW, s => prom(s.delete(k))),
46
+ remove: key => tx(RW, s => prom(s.delete(key))),
56
47
  clear: () => tx(RW, s => prom(s.clear())),
57
48
  keys: () => tx(RO, s => prom(s.getAllKeys())),
58
49
  values: () => tx(RO, s => prom(s.getAll())),
50
+ entries: () => tx(RO, async s => {
51
+ const [k, v] = await Promise.all([prom(s.getAllKeys()), prom(s.getAll())]);
52
+ return k.map((key, i) => [key, v[i]]);
53
+ }),
59
54
  count: () => tx(RO, s => prom(s.count())),
60
55
  update,
61
- push: (key, value) => update(key, c => [...(Array.isArray(c) ? c : []), value]),
62
- merge: (key, patch) => update(key, c => ({ ...(c && typeof c === 'object' ? c : {}), ...patch }))
56
+ push: (key, val) => update(key, (c = []) => [...(Array.isArray(c) ? c : []), val]),
57
+ merge: (key, obj) => update(key, (c = {}) => ({ ...(c && typeof c === 'object' ? c : {}), ...obj }))
63
58
  };
64
59
 
65
60
  ['get', 'set', 'remove'].forEach(m => api[m + 'Item'] = api[m]);
package/tiny-idb.min.js CHANGED
@@ -1 +1,2 @@
1
- const e=new Map,t=e=>new Promise((t,r)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>r(e.error)}),r="readonly",o="readwrite",n=(s="tiny-idb",c=void 0)=>{const a=s+"\0"+(c=c||s);if(e.has(a))return e.get(a);let l;const u=async(e,t)=>{const r=await(l||(l=new Promise((e,t)=>{const r=indexedDB.open(s,1);r.onupgradeneeded=()=>r.result.createObjectStore(c),r.onsuccess=()=>{const t=r.result;t.onversionchange=()=>{t.close(),l=null},e(t)},r.onerror=()=>{l=null,t(r.error)}})));return new Promise(async(o,n)=>{const s=r.transaction(c,e);s.onabort=s.onerror=()=>n(s.error||new DOMException("Aborted"));try{const e=await t(s.objectStore(c));s.oncomplete=()=>o(e)}catch(e){try{s.abort()}catch{}n(e)}})},i=async(e,r)=>u(o,async o=>{const n=await r(await t(o.get(e)));return t(o.put(n,e))}),y={open:n,set:(e,r)=>u(o,o=>t(o.put(r,e))),get:e=>u(r,r=>t(r.get(e))),remove:e=>u(o,r=>t(r.delete(e))),clear:()=>u(o,e=>t(e.clear())),keys:()=>u(r,e=>t(e.getAllKeys())),values:()=>u(r,e=>t(e.getAll())),count:()=>u(r,e=>t(e.count())),update:i,push:(e,t)=>i(e,e=>[...Array.isArray(e)?e:[],t]),merge:(e,t)=>i(e,e=>({...e&&"object"==typeof e?e:{},...t}))};return["get","set","remove"].forEach(e=>y[e+"Item"]=y[e]),e.set(a,y),y};export const tinyIDB=n();export default tinyIDB;
1
+ /** tiny-idb - MIT © Jelodar */
2
+ const e=new Map,t=e=>new Promise((t,r)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>r(e.error)}),r="readonly",o="readwrite",n=(s="tiny-idb",a=void 0)=>{const c=s+"\0"+(a=a||s);if(e.has(c))return e.get(c);let l;const i=async(e,t)=>{const r=await(l||(l=new Promise((e,t)=>{const r=indexedDB.open(s,1);r.onupgradeneeded=()=>r.result.createObjectStore(a),r.onsuccess=()=>{const t=r.result;t.onversionchange=()=>{t.close(),l=null},e(t)},r.onerror=()=>{l=null,t(r.error)}})));return new Promise(async(o,n)=>{const s=r.transaction(a,e);s.onabort=s.onerror=()=>n(s.error||new DOMException("Aborted"));try{const e=await t(s.objectStore(a));s.oncomplete=()=>o(e)}catch(e){try{s.abort()}catch{}n(e)}})},u=(e,r)=>i(o,async o=>t(o.put(await r(await t(o.get(e))),e))),y={open:n,set:(e,r)=>i(o,o=>t(o.put(r,e))),get:e=>i(r,r=>t(r.get(e))),remove:e=>i(o,r=>t(r.delete(e))),clear:()=>i(o,e=>t(e.clear())),keys:()=>i(r,e=>t(e.getAllKeys())),values:()=>i(r,e=>t(e.getAll())),entries:()=>i(r,async e=>{const[r,o]=await Promise.all([t(e.getAllKeys()),t(e.getAll())]);return r.map((e,t)=>[e,o[t]])}),count:()=>i(r,e=>t(e.count())),update:u,push:(e,t)=>u(e,(e=[])=>[...Array.isArray(e)?e:[],t]),merge:(e,t)=>u(e,(e={})=>({...e&&"object"==typeof e?e:{},...t}))};return["get","set","remove"].forEach(e=>y[e+"Item"]=y[e]),e.set(c,y),y};export const tinyIDB=n();export default tinyIDB;