idb-repo 1.0.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 ADDED
@@ -0,0 +1,270 @@
1
+ # idb-repo
2
+
3
+ Edge KV Storage.
4
+
5
+ ## Overview
6
+
7
+ This SDK provides a small, dependency-free abstraction over IndexedDB for building fast, reliable key-value stores in browser and edge-like environments. It focuses on predictable behavior, minimal surface area, and performance characteristics suitable for long-lived client applications.
8
+
9
+ The goal is not to hide IndexedDB, but to make it practical: sane defaults, explicit structure, and a repository pattern that enforces consistency without adding unnecessary complexity.
10
+
11
+ ## Design Principles
12
+ SOLID PRINCIPLES w/
13
+ - **Zero dependencies** — no runtime bloat, no transitive risk
14
+
15
+
16
+ ## What This Is
17
+ - A thin repository abstraction over IndexedDB
18
+ - A predictable KV interface with typed boundaries
19
+ - A foundation for local-first and offline-capable systems
20
+
21
+ ## What This Is Not
22
+
23
+ - An ORM
24
+ - A sync engine
25
+ - A framework replacement
26
+ - A polyfill for non-browser runtimes
27
+
28
+ ## Use Cases
29
+
30
+ - Edge-adjacent web apps (Workers + WebViews)
31
+ - Local-first applications
32
+ - Durable client caches
33
+ - Structured persistence for complex frontends
34
+ - Performance-sensitive UI state storage
35
+
36
+ ## Installation
37
+
38
+ ```bash
39
+ npm install idb-repo
40
+ ```
41
+
42
+ ## Usage
43
+
44
+ ### Basic Setup
45
+
46
+ ```typescript
47
+ import { createIndexedDbKV } from "idb-repo";
48
+
49
+ // Create a KV store instance
50
+ const kv = createIndexedDbKV({
51
+ dbName: "my-app", // IndexedDB database name (default: "kv")
52
+ storeName: "cache", // Object store name (default: "kv")
53
+ version: 1, // Schema version for migrations
54
+ cacheEntries: 2048 // In-memory LRU cache size (default: 2048)
55
+ });
56
+ ```
57
+
58
+ ### Core Operations
59
+
60
+ #### Put (Store Data)
61
+
62
+ ```typescript
63
+ // Store a string
64
+ await kv.put("key1", "value");
65
+
66
+ // Store JSON
67
+ await kv.put("user:123", { id: 123, name: "Alice" });
68
+
69
+ // Store with metadata and expiration
70
+ await kv.put("session:abc", { token: "xyz" }, {
71
+ metadata: { userId: "123" },
72
+ expirationTtl: 3600 // expires in 1 hour
73
+ });
74
+
75
+ // Store ArrayBuffer/binary data
76
+ const buffer = new TextEncoder().encode("binary data");
77
+ await kv.put("binary-key", buffer);
78
+
79
+ // Store File or Blob objects
80
+ const file = document.querySelector("input[type=file]")!.files![0];
81
+ await kv.put("files/myfile", file);
82
+ ```
83
+
84
+ #### Get (Retrieve Data)
85
+
86
+ ```typescript
87
+ // Get raw value (type determined by stored type)
88
+ const value = await kv.get("key1");
89
+
90
+ // Get with metadata
91
+ const { value, metadata } = await kv.getWithMetadata("session:abc");
92
+
93
+ // Helper functions for typed retrieval
94
+ const text = await kvGetText(kv, "key1");
95
+ const json = await kvGetJson(kv, "user:123");
96
+ const buffer = await kvGetArrayBuffer(kv, "binary-key");
97
+ const stream = await kvGetStream(kv, "large-file");
98
+
99
+ // Get with custom cache TTL (bypasses storage expiration)
100
+ const cached = await kvGetJson(kv, "user:123", 300); // 5 min cache
101
+ ```
102
+
103
+ #### Delete
104
+
105
+ ```typescript
106
+ // Delete a key
107
+ await kv.delete("key1");
108
+ ```
109
+
110
+ #### List (Enumerate Keys)
111
+
112
+ ```typescript
113
+ // List all keys
114
+ const result = await kv.list();
115
+ // { keys: ["key1", "user:123", ...], cursor: "..." }
116
+
117
+ // List with pagination
118
+ const page = await kv.list({
119
+ limit: 10,
120
+ cursor: "previous-cursor"
121
+ });
122
+
123
+ // List with key prefix filter
124
+ const userKeys = await kv.list({
125
+ prefix: "user:",
126
+ limit: 50
127
+ });
128
+ ```
129
+
130
+ #### Close
131
+
132
+ ```typescript
133
+ // Clean up resources
134
+ await kv.close();
135
+ ```
136
+
137
+ ### Advanced Usage
138
+
139
+ #### Metadata and Type Hints
140
+
141
+ ```typescript
142
+ // Store data with custom metadata
143
+ await kv.put("document:42", documentData, {
144
+ metadata: {
145
+ userId: "user:123",
146
+ createdAt: new Date().toISOString(),
147
+ contentType: "application/json"
148
+ },
149
+ expirationTtl: 86400 // 24 hours
150
+ });
151
+
152
+ // Retrieve and use metadata
153
+ const { value, metadata } = await kv.getWithMetadata("document:42");
154
+ if (metadata?.userId === "user:123") {
155
+ // Process owned document
156
+ }
157
+ ```
158
+
159
+ #### Performance Patterns
160
+
161
+ ```typescript
162
+ // Batch operations use getAll() internally for ~3-5x better throughput
163
+ const result = await kv.list({ limit: 1000 });
164
+
165
+ // In-memory LRU cache speeds up repeated reads
166
+ // First read: ~5-10ms (IndexedDB)
167
+ // Subsequent reads of same key: ~0.1ms (memory)
168
+ for (let i = 0; i < 100; i++) {
169
+ const user = await kvGetJson(kv, "user:123"); // Cache hit after first call
170
+ }
171
+
172
+ // Readonly transactions for lists are faster than readwrite
173
+ // Expired records are lazily deleted on read (not on list)
174
+ ```
175
+
176
+ #### Storing Files
177
+
178
+ ```typescript
179
+ // Store a File object (from file input)
180
+ const fileInput = document.querySelector("input[type=file]") as HTMLInputElement;
181
+ const file = fileInput.files![0];
182
+ await kv.put(`uploads/${file.name}`, file);
183
+
184
+ // Store a Blob
185
+ const blob = new Blob(["Hello, world!"], { type: "text/plain" });
186
+ await kv.put("greeting.txt", blob);
187
+
188
+ // Store binary ArrayBuffer
189
+ const uint8Array = new Uint8Array([1, 2, 3, 4, 5]);
190
+ await kv.put("binary-data", uint8Array);
191
+
192
+ // Store a ReadableStream (useful for large files or streaming uploads)
193
+ const stream = response.body; // from fetch()
194
+ await kv.put("large-file", stream);
195
+
196
+ // Retrieve files
197
+ const file = await kv.get("uploads/myfile.pdf") as ArrayBuffer;
198
+ const fileBlob = await kvGetArrayBuffer(kv, "uploads/myfile.pdf");
199
+
200
+ // Stream large files efficiently
201
+ const largeFile = await kvGetStream(kv, "large-file");
202
+ await largeFile.pipeTo(writableStream);
203
+
204
+ // List all stored files with metadata
205
+ const result = await kv.list({ prefix: "uploads/" });
206
+ for (const file of result.keys) {
207
+ console.log(`${file.name} - uploaded at ${file.metadata?.uploadedAt}`);
208
+ }
209
+ ```
210
+
211
+ #### Building Local-First Features
212
+
213
+ ```typescript
214
+ // Store user preferences
215
+ await kv.put("settings:display", {
216
+ theme: "dark",
217
+ fontSize: 14,
218
+ sidebarCollapsed: true
219
+ });
220
+
221
+ // Cache API responses
222
+ await kv.put("posts:feed", postsData, {
223
+ expirationTtl: 300, // 5 minute cache
224
+ metadata: { fetchedAt: Date.now() }
225
+ });
226
+
227
+ // Store offline queue
228
+ await kv.put(`pending:create:${uuid()}`, actionPayload, {
229
+ metadata: { type: "create", priority: 1 }
230
+ });
231
+
232
+ // Enumerate pending actions
233
+ const { keys } = await kv.list({ prefix: "pending:" });
234
+ for (const key of keys) {
235
+ const action = await kvGetJson(kv, key);
236
+ await syncAction(action);
237
+ }
238
+ ```
239
+
240
+ ## API Reference
241
+
242
+ ### `IndexedDbKV` Class
243
+
244
+ - **`constructor(opts?)`** — Create a new KV store instance
245
+ - `dbName` (string): IndexedDB database name
246
+ - `storeName` (string): Object store name
247
+ - `version` (number): Schema version
248
+ - `cacheEntries` (number): LRU cache size
249
+
250
+ - **`get(key, options?)`** → Promise — Retrieve a value
251
+ - **`getWithMetadata(key, options?)`** → Promise — Retrieve value and metadata
252
+ - **`put(key, value, options?)`** → Promise — Store a value
253
+ - **`delete(key)`** → Promise — Delete a key
254
+ - **`list(options?)`** → Promise — Enumerate keys with pagination
255
+ - **`close()`** → Promise — Close database connection
256
+
257
+ ### Helper Functions
258
+
259
+ - **`kvGetText(kv, key, cacheTtl?)`** — Get value as string
260
+ - **`kvGetJson(kv, key, cacheTtl?)`** — Get value as JSON
261
+ - **`kvGetArrayBuffer(kv, key, cacheTtl?)`** — Get value as ArrayBuffer
262
+ - **`kvGetStream(kv, key, cacheTtl?)`** — Get value as ReadableStream
263
+
264
+ ## Status
265
+
266
+ This project is intentionally small and opinionated. APIs are stable where exposed, but evolution is expected as real-world constraints surface.
267
+
268
+ ## License
269
+
270
+ MIT
@@ -0,0 +1,15 @@
1
+ /**
2
+ * IndexedDB KV Storage - A performant KV storage implementation using IndexedDB
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { createIndexedDbKV } from '@indexeddb-kv/storage';
7
+ *
8
+ * const kv = await createIndexedDbKV({ dbName: 'my-app' });
9
+ * await kv.put('key', 'value');
10
+ * const value = await kv.get('key');
11
+ * ```
12
+ */
13
+ export { IndexedDbKV, createIndexedDbKV, kvGetText, kvGetJson, kvGetArrayBuffer, kvGetStream, } from "./src/lib";
14
+ export type { KVGetOptions, KVPutOptions, KVListOptions, KVListKey, KVListResult, KVNamespace, } from "./src/types";
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACH,WAAW,EACX,iBAAiB,EACjB,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,WAAW,GACd,MAAM,WAAW,CAAC;AAGnB,YAAY,EACR,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,SAAS,EACT,YAAY,EACZ,WAAW,GACd,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ class S{cfg;dbPromise=null;constructor(G){this.cfg=G}get db(){if(!this.dbPromise)this.dbPromise=this.open();return this.dbPromise}async close(){if(!this.dbPromise)return;try{(await this.dbPromise).close()}finally{this.dbPromise=null}}open(){let{dbName:G,version:X,storeName:Q}=this.cfg;return new Promise((Z,Y)=>{let _=indexedDB.open(G,X);_.onupgradeneeded=()=>{let P=_.result;if(!P.objectStoreNames.contains(Q)){let $=P.createObjectStore(Q,{keyPath:"key"});$.createIndex("key","key",{unique:!0}),$.createIndex("expiresAt","expiresAt",{unique:!1})}else{let $=_.transaction.objectStore(Q);if(!$.indexNames.contains("expiresAt"))$.createIndex("expiresAt","expiresAt",{unique:!1});if(!$.indexNames.contains("key"))$.createIndex("key","key",{unique:!0})}},_.onsuccess=()=>{let P=_.result;P.onversionchange=()=>{try{P.close()}catch{}},Z(P)},_.onerror=()=>Y(_.error??new Error("Failed to open IndexedDB")),_.onblocked=()=>{Y(new Error("IndexedDB open blocked (another context has the DB open during upgrade)"))}})}}function K(G){return Math.floor(G/1000)}function R(G){return Math.floor(G*1000)}function J(){return Date.now()}class V{max;map=new Map;constructor(G){this.max=Math.max(0,G|0)}get(G){let X=this.map.get(G);if(!X)return null;if(X.expiresAt<=J())return this.map.delete(G),null;return{value:X.value,meta:X.meta}}set(G,X,Q,Z){if(this.max<=0)return;let Y=J()+Math.max(0,Z)*1000;this.map.set(G,{expiresAt:Y,value:X,meta:Q});while(this.map.size>this.max){let _=this.map.keys().next().value;if(_===void 0)break;this.map.delete(_)}}delete(G){this.map.delete(G)}clear(){this.map.clear()}}function q(G){let X=JSON.stringify(G);return btoa(unescape(encodeURIComponent(X))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function f(G){try{let X=G.replace(/-/g,"+").replace(/_/g,"/")+"===".slice((G.length+3)%4),Q=decodeURIComponent(escape(atob(X))),Z=JSON.parse(Q);if(!Z||Z.v!==1||typeof Z.prefix!=="string")return null;if(Z.after!==null&&typeof Z.after!=="string")return null;return Z}catch{return null}}function j(G){return!!G&&typeof G==="object"&&"buffer"in G&&G.buffer instanceof ArrayBuffer}function B(G){if(typeof G!=="string"||G.length===0)throw new TypeError("KV key must be a non-empty string")}function n(G){if(typeof G==="string")return{encoding:"text",stored:G};if(G instanceof Blob)return{encoding:"binary",stored:G};if(G instanceof ArrayBuffer)return{encoding:"binary",stored:new Blob([G])};if(j(G))return{encoding:"binary",stored:new Blob([G.buffer.slice(0)])};if(G instanceof ReadableStream)return null;return{encoding:"clone",stored:structuredClone(G)}}async function w(G){let X=n(G);if(X!==null)return X;return{encoding:"binary",stored:await c(G)}}async function c(G){let X=G.getReader(),Q=[];try{while(!0){let{value:Z,done:Y}=await X.read();if(Y)break;if(Z)Q.push(Z)}}finally{try{X.releaseLock()}catch{}}return new Blob(Q)}function m(G,X){let Q=X??"text";if(G.encoding==="text"){let Y=G.value;if(Q==="text")return Y;if(Q==="json")return JSON.parse(Y);if(Q==="arrayBuffer")return new TextEncoder().encode(Y).buffer;return new Blob([Y]).stream()}if(G.encoding==="json"){let Y=G.value;if(Q==="json")return JSON.parse(Y);if(Q==="text")return Y;if(Q==="arrayBuffer")return new TextEncoder().encode(Y).buffer;return new Blob([Y]).stream()}if(G.encoding==="clone"){let Y=G.value;if(Q==="json")return Y;let _=JSON.stringify(Y);if(_===void 0)throw new TypeError("Stored value cannot be represented as JSON text");if(Q==="text")return _;if(Q==="arrayBuffer")return new TextEncoder().encode(_).buffer;return new Blob([_]).stream()}let Z=G.value;if(Q==="stream")return Z.stream();if(Q==="arrayBuffer")return Z;if(Q==="json")return Z;return Z}async function T(G){return await G.text()}async function h(G){return await G.arrayBuffer()}async function x(G){let X=await G.text();return JSON.parse(X)}function N(G){return new Promise((X,Q)=>{G.onsuccess=()=>X(G.result),G.onerror=()=>Q(G.error??new Error("IndexedDB request failed"))})}function M(G){return new Promise((X,Q)=>{G.oncomplete=()=>X(),G.onabort=()=>Q(G.error??new Error("IndexedDB transaction aborted")),G.onerror=()=>Q(G.error??new Error("IndexedDB transaction failed"))})}function b(G){if(!G)return null;if(typeof G.expirationTtl==="number"){let X=Math.max(0,G.expirationTtl)*1000;return J()+X}if(typeof G.expiration==="number")return R(G.expiration);return null}function v(G){return G.expiresAt!==null&&G.expiresAt<=J()}class D{conn;storeName;cache;constructor(G){let X=G?.dbName??"kv";this.storeName=G?.storeName??"kv";let Q=G?.version??1;this.conn=new S({dbName:X,storeName:this.storeName,version:Q}),this.cache=new V(G?.cacheEntries??2048)}invalidateCache(G){this.cache.delete(`${G}::text`),this.cache.delete(`${G}::json`),this.cache.delete(`${G}::arrayBuffer`),this.cache.delete(`${G}::stream`)}async get(G,X){let{value:Q}=await this.getWithMetadata(G,X);return Q}async getWithMetadata(G,X){B(G);let Q=X?.type??"text",Z=X?.cacheTtl??0,Y=Z>0?`${G}::${Q}`:null;if(Y){let F=this.cache.get(Y);if(F)return{value:F.value,metadata:F.meta}}let $=(await this.conn.db).transaction(this.storeName,"readonly").objectStore(this.storeName),W=await N($.get(G));if(!W)return{value:null,metadata:null};if(v(W))return this.delete(G),{value:null,metadata:null};let H=m(W,Q);if(W.encoding==="binary"){let F=H;if(Q==="stream")H=F.stream()??null;else if(Q==="arrayBuffer")H=await h(F);else if(Q==="json")H=await x(F);else H=await T(F)}let O=W.metadata??null;if(Y)this.cache.set(Y,H,O,Z);return{value:H,metadata:O}}async put(G,X,Q){B(G);let{encoding:Z,stored:Y}=await w(X),_=b(Q),$=(await this.conn.db).transaction(this.storeName,"readwrite"),W=$.objectStore(this.storeName),H=J(),O={key:G,value:Y,encoding:Z,expiresAt:_,metadata:Q?.metadata??null,createdAt:H,updatedAt:H};W.put(O),this.invalidateCache(G),await M($)}async delete(G){B(G);let Q=(await this.conn.db).transaction(this.storeName,"readwrite");Q.objectStore(this.storeName).delete(G),this.invalidateCache(G),await M(Q)}async list(G){let X=G?.prefix??"",Q=Math.min(Math.max(1,G?.limit??1000),1e4),Z=G?.cursor??null,Y=null;if(Z){let L=f(Z);if(L&&L.prefix===X)Y=L.after}let $=(await this.conn.db).transaction(this.storeName,"readonly").objectStore(this.storeName),W=X,H=X+"￿",O=IDBKeyRange.bound(W,H,!1,!1),F=await N($.getAll(O)),U=[],g=!0,A=null,i=J(),C=Y!==null?F.findIndex((L)=>L.key>Y):0,E=C<0?F.length:C;for(let L=E;L<F.length&&U.length<Q;L++){let z=F[L];if(!z)continue;if(z.expiresAt&&z.expiresAt<=i)continue;let I={name:z.key};if(z.expiresAt)I.expiration=K(z.expiresAt);if(z.metadata)I.metadata=z.metadata;U.push(I),A=z.key}if(U.length>=Q&&E+U.length<F.length)g=!1;if(!g&&A!==null){let L=q({v:1,prefix:X,after:A});return{keys:U,list_complete:!1,cursor:L}}return{keys:U,list_complete:!0}}async close(){await this.conn.close(),this.cache.clear()}}function k(G){return new D(G)}async function u(G,X,Q){return await G.get(X,{type:"text",cacheTtl:Q})}async function p(G,X,Q){return await G.get(X,{type:"json",cacheTtl:Q})}async function y(G,X,Q){return await G.get(X,{type:"arrayBuffer",cacheTtl:Q})}async function d(G,X,Q){return await G.get(X,{type:"stream",cacheTtl:Q})}export{u as kvGetText,d as kvGetStream,p as kvGetJson,y as kvGetArrayBuffer,k as createIndexedDbKV,D as IndexedDbKV};
@@ -0,0 +1,36 @@
1
+ /**
2
+ * IndexedDB connection management
3
+ */
4
+ /**
5
+ * Configuration for opening an IndexedDB database
6
+ */
7
+ type OpenConfig = {
8
+ dbName: string;
9
+ storeName: string;
10
+ version: number;
11
+ };
12
+ /**
13
+ * Manages lifecycle of an IndexedDB connection
14
+ * - Lazy initialization (opens on first access)
15
+ * - Version change handling
16
+ * - Automatic schema creation/migration
17
+ */
18
+ export declare class IndexedDbConnection {
19
+ private cfg;
20
+ private dbPromise;
21
+ constructor(cfg: OpenConfig);
22
+ /**
23
+ * Get or open the database
24
+ */
25
+ get db(): Promise<IDBDatabase>;
26
+ /**
27
+ * Close the database connection
28
+ */
29
+ close(): Promise<void>;
30
+ /**
31
+ * Open the database with automatic schema creation/migration
32
+ */
33
+ private open;
34
+ }
35
+ export {};
36
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/connection.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;GAEG;AACH,KAAK,UAAU,GAAG;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;GAKG;AACH,qBAAa,mBAAmB;IAC5B,OAAO,CAAC,GAAG,CAAa;IACxB,OAAO,CAAC,SAAS,CAAqC;gBAE1C,GAAG,EAAE,UAAU;IAI3B;;OAEG;IACH,IAAI,EAAE,IAAI,OAAO,CAAC,WAAW,CAAC,CAG7B;IAED;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAU5B;;OAEG;IACH,OAAO,CAAC,IAAI;CA0Cf"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * TinyLRU: Small, best-effort, TTL-based in-memory cache for KV reads
3
+ * - Keeps decoded values per (key, type)
4
+ * - Eviction: simple Map insertion order (best-effort)
5
+ * - TTL: automatic expiration on access
6
+ */
7
+ /**
8
+ * Small, best-effort, TTL-based in-memory cache for reads
9
+ * Preserves "no recency refresh" optimization: doesn't refresh cache entry on hit
10
+ * to avoid 2 Map operations per cache hit. LRU eviction is best-effort anyway,
11
+ * and TTL makes staleness acceptable.
12
+ */
13
+ export declare class TinyLRU {
14
+ private max;
15
+ private map;
16
+ constructor(maxEntries: number);
17
+ /**
18
+ * Get a value from cache
19
+ * @returns Cached value and metadata, or null if not found or expired
20
+ */
21
+ get(k: string): {
22
+ value: any;
23
+ meta: any;
24
+ } | null;
25
+ /**
26
+ * Set a value in cache with TTL
27
+ */
28
+ set(k: string, value: any, meta: any, ttlSeconds: number): void;
29
+ /**
30
+ * Delete a specific key from cache
31
+ */
32
+ delete(k: string): void;
33
+ /**
34
+ * Clear all entries from cache
35
+ */
36
+ clear(): void;
37
+ }
38
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/internal/cache.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;GAKG;AACH,qBAAa,OAAO;IAChB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,GAAG,CAAmE;gBAElE,UAAU,EAAE,MAAM;IAI9B;;;OAGG;IACH,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,GAAG,CAAC;QAAC,IAAI,EAAE,GAAG,CAAA;KAAE,GAAG,IAAI;IAYhD;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAY/D;;OAEG;IACH,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAIvB;;OAEG;IACH,KAAK,IAAI,IAAI;CAGhB"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Cursor encoding/decoding for list pagination
3
+ */
4
+ /**
5
+ * Internal structure for list pagination cursor
6
+ */
7
+ export type InternalListCursor = {
8
+ v: 1;
9
+ prefix: string;
10
+ after: string | null;
11
+ };
12
+ /**
13
+ * Encode a cursor to a base64url string
14
+ */
15
+ export declare function encodeCursor(c: InternalListCursor): string;
16
+ /**
17
+ * Decode a cursor from a base64url string
18
+ * @returns Decoded cursor or null if invalid
19
+ */
20
+ export declare function decodeCursor(cursor: string): InternalListCursor | null;
21
+ //# sourceMappingURL=cursor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../../src/internal/cursor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC7B,CAAC,EAAE,CAAC,CAAC;IACL,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB,CAAC;AAEF;;GAEG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,kBAAkB,GAAG,MAAM,CAK1D;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAWtE"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * IndexedDB promise wrappers and utilities
3
+ */
4
+ /**
5
+ * Convert an IDBRequest to a Promise
6
+ */
7
+ export declare function promisifyRequest<T>(req: IDBRequest<T>): Promise<T>;
8
+ /**
9
+ * Wait for an IDBTransaction to complete
10
+ */
11
+ export declare function waitTx(tx: IDBTransaction): Promise<void>;
12
+ //# sourceMappingURL=idb-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idb-utils.d.ts","sourceRoot":"","sources":["../../../src/internal/idb-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAKlE;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAMxD"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * TTL utilities for KV storage
3
+ */
4
+ import type { KVPutOptions, StoredRecord } from "../types";
5
+ /**
6
+ * Compute expiration timestamp in milliseconds from KV put options
7
+ * @returns Expiration time in ms since epoch, or null if no expiration set
8
+ */
9
+ export declare function computeExpiresAtMs(options?: KVPutOptions): number | null;
10
+ /**
11
+ * Check if a stored record has expired
12
+ */
13
+ export declare function isExpired(rec: StoredRecord): boolean;
14
+ //# sourceMappingURL=ttl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ttl.d.ts","sourceRoot":"","sources":["../../../src/internal/ttl.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG3D;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CAUxE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAEpD"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Type guards and validation utilities for KV storage
3
+ */
4
+ /**
5
+ * Type guard to check if a value is an ArrayBufferView (TypedArray, DataView, etc.)
6
+ */
7
+ export declare function isArrayBufferView(v: unknown): v is ArrayBufferView;
8
+ /**
9
+ * Validate and assert that a key is a non-empty string
10
+ * @throws {TypeError} if key is invalid
11
+ */
12
+ export declare function assertKey(key: string): void;
13
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/internal/validation.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,eAAe,CAElE;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAI3C"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Value encoding/decoding for KV storage
3
+ * Handles multiple formats: text, json, structured clone, and binary
4
+ */
5
+ import type { KVGetType, KVValue, StoredEncoding, StoredRecord } from "../types";
6
+ /**
7
+ * Sync path for encoding values - optimized for common cases like strings
8
+ * @returns Encoded value or null if async handling required (ReadableStream)
9
+ */
10
+ export declare function normalizePutValueSync(value: KVValue): {
11
+ encoding: StoredEncoding;
12
+ stored: unknown;
13
+ } | null;
14
+ /**
15
+ * Async wrapper for encoding values
16
+ * Handles all value types including ReadableStream
17
+ */
18
+ export declare function normalizePutValue(value: KVValue): Promise<{
19
+ encoding: StoredEncoding;
20
+ stored: unknown;
21
+ }>;
22
+ /**
23
+ * Decode a stored record to the requested type
24
+ * Returns decoded value or Blob sentinel for binary data requiring async conversion
25
+ */
26
+ export declare function decodeValue(rec: StoredRecord, type: KVGetType | undefined): string | ArrayBuffer | ReadableStream<Uint8Array> | unknown;
27
+ /**
28
+ * Convert Blob to text
29
+ */
30
+ export declare function blobToText(blob: Blob): Promise<string>;
31
+ /**
32
+ * Convert Blob to ArrayBuffer
33
+ */
34
+ export declare function blobToArrayBuffer(blob: Blob): Promise<ArrayBuffer>;
35
+ /**
36
+ * Convert Blob to JSON (parse as UTF-8 text then JSON)
37
+ */
38
+ export declare function blobToJson(blob: Blob): Promise<unknown>;
39
+ //# sourceMappingURL=value-codec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"value-codec.d.ts","sourceRoot":"","sources":["../../../src/internal/value-codec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGjF;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG;IAAE,QAAQ,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAgB1G;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC,CAQ9G;AAwBD;;;GAGG;AACH,wBAAgB,WAAW,CACvB,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,SAAS,GAAG,SAAS,GAC5B,MAAM,GAAG,WAAW,GAAG,cAAc,CAAC,UAAU,CAAC,GAAG,OAAO,CAmD7D;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAE5D;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAExE;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAG7D"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * IndexedDbKV: High-performance KV over IndexedDB
3
+ */
4
+ import type { KVGetOptions, KVListOptions, KVListResult, KVNamespace, KVPutOptions, KVValue } from "./types";
5
+ /**
6
+ * High-performance KV implementation over IndexedDB
7
+ */
8
+ export declare class IndexedDbKV implements KVNamespace {
9
+ private conn;
10
+ private storeName;
11
+ private cache;
12
+ constructor(opts?: {
13
+ dbName?: string;
14
+ storeName?: string;
15
+ version?: number;
16
+ cacheEntries?: number;
17
+ });
18
+ private invalidateCache;
19
+ get(key: string, options?: KVGetOptions): Promise<string | ArrayBuffer | ReadableStream<Uint8Array> | unknown | null>;
20
+ getWithMetadata<T = unknown>(key: string, options?: KVGetOptions): Promise<{
21
+ value: string | ArrayBuffer | ReadableStream<Uint8Array> | unknown | null;
22
+ metadata: T | null;
23
+ }>;
24
+ put(key: string, value: KVValue, options?: KVPutOptions): Promise<void>;
25
+ delete(key: string): Promise<void>;
26
+ list(options?: KVListOptions): Promise<KVListResult>;
27
+ close(): Promise<void>;
28
+ }
29
+ export declare function createIndexedDbKV(opts?: ConstructorParameters<typeof IndexedDbKV>[0]): KVNamespace;
30
+ export declare function kvGetText(kv: KVNamespace, key: string, cacheTtl?: number): Promise<string | null>;
31
+ export declare function kvGetJson<T>(kv: KVNamespace, key: string, cacheTtl?: number): Promise<T | null>;
32
+ export declare function kvGetArrayBuffer(kv: KVNamespace, key: string, cacheTtl?: number): Promise<ArrayBuffer | null>;
33
+ export declare function kvGetStream(kv: KVNamespace, key: string, cacheTtl?: number): Promise<ReadableStream<Uint8Array> | null>;
34
+ //# sourceMappingURL=kv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kv.d.ts","sourceRoot":"","sources":["../../src/kv.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAa,WAAW,EAAE,YAAY,EAAE,OAAO,EAAgB,MAAM,SAAS,CAAC;AAUtI;;GAEG;AACH,qBAAa,WAAY,YAAW,WAAW;IAC3C,OAAO,CAAC,IAAI,CAAsB;IAClC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,KAAK,CAAU;gBAEX,IAAI,CAAC,EAAE;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,YAAY,CAAC,EAAE,MAAM,CAAC;KACzB;IAQD,OAAO,CAAC,eAAe;IAOjB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,WAAW,GAAG,cAAc,CAAC,UAAU,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC;IAKrH,eAAe,CAAC,CAAC,GAAG,OAAO,EAC7B,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,YAAY,GACvB,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,cAAc,CAAC,UAAU,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC;QAAC,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAA;KAAE,CAAC;IA8CvG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BvE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYlC,IAAI,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAyDpD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI/B;AAED,wBAAgB,iBAAiB,CAAC,IAAI,CAAC,EAAE,qBAAqB,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,WAAW,CAElG;AAED,wBAAsB,SAAS,CAAC,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAEvG;AAED,wBAAsB,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAErG;AAED,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAEnH;AAED,wBAAsB,WAAW,CAC7B,EAAE,EAAE,WAAW,EACf,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,CAE5C"}
@@ -0,0 +1,25 @@
1
+ import type { KVNamespace } from "./types";
2
+ import { IndexedDbKV } from "./lib";
3
+ type KVMethodName = 'get' | 'getWithMetadata' | 'put' | 'delete' | 'list';
4
+ type WrappedKV = KVNamespace & {
5
+ readonly __original?: IndexedDbKV;
6
+ };
7
+ type WrapperOptions = {
8
+ log?: boolean | ((method: KVMethodName, ...args: any[]) => void);
9
+ time?: boolean;
10
+ prefix?: string;
11
+ validateKeys?: boolean;
12
+ retry?: {
13
+ attempts: number;
14
+ delayMs?: number;
15
+ };
16
+ onError?: (method: KVMethodName, error: unknown) => void;
17
+ metrics?: (method: KVMethodName, durationMs: number, success: boolean) => void;
18
+ };
19
+ /**
20
+ * Higher-order function that wraps an existing KVNamespace instance
21
+ * and adds configurable cross-cutting behavior.
22
+ */
23
+ export declare function withKVFeatures(base: KVNamespace, opts?: WrapperOptions): WrappedKV;
24
+ export {};
25
+ //# sourceMappingURL=lib-wrapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lib-wrapper.d.ts","sourceRoot":"","sources":["../../src/lib-wrapper.ts"],"names":[],"mappings":"AAyDA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAC,WAAW,EAAC,MAAM,OAAO,CAAC;AAElC,KAAK,YAAY,GACX,KAAK,GACL,iBAAiB,GACjB,KAAK,GACL,QAAQ,GACR,MAAM,CAAC;AAEb,KAAK,SAAS,GAAG,WAAW,GAAG;IAE3B,QAAQ,CAAC,UAAU,CAAC,EAAE,WAAW,CAAC;CACrC,CAAC;AAEF,KAAK,cAAc,GAAG;IAClB,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC,CAAC;IACjE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,KAAK,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACzD,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CAClF,CAAC;AAEF;;;GAGG;AACH,wBAAgB,cAAc,CAC1B,IAAI,EAAE,WAAW,EACjB,IAAI,GAAE,cAAmB,GAC1B,SAAS,CAoGX"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Public API facade for IndexedDB KV storage
3
+ * Re-exports main classes and functions for backward compatibility
4
+ */
5
+ export { IndexedDbKV, createIndexedDbKV, kvGetText, kvGetJson, kvGetArrayBuffer, kvGetStream, } from "./kv";
6
+ //# sourceMappingURL=lib.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../../src/lib.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACH,WAAW,EACX,iBAAiB,EACjB,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,WAAW,GACd,MAAM,MAAM,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function toEpochSeconds(msEpoch: number): number;
2
+ export declare function fromEpochSeconds(sec: number): number;
3
+ export declare function nowMs(): number;
4
+ //# sourceMappingURL=time-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time-utils.d.ts","sourceRoot":"","sources":["../../src/time-utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGtD;AAGD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,wBAAgB,KAAK,IAAI,MAAM,CAE9B"}
@@ -0,0 +1,57 @@
1
+ export type KVGetType = "text" | "json" | "arrayBuffer" | "stream";
2
+ export type KVValue = string | ArrayBuffer | ArrayBufferView | Blob | ReadableStream<Uint8Array> | unknown;
3
+ export interface KVGetOptions {
4
+ type?: KVGetType;
5
+ cacheTtl?: number;
6
+ }
7
+ export interface KVPutOptions {
8
+ expiration?: number;
9
+ expirationTtl?: number;
10
+ metadata?: unknown;
11
+ }
12
+ export interface KVListOptions {
13
+ prefix?: string;
14
+ limit?: number;
15
+ cursor?: string;
16
+ }
17
+ export interface KVListKey {
18
+ name: string;
19
+ expiration?: number;
20
+ metadata?: unknown;
21
+ }
22
+ export interface KVListResult {
23
+ keys: KVListKey[];
24
+ list_complete: boolean;
25
+ cursor?: string;
26
+ }
27
+ export interface KVNamespace {
28
+ get(key: string, options?: KVGetOptions): Promise<string | ArrayBuffer | ReadableStream<Uint8Array> | unknown | null>;
29
+ getWithMetadata<T = unknown>(key: string, options?: KVGetOptions): Promise<{
30
+ value: string | ArrayBuffer | ReadableStream<Uint8Array> | unknown | null;
31
+ metadata: T | null;
32
+ }>;
33
+ put(key: string, value: KVValue, options?: KVPutOptions): Promise<void>;
34
+ delete(key: string): Promise<void>;
35
+ list(options?: KVListOptions): Promise<KVListResult>;
36
+ }
37
+ export type StoredEncoding = "text" | "json" | "clone" | "binary";
38
+ export type StoredRecord = {
39
+ key: string;
40
+ value: unknown;
41
+ encoding: StoredEncoding;
42
+ expiresAt: number | null;
43
+ metadata: unknown | null;
44
+ createdAt: number;
45
+ updatedAt: number;
46
+ };
47
+ export type InternalListCursor = {
48
+ v: 1;
49
+ prefix: string;
50
+ after: string | null;
51
+ };
52
+ export type OpenConfig = {
53
+ dbName: string;
54
+ storeName: string;
55
+ version: number;
56
+ };
57
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,aAAa,GAAG,QAAQ,CAAC;AACnE,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,WAAW,GAAG,eAAe,GAAG,IAAI,GAAG,cAAc,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC;AAG3G,MAAM,WAAW,YAAY;IACzB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IACxB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,WAAW,GAAG,cAAc,CAAC,UAAU,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC;IACtH,eAAe,CAAC,CAAC,GAAG,OAAO,EACvB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,YAAY,GACvB,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,cAAc,CAAC,UAAU,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC;QAAC,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IAE9G,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CACxD;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAElE,MAAM,MAAM,YAAY,GAAG;IACvB,GAAG,EAAE,MAAM,CAAC;IAMZ,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,cAAc,CAAC;IAEzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAEzB,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IAEzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC7B,CAAC,EAAE,CAAC,CAAC;IAEL,MAAM,EAAE,MAAM,CAAC;IAEf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACnB,CAAC"}
@@ -0,0 +1,25 @@
1
+ export type WebContainerOptions = {
2
+ headless?: boolean;
3
+ };
4
+ export declare class WebContainer {
5
+ private browser;
6
+ private page;
7
+ /** Becomes true once WebKit is launched and the page is initialized. */
8
+ ready: boolean;
9
+ /** Thin IndexedDB KV facade (string keys, JSON-serializable values). */
10
+ indexedDB: {
11
+ get<T = unknown>(store: string, key: string): Promise<T | undefined>;
12
+ set<T = unknown>(store: string, key: string, value: T): Promise<void>;
13
+ del(store: string, key: string): Promise<void>;
14
+ };
15
+ private constructor();
16
+ static create(opts?: WebContainerOptions): Promise<WebContainer>;
17
+ private init;
18
+ close(): Promise<void>;
19
+ }
20
+ declare global {
21
+ var reqToPromise: (req: IDBRequest) => Promise<any>;
22
+ var txDone: (tx: IDBTransaction) => Promise<any>;
23
+ var openDB: (name: string, version: number, stores: string[]) => Promise<IDBDatabase>;
24
+ }
25
+ //# sourceMappingURL=web-container.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-container.d.ts","sourceRoot":"","sources":["../../src/web-container.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,mBAAmB,GAAG;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAC;CAKtB,CAAC;AAEF,qBAAa,YAAY;IACrB,OAAO,CAAC,OAAO,CAAW;IAC1B,OAAO,CAAC,IAAI,CAAQ;IAEpB,wEAAwE;IACjE,KAAK,UAAS;IAErB,wEAAwE;IACjE,SAAS,EAAG;QACf,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;QACrE,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACtE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KAClD,CAAC;IAEF,OAAO;WAEM,MAAM,CAAC,IAAI,GAAE,mBAAwB,GAAG,OAAO,CAAC,YAAY,CAAC;YAM5D,IAAI;IA4GZ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAY/B;AAGD,OAAO,CAAC,MAAM,CAAC;IAEX,IAAI,YAAY,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IAEpD,IAAI,MAAM,EAAE,CAAC,EAAE,EAAE,cAAc,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IAEjD,IAAI,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CACzF"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "idb-repo",
3
+ "version": "1.0.0",
4
+ "description": "A high-performance IndexedDB-based key-value storage implementation with caching, TTL support, and full TypeScript support",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "types": "./dist/index.d.ts",
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "bun build ./index.ts --target browser --outdir ./dist --minify && tsc --emitDeclarationOnly -p tsconfig.build.json"
21
+ },
22
+ "keywords": [
23
+ "indexeddb",
24
+ "kv-storage",
25
+ "storage",
26
+ "cache",
27
+ "typescript",
28
+ "browser",
29
+ "performance"
30
+ ],
31
+ "author": "github.com/geoffsee",
32
+ "license": "MIT",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "https://github.com/geoffsee/idb-kv.git"
36
+ },
37
+ "bugs": {
38
+ "url": "https://github.com/geoffsee/idb-kv/issues"
39
+ },
40
+ "homepage": "https://github.com/geoffsee/idb-kv#readme",
41
+ "devDependencies": {
42
+ "@types/bun": "latest",
43
+ "idb-keyval": "^6.2.2",
44
+ "playwright": "^1.58.2"
45
+ },
46
+ "peerDependencies": {
47
+ "typescript": "^5"
48
+ }
49
+ }