locality-idb 1.0.1 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -16
- package/dist/index.cjs +151 -41
- package/dist/index.d.cts +43 -13
- package/dist/index.d.mts +43 -13
- package/dist/index.iife.js +151 -41
- package/dist/index.mjs +151 -41
- package/dist/index.umd.js +151 -41
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -128,7 +128,7 @@ const users = await db.from('users').findAll();
|
|
|
128
128
|
const alice = await db
|
|
129
129
|
.from('users')
|
|
130
130
|
.where((user) => user.email === 'alice@example.com')
|
|
131
|
-
.
|
|
131
|
+
.findFirst();
|
|
132
132
|
|
|
133
133
|
// Update data
|
|
134
134
|
await db
|
|
@@ -400,7 +400,7 @@ const topTenUsers = await db
|
|
|
400
400
|
const user = await db
|
|
401
401
|
.from('users')
|
|
402
402
|
.where((user) => user.email === 'john@example.com')
|
|
403
|
-
.
|
|
403
|
+
.findFirst();
|
|
404
404
|
// Returns: User | null
|
|
405
405
|
```
|
|
406
406
|
|
|
@@ -467,7 +467,7 @@ const names = await db
|
|
|
467
467
|
.findAll();
|
|
468
468
|
```
|
|
469
469
|
|
|
470
|
-
> **Note:** `sortByIndex()` uses IndexedDB cursor iteration for optimal performance when
|
|
470
|
+
> **Note:** `sortByIndex()` uses IndexedDB cursor iteration for optimal performance when `where()` filter is applied without index.
|
|
471
471
|
|
|
472
472
|
#### Chain Multiple Methods
|
|
473
473
|
|
|
@@ -787,6 +787,32 @@ Filters rows based on a predicate function.
|
|
|
787
787
|
db.from('users').where((user) => user.age >= 18)
|
|
788
788
|
```
|
|
789
789
|
|
|
790
|
+
##### `where<IdxKey>(indexName: IdxKey, query: T[IdxKey] | IDBKeyRange): SelectQuery`
|
|
791
|
+
|
|
792
|
+
Filters rows using an indexed field.
|
|
793
|
+
|
|
794
|
+
```typescript
|
|
795
|
+
db.from('users').where('age', IDBKeyRange.bound(18, 30))
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
##### `sortByIndex<IdxKey>(indexName: IdxKey, dir?: 'asc' | 'desc'): SelectQuery`
|
|
799
|
+
|
|
800
|
+
Sorts results by an indexed field using IndexedDB cursor iteration (avoiding in-memory sorting).
|
|
801
|
+
|
|
802
|
+
**Type Safety:** `indexName` must be a field with an index.
|
|
803
|
+
|
|
804
|
+
**Performance:** Uses IndexedDB's cursor for optimized sorting. For large datasets, this is significantly more efficient than in-memory sorting.
|
|
805
|
+
|
|
806
|
+
> For sorting on non-indexed fields, use [`orderBy()`](#orderbykeykey-key-direction-asc--desc-selectquery) which performs in-memory sorting.
|
|
807
|
+
|
|
808
|
+
```typescript
|
|
809
|
+
// Optimized cursor-based sort
|
|
810
|
+
const sorted = await db.from('users').sortByIndex('age', 'desc').findAll();
|
|
811
|
+
|
|
812
|
+
// Efficient pagination
|
|
813
|
+
const page = await db.from('users').sortByIndex('createdAt', 'desc').limit(20).findAll();
|
|
814
|
+
```
|
|
815
|
+
|
|
790
816
|
##### `orderBy<Key>(key: Key, direction?: 'asc' | 'desc'): SelectQuery`
|
|
791
817
|
|
|
792
818
|
Orders results by a specified key. Supports nested keys using dot notation.
|
|
@@ -796,6 +822,8 @@ db.from('users').orderBy('name', 'asc')
|
|
|
796
822
|
db.from('users').orderBy('profile.age', 'desc')
|
|
797
823
|
```
|
|
798
824
|
|
|
825
|
+
> **Note:** This method performs in-memory sorting. For large datasets, consider using [`sortByIndex()`](#sortbyindexidxkeyindexname-idxkey-dir-asc--desc-selectquery) with an indexed field for better performance.
|
|
826
|
+
|
|
799
827
|
##### `limit(count: number): SelectQuery`
|
|
800
828
|
|
|
801
829
|
Limits the number of results.
|
|
@@ -812,12 +840,12 @@ Fetches all matching records.
|
|
|
812
840
|
const users = await db.from('users').findAll()
|
|
813
841
|
```
|
|
814
842
|
|
|
815
|
-
##### `
|
|
843
|
+
##### `findFirst(): Promise<T | null>`
|
|
816
844
|
|
|
817
845
|
Fetches the first matching record.
|
|
818
846
|
|
|
819
847
|
```typescript
|
|
820
|
-
const user = await db.from('users').
|
|
848
|
+
const user = await db.from('users').findFirst()
|
|
821
849
|
```
|
|
822
850
|
|
|
823
851
|
##### `findByPk<Key>(key: Key): Promise<T | null>`
|
|
@@ -828,10 +856,10 @@ Finds a single record by its primary key value using IndexedDB's optimized `get(
|
|
|
828
856
|
|
|
829
857
|
```typescript
|
|
830
858
|
const user = await db.from('users').findByPk(1);
|
|
831
|
-
const post = await db.from('posts').findByPk('uuid-string');
|
|
859
|
+
const post = await db.from('posts').findByPk('some-uuid-string');
|
|
832
860
|
```
|
|
833
861
|
|
|
834
|
-
##### `findByIndex<
|
|
862
|
+
##### `findByIndex<IdxKey>(indexName: IdxKey, query: T[IdxKey] | IDBKeyRange): Promise<T[]>`
|
|
835
863
|
|
|
836
864
|
Finds records using an indexed field. Only accepts field names that are marked with `.index()` or `.unique()`.
|
|
837
865
|
|
|
@@ -852,22 +880,31 @@ const adults = await db.from('users').findByIndex('age', IDBKeyRange.bound(18, 6
|
|
|
852
880
|
> - Unique columns are automatically indexed.
|
|
853
881
|
> - Unique indexes are recommended for this method to ensure a single result.
|
|
854
882
|
|
|
855
|
-
##### `
|
|
883
|
+
##### `count(): Promise<number>`
|
|
856
884
|
|
|
857
|
-
|
|
885
|
+
Counts the number of matching records.
|
|
858
886
|
|
|
859
|
-
|
|
887
|
+
```typescript
|
|
888
|
+
const userCount = await db.from('users').where((user) => user.isActive).count()
|
|
889
|
+
```
|
|
860
890
|
|
|
861
|
-
**
|
|
891
|
+
> **Note:**
|
|
892
|
+
>
|
|
893
|
+
> - This method internally uses IndexedDB's `count()` for optimal performance.
|
|
894
|
+
> - If a `where()` filter is applied without index, it falls back to in-memory counting.
|
|
862
895
|
|
|
863
|
-
|
|
864
|
-
// Optimized cursor-based sort
|
|
865
|
-
const sorted = await db.from('users').sortByIndex('age', 'desc').findAll();
|
|
896
|
+
##### `exists(): Promise<boolean>`
|
|
866
897
|
|
|
867
|
-
|
|
868
|
-
|
|
898
|
+
Checks if any matching records exist.
|
|
899
|
+
|
|
900
|
+
```typescript
|
|
901
|
+
const hasAdmins = await db.from('users').where((user) => user.role === 'admin').exists()
|
|
869
902
|
```
|
|
870
903
|
|
|
904
|
+
> **Note:** This method internally uses [`count()`](#count-promisenumber) for checking existence.
|
|
905
|
+
|
|
906
|
+
---
|
|
907
|
+
|
|
871
908
|
#### InsertQuery Methods
|
|
872
909
|
|
|
873
910
|
##### `values<T>(data: T | T[]): InsertQuery`
|
|
@@ -913,6 +950,8 @@ Executes the update query and returns the number of updated records.
|
|
|
913
950
|
const count = await db.update('users').set({ name: 'Jane' }).run()
|
|
914
951
|
```
|
|
915
952
|
|
|
953
|
+
---
|
|
954
|
+
|
|
916
955
|
#### DeleteQuery Methods
|
|
917
956
|
|
|
918
957
|
##### `where(predicate: (row: T) => boolean): DeleteQuery`
|
package/dist/index.cjs
CHANGED
|
@@ -12,6 +12,9 @@ function isInteger(value) {
|
|
|
12
12
|
function isBoolean(value) {
|
|
13
13
|
return typeof value === "boolean";
|
|
14
14
|
}
|
|
15
|
+
function isUndefined(value) {
|
|
16
|
+
return value === void 0;
|
|
17
|
+
}
|
|
15
18
|
function isBigInt(value) {
|
|
16
19
|
return typeof value === "bigint";
|
|
17
20
|
}
|
|
@@ -33,6 +36,9 @@ function isObject(value) {
|
|
|
33
36
|
function isNotEmptyObject(value) {
|
|
34
37
|
return isObject(value) && Object.keys(value)?.length > 0;
|
|
35
38
|
}
|
|
39
|
+
function isFunction(value) {
|
|
40
|
+
return typeof value === "function";
|
|
41
|
+
}
|
|
36
42
|
function isDate(value) {
|
|
37
43
|
return value instanceof Date;
|
|
38
44
|
}
|
|
@@ -456,6 +462,8 @@ var SelectQuery = class {
|
|
|
456
462
|
#readyPromise;
|
|
457
463
|
#dbGetter;
|
|
458
464
|
#whereCondition;
|
|
465
|
+
#whereIndexName;
|
|
466
|
+
#whereIndexQuery;
|
|
459
467
|
#orderByKey;
|
|
460
468
|
#orderByDir = "asc";
|
|
461
469
|
#limitCount;
|
|
@@ -465,6 +473,49 @@ var SelectQuery = class {
|
|
|
465
473
|
this.#dbGetter = dbGetter;
|
|
466
474
|
this.#readyPromise = readyPromise;
|
|
467
475
|
}
|
|
476
|
+
#createTransaction() {
|
|
477
|
+
return this.#dbGetter().transaction(this.#table, "readonly");
|
|
478
|
+
}
|
|
479
|
+
#getStoreWithTransaction() {
|
|
480
|
+
return this.#createTransaction().objectStore(this.#table);
|
|
481
|
+
}
|
|
482
|
+
/** @internal Check if key is an index on the store for the `#whereIndexName` */
|
|
483
|
+
#isIndexKey(store) {
|
|
484
|
+
return isNonEmptyString(this.#whereIndexName) && store.indexNames.contains(this.#whereIndexName);
|
|
485
|
+
}
|
|
486
|
+
/** @internal Check if key is the primary key on the store for the `#whereIndexName` */
|
|
487
|
+
#isPrimaryKey(store) {
|
|
488
|
+
return isNonEmptyString(this.#whereIndexName) && store.keyPath === this.#whereIndexName;
|
|
489
|
+
}
|
|
490
|
+
/** @internal Build indexed store (primary key or index) for where queries */
|
|
491
|
+
#buildIndexedStore(store, reject) {
|
|
492
|
+
const isPK = this.#isPrimaryKey(store);
|
|
493
|
+
const isIndex = this.#isIndexKey(store);
|
|
494
|
+
if (!isPK && !isIndex) {
|
|
495
|
+
reject(/* @__PURE__ */ new RangeError(`Index '${this.#whereIndexName}' does not exist on table '${this.#table}'`));
|
|
496
|
+
return null;
|
|
497
|
+
}
|
|
498
|
+
return isPK ? store : store.index(this.#whereIndexName);
|
|
499
|
+
}
|
|
500
|
+
/** @internal Sort data in memory if needed */
|
|
501
|
+
#sort(data) {
|
|
502
|
+
if (this.#orderByKey) return sortAnArray(data, {
|
|
503
|
+
sortOrder: this.#orderByDir,
|
|
504
|
+
sortByField: this.#orderByKey
|
|
505
|
+
});
|
|
506
|
+
return data;
|
|
507
|
+
}
|
|
508
|
+
/** Projects a row based on selected fields */
|
|
509
|
+
#projectRow(row) {
|
|
510
|
+
if (!isNotEmptyObject(this?.[Selected])) return row;
|
|
511
|
+
const projected = {};
|
|
512
|
+
const selectionEntries = Object.entries(this[Selected]);
|
|
513
|
+
const selectionKeys = new Set(Object.keys(this[Selected]));
|
|
514
|
+
if (selectionEntries.some(([, value]) => value === true)) {
|
|
515
|
+
for (const [key, value] of selectionEntries) if (value === true) projected[key] = row[key];
|
|
516
|
+
} else for (const key of Object.keys(row)) if (!selectionKeys.has(key) || this[Selected][key] !== false) projected[key] = row[key];
|
|
517
|
+
return projected;
|
|
518
|
+
}
|
|
468
519
|
/**
|
|
469
520
|
* @instance Select or exclude specific columns
|
|
470
521
|
* @param cols Columns to select or exclude
|
|
@@ -473,18 +524,26 @@ var SelectQuery = class {
|
|
|
473
524
|
this[Selected] = cols;
|
|
474
525
|
return this;
|
|
475
526
|
}
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
527
|
+
where(condition, query) {
|
|
528
|
+
if (isFunction(condition)) {
|
|
529
|
+
this.#whereCondition = condition;
|
|
530
|
+
this.#whereIndexName = void 0;
|
|
531
|
+
this.#whereIndexQuery = void 0;
|
|
532
|
+
} else if (isNonEmptyString(condition) && !isUndefined(query)) {
|
|
533
|
+
this.#whereIndexName = condition;
|
|
534
|
+
this.#whereIndexQuery = query;
|
|
535
|
+
this.#whereCondition = void 0;
|
|
536
|
+
}
|
|
482
537
|
return this;
|
|
483
538
|
}
|
|
484
539
|
/**
|
|
485
540
|
* @instance Order results by specified key and direction
|
|
486
541
|
* @param key Key to order by
|
|
487
542
|
* @param dir Direction: 'asc' | 'desc' (default: 'asc')
|
|
543
|
+
*
|
|
544
|
+
* @remarks
|
|
545
|
+
* - This method performs in-memory sorting.
|
|
546
|
+
* - For optimized sorting using `IndexedDB` indexes, use {@link sortByIndex} instead.
|
|
488
547
|
*/
|
|
489
548
|
orderBy(key, dir = "asc") {
|
|
490
549
|
this.#orderByKey = key;
|
|
@@ -492,6 +551,22 @@ var SelectQuery = class {
|
|
|
492
551
|
return this;
|
|
493
552
|
}
|
|
494
553
|
/**
|
|
554
|
+
* @instance Order results by index using optimized `IndexedDB` cursor
|
|
555
|
+
* @param indexName Name of the index to sort by
|
|
556
|
+
* @param dir Direction: 'asc' | 'desc' (default: 'asc')
|
|
557
|
+
*
|
|
558
|
+
* @remarks
|
|
559
|
+
* - This method uses `IndexedDB` indexes for sorting, which is more efficient for large datasets.
|
|
560
|
+
* - Ensure that the specified index exists on the table.
|
|
561
|
+
* - For in-memory sorting, use {@link orderBy} instead.
|
|
562
|
+
*/
|
|
563
|
+
sortByIndex(indexName, dir = "asc") {
|
|
564
|
+
this.#orderByKey = indexName;
|
|
565
|
+
this.#orderByDir = dir;
|
|
566
|
+
this.#useIndexCursor = true;
|
|
567
|
+
return this;
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
495
570
|
* @instance Limit number of results
|
|
496
571
|
* @param count Maximum number of results to return
|
|
497
572
|
*/
|
|
@@ -499,21 +574,23 @@ var SelectQuery = class {
|
|
|
499
574
|
this.#limitCount = count;
|
|
500
575
|
return this;
|
|
501
576
|
}
|
|
502
|
-
/** Projects a row based on selected fields */
|
|
503
|
-
#projectRow(row) {
|
|
504
|
-
if (!isNotEmptyObject(this?.[Selected])) return row;
|
|
505
|
-
const projected = {};
|
|
506
|
-
const selectionEntries = Object.entries(this[Selected]);
|
|
507
|
-
const selectionKeys = new Set(Object.keys(this[Selected]));
|
|
508
|
-
if (selectionEntries.some(([, value]) => value === true)) {
|
|
509
|
-
for (const [key, value] of selectionEntries) if (value === true) projected[key] = row[key];
|
|
510
|
-
} else for (const key of Object.keys(row)) if (!selectionKeys.has(key) || this[Selected][key] !== false) projected[key] = row[key];
|
|
511
|
-
return projected;
|
|
512
|
-
}
|
|
513
577
|
async findAll() {
|
|
514
578
|
await this.#readyPromise;
|
|
515
579
|
return new Promise((resolve, reject) => {
|
|
516
|
-
const store = this.#
|
|
580
|
+
const store = this.#getStoreWithTransaction();
|
|
581
|
+
if (this.#whereIndexName && !isUndefined(this.#whereIndexQuery)) {
|
|
582
|
+
const source = this.#buildIndexedStore(store, reject);
|
|
583
|
+
if (!source) return;
|
|
584
|
+
const request = source.getAll(this.#whereIndexQuery);
|
|
585
|
+
request.onsuccess = () => {
|
|
586
|
+
let results = request.result;
|
|
587
|
+
results = this.#sort(results);
|
|
588
|
+
if (this.#limitCount) results = results.slice(0, this.#limitCount);
|
|
589
|
+
resolve(results.map((row) => this.#projectRow(row)));
|
|
590
|
+
};
|
|
591
|
+
request.onerror = () => reject(request.error);
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
517
594
|
if (this.#useIndexCursor && this.#orderByKey && isNonEmptyString(this.#orderByKey) && store.indexNames.contains(this.#orderByKey) && !this.#whereCondition) {
|
|
518
595
|
const index = store.index(this.#orderByKey);
|
|
519
596
|
const direction = this.#orderByDir === "desc" ? "prev" : "next";
|
|
@@ -546,10 +623,23 @@ var SelectQuery = class {
|
|
|
546
623
|
}
|
|
547
624
|
});
|
|
548
625
|
}
|
|
549
|
-
async
|
|
626
|
+
async findFirst() {
|
|
550
627
|
await this.#readyPromise;
|
|
551
628
|
return new Promise((resolve, reject) => {
|
|
552
|
-
const
|
|
629
|
+
const store = this.#getStoreWithTransaction();
|
|
630
|
+
if (this.#whereIndexName && !isUndefined(this.#whereIndexQuery)) {
|
|
631
|
+
const source = this.#buildIndexedStore(store, reject);
|
|
632
|
+
if (!source) return;
|
|
633
|
+
const request = source.getAll(this.#whereIndexQuery);
|
|
634
|
+
request.onsuccess = () => {
|
|
635
|
+
const results = request.result;
|
|
636
|
+
if (results.length > 0) resolve(this.#projectRow(results[0]));
|
|
637
|
+
else resolve(null);
|
|
638
|
+
};
|
|
639
|
+
request.onerror = () => reject(request.error);
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
const request = store.getAll();
|
|
553
643
|
request.onsuccess = () => {
|
|
554
644
|
let results = request.result;
|
|
555
645
|
if (this.#whereCondition) results = results.filter(this.#whereCondition);
|
|
@@ -562,11 +652,16 @@ var SelectQuery = class {
|
|
|
562
652
|
/**
|
|
563
653
|
* @instance Find record by primary key (optimized `IndexedDB` get)
|
|
564
654
|
* @param key Primary key value
|
|
655
|
+
*
|
|
656
|
+
* @remarks
|
|
657
|
+
* - This method uses the `IndexedDB` primary key for efficient querying.
|
|
658
|
+
* - Ensure that the specified key exists on the table.
|
|
659
|
+
* - To find by index, use {@link findByIndex} instead.
|
|
565
660
|
*/
|
|
566
661
|
async findByPk(key) {
|
|
567
662
|
await this.#readyPromise;
|
|
568
663
|
return new Promise((resolve, reject) => {
|
|
569
|
-
const request = this.#
|
|
664
|
+
const request = this.#getStoreWithTransaction().get(key);
|
|
570
665
|
request.onsuccess = () => {
|
|
571
666
|
const result = request.result;
|
|
572
667
|
if (!result) {
|
|
@@ -583,16 +678,21 @@ var SelectQuery = class {
|
|
|
583
678
|
});
|
|
584
679
|
}
|
|
585
680
|
/**
|
|
586
|
-
* @instance Find records by index (optimized IndexedDB index query)
|
|
681
|
+
* @instance Find records by index (optimized `IndexedDB` index query)
|
|
587
682
|
* @param indexName Name of the index to query
|
|
588
683
|
* @param query Key value to search for
|
|
684
|
+
*
|
|
685
|
+
* @remarks
|
|
686
|
+
* - This method uses `IndexedDB` indexes for efficient querying.
|
|
687
|
+
* - Ensure that the specified index exists on the table.
|
|
688
|
+
* - To find by primary key, use {@link findByPk} instead.
|
|
589
689
|
*/
|
|
590
690
|
async findByIndex(indexName, query) {
|
|
591
691
|
await this.#readyPromise;
|
|
592
692
|
return new Promise((resolve, reject) => {
|
|
593
|
-
const store = this.#
|
|
693
|
+
const store = this.#getStoreWithTransaction();
|
|
594
694
|
if (!store.indexNames.contains(indexName)) {
|
|
595
|
-
reject(/* @__PURE__ */ new Error(`Index
|
|
695
|
+
reject(/* @__PURE__ */ new Error(`Index '${indexName}' does not exist on table '${this.#table}'`));
|
|
596
696
|
return;
|
|
597
697
|
}
|
|
598
698
|
const request = store.index(indexName).getAll(query);
|
|
@@ -606,24 +706,34 @@ var SelectQuery = class {
|
|
|
606
706
|
request.onerror = () => reject(request.error);
|
|
607
707
|
});
|
|
608
708
|
}
|
|
609
|
-
/**
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
709
|
+
/** @instance Count matching records */
|
|
710
|
+
async count() {
|
|
711
|
+
await this.#readyPromise;
|
|
712
|
+
return new Promise((resolve, reject) => {
|
|
713
|
+
const store = this.#getStoreWithTransaction();
|
|
714
|
+
if (this.#whereIndexName && !isUndefined(this.#whereIndexQuery)) {
|
|
715
|
+
const source = this.#buildIndexedStore(store, reject);
|
|
716
|
+
if (!source) return;
|
|
717
|
+
const request = source.count(this.#whereIndexQuery);
|
|
718
|
+
request.onsuccess = () => resolve(request.result);
|
|
719
|
+
request.onerror = () => reject(request.error);
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
if (this.#whereCondition) {
|
|
723
|
+
const request = store.getAll();
|
|
724
|
+
request.onsuccess = () => {
|
|
725
|
+
resolve(request.result.filter(this.#whereCondition).length);
|
|
726
|
+
};
|
|
727
|
+
request.onerror = () => reject(request.error);
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
const request = store.count();
|
|
731
|
+
request.onsuccess = () => resolve(request.result);
|
|
732
|
+
request.onerror = () => reject(request.error);
|
|
625
733
|
});
|
|
626
|
-
|
|
734
|
+
}
|
|
735
|
+
async exists() {
|
|
736
|
+
return await this.count() > 0;
|
|
627
737
|
}
|
|
628
738
|
};
|
|
629
739
|
/** @class Insert query builder. */
|
package/dist/index.d.cts
CHANGED
|
@@ -329,6 +329,8 @@ type $InferTimestamp<T extends ColumnDefinition> = { [K in keyof T]: T[K] extend
|
|
|
329
329
|
type Timestamp = Branded<string, 'Timestamp'>;
|
|
330
330
|
/** Sort direction type for ordering queries */
|
|
331
331
|
type SortDirection = 'asc' | 'desc';
|
|
332
|
+
/** Predicate function type for WHERE clauses in queries */
|
|
333
|
+
type WherePredicate<T extends GenericObject> = (row: T) => boolean;
|
|
332
334
|
/** Creates a type for insert operations with auto-generated fields optional. */
|
|
333
335
|
type InferInsertType<T extends Table> = Prettify<Omit<$InferRow<T['columns']>, $InferAutoInc<T['columns']> | $InferDefault<T['columns']> | $InferTimestamp<T['columns']> | $InferUUID<T['columns']>> & { [K in $InferAutoInc<T['columns']> | $InferDefault<T['columns']> | $InferTimestamp<T['columns']> | $InferUUID<T['columns']>]?: K extends keyof $InferRow<T['columns']> ? $InferRow<T['columns']>[K] : never }>;
|
|
334
336
|
/** Creates a type for update operations with all fields optional except primary key. */
|
|
@@ -376,13 +378,34 @@ declare class SelectQuery<T extends GenericObject, S extends Partial<Record<stri
|
|
|
376
378
|
* @instance Filter rows based on predicate function
|
|
377
379
|
* @param predicate Filtering function
|
|
378
380
|
*/
|
|
379
|
-
where(predicate:
|
|
381
|
+
where(predicate: WherePredicate<T>): this;
|
|
382
|
+
/**
|
|
383
|
+
* @instance Filter rows based on index query
|
|
384
|
+
* @param indexName Name of the index/primary key to query
|
|
385
|
+
* @param query Key value or {@link IDBKeyRange} to search for
|
|
386
|
+
*/
|
|
387
|
+
where<IdxKey extends $InferPrimaryKey<Tbl['columns']> | $InferIndex<Tbl['columns']>>(indexName: IdxKey, query: IDBKeyRange | T[IdxKey]): this;
|
|
380
388
|
/**
|
|
381
389
|
* @instance Order results by specified key and direction
|
|
382
390
|
* @param key Key to order by
|
|
383
391
|
* @param dir Direction: 'asc' | 'desc' (default: 'asc')
|
|
392
|
+
*
|
|
393
|
+
* @remarks
|
|
394
|
+
* - This method performs in-memory sorting.
|
|
395
|
+
* - For optimized sorting using `IndexedDB` indexes, use {@link sortByIndex} instead.
|
|
384
396
|
*/
|
|
385
397
|
orderBy<Key extends NestedPrimitiveKey<T>>(key: Key, dir?: SortDirection): this;
|
|
398
|
+
/**
|
|
399
|
+
* @instance Order results by index using optimized `IndexedDB` cursor
|
|
400
|
+
* @param indexName Name of the index to sort by
|
|
401
|
+
* @param dir Direction: 'asc' | 'desc' (default: 'asc')
|
|
402
|
+
*
|
|
403
|
+
* @remarks
|
|
404
|
+
* - This method uses `IndexedDB` indexes for sorting, which is more efficient for large datasets.
|
|
405
|
+
* - Ensure that the specified index exists on the table.
|
|
406
|
+
* - For in-memory sorting, use {@link orderBy} instead.
|
|
407
|
+
*/
|
|
408
|
+
sortByIndex<IdxKey extends $InferIndex<Tbl['columns']> | $InferPrimaryKey<Tbl['columns']>>(indexName: IdxKey, dir?: SortDirection): this;
|
|
386
409
|
/**
|
|
387
410
|
* @instance Limit number of results
|
|
388
411
|
* @param count Maximum number of results to return
|
|
@@ -393,26 +416,33 @@ declare class SelectQuery<T extends GenericObject, S extends Partial<Record<stri
|
|
|
393
416
|
/** Fetch all matching records with selected fields */
|
|
394
417
|
findAll<Selection extends Partial<Record<keyof T, boolean>>>(this: SelectQuery<T, Selection>): Promise<SelectFields<T, Selection>[]>;
|
|
395
418
|
/** Fetch first matching record */
|
|
396
|
-
|
|
419
|
+
findFirst(this: SelectQuery<T, null>): Promise<T | null>;
|
|
397
420
|
/** Fetch first matching record with selected fields */
|
|
398
|
-
|
|
421
|
+
findFirst<Selection extends Partial<Record<keyof T, boolean>>>(this: SelectQuery<T, Selection>): Promise<SelectFields<T, Selection> | null>;
|
|
399
422
|
/**
|
|
400
423
|
* @instance Find record by primary key (optimized `IndexedDB` get)
|
|
401
424
|
* @param key Primary key value
|
|
425
|
+
*
|
|
426
|
+
* @remarks
|
|
427
|
+
* - This method uses the `IndexedDB` primary key for efficient querying.
|
|
428
|
+
* - Ensure that the specified key exists on the table.
|
|
429
|
+
* - To find by index, use {@link findByIndex} instead.
|
|
402
430
|
*/
|
|
403
431
|
findByPk(key: $InferPrimaryKey<Tbl['columns']> extends keyof T ? T[$InferPrimaryKey<Tbl['columns']>] : T[keyof T]): Promise<S extends null ? T | null : S extends Partial<Record<keyof T, boolean>> ? SelectFields<T, S> | null : never>;
|
|
404
432
|
/**
|
|
405
|
-
* @instance Find records by index (optimized IndexedDB index query)
|
|
433
|
+
* @instance Find records by index (optimized `IndexedDB` index query)
|
|
406
434
|
* @param indexName Name of the index to query
|
|
407
435
|
* @param query Key value to search for
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
*
|
|
412
|
-
*
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
436
|
+
*
|
|
437
|
+
* @remarks
|
|
438
|
+
* - This method uses `IndexedDB` indexes for efficient querying.
|
|
439
|
+
* - Ensure that the specified index exists on the table.
|
|
440
|
+
* - To find by primary key, use {@link findByPk} instead.
|
|
441
|
+
*/
|
|
442
|
+
findByIndex<IdxKey extends $InferIndex<Tbl['columns']> & keyof T & string>(indexName: IdxKey, query: T[IdxKey] | IDBKeyRange): Promise<S extends null ? T[] : S extends Partial<Record<keyof T, boolean>> ? SelectFields<T, S>[] : never>;
|
|
443
|
+
/** @instance Count matching records */
|
|
444
|
+
count(): Promise<number>;
|
|
445
|
+
exists(): Promise<boolean>;
|
|
416
446
|
}
|
|
417
447
|
/** @class Insert query builder. */
|
|
418
448
|
declare class InsertQuery<Raw extends GenericObject, Inserted extends Raw | Raw[], Data extends GenericObject, Return extends (Inserted extends Array<infer _> ? Data[] : Data)> {
|
|
@@ -848,4 +878,4 @@ declare function deleteDB(name: string): Promise<void>;
|
|
|
848
878
|
*/
|
|
849
879
|
declare function validateColumnType<T extends TypeName>(type: T, value: unknown): string | null;
|
|
850
880
|
//#endregion
|
|
851
|
-
export { $InferAutoInc, $InferDefault, $InferIndex, $InferOptional, $InferPrimaryKey, $InferRow, $InferTimestamp, $InferUUID, $InferUnique, $UUID, $UUIDVersion, $UnionToIntersection, $ValidateSinglePK, AdvancedTypes, ArrayToTuple, AsyncFunction, BasicPrimitive, Branded, type Column, ColumnDefinition, ColumnRecord, Constructor, DateLike, FirstOverloadParams, GenericFn, GenericObject, IndexConfig, IndexKeyType, InferInsertType, InferSelectType, InferUpdateType, List, Locality, LocalityConfig, LooseLiteral, MapObjectValues, Maybe, NestedPrimitiveKey, NormalPrimitive, Numeric, Prettify, PrimaryKeyType, Primitive, RejectFn, SchemaDefinition, SchemaRecord, SelectFields, SortDirection, StoreConfig, type Table, Timestamp, Tuple, TypeName, UUID, UUIDVersion, UniqueKeyType, ValidatedColumnDefinition, VoidFn, column, defineSchema, deleteDB, getTimestamp, isTimestamp, openDBWithStores, table, uuidV4, validateColumnType };
|
|
881
|
+
export { $InferAutoInc, $InferDefault, $InferIndex, $InferOptional, $InferPrimaryKey, $InferRow, $InferTimestamp, $InferUUID, $InferUnique, $UUID, $UUIDVersion, $UnionToIntersection, $ValidateSinglePK, AdvancedTypes, ArrayToTuple, AsyncFunction, BasicPrimitive, Branded, type Column, ColumnDefinition, ColumnRecord, Constructor, DateLike, FirstOverloadParams, GenericFn, GenericObject, IndexConfig, IndexKeyType, InferInsertType, InferSelectType, InferUpdateType, List, Locality, LocalityConfig, LooseLiteral, MapObjectValues, Maybe, NestedPrimitiveKey, NormalPrimitive, Numeric, Prettify, PrimaryKeyType, Primitive, RejectFn, SchemaDefinition, SchemaRecord, SelectFields, SortDirection, StoreConfig, type Table, Timestamp, Tuple, TypeName, UUID, UUIDVersion, UniqueKeyType, ValidatedColumnDefinition, VoidFn, WherePredicate, column, defineSchema, deleteDB, getTimestamp, isTimestamp, openDBWithStores, table, uuidV4, validateColumnType };
|
package/dist/index.d.mts
CHANGED
|
@@ -329,6 +329,8 @@ type $InferTimestamp<T extends ColumnDefinition> = { [K in keyof T]: T[K] extend
|
|
|
329
329
|
type Timestamp = Branded<string, 'Timestamp'>;
|
|
330
330
|
/** Sort direction type for ordering queries */
|
|
331
331
|
type SortDirection = 'asc' | 'desc';
|
|
332
|
+
/** Predicate function type for WHERE clauses in queries */
|
|
333
|
+
type WherePredicate<T extends GenericObject> = (row: T) => boolean;
|
|
332
334
|
/** Creates a type for insert operations with auto-generated fields optional. */
|
|
333
335
|
type InferInsertType<T extends Table> = Prettify<Omit<$InferRow<T['columns']>, $InferAutoInc<T['columns']> | $InferDefault<T['columns']> | $InferTimestamp<T['columns']> | $InferUUID<T['columns']>> & { [K in $InferAutoInc<T['columns']> | $InferDefault<T['columns']> | $InferTimestamp<T['columns']> | $InferUUID<T['columns']>]?: K extends keyof $InferRow<T['columns']> ? $InferRow<T['columns']>[K] : never }>;
|
|
334
336
|
/** Creates a type for update operations with all fields optional except primary key. */
|
|
@@ -376,13 +378,34 @@ declare class SelectQuery<T extends GenericObject, S extends Partial<Record<stri
|
|
|
376
378
|
* @instance Filter rows based on predicate function
|
|
377
379
|
* @param predicate Filtering function
|
|
378
380
|
*/
|
|
379
|
-
where(predicate:
|
|
381
|
+
where(predicate: WherePredicate<T>): this;
|
|
382
|
+
/**
|
|
383
|
+
* @instance Filter rows based on index query
|
|
384
|
+
* @param indexName Name of the index/primary key to query
|
|
385
|
+
* @param query Key value or {@link IDBKeyRange} to search for
|
|
386
|
+
*/
|
|
387
|
+
where<IdxKey extends $InferPrimaryKey<Tbl['columns']> | $InferIndex<Tbl['columns']>>(indexName: IdxKey, query: IDBKeyRange | T[IdxKey]): this;
|
|
380
388
|
/**
|
|
381
389
|
* @instance Order results by specified key and direction
|
|
382
390
|
* @param key Key to order by
|
|
383
391
|
* @param dir Direction: 'asc' | 'desc' (default: 'asc')
|
|
392
|
+
*
|
|
393
|
+
* @remarks
|
|
394
|
+
* - This method performs in-memory sorting.
|
|
395
|
+
* - For optimized sorting using `IndexedDB` indexes, use {@link sortByIndex} instead.
|
|
384
396
|
*/
|
|
385
397
|
orderBy<Key extends NestedPrimitiveKey<T>>(key: Key, dir?: SortDirection): this;
|
|
398
|
+
/**
|
|
399
|
+
* @instance Order results by index using optimized `IndexedDB` cursor
|
|
400
|
+
* @param indexName Name of the index to sort by
|
|
401
|
+
* @param dir Direction: 'asc' | 'desc' (default: 'asc')
|
|
402
|
+
*
|
|
403
|
+
* @remarks
|
|
404
|
+
* - This method uses `IndexedDB` indexes for sorting, which is more efficient for large datasets.
|
|
405
|
+
* - Ensure that the specified index exists on the table.
|
|
406
|
+
* - For in-memory sorting, use {@link orderBy} instead.
|
|
407
|
+
*/
|
|
408
|
+
sortByIndex<IdxKey extends $InferIndex<Tbl['columns']> | $InferPrimaryKey<Tbl['columns']>>(indexName: IdxKey, dir?: SortDirection): this;
|
|
386
409
|
/**
|
|
387
410
|
* @instance Limit number of results
|
|
388
411
|
* @param count Maximum number of results to return
|
|
@@ -393,26 +416,33 @@ declare class SelectQuery<T extends GenericObject, S extends Partial<Record<stri
|
|
|
393
416
|
/** Fetch all matching records with selected fields */
|
|
394
417
|
findAll<Selection extends Partial<Record<keyof T, boolean>>>(this: SelectQuery<T, Selection>): Promise<SelectFields<T, Selection>[]>;
|
|
395
418
|
/** Fetch first matching record */
|
|
396
|
-
|
|
419
|
+
findFirst(this: SelectQuery<T, null>): Promise<T | null>;
|
|
397
420
|
/** Fetch first matching record with selected fields */
|
|
398
|
-
|
|
421
|
+
findFirst<Selection extends Partial<Record<keyof T, boolean>>>(this: SelectQuery<T, Selection>): Promise<SelectFields<T, Selection> | null>;
|
|
399
422
|
/**
|
|
400
423
|
* @instance Find record by primary key (optimized `IndexedDB` get)
|
|
401
424
|
* @param key Primary key value
|
|
425
|
+
*
|
|
426
|
+
* @remarks
|
|
427
|
+
* - This method uses the `IndexedDB` primary key for efficient querying.
|
|
428
|
+
* - Ensure that the specified key exists on the table.
|
|
429
|
+
* - To find by index, use {@link findByIndex} instead.
|
|
402
430
|
*/
|
|
403
431
|
findByPk(key: $InferPrimaryKey<Tbl['columns']> extends keyof T ? T[$InferPrimaryKey<Tbl['columns']>] : T[keyof T]): Promise<S extends null ? T | null : S extends Partial<Record<keyof T, boolean>> ? SelectFields<T, S> | null : never>;
|
|
404
432
|
/**
|
|
405
|
-
* @instance Find records by index (optimized IndexedDB index query)
|
|
433
|
+
* @instance Find records by index (optimized `IndexedDB` index query)
|
|
406
434
|
* @param indexName Name of the index to query
|
|
407
435
|
* @param query Key value to search for
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
*
|
|
412
|
-
*
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
436
|
+
*
|
|
437
|
+
* @remarks
|
|
438
|
+
* - This method uses `IndexedDB` indexes for efficient querying.
|
|
439
|
+
* - Ensure that the specified index exists on the table.
|
|
440
|
+
* - To find by primary key, use {@link findByPk} instead.
|
|
441
|
+
*/
|
|
442
|
+
findByIndex<IdxKey extends $InferIndex<Tbl['columns']> & keyof T & string>(indexName: IdxKey, query: T[IdxKey] | IDBKeyRange): Promise<S extends null ? T[] : S extends Partial<Record<keyof T, boolean>> ? SelectFields<T, S>[] : never>;
|
|
443
|
+
/** @instance Count matching records */
|
|
444
|
+
count(): Promise<number>;
|
|
445
|
+
exists(): Promise<boolean>;
|
|
416
446
|
}
|
|
417
447
|
/** @class Insert query builder. */
|
|
418
448
|
declare class InsertQuery<Raw extends GenericObject, Inserted extends Raw | Raw[], Data extends GenericObject, Return extends (Inserted extends Array<infer _> ? Data[] : Data)> {
|
|
@@ -848,4 +878,4 @@ declare function deleteDB(name: string): Promise<void>;
|
|
|
848
878
|
*/
|
|
849
879
|
declare function validateColumnType<T extends TypeName>(type: T, value: unknown): string | null;
|
|
850
880
|
//#endregion
|
|
851
|
-
export { $InferAutoInc, $InferDefault, $InferIndex, $InferOptional, $InferPrimaryKey, $InferRow, $InferTimestamp, $InferUUID, $InferUnique, $UUID, $UUIDVersion, $UnionToIntersection, $ValidateSinglePK, AdvancedTypes, ArrayToTuple, AsyncFunction, BasicPrimitive, Branded, type Column, ColumnDefinition, ColumnRecord, Constructor, DateLike, FirstOverloadParams, GenericFn, GenericObject, IndexConfig, IndexKeyType, InferInsertType, InferSelectType, InferUpdateType, List, Locality, LocalityConfig, LooseLiteral, MapObjectValues, Maybe, NestedPrimitiveKey, NormalPrimitive, Numeric, Prettify, PrimaryKeyType, Primitive, RejectFn, SchemaDefinition, SchemaRecord, SelectFields, SortDirection, StoreConfig, type Table, Timestamp, Tuple, TypeName, UUID, UUIDVersion, UniqueKeyType, ValidatedColumnDefinition, VoidFn, column, defineSchema, deleteDB, getTimestamp, isTimestamp, openDBWithStores, table, uuidV4, validateColumnType };
|
|
881
|
+
export { $InferAutoInc, $InferDefault, $InferIndex, $InferOptional, $InferPrimaryKey, $InferRow, $InferTimestamp, $InferUUID, $InferUnique, $UUID, $UUIDVersion, $UnionToIntersection, $ValidateSinglePK, AdvancedTypes, ArrayToTuple, AsyncFunction, BasicPrimitive, Branded, type Column, ColumnDefinition, ColumnRecord, Constructor, DateLike, FirstOverloadParams, GenericFn, GenericObject, IndexConfig, IndexKeyType, InferInsertType, InferSelectType, InferUpdateType, List, Locality, LocalityConfig, LooseLiteral, MapObjectValues, Maybe, NestedPrimitiveKey, NormalPrimitive, Numeric, Prettify, PrimaryKeyType, Primitive, RejectFn, SchemaDefinition, SchemaRecord, SelectFields, SortDirection, StoreConfig, type Table, Timestamp, Tuple, TypeName, UUID, UUIDVersion, UniqueKeyType, ValidatedColumnDefinition, VoidFn, WherePredicate, column, defineSchema, deleteDB, getTimestamp, isTimestamp, openDBWithStores, table, uuidV4, validateColumnType };
|