iodm 0.0.1 → 0.0.3

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.
Files changed (42) hide show
  1. package/README.md +2 -67
  2. package/dist/configure.d.ts +10 -0
  3. package/dist/configure.d.ts.map +1 -0
  4. package/dist/index.d.ts +3 -2
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.es.js +1203 -6
  7. package/dist/model/index.d.ts +7 -0
  8. package/dist/model/index.d.ts.map +1 -0
  9. package/dist/model/types.d.ts +26 -0
  10. package/dist/model/types.d.ts.map +1 -0
  11. package/dist/models.d.ts +3 -0
  12. package/dist/models.d.ts.map +1 -0
  13. package/dist/schema/base-schema.d.ts +21 -0
  14. package/dist/schema/base-schema.d.ts.map +1 -0
  15. package/dist/schema/index.d.ts +32 -0
  16. package/dist/schema/index.d.ts.map +1 -0
  17. package/dist/schema/non-primitive/array/index.d.ts +12 -0
  18. package/dist/schema/non-primitive/array/index.d.ts.map +1 -0
  19. package/dist/schema/non-primitive/ref/index.d.ts +17 -0
  20. package/dist/schema/non-primitive/ref/index.d.ts.map +1 -0
  21. package/dist/schema/non-primitive/ref-array/index.d.ts +15 -0
  22. package/dist/schema/non-primitive/ref-array/index.d.ts.map +1 -0
  23. package/dist/schema/primitive/number.ts/index.d.ts +9 -0
  24. package/dist/schema/primitive/number.ts/index.d.ts.map +1 -0
  25. package/dist/schema/primitive/string.ts/index.d.ts +5 -0
  26. package/dist/schema/primitive/string.ts/index.d.ts.map +1 -0
  27. package/dist/schema/types.d.ts +9 -0
  28. package/dist/schema/types.d.ts.map +1 -0
  29. package/dist/schema/validation-rule/min.d.ts +11 -0
  30. package/dist/schema/validation-rule/min.d.ts.map +1 -0
  31. package/dist/schema/validation-rule/required.d.ts +5 -0
  32. package/dist/schema/validation-rule/required.d.ts.map +1 -0
  33. package/dist/schema/validation-rule/type.d.ts +13 -0
  34. package/dist/schema/validation-rule/type.d.ts.map +1 -0
  35. package/dist/test.d.ts +2 -0
  36. package/dist/test.d.ts.map +1 -0
  37. package/dist/types.d.ts +2 -0
  38. package/dist/types.d.ts.map +1 -0
  39. package/package.json +7 -3
  40. package/dist/Model/index.d.ts +0 -8
  41. package/dist/Model/index.d.ts.map +0 -1
  42. package/dist/tsdoc-metadata.json +0 -11
package/dist/index.es.js CHANGED
@@ -1,14 +1,1211 @@
1
- class r {
1
+ const D = (s) => typeof s == "function", O = (s) => s == null, P = (s) => s?.constructor ? s.constructor.toString().includes("RegExp()") : !1, C = [
2
+ "$eq",
3
+ "$nq",
4
+ "$gt",
5
+ "$gte",
6
+ "$lt",
7
+ "$lte",
8
+ "$not",
9
+ "$regex"
10
+ ], j = (s) => typeof s != "object" || !s ? !1 : C.some((t) => t in s), q = (s, t, e) => !("$eq" in t && t.$eq !== e[s] || "$nq" in t && t.$nq === e[s] || !O(t.$gt) && !(t.$gt < e[s]) || !O(t.$gte) && !(t.$gte <= e[s]) || !O(t.$lt) && !(t.$lt > e[s]) || !O(t.$lte) && !(t.$lte >= e[s]) || !O(t.$not) && q(s, t.$not, e) || !O(t.$regex) && !t.$regex.test(e[s])), b = (s, t) => {
11
+ if (typeof t != "object" || !t) return !0;
12
+ const e = Object.keys(s).filter((r) => r != "$key");
13
+ for (const r of e) {
14
+ const n = s[r];
15
+ if (r === "$and" && s.$and) {
16
+ if (!s.$and.every((o) => b(o, t)))
17
+ return !1;
18
+ } else if (r === "$or" && s.$or) {
19
+ if (!s.$or.some((o) => b(o, t)))
20
+ return !1;
21
+ } else if (j(n)) {
22
+ if (!q(r, n, t)) return !1;
23
+ } else if (P(s[r])) {
24
+ if (!s[r].test(t[r])) return !1;
25
+ } else if (s[r] !== t[r]) return !1;
26
+ }
27
+ return !0;
28
+ }, E = (s, t) => {
29
+ if (typeof s != "object" || !s) return s;
30
+ if (t.$set)
31
+ for (const e in t.$set)
32
+ s[e] = t.$set[e];
33
+ if (t.$unset)
34
+ for (const e in t.$unset)
35
+ delete s[e];
36
+ if (t.$push)
37
+ for (const e in t.$push)
38
+ Array.isArray(s[e]) && s[e].push(t.$push[e]);
39
+ if (t.$pop)
40
+ for (const e in t.$pop)
41
+ Array.isArray(s[e]) && (t.$pop[e] == 1 ? s[e].pop() : s[e].shift());
42
+ return s;
43
+ };
44
+ class M {
45
+ async openCursor(t, e) {
46
+ const { storeName: r, transaction: n, throwOnError: o = !0 } = e;
47
+ return {
48
+ async *[Symbol.asyncIterator]() {
49
+ const d = n.objectStore(r).openCursor(t.$key), c = () => new Promise((i, a) => {
50
+ d.onsuccess = function() {
51
+ i(this.result);
52
+ }, d.onerror = function(h) {
53
+ if (o)
54
+ return a(h);
55
+ h.preventDefault(), i(null);
56
+ };
57
+ });
58
+ let u = c();
59
+ try {
60
+ for (; ; ) {
61
+ const i = await u;
62
+ if (i && i.value)
63
+ u = c(), i.continue(), b(t, i.value) && (yield i.value);
64
+ else
65
+ break;
66
+ }
67
+ } catch (i) {
68
+ if (o)
69
+ throw i;
70
+ return { done: !0 };
71
+ }
72
+ }
73
+ };
74
+ }
75
+ async find(t, e) {
76
+ return new Promise((r, n) => {
77
+ const { storeName: o, transaction: d, Constructor: c } = e, u = [], i = d.objectStore(o).openCursor(t.$key);
78
+ i.onsuccess = async function() {
79
+ const a = this.result;
80
+ if (!a || !a.value) {
81
+ r(u);
82
+ return;
83
+ }
84
+ if (b(t, a.value)) {
85
+ const h = a.value && c ? await c.preProcess(a.value, e) : a.value;
86
+ u.push(h && c ? new c(h) : h);
87
+ }
88
+ a.continue();
89
+ }, i.onerror = (a) => {
90
+ n(a);
91
+ };
92
+ });
93
+ }
94
+ async findById(t, e) {
95
+ return new Promise((r, n) => {
96
+ const { storeName: o, transaction: d, Constructor: c } = e, u = d.objectStore(o).get(t);
97
+ u.onsuccess = async (i) => {
98
+ let a = null;
99
+ if (i.target && "result" in i.target) {
100
+ const h = i.target.result && c ? await c.preProcess(i.target.result, e) : i.target.result;
101
+ a = h && c ? new c(h) : h;
102
+ }
103
+ r(a);
104
+ }, u.onerror = (i) => {
105
+ n(i);
106
+ };
107
+ });
108
+ }
109
+ async insertMany(t, e) {
110
+ const { storeName: r, transaction: n, throwOnError: o } = e, d = n.objectStore(r), c = {
111
+ result: []
112
+ };
113
+ for (let u = 0; u < t.length; ++u) {
114
+ const i = await new Promise(
115
+ (a, h) => {
116
+ const p = d.add(t[u]);
117
+ p.onsuccess = (l) => {
118
+ a({ status: "success", event: l });
119
+ }, p.onerror = (l) => {
120
+ o ? h(l) : (l.preventDefault(), a({ status: "error", event: l }));
121
+ };
122
+ }
123
+ );
124
+ c.result.push(i);
125
+ }
126
+ return c;
127
+ }
128
+ async insertOne(t, e) {
129
+ return { result: (await this.insertMany(
130
+ [t],
131
+ e
132
+ )).result[0] };
133
+ }
134
+ async replaceOne(t, e) {
135
+ const { storeName: r, transaction: n } = e;
136
+ return new Promise((o, d) => {
137
+ let c = e.objectStore;
138
+ c || (c = n.objectStore(r));
139
+ const u = c.put(t);
140
+ u.onsuccess = (i) => {
141
+ let a;
142
+ i.target && "result" in i.target && (a = i.target.result), o(a);
143
+ }, u.onerror = (i) => {
144
+ d(i);
145
+ };
146
+ });
147
+ }
148
+ async updateMany(t, e, r) {
149
+ const { storeName: n, transaction: o, updateLimit: d, throwOnError: c } = r, u = {
150
+ modifiedCount: 0,
151
+ matchedCount: 0
152
+ };
153
+ return new Promise((i, a) => {
154
+ const h = o.objectStore(n).openCursor(t.$key);
155
+ h.onsuccess = (p) => {
156
+ if (!p.target || !("result" in p.target) || !p.target.result) {
157
+ i(u);
158
+ return;
159
+ }
160
+ const l = p.target.result;
161
+ if (!b(t, l.value)) {
162
+ l.continue();
163
+ return;
164
+ }
165
+ ++u.matchedCount;
166
+ try {
167
+ const f = D(e) ? e(l.value) : E(l.value, e), N = l.update(f);
168
+ N.onsuccess = () => {
169
+ ++u.modifiedCount, d !== u.modifiedCount ? l.continue() : i(u);
170
+ }, N.onerror = (v) => {
171
+ c ? a(v) : (v.preventDefault(), l.continue());
172
+ };
173
+ } catch (f) {
174
+ c ? (o.abort(), a(f)) : l.continue();
175
+ }
176
+ }, h.onerror = (p) => {
177
+ if (c)
178
+ return a(p);
179
+ p.preventDefault(), i(u);
180
+ };
181
+ });
182
+ }
183
+ async updateOne(t, e, r) {
184
+ return this.updateMany(t, e, {
185
+ ...r,
186
+ updateLimit: 1
187
+ });
188
+ }
189
+ async deleteMany(t, e) {
190
+ const { storeName: r, transaction: n, deleteLimit: o, throwOnError: d } = e, c = {
191
+ deletedCount: 0,
192
+ matchedCount: 0
193
+ };
194
+ return new Promise((u, i) => {
195
+ const a = n.objectStore(r).openCursor(t.$key);
196
+ a.onsuccess = (h) => {
197
+ if (!h.target || !("result" in h.target) || !h.target.result) {
198
+ u(c);
199
+ return;
200
+ }
201
+ const p = h.target.result;
202
+ if (!b(t, p.value)) {
203
+ p.continue();
204
+ return;
205
+ }
206
+ ++c.matchedCount;
207
+ try {
208
+ const l = p.delete();
209
+ l.onsuccess = () => {
210
+ ++c.deletedCount, o !== c.deletedCount ? p.continue() : u(c);
211
+ }, l.onerror = (f) => {
212
+ if (d)
213
+ return i(f);
214
+ f.preventDefault(), p.continue();
215
+ };
216
+ } catch (l) {
217
+ if (d)
218
+ return n.abort(), i(l);
219
+ p.continue();
220
+ }
221
+ }, a.onerror = (h) => {
222
+ if (d)
223
+ return i(h);
224
+ h.preventDefault(), u(c);
225
+ };
226
+ });
227
+ }
228
+ async deleteOne(t, e) {
229
+ return this.deleteMany(t, { ...e, deleteLimit: 1 });
230
+ }
231
+ async findByIdAndDelete(t, e) {
232
+ const {
233
+ storeName: r,
234
+ transaction: n,
235
+ Constructor: o,
236
+ throwOnError: d = !0
237
+ } = e, c = n.objectStore(r);
238
+ return new Promise((u, i) => {
239
+ const a = c.get(t);
240
+ a.onsuccess = async (h) => {
241
+ let p;
242
+ if (h.target && "result" in h.target && (p = h.target.result), !p) {
243
+ u(p);
244
+ return;
245
+ }
246
+ p = o ? await o.preProcess(p, e) : p, p = o ? new o(p) : p;
247
+ try {
248
+ const l = c.delete(t);
249
+ l.onsuccess = () => {
250
+ u(p);
251
+ }, l.onerror = (f) => {
252
+ if (d)
253
+ return i(f);
254
+ f.preventDefault(), u(void 0);
255
+ };
256
+ } catch {
257
+ if (d)
258
+ return n.abort(), i(h);
259
+ u(void 0);
260
+ }
261
+ }, a.onerror = (h) => {
262
+ if (d)
263
+ return i(h);
264
+ h.preventDefault(), u(void 0);
265
+ };
266
+ });
267
+ }
268
+ async findByIdAndUpdate(t, e, r) {
269
+ const {
270
+ storeName: n,
271
+ transaction: o,
272
+ Constructor: d,
273
+ throwOnError: c = !0,
274
+ new: u = !0
275
+ } = r, i = o.objectStore(n);
276
+ return new Promise((a, h) => {
277
+ const p = i.get(t);
278
+ p.onsuccess = (l) => {
279
+ let f;
280
+ if (l.target && "result" in l.target && (f = l.target.result), !f) {
281
+ a(f);
282
+ return;
283
+ }
284
+ try {
285
+ const N = D(e) ? e(f) : E(f, e), v = i.put(N);
286
+ v.onsuccess = async () => {
287
+ let m = f;
288
+ u && (m = N), m = d ? await d.preProcess(m, r) : m, a(d ? new d(m) : m);
289
+ }, v.onerror = (m) => {
290
+ if (c)
291
+ return h(m);
292
+ m.preventDefault(), a(void 0);
293
+ };
294
+ } catch {
295
+ if (c)
296
+ return o.abort(), h(l);
297
+ a(void 0);
298
+ }
299
+ }, p.onerror = (l) => {
300
+ if (c)
301
+ return h(l);
302
+ l.preventDefault(), a(void 0);
303
+ };
304
+ });
305
+ }
306
+ async countDocuments(t, e) {
307
+ return new Promise((r, n) => {
308
+ const { storeName: o, transaction: d, throwOnError: c } = e;
309
+ let u = 0;
310
+ const i = d.objectStore(o).openCursor(t.$key);
311
+ i.onsuccess = function() {
312
+ const a = this.result;
313
+ if (!a || !a.value) {
314
+ r(u);
315
+ return;
316
+ }
317
+ b(t, a.value) && ++u, a.continue();
318
+ }, i.onerror = (a) => {
319
+ c ? n(a) : (a.preventDefault(), r(void 0));
320
+ };
321
+ });
322
+ }
323
+ }
324
+ class y {
325
+ static executor;
326
+ static getInstance() {
327
+ return this.executor || (this.executor = new M()), this.executor;
328
+ }
329
+ }
330
+ class w {
331
+ idb;
332
+ storeName;
333
+ options;
334
+ /**
335
+ *
336
+ * @param idb - Instance of the IndexedDB database
337
+ * @param storeName - Query operations will be performed on store object that having this store name
338
+ */
339
+ constructor(t, e) {
340
+ this.idb = t, this.storeName = e;
341
+ }
342
+ /**
343
+ * Opens a iterable cursor, with the cursor object it's possible to iterate one document after another
344
+ *
345
+ * @example
346
+ * ```ts
347
+ * const query = new Query(idb, "store-name");
348
+ * const itr = await query.openCursor({ $key: "text", value: { $gte: 4 } });
349
+ *
350
+ * for await (const doc of itr) {
351
+ * console.log(doc);
352
+ * }
353
+ * ```
354
+ *
355
+ * @param query - Search query object
356
+ * @param options - Query options
357
+ * @returns
358
+ */
359
+ openCursor(t = { $key: null }, e = {}) {
360
+ return this.options = { type: "_openCursor", query: t, execOptions: e }, this;
361
+ }
362
+ _openCursor() {
363
+ if (this.options?.type !== "_openCursor")
364
+ throw new Error("Invalid openCursor method options");
365
+ const { query: t, execOptions: e } = this.options;
366
+ let r = e?.transaction;
367
+ return r || (r = this.idb.transaction(this.storeName, "readonly")), y.getInstance().openCursor(t, {
368
+ ...e,
369
+ idb: this.idb,
370
+ transaction: r,
371
+ storeName: this.storeName
372
+ });
373
+ }
374
+ /**
375
+ * Finds list of item from the IndexedDB
376
+ *
377
+ * @example
378
+ * ```ts
379
+ * const query = new Query(idb, "store-name");
380
+ * const data = await query.find({ $key: "text" });
381
+ * ```
382
+ *
383
+ * @param query - Search query object
384
+ * @param options - Query options
385
+ *
386
+ * @returns
387
+ */
388
+ find(t = { $key: null }, e = {}) {
389
+ return this.options = { type: "_find", query: t, execOptions: e }, this;
390
+ }
391
+ async _find() {
392
+ if (this.options?.type !== "_find")
393
+ throw new Error("Invalid find method options");
394
+ const { query: t, execOptions: e } = this.options;
395
+ let r = e?.transaction;
396
+ return r || (r = this.idb.transaction(this.storeName, "readonly")), y.getInstance().find(t, {
397
+ ...e,
398
+ idb: this.idb,
399
+ transaction: r,
400
+ storeName: this.storeName
401
+ });
402
+ }
403
+ /**
404
+ * Finds single item from the IndexedDB
405
+ *
406
+ * @example
407
+ * ```ts
408
+ * const query = new Query(idb, "store-name");
409
+ * const item = await query.findById("id");
410
+ * ```
411
+ *
412
+ * @param id - Search id
413
+ * @param options - Query options
414
+ * @returns
415
+ */
416
+ findById(t, e = {}) {
417
+ return this.options = {
418
+ type: "_findById",
419
+ query: { $key: t },
420
+ execOptions: e
421
+ }, this;
422
+ }
423
+ async _findById() {
424
+ if (this.options?.type !== "_findById")
425
+ throw new Error("Invalid findById method options");
426
+ if (!this.options.query.$key)
427
+ throw new Error("search key is required");
428
+ const { query: t, execOptions: e } = this.options;
429
+ let r = e.transaction;
430
+ return r || (r = this.idb.transaction(this.storeName, "readonly")), y.getInstance().findById(t.$key, {
431
+ ...e,
432
+ idb: this.idb,
433
+ transaction: r,
434
+ storeName: this.storeName
435
+ });
436
+ }
437
+ /**
438
+ * Inserts a single Document into IndexedDB object store
439
+ *
440
+ * @example
441
+ * ```ts
442
+ * const query = new Query(idb, "store-name");
443
+ * await query.insertOne(document, options);
444
+ * ```
445
+ *
446
+ * @param payload - Document to insert
447
+ * @param options - Query options
448
+ * @returns
449
+ */
450
+ insertOne(t, e = {}) {
451
+ return this.options = {
452
+ type: "_insertOne",
453
+ insertList: [t],
454
+ execOptions: e
455
+ }, this;
456
+ }
457
+ async _insertOne() {
458
+ if (this.options?.type !== "_insertOne")
459
+ throw new Error("Invalid insertOne method options");
460
+ const t = this.options.insertList[0];
461
+ if (!t)
462
+ throw new Error(
463
+ "At least one document is required to perform insertOne operations"
464
+ );
465
+ this.options.insertList = [];
466
+ let e = this.options.execOptions.transaction;
467
+ return e || (e = this.idb.transaction(this.storeName, "readwrite")), y.getInstance().insertOne(t, {
468
+ idb: this.idb,
469
+ transaction: e,
470
+ storeName: this.storeName
471
+ });
472
+ }
473
+ /**
474
+ * Inserts multiple documents into IndexedDB object store
475
+ *
476
+ * @example
477
+ * ```ts
478
+ * const query = new Query(idb, "store-name");
479
+ * await query.insertMany([document1, document2, ...], options);
480
+ * ```
481
+ *
482
+ * @remarks
483
+ * Insertion operation done using a single transaction,
484
+ * by default when error is thrown during a document insert the entire transaction will not be aborted.
485
+ * This behavior can be changed using the throwOnError option
486
+ *
487
+ * @param payload - Array of documents
488
+ * @param options - Query options
489
+ * @returns
490
+ */
491
+ insertMany(t, e = {}) {
492
+ return this.options = {
493
+ type: "_insertMany",
494
+ insertList: t,
495
+ execOptions: e
496
+ }, this;
497
+ }
498
+ async _insertMany() {
499
+ if (this.options?.type !== "_insertMany")
500
+ throw new Error("Invalid insertMany method options");
501
+ const t = this.options.insertList.slice();
502
+ this.options.insertList = [];
503
+ let e = this.options.execOptions.transaction;
504
+ return e || (e = this.idb.transaction(this.storeName, "readwrite")), y.getInstance().insertMany(t, {
505
+ idb: this.idb,
506
+ transaction: e,
507
+ storeName: this.storeName,
508
+ throwOnError: this.options.execOptions.throwOnError
509
+ });
510
+ }
511
+ /**
512
+ * To replace existing document with new document, if key is not present new document will be inserted
513
+ *
514
+ * @example
515
+ * ```ts
516
+ * const query = new Query(idb, "store-name");
517
+ * await query.replaceOne({ $key: key }, newDoc, options);
518
+ * ```
519
+ *
520
+ * @param payload - Document object to override
521
+ * @param options - Query options
522
+ * @returns
523
+ */
524
+ replaceOne(t, e = {}) {
525
+ return this.options = {
526
+ type: "_replaceOne",
527
+ payload: t,
528
+ execOptions: {
529
+ ...e
530
+ }
531
+ }, this;
532
+ }
533
+ async _replaceOne() {
534
+ if (this.options?.type !== "_replaceOne")
535
+ throw new Error("Invalid replaceOne method options");
536
+ const { payload: t, execOptions: e } = this.options;
537
+ let r = e.transaction;
538
+ return r || (r = this.idb.transaction(this.storeName, "readwrite")), y.getInstance().replaceOne(t, {
539
+ ...e,
540
+ idb: this.idb,
541
+ storeName: this.storeName,
542
+ transaction: r
543
+ });
544
+ }
545
+ /**
546
+ * Based on the query, matched documents will be updated
547
+ *
548
+ * @example
549
+ * ```ts
550
+ * const query = new Query(idb, "store-name");
551
+ * await query.updateMany({ $key: keyRange }, newDoc, options);
552
+ * ```
553
+ *
554
+ * @param query - Update query to find match
555
+ * @param payload - Callback to update the found document
556
+ * @param options - Query options
557
+ * @returns
558
+ */
559
+ updateMany(t, e, r = {}) {
560
+ return this.options = {
561
+ type: "_updateMany",
562
+ query: t,
563
+ payload: e,
564
+ execOptions: r
565
+ }, this;
566
+ }
567
+ async _updateMany() {
568
+ if (this.options?.type !== "_updateMany")
569
+ throw new Error("Invalid updateMany method options");
570
+ const { query: t, payload: e, execOptions: r } = this.options;
571
+ let n = r.transaction;
572
+ return n || (n = this.idb.transaction(this.storeName, "readwrite")), y.getInstance().updateMany(t, e, {
573
+ ...r,
574
+ idb: this.idb,
575
+ storeName: this.storeName,
576
+ transaction: n
577
+ });
578
+ }
579
+ /**
580
+ * Based on the query, first matched document will be updated
581
+ *
582
+ * @example
583
+ * ```ts
584
+ * const query = new Query(idb, "store-name");
585
+ * await query.updateOne({ $key: key }, newDoc, options);
586
+ * ```
587
+ *
588
+ * @param query - Update query to find match
589
+ * @param payload - New document or Callback to update the found document
590
+ * @param options - Query options
591
+ * @returns
592
+ */
593
+ updateOne(t, e, r = {}) {
594
+ return this.options = {
595
+ type: "_updateOne",
596
+ query: t,
597
+ payload: e,
598
+ execOptions: r
599
+ }, this;
600
+ }
601
+ async _updateOne() {
602
+ if (this.options?.type !== "_updateOne")
603
+ throw new Error("Invalid updateOne method options");
604
+ const { query: t, payload: e, execOptions: r } = this.options;
605
+ let n = r.transaction;
606
+ return n || (n = this.idb.transaction(this.storeName, "readwrite")), y.getInstance().updateOne(t, e, {
607
+ ...r,
608
+ idb: this.idb,
609
+ storeName: this.storeName,
610
+ transaction: n
611
+ });
612
+ }
613
+ /**
614
+ * Deletes all matched documents
615
+ *
616
+ * @example
617
+ * ```ts
618
+ * const query = new Query(idb, "store-name");
619
+ * await query.deleteMany({ $key: key }, options);
620
+ * ```
621
+ *
622
+ * @param query - Delete query to match documents
623
+ * @param options - Query options
624
+ * @returns
625
+ */
626
+ deleteMany(t = { $key: null }, e = {}) {
627
+ return this.options = {
628
+ type: "_deleteMany",
629
+ query: t,
630
+ execOptions: e
631
+ }, this;
632
+ }
633
+ async _deleteMany() {
634
+ if (this.options?.type !== "_deleteMany")
635
+ throw new Error("Invalid deleteMany method options");
636
+ const { query: t, execOptions: e } = this.options;
637
+ let r = e.transaction;
638
+ return r || (r = this.idb.transaction(this.storeName, "readwrite")), y.getInstance().deleteMany(t, {
639
+ ...e,
640
+ idb: this.idb,
641
+ storeName: this.storeName,
642
+ transaction: r
643
+ });
644
+ }
645
+ /**
646
+ * Based on the query, first matched document will be deleted
647
+ *
648
+ * @example
649
+ * ```ts
650
+ * const query = new Query(idb, "store-name");
651
+ * await query.deleteOne({ $key: key }, options);
652
+ * ```
653
+ *
654
+ * @remarks
655
+ * This is similar to calling the `deleteMany` with `deleteLimit = 1` option
656
+ *
657
+ * @param query - Delete query to match documents
658
+ * @param options - Query options
659
+ * @returns
660
+ */
661
+ deleteOne(t = { $key: null }, e = {}) {
662
+ return this.options = {
663
+ type: "_deleteOne",
664
+ query: t,
665
+ execOptions: e
666
+ }, this;
667
+ }
668
+ async _deleteOne() {
669
+ if (this.options?.type !== "_deleteOne")
670
+ throw new Error("Invalid deleteOne method options");
671
+ const { query: t, execOptions: e } = this.options;
672
+ let r = e.transaction;
673
+ return r || (r = this.idb.transaction(this.storeName, "readwrite")), y.getInstance().deleteOne(t, {
674
+ ...e,
675
+ idb: this.idb,
676
+ storeName: this.storeName,
677
+ transaction: r
678
+ });
679
+ }
680
+ /**
681
+ * Removes the document with the id and returnes the deleted document.
682
+ * if the document is not present `undefined` will be returned
683
+ *
684
+ * @example
685
+ * ```ts
686
+ * const query = new Query(idb, "store-name");
687
+ * const deletedDoc = await query.findByIdAndDelete(id, options);
688
+ * ```
689
+ *
690
+ * @param id - Valid search key to find a document
691
+ * @param options - Query options
692
+ * @returns
693
+ */
694
+ findByIdAndDelete(t, e = {}) {
695
+ return this.options = {
696
+ type: "_findByIdAndDelete",
697
+ id: t,
698
+ execOptions: e
699
+ }, this;
700
+ }
701
+ async _findByIdAndDelete() {
702
+ if (this.options?.type !== "_findByIdAndDelete")
703
+ throw new Error("Invalid findByIdAndDelete method options");
704
+ const { id: t, execOptions: e } = this.options;
705
+ let r = e.transaction;
706
+ return r || (r = this.idb.transaction(this.storeName, "readwrite")), y.getInstance().findByIdAndDelete(
707
+ t,
708
+ {
709
+ ...e,
710
+ idb: this.idb,
711
+ storeName: this.storeName,
712
+ transaction: r
713
+ }
714
+ );
715
+ }
716
+ /**
717
+ * Updates the document with the id and returns the updated document.
718
+ * if the document is not present `undefined` will be returned
719
+ *
720
+ * @example
721
+ * ```ts
722
+ * const query = new Query(idb, "store-name");
723
+ * const updatedDoc = await query.findByIdAndUpdate(
724
+ * id,
725
+ * (oldDoc) => newDoc,
726
+ * options
727
+ * );
728
+ * ```
729
+ *
730
+ * @param id - Valid search key to find a document
731
+ * @param payload - Callback to update the found document
732
+ * @param options - Query options
733
+ * @returns
734
+ */
735
+ findByIdAndUpdate(t, e, r = {}) {
736
+ return this.options = {
737
+ type: "_findByIdAndUpdate",
738
+ id: t,
739
+ payload: e,
740
+ execOptions: r
741
+ }, this;
742
+ }
743
+ async _findByIdAndUpdate() {
744
+ if (this.options?.type !== "_findByIdAndUpdate")
745
+ throw new Error("Invalid findByIdAndUpdate method options");
746
+ const { id: t, payload: e, execOptions: r } = this.options;
747
+ let n = r.transaction;
748
+ return n || (n = this.idb.transaction(this.storeName, "readwrite")), y.getInstance().findByIdAndUpdate(t, e, {
749
+ ...r,
750
+ idb: this.idb,
751
+ storeName: this.storeName,
752
+ transaction: n
753
+ });
754
+ }
755
+ /**
756
+ * Returns the documents count that matches the search query
757
+ *
758
+ * @example
759
+ * ```ts
760
+ * const query = new Query(idb, "store-name");
761
+ * const count = await query.countDocuments(
762
+ * query,
763
+ * options
764
+ * );
765
+ * ```
766
+ *
767
+ * @param query - Search query
768
+ * @param options - Query options
769
+ * @returns
770
+ */
771
+ countDocuments(t = { $key: null }, e = {}) {
772
+ return this.options = {
773
+ type: "_countDocuments",
774
+ query: t,
775
+ execOptions: e
776
+ }, this;
777
+ }
778
+ async _countDocuments() {
779
+ if (this.options?.type !== "_countDocuments")
780
+ throw new Error("Invalid countDocuments method options");
781
+ const { query: t, execOptions: e } = this.options;
782
+ let r = e.transaction;
783
+ return r || (r = this.idb.transaction(this.storeName, "readonly")), y.getInstance().countDocuments(
784
+ t,
785
+ {
786
+ ...e,
787
+ idb: this.idb,
788
+ storeName: this.storeName,
789
+ transaction: r
790
+ }
791
+ );
792
+ }
793
+ populate(t) {
794
+ return (this.options?.type === "_find" || this.options?.type === "_findById" || this.options?.type === "_findByIdAndUpdate" || this.options?.type === "_findByIdAndDelete") && (this.options.execOptions.populateFields = this.options.execOptions.populateFields || {}, typeof t == "string" ? this.options.execOptions.populateFields[t] = { path: t } : this.options.execOptions.populateFields[t.path] = t), this;
795
+ }
796
+ /**
797
+ * Executes the query with accumulated options
798
+ *
799
+ * @example
800
+ * ```ts
801
+ * const query = new Query(idb, "store-name");
802
+ * const item = await query.findById("id").exec();
803
+ * ```
804
+ *
805
+ * @returns
806
+ */
807
+ async exec() {
808
+ if (!this.options?.type)
809
+ throw new Error(
810
+ "Once of the query operations must be called before calling exec"
811
+ );
812
+ return this[this.options.type]();
813
+ }
814
+ then(t, e) {
815
+ return this.exec().then(t, e);
816
+ }
817
+ }
818
+ const g = {}, F = class S {
819
+ // instance properties and methods
820
+ constructor(t) {
821
+ if (t && typeof t == "object")
822
+ for (const e in t)
823
+ this[e] = t[e];
824
+ }
825
+ async save() {
826
+ return this.validate(), await this.getInstanceSchema().save(this, {
827
+ modelInstance: this
828
+ }), new w(
829
+ this.getInstanceDB(),
830
+ this.getInstanceStoreName()
831
+ ).replaceOne(this.toJSON());
832
+ }
833
+ validate() {
834
+ return this.getInstanceSchema().validate(this, {
835
+ modelInstance: this
836
+ });
837
+ }
838
+ toJSON() {
839
+ return this.getInstanceSchema().castFrom(this);
840
+ }
841
+ getInstanceSchema() {
842
+ return S.getSchema(this);
843
+ }
844
+ getInstanceDB() {
845
+ return S.getDB(this);
846
+ }
847
+ getInstanceStoreName() {
848
+ return S.getStoreName(this);
849
+ }
850
+ // static properties and methods
851
+ static _schema;
852
+ static _storeName;
853
+ static _db;
854
+ static getSchema(t) {
855
+ const r = (t ? Object.getPrototypeOf(t).constructor : this)._schema;
856
+ if (!r)
857
+ throw new Error("Schema is required");
858
+ return r;
859
+ }
860
+ static getDB(t) {
861
+ const r = (t ? Object.getPrototypeOf(t).constructor : this)._db;
862
+ if (!r)
863
+ throw new Error("db is required");
864
+ return r;
865
+ }
866
+ static setDB(t) {
867
+ this._db = t;
868
+ }
869
+ static getStoreName(t) {
870
+ const r = (t ? Object.getPrototypeOf(t).constructor : this)._storeName;
871
+ if (!r)
872
+ throw new Error("db is required");
873
+ return r;
874
+ }
875
+ static init(t) {
876
+ this.setDB(t);
877
+ }
878
+ static onUpgradeNeeded(t) {
879
+ this._storeName && !t.objectStoreNames.contains(this._storeName) && t.createObjectStore(this._storeName, {
880
+ keyPath: "_id"
881
+ });
882
+ }
883
+ static async preProcess(t, e) {
884
+ return !t || typeof t != "object" ? t : this.getSchema().preProcess(t, e);
885
+ }
886
+ static createTransaction(t) {
887
+ return this.getDB().transaction(
888
+ [this.getStoreName(), ...this.getSchema().getRefNames()],
889
+ t
890
+ );
891
+ }
2
892
  /**
3
893
  * Model find method that overrieds the IQuery find method
4
894
  * @returns empty array
5
895
  */
6
- find() {
7
- return console.log("finding with update for browser IModel..."), [];
896
+ static find(t) {
897
+ return new w(this.getDB(), this.getStoreName()).find(
898
+ t,
899
+ {
900
+ Constructor: this,
901
+ transaction: this.createTransaction("readonly")
902
+ }
903
+ );
904
+ }
905
+ static findById(t) {
906
+ return new w(this.getDB(), this.getStoreName()).findById(t, {
907
+ Constructor: this,
908
+ transaction: this.createTransaction("readonly")
909
+ });
910
+ }
911
+ static findByIdAndUpdate(t, e, r) {
912
+ return new w(
913
+ this.getDB(),
914
+ this.getStoreName()
915
+ ).findByIdAndUpdate(t, e, {
916
+ Constructor: this,
917
+ transaction: this.createTransaction("readwrite"),
918
+ ...r
919
+ });
920
+ }
921
+ static findByIdAndDelete(t) {
922
+ return new w(
923
+ this.getDB(),
924
+ this.getStoreName()
925
+ ).findByIdAndDelete(t, {
926
+ Constructor: this,
927
+ transaction: this.createTransaction("readwrite")
928
+ });
929
+ }
930
+ static deleteOne(t) {
931
+ return new w(this.getDB(), this.getStoreName()).deleteOne(
932
+ t,
933
+ {
934
+ transaction: this.createTransaction("readwrite")
935
+ }
936
+ );
937
+ }
938
+ };
939
+ function T(s, t) {
940
+ class e extends F {
941
+ }
942
+ return e._schema = t.clone(), e._storeName = s, g[s] = e;
943
+ }
944
+ class A {
945
+ message;
946
+ constructor(t) {
947
+ this.message = t.message;
948
+ }
949
+ }
950
+ class k extends A {
951
+ validate(t) {
952
+ if (t == null || t === "")
953
+ throw new Error(this.message);
954
+ return !0;
955
+ }
956
+ }
957
+ class I {
958
+ name;
959
+ isVirtual;
960
+ validationRules;
961
+ constructor({
962
+ name: t,
963
+ isVirtual: e = !1,
964
+ validationRules: r = [],
965
+ required: n
966
+ } = {}) {
967
+ this.name = t, this.isVirtual = e, this.validationRules = r, n && this.validationRules.push(
968
+ new k({ message: `${t} is required!` })
969
+ );
970
+ }
971
+ clone() {
972
+ return null;
973
+ }
974
+ getIsVirtual() {
975
+ return this.isVirtual;
976
+ }
977
+ async preProcess(t, e) {
978
+ return this.name ? t[this.name] : t;
979
+ }
980
+ async save(t, e) {
981
+ }
982
+ validate(t, e) {
983
+ const r = this.castFrom(t);
984
+ return this.validationRules.forEach((n) => n.validate(r, e)), !0;
985
+ }
986
+ }
987
+ class R extends I {
988
+ valueSchema;
989
+ constructor(t) {
990
+ super(t), this.valueSchema = t.valueSchema;
991
+ }
992
+ validate(t, e) {
993
+ const r = this.castFrom(t);
994
+ return this.validationRules.forEach((n) => n.validate(r, e)), r && r.forEach((n) => {
995
+ this.valueSchema.validate(n, e);
996
+ }), !0;
997
+ }
998
+ castFrom(t) {
999
+ if (t == null) return t;
1000
+ if (!Array.isArray(t))
1001
+ throw new Error("cant cast to a array");
1002
+ return t.map((e) => this.valueSchema.castFrom(e));
1003
+ }
1004
+ }
1005
+ class $ extends I {
1006
+ ref;
1007
+ valueSchema;
1008
+ constructor(t) {
1009
+ super(t), this.ref = t.ref, this.valueSchema = t.valueSchema;
1010
+ }
1011
+ validate(t, e) {
1012
+ return t && typeof t == "object" && "_id" in t ? this.valueSchema.validate(t._id, e) : this.valueSchema.validate(t, e);
1013
+ }
1014
+ async save(t, e) {
1015
+ if (!t || typeof t != "object") return;
1016
+ if (!g[this.ref])
1017
+ throw new Error(`Ref ${this.ref} model is not created`);
1018
+ const r = t instanceof g[this.ref] ? t : new g[this.ref](t);
1019
+ return r.validate(), r.save();
1020
+ }
1021
+ async preProcess(t, e) {
1022
+ if (this.name && e.populateFields && e.populateFields[this.name]) {
1023
+ let r = t[this.name];
1024
+ if (typeof r == "string" || typeof r == "number") {
1025
+ if (!g[this.ref])
1026
+ throw new Error(`Ref ${this.ref} model is not created`);
1027
+ return await new w(e.idb, this.ref).findById(r, {
1028
+ Constructor: g[this.ref],
1029
+ // need to remove the prefix for nested objects
1030
+ // populateFields: options.populateFields,
1031
+ transaction: e.transaction
1032
+ });
1033
+ }
1034
+ }
1035
+ return this.name ? t[this.name] : t;
1036
+ }
1037
+ castFrom(t) {
1038
+ return t && typeof t == "object" && "_id" in t ? t._id && this.valueSchema.castFrom(t._id) : t && this.valueSchema.castFrom(t);
1039
+ }
1040
+ }
1041
+ class U extends A {
1042
+ min;
1043
+ constructor(t) {
1044
+ super(t), this.min = t.min;
1045
+ }
1046
+ validate(t) {
1047
+ if (typeof t == "number" && t < this.min)
1048
+ throw new Error(this.message);
1049
+ return !0;
1050
+ }
1051
+ }
1052
+ class B extends I {
1053
+ constructor(t) {
1054
+ super(t), typeof t.min == "number" && this.validationRules.push(
1055
+ new U({
1056
+ message: `${t.name} must be greater then or equal to ${t.min}`,
1057
+ min: t.min
1058
+ })
1059
+ );
1060
+ }
1061
+ castFrom(t) {
1062
+ if (t == null) return t;
1063
+ if (typeof t != "number" || isNaN(t))
1064
+ throw new Error("cant cast to a number");
1065
+ return Number(t);
1066
+ }
1067
+ }
1068
+ class _ extends I {
1069
+ castFrom(t) {
1070
+ return String(t);
1071
+ }
1072
+ }
1073
+ class L extends $ {
1074
+ validate(t, e) {
1075
+ return this.validationRules.forEach((r) => r.validate(t, e)), Array.isArray(t) ? t.every((r) => super.validate(r, e)) : !0;
1076
+ }
1077
+ async save(t, e) {
1078
+ if (Array.isArray(t))
1079
+ return Promise.all(t.map((r) => super.save(r, e)));
1080
+ }
1081
+ async preProcess(t, e) {
1082
+ const r = /* @__PURE__ */ new Set();
1083
+ if (this.name && e.populateFields)
1084
+ for (const o in e.populateFields)
1085
+ (o == this.name || o.startsWith(`${this.name}.`)) && r.add(o);
1086
+ const n = this.name ? t[this.name] : t;
1087
+ return this.name && Array.isArray(n) && r.size > 0 ? await Promise.all(
1088
+ n.map((o, d) => {
1089
+ if (typeof o != "string" && typeof o != "number")
1090
+ return o;
1091
+ if (!g[this.ref])
1092
+ throw new Error(`Ref ${this.ref} model is not created`);
1093
+ return !r.has(this.name) && !r.has(`${this.name}.${d}`) ? o : new w(e.idb, this.ref).findById(o, {
1094
+ Constructor: g[this.ref],
1095
+ // need to remove the prefix for nested objects
1096
+ // populateFields: options.populateFields,
1097
+ transaction: e.transaction
1098
+ });
1099
+ })
1100
+ ) : n;
1101
+ }
1102
+ castFrom(t) {
1103
+ if (Array.isArray(t))
1104
+ return t.map((e) => super.castFrom(e));
1105
+ }
1106
+ }
1107
+ class x extends I {
1108
+ refNames;
1109
+ tree;
1110
+ rawDefinition;
1111
+ constructor(t) {
1112
+ super(), this.rawDefinition = t, this.tree = {}, this.refNames = [];
1113
+ for (let e in t)
1114
+ "type" in this.rawDefinition[e] && (this.rawDefinition[e] = {
1115
+ ...this.rawDefinition[e]
1116
+ }), this.tree[e] = this.parseSchemaDefinition(e, t[e]);
1117
+ this.tree._id || (this.tree._id = new _({ name: "_id", required: !0 }));
1118
+ }
1119
+ parseSchemaDefinition(t, e) {
1120
+ const r = "type" in e ? e.type : e, n = {
1121
+ name: t,
1122
+ required: void 0
1123
+ };
1124
+ if ("type" in e && (n.required = e.required), r === String)
1125
+ return "ref" in e && e.ref ? (this.refNames.push(e.ref), new $({
1126
+ name: t,
1127
+ ref: e.ref,
1128
+ valueSchema: new _(n),
1129
+ required: e.required
1130
+ })) : new _(n);
1131
+ if (r === Number) {
1132
+ const o = n;
1133
+ return "min" in e && (o.min = e.min), "ref" in e && e.ref ? (this.refNames.push(e.ref), new $({
1134
+ name: t,
1135
+ ref: e.ref,
1136
+ valueSchema: new B(o),
1137
+ required: e.required
1138
+ })) : new B(o);
1139
+ } else if (Array.isArray(r)) {
1140
+ if (r.length === 0)
1141
+ throw new Error("Array type must have a value type");
1142
+ return "ref" in r[0] && r[0].ref ? (this.refNames.push(r[0].ref), new L({
1143
+ name: t,
1144
+ ref: r[0].ref,
1145
+ valueSchema: this.parseSchemaDefinition(t, r[0].type),
1146
+ required: r[0].required
1147
+ })) : new R({
1148
+ valueSchema: this.parseSchemaDefinition(t, r[0]),
1149
+ ...n
1150
+ });
1151
+ } else if (r instanceof x)
1152
+ return r.clone();
1153
+ throw new Error(`Type for ${t} is not supported`);
1154
+ }
1155
+ getRefNames() {
1156
+ return this.refNames;
1157
+ }
1158
+ clone() {
1159
+ return new x(
1160
+ this.rawDefinition
1161
+ );
1162
+ }
1163
+ async save(t, e) {
1164
+ if (!t || typeof t != "object")
1165
+ throw new Error("value must be an Object");
1166
+ for (const r in this.tree)
1167
+ await this.tree[r].save(t[r], e);
1168
+ }
1169
+ validate(t, e) {
1170
+ if (!t || typeof t != "object")
1171
+ throw new Error("value must be an Object");
1172
+ for (const r in this.tree)
1173
+ this.tree[r].validate(t[r], e);
1174
+ return !0;
1175
+ }
1176
+ async preProcess(t, e) {
1177
+ const r = {};
1178
+ for (const n in t)
1179
+ this.tree[n] && (r[n] = await this.tree[n].preProcess(t, e));
1180
+ return r;
1181
+ }
1182
+ castFrom(t) {
1183
+ if (!t || typeof t != "object")
1184
+ throw new Error("Cant cast value to object schema");
1185
+ const e = {};
1186
+ for (const r in this.tree)
1187
+ e[r] = this.tree[r].castFrom(t[r]);
1188
+ return e;
8
1189
  }
9
1190
  }
10
- const d = (o, e) => o + e;
1191
+ const V = async (s) => {
1192
+ const { models: t, db: e, version: r, onupgradeneeded: n } = s;
1193
+ return new Promise((o, d) => {
1194
+ const c = indexedDB.open(e, r);
1195
+ c.onerror = d, c.onsuccess = function() {
1196
+ t.forEach((u) => {
1197
+ u.init(this.result);
1198
+ }), o(this.result);
1199
+ }, c.onupgradeneeded = function() {
1200
+ t.forEach((u) => {
1201
+ u.onUpgradeNeeded(this.result);
1202
+ }), n && n(this);
1203
+ };
1204
+ });
1205
+ };
11
1206
  export {
12
- r as IModel,
13
- d as add
1207
+ F as AbstractModel,
1208
+ x as Schema,
1209
+ V as configureIDB,
1210
+ T as model
14
1211
  };