qutedb 0.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.
@@ -0,0 +1,24 @@
1
+ import type { Codec, Schema, WhereClause } from "./types.js";
2
+ export declare class Engine<S extends Schema, Wire> {
3
+ private dbName;
4
+ private version;
5
+ private schema;
6
+ private codec;
7
+ private cache_limit;
8
+ private db;
9
+ private cache;
10
+ constructor(dbName: string, version: number, schema: S, codec: Codec<Wire>, cache_limit?: number);
11
+ open(): Promise<void>;
12
+ private normalizeUint8Arrays;
13
+ private encode;
14
+ private decode;
15
+ toStorage<K extends keyof S>(storeName: K, userData: any): any;
16
+ fromStorage<K extends keyof S>(storeName: K, storageData: any): any;
17
+ put<K extends keyof S>(storeName: K, userData: any): Promise<void>;
18
+ delete<K extends keyof S>(storeName: K, key: any): Promise<void>;
19
+ getSchema<K extends keyof S>(storeName: K): S[K];
20
+ getRecordsByKeys<K extends keyof S>(storeName: K, keys: IDBValidKey[]): Promise<Record<K, S>[]>;
21
+ getKeysByIndexes<K extends keyof S>(storeName: K, wheres: WhereClause[], orderField?: string, orderDir?: "asc" | "desc", limit?: number, offset?: number): Promise<IDBValidKey[]>;
22
+ close(): void;
23
+ }
24
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/db/engine.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE7D,qBAAa,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI;IAKtC,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,WAAW;IARrB,OAAO,CAAC,EAAE,CAA4B;IACtC,OAAO,CAAC,KAAK,CAA6B;gBAGhC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,CAAC,EACT,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,WAAW,GAAE,MAAa;IAK9B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAgD3B,OAAO,CAAC,oBAAoB;IA+B5B,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,MAAM;IAId,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,GAAG,GAAG;IAmC9D,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,GAAG,GAAG,GAAG;IA0B7D,GAAG,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBlE,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAetE,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAI1C,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,EACtC,SAAS,EAAE,CAAC,EACZ,IAAI,EAAE,WAAW,EAAE,GAClB,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IAqCpB,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,EACtC,SAAS,EAAE,CAAC,EACZ,MAAM,EAAE,WAAW,EAAE,EACrB,UAAU,CAAC,EAAE,MAAM,EACnB,QAAQ,GAAE,KAAK,GAAG,MAAc,EAChC,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,SAAI,GACT,OAAO,CAAC,WAAW,EAAE,CAAC;IA6GzB,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,291 @@
1
+ import { LRUCache } from "./lru.js";
2
+ export class Engine {
3
+ dbName;
4
+ version;
5
+ schema;
6
+ codec;
7
+ cache_limit;
8
+ db = null;
9
+ cache;
10
+ constructor(dbName, version, schema, codec, cache_limit = 1000) {
11
+ this.dbName = dbName;
12
+ this.version = version;
13
+ this.schema = schema;
14
+ this.codec = codec;
15
+ this.cache_limit = cache_limit;
16
+ this.cache = new LRUCache(this.cache_limit);
17
+ }
18
+ async open() {
19
+ return new Promise((resolve, reject) => {
20
+ const request = indexedDB.open(this.dbName, this.version);
21
+ request.onerror = () => reject(request.error);
22
+ request.onsuccess = () => {
23
+ this.db = request.result;
24
+ console.log(`%c[quteDB]: %cDatabase opened ${this.dbName} v${this.version}`, "color: lightgreen; font-weight: bold;", "font-style:italic;color:lightgrey");
25
+ for (const storeName of Object.keys(this.schema)) {
26
+ if (!this.db.objectStoreNames.contains(storeName)) {
27
+ reject(new Error(`[quteDB]: Store "${storeName}" not found`));
28
+ return;
29
+ }
30
+ }
31
+ resolve();
32
+ };
33
+ request.onupgradeneeded = (event) => {
34
+ const db = event.target.result;
35
+ for (const [storeName, config] of Object.entries(this.schema)) {
36
+ if (!db.objectStoreNames.contains(storeName)) {
37
+ const keyPath = config.pk.length === 1 ? config.pk[0] : config.pk;
38
+ if (!keyPath) {
39
+ throw new Error(`[quteDB]: Primary Key for the Store "${storeName}" , Is Not defined`);
40
+ }
41
+ const store = db.createObjectStore(storeName, { keyPath });
42
+ for (const indexField of config.index) {
43
+ store.createIndex(indexField, indexField, { unique: false });
44
+ }
45
+ }
46
+ }
47
+ };
48
+ });
49
+ }
50
+ normalizeUint8Arrays(obj) {
51
+ if (obj === null || obj === undefined) {
52
+ return obj;
53
+ }
54
+ if (obj instanceof Uint8Array) {
55
+ return obj;
56
+ }
57
+ if (obj.constructor?.name === "Buffer" ||
58
+ (obj.buffer && obj.byteLength !== undefined)) {
59
+ return new Uint8Array(obj);
60
+ }
61
+ if (typeof obj === "object" && !Array.isArray(obj)) {
62
+ const normalized = {};
63
+ for (const key in obj) {
64
+ normalized[key] = this.normalizeUint8Arrays(obj[key]);
65
+ }
66
+ return normalized;
67
+ }
68
+ if (Array.isArray(obj)) {
69
+ return obj.map((item) => this.normalizeUint8Arrays(item));
70
+ }
71
+ return obj;
72
+ }
73
+ encode(v) {
74
+ return this.codec.encode(v);
75
+ }
76
+ decode(w) {
77
+ return this.codec.decode(w);
78
+ }
79
+ toStorage(storeName, userData) {
80
+ try {
81
+ const config = this.schema[storeName];
82
+ if (!config) {
83
+ throw new Error("[quteDB]: The Store Schema is Not Defined/Corrupted");
84
+ }
85
+ const indexedFields = [...new Set([...config.pk, ...config.index])];
86
+ const indexed = {};
87
+ const dataObj = {};
88
+ // Iterate over actual userData fields, not schema
89
+ for (const field in userData) {
90
+ if (indexedFields.includes(field)) {
91
+ // Indexed field - store directly
92
+ indexed[field] = userData[field];
93
+ }
94
+ else {
95
+ // Non-indexed field - goes into data blob
96
+ dataObj[field] = userData[field];
97
+ }
98
+ }
99
+ // console.log("dataObj:", dataObj); // Should have data now
100
+ const encoded = this.encode(dataObj);
101
+ return {
102
+ ...indexed,
103
+ data: encoded,
104
+ };
105
+ }
106
+ catch (e) {
107
+ throw new Error(`[quteDB]: toStorage Error : ${e}`);
108
+ }
109
+ }
110
+ fromStorage(storeName, storageData) {
111
+ try {
112
+ const config = this.schema[storeName];
113
+ if (!config) {
114
+ throw new Error("[quteDB]: The Store Schema is Not Defined/Corrupted");
115
+ }
116
+ const indexedFields = [...new Set([...config.pk, ...config.index])];
117
+ const indexed = {};
118
+ // Extract indexed fields
119
+ for (const field of indexedFields) {
120
+ indexed[field] = storageData[field];
121
+ }
122
+ // Decode data blob
123
+ const decoded = this.decode(storageData.data);
124
+ const normalized = this.normalizeUint8Arrays(decoded);
125
+ return { ...indexed, ...normalized };
126
+ }
127
+ catch (e) {
128
+ throw new Error(`[quteDB]: fromStorage Error : ${e}`);
129
+ }
130
+ }
131
+ async put(storeName, userData) {
132
+ if (!this.db)
133
+ throw new Error("[quteDB]: Database not opened");
134
+ const storageData = this.toStorage(storeName, userData);
135
+ // console.log("Storagedata : ", storageData, "\nusdata : ", userData);
136
+ return new Promise((resolve, reject) => {
137
+ const tx = this.db.transaction(storeName, "readwrite");
138
+ const store = tx.objectStore(storeName);
139
+ const request = store.put(storageData);
140
+ request.onsuccess = () => resolve();
141
+ request.onerror = () => reject(request.error);
142
+ });
143
+ }
144
+ async delete(storeName, key) {
145
+ if (!this.db)
146
+ throw new Error("[quteDB]: Database not opened");
147
+ return new Promise((resolve, reject) => {
148
+ const tx = this.db.transaction(storeName, "readwrite");
149
+ const store = tx.objectStore(storeName);
150
+ const request = store.delete(key);
151
+ request.onsuccess = () => {
152
+ resolve();
153
+ };
154
+ request.onerror = () => reject(request.error);
155
+ });
156
+ }
157
+ getSchema(storeName) {
158
+ return this.schema[storeName];
159
+ }
160
+ async getRecordsByKeys(storeName, keys) {
161
+ const results = new Map();
162
+ const misses = [];
163
+ for (const k of keys) {
164
+ const v = this.cache.get(k);
165
+ if (v !== undefined)
166
+ results.set(k, v);
167
+ else
168
+ misses.push(k);
169
+ }
170
+ if (misses.length) {
171
+ const tx = this.db.transaction(storeName, "readonly");
172
+ const store = tx.objectStore(storeName);
173
+ await Promise.all(misses.map((k) => new Promise((resolve, reject) => {
174
+ const r = store.get(k);
175
+ r.onsuccess = () => {
176
+ if (r.result !== undefined) {
177
+ let res = this.fromStorage(storeName, r.result);
178
+ this.cache.set(k, res);
179
+ results.set(k, res);
180
+ }
181
+ resolve();
182
+ };
183
+ r.onerror = () => reject(r.error);
184
+ })));
185
+ }
186
+ return keys.map((k) => results.get(k)).filter(Boolean);
187
+ }
188
+ async getKeysByIndexes(storeName, wheres, orderField, orderDir = "asc", limit, offset = 0) {
189
+ if (!this.db)
190
+ throw new Error("[quteDB]: DB not opened");
191
+ const tx = this.db.transaction(storeName, "readonly");
192
+ const store = tx.objectStore(storeName);
193
+ const direction = orderDir === "desc" ? "prev" : "next";
194
+ // ─────────────────────────────────────────────
195
+ // 1. Decide ordering source (PK or index)
196
+ // ─────────────────────────────────────────────
197
+ let orderingSource = store;
198
+ if (orderField) {
199
+ const isPK = store.keyPath === orderField;
200
+ const isIndex = store.indexNames.contains(orderField);
201
+ if (!isPK && !isIndex) {
202
+ throw new Error(`[quteDB]: ORDER BY field "${orderField}" is not indexed`);
203
+ }
204
+ orderingSource = isPK ? store : store.index(orderField);
205
+ }
206
+ // ─────────────────────────────────────────────
207
+ // 2. Build sets for non-ordering WHERE clauses
208
+ // ─────────────────────────────────────────────
209
+ const filterSets = [];
210
+ for (const w of wheres) {
211
+ // skip where that matches ordering field (handled by cursor)
212
+ if (w.field === orderField)
213
+ continue;
214
+ const isPK = store.keyPath === w.field;
215
+ const isIndex = store.indexNames.contains(w.field);
216
+ if (!isPK && !isIndex) {
217
+ throw new Error(`[quteDB]: Field ${w.field} not indexed`);
218
+ }
219
+ const source = isPK ? store : store.index(w.field);
220
+ const range = w.op === "=="
221
+ ? IDBKeyRange.only(w.value)
222
+ : w.op === ">"
223
+ ? IDBKeyRange.lowerBound(w.value, true)
224
+ : w.op === ">="
225
+ ? IDBKeyRange.lowerBound(w.value)
226
+ : w.op === "<"
227
+ ? IDBKeyRange.upperBound(w.value, true)
228
+ : IDBKeyRange.upperBound(w.value);
229
+ const keys = await scanKeys(source, range);
230
+ filterSets.push(new Set(keys));
231
+ }
232
+ // ─────────────────────────────────────────────
233
+ // 3. Walk ordering cursor + apply intersection
234
+ // + offset + limit INSIDE cursor
235
+ // ─────────────────────────────────────────────
236
+ const results = [];
237
+ let skipped = 0;
238
+ return new Promise((resolve, reject) => {
239
+ const req = orderingSource.openKeyCursor(null, direction);
240
+ req.onsuccess = () => {
241
+ const cursor = req.result;
242
+ if (!cursor) {
243
+ resolve(results);
244
+ return;
245
+ }
246
+ const pk = cursor.primaryKey !== undefined ? cursor.primaryKey : cursor.key;
247
+ // AND semantics: must exist in all filter sets
248
+ for (const set of filterSets) {
249
+ if (!set.has(pk)) {
250
+ cursor.continue();
251
+ return;
252
+ }
253
+ }
254
+ // offset
255
+ if (skipped < offset) {
256
+ skipped++;
257
+ cursor.continue();
258
+ return;
259
+ }
260
+ results.push(pk);
261
+ // limit
262
+ if (limit !== undefined && results.length >= limit) {
263
+ resolve(results);
264
+ return;
265
+ }
266
+ cursor.continue();
267
+ };
268
+ req.onerror = () => reject(req.error);
269
+ tx.onerror = () => reject(tx.error);
270
+ });
271
+ }
272
+ close() {
273
+ this.db?.close();
274
+ }
275
+ }
276
+ async function scanKeys(source, range) {
277
+ return new Promise((resolve, reject) => {
278
+ const keys = [];
279
+ const req = source.openKeyCursor(range);
280
+ req.onsuccess = () => {
281
+ const c = req.result;
282
+ if (!c)
283
+ return resolve(keys);
284
+ const pk = c.primaryKey !== undefined ? c.primaryKey : c.key;
285
+ keys.push(pk);
286
+ c.continue();
287
+ };
288
+ req.onerror = () => reject(req.error);
289
+ });
290
+ }
291
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/db/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export declare class LRUCache<K, V> {
2
+ private cache;
3
+ private capacity;
4
+ constructor(capacity: number);
5
+ get(key: K): V | undefined;
6
+ set(key: K, value: V): void;
7
+ has(key: K): boolean;
8
+ delete(key: K): void;
9
+ clear(): void;
10
+ get size(): number;
11
+ }
12
+ //# sourceMappingURL=lru.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lru.d.ts","sourceRoot":"","sources":["../../src/db/lru.ts"],"names":[],"mappings":"AAAA,qBAAa,QAAQ,CAAC,CAAC,EAAE,CAAC;IACxB,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,QAAQ,CAAS;gBAEb,QAAQ,EAAE,MAAM;IAQ5B,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS;IAW1B,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAe3B,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO;IAIpB,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI;IAIpB,KAAK,IAAI,IAAI;IAIb,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
package/dist/db/lru.js ADDED
@@ -0,0 +1,46 @@
1
+ export class LRUCache {
2
+ cache;
3
+ capacity;
4
+ constructor(capacity) {
5
+ if (capacity <= 0) {
6
+ throw new Error("LRU capacity must be > 0");
7
+ }
8
+ this.capacity = capacity;
9
+ this.cache = new Map();
10
+ }
11
+ get(key) {
12
+ if (!this.cache.has(key))
13
+ return undefined;
14
+ // move to most-recently-used
15
+ const value = this.cache.get(key);
16
+ this.cache.delete(key);
17
+ this.cache.set(key, value);
18
+ return value;
19
+ }
20
+ set(key, value) {
21
+ // update existing → move to MRU
22
+ if (this.cache.has(key)) {
23
+ this.cache.delete(key);
24
+ }
25
+ this.cache.set(key, value);
26
+ // evict LRU if over capacity
27
+ if (this.cache.size > this.capacity) {
28
+ const lruKey = this.cache.keys().next().value;
29
+ if (lruKey)
30
+ this.cache.delete(lruKey);
31
+ }
32
+ }
33
+ has(key) {
34
+ return this.cache.has(key);
35
+ }
36
+ delete(key) {
37
+ this.cache.delete(key);
38
+ }
39
+ clear() {
40
+ this.cache.clear();
41
+ }
42
+ get size() {
43
+ return this.cache.size;
44
+ }
45
+ }
46
+ //# sourceMappingURL=lru.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lru.js","sourceRoot":"","sources":["../../src/db/lru.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,QAAQ;IACX,KAAK,CAAY;IACjB,QAAQ,CAAS;IAEzB,YAAY,QAAgB;QAC1B,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC9C,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;IACzB,CAAC;IAED,GAAG,CAAC,GAAM;QACR,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC;QAE3C,6BAA6B;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;QACnC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAE3B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,GAAG,CAAC,GAAM,EAAE,KAAQ;QAClB,gCAAgC;QAChC,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAE3B,6BAA6B;QAC7B,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;YAC9C,IAAI,MAAM;gBAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,GAAG,CAAC,GAAM;QACR,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,MAAM,CAAC,GAAM;QACX,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;CACF"}
@@ -0,0 +1,65 @@
1
+ import { Query, UpdateQuery, RemoveQuery } from "./query.js";
2
+ import type { Codec, Schema, StoreData } from "./types.js";
3
+ export default class qdb<S extends Schema, Wire> {
4
+ private engine;
5
+ private events;
6
+ constructor(dbName: string, version: number, schema: S, codec: Codec<Wire>, cache_limit?: number);
7
+ /**
8
+ * Open the db (Must)
9
+ */
10
+ open(): Promise<this>;
11
+ /**
12
+ * put data into db
13
+ */
14
+ put<K extends keyof S>(storeName: K, data: StoreData<S, K>): Promise<void>;
15
+ /**
16
+ * fetch Record by query callbacks
17
+ *
18
+ * end with `all()` or `one()`
19
+ */
20
+ query<store extends keyof S & string>(storeName: store): Query<S, store>;
21
+ /**
22
+ * update Record by query callbacks
23
+ *
24
+ * end with `exec()`
25
+ */
26
+ update<store extends keyof S & string>(storeName: store, updates: Partial<StoreData<S, store>>): UpdateQuery<S, store>;
27
+ /**
28
+ * update Record by query callbacks
29
+ *
30
+ * end with `exec()`
31
+ */
32
+ remove<K extends keyof S & string>(storeName: K): RemoveQuery<S, K>;
33
+ /**
34
+ * close db as clean up measure
35
+ */
36
+ close(): void;
37
+ /**
38
+ * static method to delete indexed-db
39
+ */
40
+ static deleteDatabase(dbName: string): Promise<void>;
41
+ /**
42
+ * setup event and fire across application
43
+ * @param store - Store name extends `const stores`
44
+ * @param action - "ADD" | "DEL" | "UPT" : type of event
45
+ * @param data - `StoreData[K]` to deliver
46
+ */
47
+ private emit;
48
+ /**
49
+ * Subscribe to STORE-specific events.
50
+ *
51
+ * @param event - Event name derived from the store:
52
+ * `{store}-UP` | `{store}-ADD` | `{store}-RM`
53
+ *
54
+ * @param listener - Callback invoked with event payload:
55
+ * - `{store}-UP` → Partial<Record>
56
+ * - `{store}-ADD` → Record
57
+ * - `{store}-RM` → Keys[]
58
+ *
59
+ * @returns Cleanup function to unsubscribe.
60
+ */
61
+ subscribe<store extends keyof S & string>(event: `${store}-UP`, listener: (data: Partial<StoreData<S, store>>) => void): () => void;
62
+ subscribe<store extends keyof S & string>(event: `${store}-ADD`, listener: (data: StoreData<S, store>) => void): () => void;
63
+ subscribe<store extends keyof S & string>(event: `${store}-RM`, listener: (data: IDBValidKey[]) => void): () => void;
64
+ }
65
+ //# sourceMappingURL=qdb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qdb.d.ts","sourceRoot":"","sources":["../../src/db/qdb.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE7D,OAAO,KAAK,EACV,KAAK,EAGL,MAAM,EACN,SAAS,EACV,MAAM,YAAY,CAAC;AAEpB,MAAM,CAAC,OAAO,OAAO,GAAG,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI;IAC7C,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,MAAM,CAAc;gBAG1B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,CAAC,EACT,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,WAAW,GAAE,MAAa;IAM5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B;;OAEG;IACG,GAAG,CAAC,CAAC,SAAS,MAAM,CAAC,EACzB,SAAS,EAAE,CAAC,EACZ,IAAI,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,GACpB,OAAO,CAAC,IAAI,CAAC;IAMhB;;;;OAIG;IACH,KAAK,CAAC,KAAK,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,KAAK,GAAG,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;IAIxE;;;;OAIG;IACH,MAAM,CAAC,KAAK,SAAS,MAAM,CAAC,GAAG,MAAM,EACnC,SAAS,EAAE,KAAK,EAChB,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GACpC,WAAW,CAAC,CAAC,EAAE,KAAK,CAAC;IAiBxB;;;;OAIG;IACH,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC;IAkBnE;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;WACU,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ1D;;;;;OAKG;IACH,OAAO,CAAC,IAAI;IAkCZ;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,KAAK,SAAS,MAAM,CAAC,GAAG,MAAM,EACtC,KAAK,EAAE,GAAG,KAAK,KAAK,EACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,IAAI,GACrD,MAAM,IAAI;IACb,SAAS,CAAC,KAAK,SAAS,MAAM,CAAC,GAAG,MAAM,EACtC,KAAK,EAAE,GAAG,KAAK,MAAM,EACrB,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,IAAI,GAC5C,MAAM,IAAI;IACb,SAAS,CAAC,KAAK,SAAS,MAAM,CAAC,GAAG,MAAM,EACtC,KAAK,EAAE,GAAG,KAAK,KAAK,EACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,IAAI,GACtC,MAAM,IAAI;CAmBd"}
package/dist/db/qdb.js ADDED
@@ -0,0 +1,107 @@
1
+ import { Engine } from "./engine.js";
2
+ import { Query, UpdateQuery, RemoveQuery } from "./query.js";
3
+ export default class qdb {
4
+ engine;
5
+ events; // Private EventTarget
6
+ constructor(dbName, version, schema, codec, cache_limit = 1000) {
7
+ this.events = new EventTarget();
8
+ this.engine = new Engine(dbName, version, schema, codec, cache_limit);
9
+ }
10
+ /**
11
+ * Open the db (Must)
12
+ */
13
+ async open() {
14
+ await this.engine.open();
15
+ return this;
16
+ }
17
+ /**
18
+ * put data into db
19
+ */
20
+ async put(storeName, data) {
21
+ await this.engine.put(storeName, data);
22
+ this.emit(storeName, "ADD", data);
23
+ }
24
+ /**
25
+ * fetch Record by query callbacks
26
+ *
27
+ * end with `all()` or `one()`
28
+ */
29
+ query(storeName) {
30
+ return new Query(this.engine, storeName);
31
+ }
32
+ /**
33
+ * update Record by query callbacks
34
+ *
35
+ * end with `exec()`
36
+ */
37
+ update(storeName, updates) {
38
+ const query = new UpdateQuery(this.engine, storeName, updates);
39
+ // Wrap exec method
40
+ const originalExec = query.exec.bind(query);
41
+ query.exec = async () => {
42
+ const count = await originalExec();
43
+ // Emit UPT event after successful update
44
+ this.emit(storeName, "UP", updates);
45
+ return count;
46
+ };
47
+ return query;
48
+ }
49
+ /**
50
+ * update Record by query callbacks
51
+ *
52
+ * end with `exec()`
53
+ */
54
+ remove(storeName) {
55
+ // let name = storeName
56
+ const query = new RemoveQuery(this.engine, storeName);
57
+ // Wrap exec method
58
+ const originalExec = query.exec.bind(query);
59
+ query.exec = async () => {
60
+ const keys = await originalExec();
61
+ // Emit DEL event after successful delete
62
+ this.emit(storeName, "RM", keys);
63
+ return keys;
64
+ };
65
+ return query;
66
+ }
67
+ /**
68
+ * close db as clean up measure
69
+ */
70
+ close() {
71
+ this.engine.close();
72
+ }
73
+ /**
74
+ * static method to delete indexed-db
75
+ */
76
+ static async deleteDatabase(dbName) {
77
+ return new Promise((resolve, reject) => {
78
+ const request = indexedDB.deleteDatabase(dbName);
79
+ request.onsuccess = () => resolve();
80
+ request.onerror = () => reject(request.error);
81
+ });
82
+ }
83
+ emit(store, action, data) {
84
+ const event = {
85
+ data,
86
+ name: `${store}-${action}`,
87
+ };
88
+ this.events.dispatchEvent(new CustomEvent(event.name, {
89
+ detail: event.data,
90
+ bubbles: true,
91
+ cancelable: true,
92
+ }));
93
+ }
94
+ subscribe(event, listener) {
95
+ // wrap the listener to extract custom payload
96
+ const wrapped = (e) => {
97
+ const customEvent = e;
98
+ // console.log(`listener.fired @${event}`);
99
+ listener(customEvent.detail);
100
+ };
101
+ this.events.addEventListener(event, wrapped);
102
+ return () => {
103
+ this.events.removeEventListener(event, wrapped);
104
+ };
105
+ }
106
+ }
107
+ //# sourceMappingURL=qdb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qdb.js","sourceRoot":"","sources":["../../src/db/qdb.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ import type { Engine } from "./engine.js";
2
+ import type { StoreData, WhereClause } from "./types.js";
3
+ declare class QueryBuilder<S, K extends keyof S> {
4
+ protected engine: Engine<any, any>;
5
+ protected storeName: K & string;
6
+ protected _where: WhereClause[];
7
+ protected limitVal?: number;
8
+ protected offsetVal?: number;
9
+ protected orderField?: string;
10
+ protected orderDir?: "asc" | "desc";
11
+ protected keysOnly: boolean;
12
+ constructor(engine: Engine<any, any>, storeName: K & string);
13
+ /**
14
+ * Query by indexed fields and primary keys
15
+ */
16
+ where(field: string, op: "==" | ">" | ">=" | "<" | "<=", value: any): this;
17
+ /**
18
+ * limits the result
19
+ */
20
+ limit(n: number): this;
21
+ /**
22
+ * start ur results from a given index
23
+ */
24
+ offset(n: number): this;
25
+ /**
26
+ * ascending order by index
27
+ */
28
+ asc(field?: string): this;
29
+ /**
30
+ * descending order by index
31
+ */
32
+ desc(field?: string): this;
33
+ protected executeQuery(): Promise<any[]>;
34
+ }
35
+ export declare class Query<S, K extends keyof S> extends QueryBuilder<S, K> {
36
+ all(): Promise<StoreData<S, K>[]>;
37
+ one(): Promise<StoreData<S, K> | undefined>;
38
+ nextPage(): this;
39
+ /**
40
+ * Ergonomic primary keys function runs that with query plan
41
+ * @returns `IDBValidKey[]`
42
+ */
43
+ keys(): Promise<IDBValidKey[]>;
44
+ }
45
+ export declare class UpdateQuery<S, K extends keyof S> extends QueryBuilder<S, K> {
46
+ private updates;
47
+ constructor(engine: Engine<any, any>, storeName: K & string, updates: Partial<StoreData<S, K>>);
48
+ preview(): Promise<StoreData<S, K>[]>;
49
+ exec(): Promise<number>;
50
+ }
51
+ export declare class RemoveQuery<S, K extends keyof S> extends QueryBuilder<S, K> {
52
+ preview(): Promise<StoreData<S, K>[]>;
53
+ exec(): Promise<IDBValidKey[]>;
54
+ }
55
+ export {};
56
+ //# sourceMappingURL=query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/db/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGzD,cAAM,YAAY,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC;IASnC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC;IAClC,SAAS,CAAC,SAAS,EAAE,CAAC,GAAG,MAAM;IATjC,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,CAAM;IACrC,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC9B,SAAS,CAAC,QAAQ,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACpC,SAAS,CAAC,QAAQ,UAAS;gBAGf,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EACxB,SAAS,EAAE,CAAC,GAAG,MAAM;IAGjC;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI;IAK1E;;OAEG;IACH,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAKtB;;OAEG;IACH,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAKvB;;OAEG;IACH,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAOzB;;OAEG;IACH,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;cAOV,YAAY,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;CAoB/C;AAGD,qBAAa,KAAK,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,CAAE,SAAQ,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC;IAC3D,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IAIjC,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC;IAMjD,QAAQ,IAAI,IAAI;IAKhB;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;CAIrC;AAGD,qBAAa,WAAW,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,CAAE,SAAQ,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC;IAIrE,OAAO,CAAC,OAAO;gBAFf,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EACxB,SAAS,EAAE,CAAC,GAAG,MAAM,EACb,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAKrC,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IAIrC,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;CAU9B;AAGD,qBAAa,WAAW,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,CAAE,SAAQ,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC;IACjE,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IAIrC,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;CAYrC"}
@@ -0,0 +1,123 @@
1
+ // Shared filter builder
2
+ class QueryBuilder {
3
+ engine;
4
+ storeName;
5
+ _where = [];
6
+ limitVal;
7
+ offsetVal;
8
+ orderField;
9
+ orderDir;
10
+ keysOnly = false;
11
+ constructor(engine, storeName) {
12
+ this.engine = engine;
13
+ this.storeName = storeName;
14
+ }
15
+ /**
16
+ * Query by indexed fields and primary keys
17
+ */
18
+ where(field, op, value) {
19
+ this._where.push({ field, op, value });
20
+ return this;
21
+ }
22
+ /**
23
+ * limits the result
24
+ */
25
+ limit(n) {
26
+ this.limitVal = n;
27
+ return this;
28
+ }
29
+ /**
30
+ * start ur results from a given index
31
+ */
32
+ offset(n) {
33
+ this.offsetVal = n;
34
+ return this;
35
+ }
36
+ /**
37
+ * ascending order by index
38
+ */
39
+ asc(field) {
40
+ const schema = this.engine.getSchema(this.storeName);
41
+ this.orderField = field || schema.pk[0];
42
+ this.orderDir = "asc";
43
+ return this;
44
+ }
45
+ /**
46
+ * descending order by index
47
+ */
48
+ desc(field) {
49
+ const schema = this.engine.getSchema(this.storeName);
50
+ this.orderField = field || schema.pk[0];
51
+ this.orderDir = "desc";
52
+ return this;
53
+ }
54
+ async executeQuery() {
55
+ // 1. ask engine for keys
56
+ const keys = await this.engine.getKeysByIndexes(this.storeName, this._where, this.orderField, this.orderDir, this.limitVal, this.offsetVal);
57
+ // console.log("pk are : ", keys);
58
+ if (this.keysOnly) {
59
+ return keys;
60
+ }
61
+ // 2. hydrate via cache + db
62
+ return this.engine.getRecordsByKeys(this.storeName, keys);
63
+ }
64
+ }
65
+ // Query for reads
66
+ export class Query extends QueryBuilder {
67
+ async all() {
68
+ return this.executeQuery();
69
+ }
70
+ async one() {
71
+ this.limitVal = 1;
72
+ const results = await this.executeQuery();
73
+ return results[0];
74
+ }
75
+ nextPage() {
76
+ this.offsetVal = (this.offsetVal || 0) + (this.limitVal || 0);
77
+ return this;
78
+ }
79
+ /**
80
+ * Ergonomic primary keys function runs that with query plan
81
+ * @returns `IDBValidKey[]`
82
+ */
83
+ async keys() {
84
+ this.keysOnly = true;
85
+ return this.executeQuery();
86
+ }
87
+ }
88
+ // Update Query
89
+ export class UpdateQuery extends QueryBuilder {
90
+ updates;
91
+ constructor(engine, storeName, updates) {
92
+ super(engine, storeName);
93
+ this.updates = updates;
94
+ }
95
+ async preview() {
96
+ return this.executeQuery();
97
+ }
98
+ async exec() {
99
+ const results = await this.executeQuery();
100
+ for (const record of results) {
101
+ const updated = Object.assign({}, record, this.updates);
102
+ await this.engine.put(this.storeName, updated);
103
+ }
104
+ return results.length;
105
+ }
106
+ }
107
+ // Remove Query
108
+ export class RemoveQuery extends QueryBuilder {
109
+ async preview() {
110
+ return this.executeQuery();
111
+ }
112
+ async exec() {
113
+ this.keysOnly = true; // we want just the keys
114
+ const keys = await this.executeQuery();
115
+ const deletedKeys = [];
116
+ for (const key of keys) {
117
+ await this.engine.delete(this.storeName, key);
118
+ deletedKeys.push(key); // Collect keys
119
+ }
120
+ return deletedKeys; // Return keys instead of count
121
+ }
122
+ }
123
+ //# sourceMappingURL=query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/db/query.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ export type Schema = {
2
+ [storeName: string]: {
3
+ pk: readonly string[];
4
+ index: readonly string[];
5
+ data: Record<string, any>;
6
+ };
7
+ };
8
+ export interface Codec<Wire> {
9
+ encode(data: unknown): Wire;
10
+ decode(data: Wire): unknown;
11
+ }
12
+ export type StoreData<S, K extends keyof S> = S[K] extends {
13
+ data: infer D;
14
+ } ? D : never;
15
+ export type EventActions = "ADD" | "UP" | "RM";
16
+ export type EventName<K extends keyof Schema & string> = `${K}-${EventActions}`;
17
+ export type WhereClause = {
18
+ field: string;
19
+ op: "==" | ">" | ">=" | "<" | "<=";
20
+ value: any;
21
+ };
22
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/db/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GAAG;IACnB,CAAC,SAAS,EAAE,MAAM,GAAG;QACnB,EAAE,EAAE,SAAS,MAAM,EAAE,CAAC;QACtB,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;QACzB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KAC3B,CAAC;CACH,CAAC;AAEF,MAAM,WAAW,KAAK,CAAC,IAAI;IACzB,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC;CAC7B;AAED,MAAM,MAAM,SAAS,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC,CAAA;CAAE,GACxE,CAAC,GACD,KAAK,CAAC;AAEV,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC;AAC/C,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,MAAM,MAAM,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,YAAY,EAAE,CAAC;AAEhF,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC;IACnC,KAAK,EAAE,GAAG,CAAC;CACZ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/db/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export { default } from "./db/qdb.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { default } from "./db/qdb.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC"}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "qutedb",
3
+ "version": "0.0.1",
4
+ "description": "Very simple and thin IndexedDB wrapper",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./dist/index.js",
10
+ "require": "./dist/index.cjs"
11
+ }
12
+ },
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "test": "vitest"
16
+ },
17
+ "type": "module",
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "keywords": [
22
+ "indexeddb",
23
+ "browser",
24
+ "database",
25
+ "fast",
26
+ "idb",
27
+ "thin",
28
+ "Store",
29
+ "small",
30
+ "cute",
31
+ "qute"
32
+ ],
33
+ "author": "latenightentropy",
34
+ "license": "ISC",
35
+ "devDependencies": {
36
+ "@msgpack/msgpack": "^3.1.3",
37
+ "@types/node": "^25.0.3",
38
+ "@vitest/coverage-v8": "^4.0.16",
39
+ "fake-indexeddb": "^6.2.5",
40
+ "ts-node": "^10.9.2",
41
+ "typescript": "^5.9.3",
42
+ "vitest": "^4.0.16"
43
+ }
44
+ }
package/readme.md ADDED
@@ -0,0 +1,157 @@
1
+ # QuteDb 🙈
2
+
3
+ ### Very Simple and thin and Ergonomic IDB wrapper
4
+
5
+ - Make ur life easier duh and its super thin (~10KB)
6
+ - 0 extra dependencies
7
+ - it just works predictable and explicit
8
+
9
+ Some Stats:
10
+ | N | Cold | Hot |
11
+ | ---- | ------ | ------- |
12
+ | 50k | ~2.3 s | ~0.38 s |
13
+ | 100k | ~6.6 s | ~0.88 s |
14
+
15
+ ### Storage
16
+
17
+ Indexes and primary keys are stored plaintext and any fields that are not index is mushed into a object then serialized/deserialized using a user given custom encode/decode function
18
+
19
+ ### Declare Your Database
20
+
21
+ ```ts
22
+ // YourDatabase.ts
23
+ import qdb from "qdb";
24
+
25
+ interface Employee {
26
+ name: string;
27
+ id: string;
28
+ age: number;
29
+ joined: number;
30
+ salary: number;
31
+ addr: string;
32
+ office: string;
33
+ }
34
+
35
+ const schema = {
36
+ Employees: {
37
+ pk: ["name","id"],
38
+ index:["age","office"],
39
+ data: {} as Employee & {
40
+ // u can add extra fields not in ur interface
41
+ years:number;
42
+ }
43
+ },
44
+ } as const;
45
+
46
+
47
+ const mydb = await new qdb(
48
+ "my-db", // db name
49
+ 1, // db version
50
+ scehma, // db schema
51
+ {
52
+ decode: JSON.parse, // decode function of ur choice
53
+ encode: JSON.stringify, // encode function of ur choice
54
+ },
55
+ 2000 // cache records limit (this is crucial)
56
+ ).open();
57
+
58
+ export mydb;
59
+ ```
60
+
61
+ ### 1. Put
62
+
63
+ ```ts
64
+ await mydb.put("Employees", {
65
+ name: "Alice",
66
+ id: "e-1",
67
+ age: 28,
68
+ joined: Date.now(),
69
+ salary: 90000,
70
+ addr: "NY",
71
+ office: "HQ",
72
+ years: 3,
73
+ });
74
+ ```
75
+
76
+ ### 2. Query Functions
77
+
78
+ supported operations
79
+ `== > >= < <=`
80
+ the `where` clause can only be used with
81
+ primary keys and indexes
82
+
83
+ ```ts
84
+ mydb
85
+ .query("Employees")
86
+ .where("office", "==", "HQ")
87
+ .where("age", ">=", 25)
88
+ .asc("age")
89
+ .limit(20)
90
+ .all();
91
+ ```
92
+
93
+ ### 3. Update/Remove
94
+
95
+ and similar operations for `update` and `remove`
96
+
97
+ ```ts
98
+ // update
99
+ mydb
100
+ .update("Employees", {
101
+ salary: 100_000, // partial data
102
+ })
103
+ .where("office", "==", "HQ")
104
+ .where("age", ">=", 25)
105
+ .asc("age")
106
+ .limit(20)
107
+ .exec(); // exec() here
108
+
109
+ //remove
110
+ mydb
111
+ .remove("Employees")
112
+ .where("office", "==", "HQ")
113
+ .where("age", ">=", 25)
114
+ .asc("age")
115
+ .limit(20)
116
+ .exec(); // exec() here
117
+ ```
118
+
119
+ u can use `one()` instead of `all()` to get a single result
120
+
121
+ ### 3. Pagination
122
+
123
+ `offset(a:number)` and `limit(b:number)` clauses are provided , and u can build a paginator very easily
124
+
125
+ ### 4. Subscriptions
126
+
127
+ This is some `svelte` code and u can use the subscription like that , very easy and intuitive
128
+
129
+ ```ts
130
+ let lis: Function[] = [];
131
+ let rooms: RoomSchema[] = $state([]);
132
+
133
+ ChatStore.query(STORES.ROOMS)
134
+ .limit(20)
135
+ .all()
136
+ .then((data) => {
137
+ rooms = data;
138
+ });
139
+
140
+ lis[0] = ChatStore.subscribe("ROOMS-ADD", (data) => {
141
+ // here data is the full Room Schema
142
+ ...
143
+ });
144
+ lis[1] = ChatStore.subscribe("ROOMS-UP", (data) => {
145
+ // here data is the Partial Room Schema
146
+ // the Part which is updated
147
+ ...
148
+ });
149
+ lis[2] = ChatStore.subscribe("ROOMS-RM", (keys) => {
150
+ // here keys are the Primary Keys belonging to the Reocrd
151
+ // which are droped
152
+ ...
153
+ });
154
+
155
+ // clean up the eventListeners on Dismount
156
+ onDestroy(() => lis.forEach((l) => l()));
157
+ ```