locality-idb 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/index.cjs +174 -26
- package/dist/index.d.cts +84 -32
- package/dist/index.d.mts +84 -32
- package/dist/index.iife.js +173 -25
- package/dist/index.mjs +172 -26
- package/dist/index.umd.js +173 -25
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Locality IDB
|
|
2
2
|
|
|
3
|
+
> **SQL**-like query builder for [**IndexedDB**](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB) with [**Drizzle**](https://github.com/drizzle-team/drizzle-orm)-style API
|
|
4
|
+
|
|
3
5
|
<!-- markdownlint-disable-file MD024 -->
|
|
4
6
|
|
|
5
7
|
<div align="center">
|
|
@@ -11,8 +13,6 @@
|
|
|
11
13
|
<!--  -->
|
|
12
14
|

|
|
13
15
|
|
|
14
|
-
## SQL-like query builder for IndexedDB with Drizzle-style API
|
|
15
|
-
|
|
16
16
|
[Documentation](#-api-reference) • [Examples](#-usage) • [Contributing](#-contributing)
|
|
17
17
|
|
|
18
18
|
</div>
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
## ⚠️ Beta Status
|
|
23
23
|
|
|
24
|
-
>This package is currently in **beta
|
|
24
|
+
>This development of the package is currently in **beta stage**. The API is subject to change. Use in production at your own risk.
|
|
25
25
|
|
|
26
26
|
---
|
|
27
27
|
|
|
@@ -496,7 +496,7 @@ const query = db.delete('users');
|
|
|
496
496
|
|
|
497
497
|
### Schema Functions
|
|
498
498
|
|
|
499
|
-
#### `defineSchema<
|
|
499
|
+
#### `defineSchema<Schema extends ColumnRecord, Keys extends keyof Schema>(schema: Schema): SchemaRecord<Schema, Keys>`
|
|
500
500
|
|
|
501
501
|
Defines a database schema from an object mapping table names to column definitions.
|
|
502
502
|
|
package/dist/index.cjs
CHANGED
|
@@ -9,12 +9,12 @@ function isString(value) {
|
|
|
9
9
|
function isInteger(value) {
|
|
10
10
|
return isNumber(value) && Number.isInteger(value);
|
|
11
11
|
}
|
|
12
|
-
function isPositiveInteger(value) {
|
|
13
|
-
return isInteger(value) && value > 0;
|
|
14
|
-
}
|
|
15
12
|
function isBoolean(value) {
|
|
16
13
|
return typeof value === "boolean";
|
|
17
14
|
}
|
|
15
|
+
function isBigInt(value) {
|
|
16
|
+
return typeof value === "bigint";
|
|
17
|
+
}
|
|
18
18
|
function isNonEmptyString(value) {
|
|
19
19
|
return isString(value) && value?.length > 0;
|
|
20
20
|
}
|
|
@@ -33,9 +33,35 @@ function isObject(value) {
|
|
|
33
33
|
function isNotEmptyObject(value) {
|
|
34
34
|
return isObject(value) && Object.keys(value)?.length > 0;
|
|
35
35
|
}
|
|
36
|
+
function isDate(value) {
|
|
37
|
+
return value instanceof Date;
|
|
38
|
+
}
|
|
36
39
|
function isArrayOfType(value, typeCheck) {
|
|
37
40
|
return isArray(value) && value?.every(typeCheck);
|
|
38
41
|
}
|
|
42
|
+
function isSet(value) {
|
|
43
|
+
return value instanceof Set;
|
|
44
|
+
}
|
|
45
|
+
function isMap(value) {
|
|
46
|
+
return value instanceof Map;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region node_modules/.pnpm/nhb-toolbox@4.28.66/node_modules/nhb-toolbox/dist/esm/string/utilities.js
|
|
51
|
+
const extractNumbersFromString = (input) => {
|
|
52
|
+
return (input.match(/\d+/g) || [])?.map(Number);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
//#endregion
|
|
56
|
+
//#region node_modules/.pnpm/nhb-toolbox@4.28.66/node_modules/nhb-toolbox/dist/esm/guards/specials.js
|
|
57
|
+
function isUUID(value) {
|
|
58
|
+
const h = "[0-9a-f]";
|
|
59
|
+
const expr = new RegExp(`^${h}{8}-${h}{4}-[1-8]${h}{3}-[89ab]${h}{3}-${h}{12}$`, "i");
|
|
60
|
+
return isString(value) && expr.test(value);
|
|
61
|
+
}
|
|
62
|
+
function isNumericString(value) {
|
|
63
|
+
return isString(value) && value?.trim() !== "" && Number.isFinite(Number(value));
|
|
64
|
+
}
|
|
39
65
|
|
|
40
66
|
//#endregion
|
|
41
67
|
//#region node_modules/.pnpm/nhb-toolbox@4.28.66/node_modules/nhb-toolbox/dist/esm/array/sort.js
|
|
@@ -145,7 +171,7 @@ var Column = class {
|
|
|
145
171
|
"integer",
|
|
146
172
|
"float",
|
|
147
173
|
"number"
|
|
148
|
-
].includes(colType
|
|
174
|
+
].includes(colType)) throw new Error(`auto() can only be used with integer columns, got: ${colType}`);
|
|
149
175
|
this[IsAutoInc] = true;
|
|
150
176
|
return this;
|
|
151
177
|
}
|
|
@@ -178,7 +204,7 @@ var Table = class {
|
|
|
178
204
|
//#endregion
|
|
179
205
|
//#region src/factory.ts
|
|
180
206
|
/**
|
|
181
|
-
* * Opens an `IndexedDB` database with the specified stores.
|
|
207
|
+
* * Opens an `IndexedDB` database instance with the specified stores.
|
|
182
208
|
* @param name Database name
|
|
183
209
|
* @param stores Array of store configurations
|
|
184
210
|
* @param version Database version (default is `1`)
|
|
@@ -245,6 +271,122 @@ function getTimestamp(value) {
|
|
|
245
271
|
if (isNaN(date.getTime())) date = /* @__PURE__ */ new Date();
|
|
246
272
|
return date.toISOString();
|
|
247
273
|
}
|
|
274
|
+
/**
|
|
275
|
+
* * Check if a value is a valid Timestamp string in ISO 8601 format
|
|
276
|
+
* @param value The value to check
|
|
277
|
+
* @returns `true` if the value is a valid Timestamp, otherwise `false`
|
|
278
|
+
*/
|
|
279
|
+
function isTimestamp(value) {
|
|
280
|
+
return isNonEmptyString(value) && value.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/) !== null;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
//#endregion
|
|
284
|
+
//#region src/validators.ts
|
|
285
|
+
/**
|
|
286
|
+
* * Validate if a value matches the specified column data type
|
|
287
|
+
* @param type The column data type
|
|
288
|
+
* @param value The value to validate
|
|
289
|
+
* @returns `null` if valid, otherwise an error message string
|
|
290
|
+
*/
|
|
291
|
+
function validateColumnType(type, value) {
|
|
292
|
+
const strVal = JSON.stringify(value);
|
|
293
|
+
switch (type) {
|
|
294
|
+
case "int":
|
|
295
|
+
if (isInteger(type)) return null;
|
|
296
|
+
return `'${strVal}' is not an integer`;
|
|
297
|
+
case "float":
|
|
298
|
+
case "number":
|
|
299
|
+
if (isNumber(value)) return null;
|
|
300
|
+
return `'${strVal}' is not a ${type === "float" ? "float " : ""}number`;
|
|
301
|
+
case "numeric":
|
|
302
|
+
if (isNumericString(value) || isNumber(value)) return null;
|
|
303
|
+
return `'${strVal}' is not a numeric value`;
|
|
304
|
+
case "bigint":
|
|
305
|
+
if (isBigInt(value)) return null;
|
|
306
|
+
return `'${strVal}' is not a bigint`;
|
|
307
|
+
case "text":
|
|
308
|
+
case "string":
|
|
309
|
+
if (isString(value)) return null;
|
|
310
|
+
return `'${strVal}' is not a ${type === "text" ? "text " : ""}string`;
|
|
311
|
+
case "timestamp":
|
|
312
|
+
if (isTimestamp(value)) return null;
|
|
313
|
+
return `'${strVal}' is not a timestamp string`;
|
|
314
|
+
case "uuid":
|
|
315
|
+
if (isUUID(value)) return null;
|
|
316
|
+
return `'${strVal}' is not a UUID string`;
|
|
317
|
+
case "bool":
|
|
318
|
+
case "boolean":
|
|
319
|
+
if (isBoolean(value)) return null;
|
|
320
|
+
return `'${strVal}' is not a boolean`;
|
|
321
|
+
case "array":
|
|
322
|
+
if (isArray(value)) return null;
|
|
323
|
+
return `'${strVal}' is not an array`;
|
|
324
|
+
case "list":
|
|
325
|
+
if (isArray(value)) return null;
|
|
326
|
+
return `'${strVal}' is not a list`;
|
|
327
|
+
case "tuple":
|
|
328
|
+
if (isArray(value)) return null;
|
|
329
|
+
return `'${strVal}' is not a tuple`;
|
|
330
|
+
case "set":
|
|
331
|
+
if (isSet(value)) return null;
|
|
332
|
+
return `'${strVal}' is not a set`;
|
|
333
|
+
case "object":
|
|
334
|
+
if (isObject(value)) return null;
|
|
335
|
+
return `'${strVal}' is not an object`;
|
|
336
|
+
case "date":
|
|
337
|
+
if (isDate(value)) return null;
|
|
338
|
+
return `'${strVal}' is not a Date object`;
|
|
339
|
+
case "map":
|
|
340
|
+
if (isMap(value)) return null;
|
|
341
|
+
return `'${strVal}' is not a Map object`;
|
|
342
|
+
case "custom": return null;
|
|
343
|
+
default:
|
|
344
|
+
if (type.includes("varchar(")) {
|
|
345
|
+
if (isString(value)) {
|
|
346
|
+
const length = extractNumbersFromString(type)[0];
|
|
347
|
+
if (isNumber(length) && value.length <= length) return null;
|
|
348
|
+
return `'${strVal}' does not satisfy the constraint: varchar length ${length}`;
|
|
349
|
+
}
|
|
350
|
+
return `'${strVal}' is not a varchar string`;
|
|
351
|
+
}
|
|
352
|
+
if (type.includes("char(")) {
|
|
353
|
+
if (isString(value)) {
|
|
354
|
+
const length = extractNumbersFromString(type)[0];
|
|
355
|
+
if (isNumber(length) && value.length === length) return null;
|
|
356
|
+
return `'${strVal}' does not satisfy the constraint: char length ${length}`;
|
|
357
|
+
}
|
|
358
|
+
return `'${strVal}' is not a char string`;
|
|
359
|
+
}
|
|
360
|
+
return null;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* * Validate and prepare data for insertion or update based on column definitions
|
|
365
|
+
*
|
|
366
|
+
* @param data The data object to validate and prepare
|
|
367
|
+
* @param columns The column definitions
|
|
368
|
+
* @param keyPath The key path of the primary key column (if any)
|
|
369
|
+
* @param forUpdate Whether the operation is an update (default: `false`)
|
|
370
|
+
*
|
|
371
|
+
* @returns The validated and prepared data object
|
|
372
|
+
* @throws {TypeError} If any value does not match the expected column type
|
|
373
|
+
*/
|
|
374
|
+
function validateAndPrepareData(data, columns, keyPath, forUpdate = false) {
|
|
375
|
+
const prepared = { ...data };
|
|
376
|
+
if (columns) Object.entries(columns).forEach((entry) => {
|
|
377
|
+
const [fieldName, column] = entry;
|
|
378
|
+
const defaultValue = column[DefaultValue];
|
|
379
|
+
if (!(fieldName in prepared) && defaultValue !== void 0 && !forUpdate) prepared[fieldName] = defaultValue;
|
|
380
|
+
const columnType = column[ColumnType];
|
|
381
|
+
if (columnType === "uuid" && !(fieldName in prepared) && !forUpdate) prepared[fieldName] = uuidV4();
|
|
382
|
+
if (columnType === "timestamp" && !(fieldName in prepared) && !forUpdate) prepared[fieldName] = getTimestamp();
|
|
383
|
+
if (fieldName !== keyPath) {
|
|
384
|
+
const errorMsg = validateColumnType(columnType, prepared[fieldName]);
|
|
385
|
+
if (errorMsg) throw new TypeError(errorMsg);
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
return prepared;
|
|
389
|
+
}
|
|
248
390
|
|
|
249
391
|
//#endregion
|
|
250
392
|
//#region src/query.ts
|
|
@@ -351,11 +493,13 @@ var InsertQuery = class {
|
|
|
351
493
|
#readyPromise;
|
|
352
494
|
#dataToInsert = [];
|
|
353
495
|
#columns;
|
|
354
|
-
|
|
496
|
+
#keyPath;
|
|
497
|
+
constructor(table, dbGetter, readyPromise, columns, keyPath) {
|
|
355
498
|
this.#table = table;
|
|
356
499
|
this.#dbGetter = dbGetter;
|
|
357
500
|
this.#readyPromise = readyPromise;
|
|
358
501
|
this.#columns = columns;
|
|
502
|
+
this.#keyPath = keyPath;
|
|
359
503
|
}
|
|
360
504
|
/**
|
|
361
505
|
* @instance Sets the data to be inserted
|
|
@@ -378,15 +522,7 @@ var InsertQuery = class {
|
|
|
378
522
|
const insertedDocs = [];
|
|
379
523
|
const promises = this.#dataToInsert.map((data) => {
|
|
380
524
|
return new Promise((res, rej) => {
|
|
381
|
-
const
|
|
382
|
-
if (this.#columns) Object.entries(this.#columns).forEach(([fieldName, column]) => {
|
|
383
|
-
const defaultValue = column[DefaultValue];
|
|
384
|
-
if (!(fieldName in updated) && defaultValue !== void 0) updated[fieldName] = defaultValue;
|
|
385
|
-
const columnType = column[ColumnType];
|
|
386
|
-
if (columnType === "uuid" && !(fieldName in updated)) updated[fieldName] = uuidV4();
|
|
387
|
-
if (columnType === "timestamp" && !(fieldName in updated)) updated[fieldName] = getTimestamp();
|
|
388
|
-
});
|
|
389
|
-
const request = store.add(updated);
|
|
525
|
+
const request = store.add(validateAndPrepareData(data, this.#columns, this.#keyPath));
|
|
390
526
|
request.onsuccess = () => {
|
|
391
527
|
const key = request.result;
|
|
392
528
|
const getRequest = store.get(key);
|
|
@@ -411,10 +547,14 @@ var UpdateQuery = class {
|
|
|
411
547
|
#readyPromise;
|
|
412
548
|
#dataToUpdate;
|
|
413
549
|
#whereCondition;
|
|
414
|
-
|
|
550
|
+
#columns;
|
|
551
|
+
#keyPath;
|
|
552
|
+
constructor(table, dbGetter, readyPromise, columns, keyPath) {
|
|
415
553
|
this.#table = table;
|
|
416
554
|
this.#dbGetter = dbGetter;
|
|
417
555
|
this.#readyPromise = readyPromise;
|
|
556
|
+
this.#columns = columns;
|
|
557
|
+
this.#keyPath = keyPath;
|
|
418
558
|
}
|
|
419
559
|
/**
|
|
420
560
|
* @instance Sets the data to be updated
|
|
@@ -448,10 +588,10 @@ var UpdateQuery = class {
|
|
|
448
588
|
if (this.#whereCondition) rows = rows.filter(this.#whereCondition);
|
|
449
589
|
const updatePromises = rows.map((row) => {
|
|
450
590
|
return new Promise((res, rej) => {
|
|
451
|
-
const updatedRow = {
|
|
591
|
+
const updatedRow = validateAndPrepareData({
|
|
452
592
|
...row,
|
|
453
593
|
...this.#dataToUpdate
|
|
454
|
-
};
|
|
594
|
+
}, this.#columns, this.#keyPath, true);
|
|
455
595
|
const putRequest = store.put(updatedRow);
|
|
456
596
|
putRequest.onsuccess = () => {
|
|
457
597
|
updateCount++;
|
|
@@ -561,17 +701,22 @@ var DeleteQuery = class {
|
|
|
561
701
|
var Locality = class {
|
|
562
702
|
#name;
|
|
563
703
|
#schema;
|
|
564
|
-
#
|
|
704
|
+
#keyPath;
|
|
705
|
+
version;
|
|
565
706
|
#db;
|
|
707
|
+
#version;
|
|
566
708
|
#readyPromise;
|
|
567
709
|
constructor(config) {
|
|
568
710
|
this.#name = config.dbName;
|
|
569
711
|
this.#schema = config.schema;
|
|
570
|
-
this.#version = config.version;
|
|
571
712
|
const store = this.#buildStoresConfig();
|
|
572
|
-
this.#
|
|
713
|
+
this.#keyPath = store.find((s) => s.autoIncrement)?.keyPath;
|
|
714
|
+
this.#readyPromise = openDBWithStores(this.#name, store, config.version).then((db) => {
|
|
573
715
|
this.#db = db;
|
|
716
|
+
}).finally(() => {
|
|
717
|
+
this.#version = this.#db?.version;
|
|
574
718
|
});
|
|
719
|
+
this.version = this.#version ?? config.version;
|
|
575
720
|
}
|
|
576
721
|
/** Build store configurations from schema. */
|
|
577
722
|
#buildStoresConfig() {
|
|
@@ -602,14 +747,14 @@ var Locality = class {
|
|
|
602
747
|
* @param table Table name.
|
|
603
748
|
*/
|
|
604
749
|
insert(table) {
|
|
605
|
-
return new InsertQuery(table, () => this.#db, this.#readyPromise, this.#schema[table].columns);
|
|
750
|
+
return new InsertQuery(table, () => this.#db, this.#readyPromise, this.#schema[table].columns, this.#keyPath);
|
|
606
751
|
}
|
|
607
752
|
/**
|
|
608
753
|
* @instance Update records in a table.
|
|
609
754
|
* @param table Table name.
|
|
610
755
|
*/
|
|
611
756
|
update(table) {
|
|
612
|
-
return new UpdateQuery(table, () => this.#db, this.#readyPromise);
|
|
757
|
+
return new UpdateQuery(table, () => this.#db, this.#readyPromise, this.#schema[table].columns, this.#keyPath);
|
|
613
758
|
}
|
|
614
759
|
/**
|
|
615
760
|
* @instance Delete records from a table.
|
|
@@ -716,11 +861,12 @@ const column = {
|
|
|
716
861
|
int: () => new Column("int"),
|
|
717
862
|
float: () => new Column("float"),
|
|
718
863
|
number: () => new Column("number"),
|
|
864
|
+
numeric: () => new Column("numeric"),
|
|
719
865
|
bigint: () => new Column("bigint"),
|
|
720
866
|
text: () => new Column("text"),
|
|
721
867
|
string: () => new Column("string"),
|
|
722
|
-
char: (
|
|
723
|
-
varchar: (
|
|
868
|
+
char: (length = 8) => new Column(`char(${length})`),
|
|
869
|
+
varchar: (length = 32) => new Column(`varchar(${length})`),
|
|
724
870
|
uuid: () => new Column("uuid"),
|
|
725
871
|
timestamp: () => new Column("timestamp"),
|
|
726
872
|
bool: () => new Column("bool"),
|
|
@@ -739,6 +885,8 @@ exports.Locality = Locality;
|
|
|
739
885
|
exports.column = column;
|
|
740
886
|
exports.defineSchema = defineSchema;
|
|
741
887
|
exports.getTimestamp = getTimestamp;
|
|
888
|
+
exports.isTimestamp = isTimestamp;
|
|
742
889
|
exports.openDBWithStores = openDBWithStores;
|
|
743
890
|
exports.table = table;
|
|
744
|
-
exports.uuidV4 = uuidV4;
|
|
891
|
+
exports.uuidV4 = uuidV4;
|
|
892
|
+
exports.validateColumnType = validateColumnType;
|
package/dist/index.d.cts
CHANGED
|
@@ -16,16 +16,16 @@ declare const IsUnique: unique symbol;
|
|
|
16
16
|
/** Symbol key for default value */
|
|
17
17
|
declare const DefaultValue: unique symbol;
|
|
18
18
|
/** @class Represents a column definition. */
|
|
19
|
-
declare class Column<T = any> {
|
|
19
|
+
declare class Column<T = any, TName extends TypeName = TypeName> {
|
|
20
20
|
[$ColumnType]: T;
|
|
21
|
-
[ColumnType]:
|
|
21
|
+
[ColumnType]: TName;
|
|
22
22
|
[IsPrimaryKey]?: boolean;
|
|
23
23
|
[IsAutoInc]?: boolean;
|
|
24
24
|
[IsOptional]?: boolean;
|
|
25
25
|
[IsIndexed]?: boolean;
|
|
26
26
|
[IsUnique]?: boolean;
|
|
27
27
|
[DefaultValue]?: T;
|
|
28
|
-
constructor(type:
|
|
28
|
+
constructor(type: TName);
|
|
29
29
|
/** @instance Marks column as primary key */
|
|
30
30
|
pk(): this & {
|
|
31
31
|
[IsPrimaryKey]: true;
|
|
@@ -103,6 +103,8 @@ type Branded<T, B> = T & $Brand<B>;
|
|
|
103
103
|
* @note Technically, this uses intersection with primitive base types (`string & {}` or `number & {}`) to retain IntelliSense while avoiding type narrowing.
|
|
104
104
|
*/
|
|
105
105
|
type LooseLiteral<T extends string | number> = T | (T extends string ? string & {} : number & {});
|
|
106
|
+
/** Union of `number` and numeric string */
|
|
107
|
+
type Numeric = number | `${number}`;
|
|
106
108
|
/**
|
|
107
109
|
* * A readonly array of elements of type `T`.
|
|
108
110
|
*
|
|
@@ -188,6 +190,28 @@ interface DateLike {
|
|
|
188
190
|
}
|
|
189
191
|
/** Advanced types to exclude from counting as object key */
|
|
190
192
|
type AdvancedTypes = Array<unknown> | File | FileList | Blob | Date | RegExp | Constructor | DateLike | WeakMap<WeakKey, unknown> | WeakSet<WeakKey> | Map<unknown, unknown> | Set<unknown> | Function | GenericFn | VoidFn | AsyncFunction<unknown> | Promise<unknown> | Error | EvalError | RangeError | ReferenceError | SyntaxError | TypeError | URIError | bigint | symbol;
|
|
193
|
+
/**
|
|
194
|
+
* * Extracts the parameters of the first overload of a function type `T`.
|
|
195
|
+
*
|
|
196
|
+
* @template T - The function type to extract parameters from.
|
|
197
|
+
*
|
|
198
|
+
* @returns A tuple type representing the parameters of the first overload of `T`.
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* type Fn = {
|
|
202
|
+
* (a: number, b: string): void;
|
|
203
|
+
* (x: boolean): void;
|
|
204
|
+
* };
|
|
205
|
+
*
|
|
206
|
+
* type Params = FirstOverloadParams<Fn>; // [a: number, b: string]
|
|
207
|
+
*/
|
|
208
|
+
type FirstOverloadParams<T> = T extends ({
|
|
209
|
+
(a1: infer P1, ...args: infer P2): any;
|
|
210
|
+
(...args: any[]): any;
|
|
211
|
+
}) ? [P1, ...P2] : T extends ({
|
|
212
|
+
(...args: infer P): any;
|
|
213
|
+
(...args: any[]): any;
|
|
214
|
+
}) ? P : T extends ((...args: infer P) => any) ? P : never;
|
|
191
215
|
/**
|
|
192
216
|
* * Maps all values of object `T` to a fixed type `R`, keeping original keys.
|
|
193
217
|
*
|
|
@@ -235,8 +259,6 @@ type $UUIDVersion = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
|
|
|
235
259
|
type UUIDVersion = `v${$UUIDVersion}`;
|
|
236
260
|
/** General 5 parts UUID string as {@link Branded} type */
|
|
237
261
|
type UUID<V extends UUIDVersion> = Branded<$UUID, V>;
|
|
238
|
-
/** Schema definition type */
|
|
239
|
-
type SchemaDefinition<T extends ColumnDefinition = ColumnDefinition> = Record<string, Table<T>>;
|
|
240
262
|
/** Locality database configuration type */
|
|
241
263
|
type LocalityConfig<DB extends string, V extends number, S extends SchemaDefinition> = {
|
|
242
264
|
/** Database name */dbName: DB; /** Database version */
|
|
@@ -245,6 +267,12 @@ type LocalityConfig<DB extends string, V extends number, S extends SchemaDefinit
|
|
|
245
267
|
};
|
|
246
268
|
/** Column definition type */
|
|
247
269
|
type ColumnDefinition<T = any> = Record<string, Column<T>>;
|
|
270
|
+
/** Record of column definitions */
|
|
271
|
+
type ColumnRecord = Record<string, ColumnDefinition>;
|
|
272
|
+
/** Schema record type mapping table names to {@link Table} instances */
|
|
273
|
+
type SchemaRecord<T extends ColumnRecord, Keys extends keyof T> = { [K in Keys]: Table<T[K]> };
|
|
274
|
+
/** Schema definition type */
|
|
275
|
+
type SchemaDefinition<T extends ColumnDefinition = ColumnDefinition> = Record<string, Table<T>>;
|
|
248
276
|
/** Helper to reliably extract the generic type parameter from a Column using a symbol property. */
|
|
249
277
|
type ExtractColumnType<C> = C extends {
|
|
250
278
|
[$ColumnType]: infer U;
|
|
@@ -283,10 +311,12 @@ type InferInsertType<T extends Table> = Prettify<Omit<$InferRow<T['columns']>, $
|
|
|
283
311
|
type InferUpdateType<T extends Table> = Prettify<Partial<Omit<$InferRow<T['columns']>, $InferPkField<T['columns']>>>>;
|
|
284
312
|
/** Creates a type for select operations. */
|
|
285
313
|
type InferSelectType<S extends Table> = Prettify<S extends infer T ? T extends Table<infer C> ? $InferRow<C> : never : never>;
|
|
314
|
+
/** Column type strings used in {@link Column} definitions */
|
|
315
|
+
type TypeName = LooseLiteral<'int' | 'float' | 'number' | 'numeric' | 'bigint' | 'text' | 'string' | 'uuid' | 'timestamp' | 'bool' | 'date' | 'object' | 'array' | 'list' | 'tuple' | 'set' | 'map' | 'custom'>;
|
|
286
316
|
/** Store configuration type for {@link IndexedDB} */
|
|
287
317
|
type StoreConfig = {
|
|
288
318
|
/** Store name */name: string; /** Primary key path(s) */
|
|
289
|
-
keyPath?: string
|
|
319
|
+
keyPath?: string; /** Whether the primary key is auto-incrementing */
|
|
290
320
|
autoIncrement?: boolean;
|
|
291
321
|
};
|
|
292
322
|
//#endregion
|
|
@@ -336,7 +366,7 @@ declare class SelectQuery<T extends GenericObject, S = null> {
|
|
|
336
366
|
declare class InsertQuery<Raw extends GenericObject, Inserted, Data extends GenericObject, Return extends (Inserted extends Array<infer _> ? Data[] : Data)> {
|
|
337
367
|
#private;
|
|
338
368
|
[IsArray]: boolean;
|
|
339
|
-
constructor(table: string, dbGetter: () => IDBDatabase, readyPromise: Promise<void>, columns?: ColumnDefinition);
|
|
369
|
+
constructor(table: string, dbGetter: () => IDBDatabase, readyPromise: Promise<void>, columns?: ColumnDefinition, keyPath?: string);
|
|
340
370
|
/**
|
|
341
371
|
* @instance Sets the data to be inserted
|
|
342
372
|
* @param data Data object or array of data objects to insert
|
|
@@ -351,7 +381,7 @@ declare class InsertQuery<Raw extends GenericObject, Inserted, Data extends Gene
|
|
|
351
381
|
/** @class Update query builder. */
|
|
352
382
|
declare class UpdateQuery<T extends GenericObject, S extends Table> {
|
|
353
383
|
#private;
|
|
354
|
-
constructor(table: string, dbGetter: () => IDBDatabase, readyPromise: Promise<void
|
|
384
|
+
constructor(table: string, dbGetter: () => IDBDatabase, readyPromise: Promise<void>, columns?: ColumnDefinition, keyPath?: string);
|
|
355
385
|
/**
|
|
356
386
|
* @instance Sets the data to be updated
|
|
357
387
|
* @param values Values to update
|
|
@@ -425,6 +455,7 @@ declare class DeleteQuery<T extends GenericObject, Key extends keyof T> {
|
|
|
425
455
|
*/
|
|
426
456
|
declare class Locality<DBName extends string = string, Version extends number = 1, Schema extends SchemaDefinition = SchemaDefinition> {
|
|
427
457
|
#private;
|
|
458
|
+
readonly version: Version;
|
|
428
459
|
constructor(config: LocalityConfig<DBName, Version, Schema>);
|
|
429
460
|
/** @instance Waits for database initialization to complete. */
|
|
430
461
|
ready(): Promise<void>;
|
|
@@ -453,7 +484,7 @@ declare class Locality<DBName extends string = string, Version extends number =
|
|
|
453
484
|
//#endregion
|
|
454
485
|
//#region src/factory.d.ts
|
|
455
486
|
/**
|
|
456
|
-
* * Opens an `IndexedDB` database with the specified stores.
|
|
487
|
+
* * Opens an `IndexedDB` database instance with the specified stores.
|
|
457
488
|
* @param name Database name
|
|
458
489
|
* @param stores Array of store configurations
|
|
459
490
|
* @param version Database version (default is `1`)
|
|
@@ -494,7 +525,7 @@ declare function openDBWithStores(name: string, stores: StoreConfig[], version?:
|
|
|
494
525
|
* type InsertPost = InferInsertType<typeof schema.posts>;
|
|
495
526
|
* type UpdatePost = InferUpdateType<typeof schema.posts>;
|
|
496
527
|
*/
|
|
497
|
-
declare function defineSchema<
|
|
528
|
+
declare function defineSchema<Schema extends ColumnRecord, Keys extends keyof Schema>(schema: Schema): SchemaRecord<Schema, Keys>;
|
|
498
529
|
/**
|
|
499
530
|
* * Factory function to create a new {@link Table} instance.
|
|
500
531
|
* @param name The name of the table.
|
|
@@ -550,51 +581,57 @@ declare const column: {
|
|
|
550
581
|
* @returns A new {@link Column} instance for integers.
|
|
551
582
|
* @remarks column type is typically used for whole numbers.
|
|
552
583
|
*/
|
|
553
|
-
readonly int: () => Column<number>;
|
|
584
|
+
readonly int: () => Column<number, "int">;
|
|
554
585
|
/**
|
|
555
586
|
* Creates a float column.
|
|
556
587
|
* @returns A new {@link Column} instance for floating-point numbers.
|
|
557
588
|
* @remarks This column type is specifically for decimal numbers.
|
|
558
589
|
*/
|
|
559
|
-
readonly float: () => Column<number>;
|
|
590
|
+
readonly float: () => Column<number, "float">;
|
|
560
591
|
/**
|
|
561
592
|
* Creates a number column.
|
|
562
593
|
* @returns A new {@link Column} instance for numbers.
|
|
563
594
|
* @remarks This column type is used for both whole & floating-point numbers.
|
|
564
595
|
*/
|
|
565
|
-
readonly number: () => Column<number>;
|
|
596
|
+
readonly number: () => Column<number, "number">;
|
|
597
|
+
/**
|
|
598
|
+
* Creates a numeric (number or numeric string) column.
|
|
599
|
+
* @returns A new {@link Column} instance for numeric.
|
|
600
|
+
* @remarks This column type is used for both whole & floating-point numbers or numeric strings.
|
|
601
|
+
*/
|
|
602
|
+
readonly numeric: () => Column<Numeric, "numeric">;
|
|
566
603
|
/**
|
|
567
604
|
* Creates a bigint column.
|
|
568
605
|
* @returns A new {@link Column} instance for bigints.
|
|
569
606
|
* @remarks This column type is used for large integers beyond the safe integer limit of JavaScript.
|
|
570
607
|
*/
|
|
571
|
-
readonly bigint: () => Column<bigint>;
|
|
608
|
+
readonly bigint: () => Column<bigint, "bigint">;
|
|
572
609
|
/**
|
|
573
610
|
* Creates a text column.
|
|
574
611
|
* @returns A new {@link Column} instance for text.
|
|
575
612
|
* @remarks This column type is used for large strings of text.
|
|
576
613
|
*/
|
|
577
|
-
readonly text: () => Column<string>;
|
|
614
|
+
readonly text: () => Column<string, "text">;
|
|
578
615
|
/**
|
|
579
616
|
* Creates a string column.
|
|
580
617
|
* @returns A new {@link Column} instance for strings.
|
|
581
618
|
* @remarks This column type is used for general string data.
|
|
582
619
|
*/
|
|
583
|
-
readonly string: () => Column<string>;
|
|
620
|
+
readonly string: () => Column<string, "string">;
|
|
584
621
|
/**
|
|
585
622
|
* Creates a char column with optional length.
|
|
586
|
-
* @param
|
|
623
|
+
* @param length Optional length of the char column. Defaults to `8`.
|
|
587
624
|
* @returns A new {@link Column} instance for char.
|
|
588
625
|
* @remarks This column type is used for fixed-length strings.
|
|
589
626
|
*/
|
|
590
|
-
readonly char: (
|
|
627
|
+
readonly char: <L extends number = 8>(length?: L) => Column<string, `char(${L})`>;
|
|
591
628
|
/**
|
|
592
629
|
* Creates a varchar column with optional length.
|
|
593
|
-
* @param
|
|
630
|
+
* @param length Optional length of the varchar column. Defaults to `32`.
|
|
594
631
|
* @returns A new {@link Column} instance for varchar.
|
|
595
632
|
* @remarks This column type is used for variable-length strings.
|
|
596
633
|
*/
|
|
597
|
-
readonly varchar: (
|
|
634
|
+
readonly varchar: <L extends number = 32>(length?: L) => Column<string, `varchar(${L})`>;
|
|
598
635
|
/**
|
|
599
636
|
* Creates a UUID column.
|
|
600
637
|
* @returns A new {@link Column} instance for UUIDs.
|
|
@@ -603,7 +640,7 @@ declare const column: {
|
|
|
603
640
|
* - UUIDs are typically used as unique identifiers.
|
|
604
641
|
* - Automatically genrates UUID v4 values when no value is provided.
|
|
605
642
|
*/
|
|
606
|
-
readonly uuid: () => Column<`${string}-${string}-${string}-${string}-${string}
|
|
643
|
+
readonly uuid: () => Column<`${string}-${string}-${string}-${string}-${string}`, "uuid">;
|
|
607
644
|
/**
|
|
608
645
|
* Creates a timestamp column.
|
|
609
646
|
* @returns A new {@link Column} instance for timestamps.
|
|
@@ -611,55 +648,55 @@ declare const column: {
|
|
|
611
648
|
* - This column type is used for storing date and time information in ISO 8601 format.
|
|
612
649
|
* - Automatically generates the current timestamp when no value is provided.
|
|
613
650
|
*/
|
|
614
|
-
readonly timestamp: () => Column<Timestamp>;
|
|
651
|
+
readonly timestamp: () => Column<Timestamp, "timestamp">;
|
|
615
652
|
/**
|
|
616
653
|
* Creates a boolean column.
|
|
617
654
|
* @returns A new {@link Column} instance for booleans.
|
|
618
655
|
* @remarks This column type is used for true/false values.
|
|
619
656
|
*/
|
|
620
|
-
readonly bool: () => Column<boolean>;
|
|
657
|
+
readonly bool: () => Column<boolean, "bool">;
|
|
621
658
|
/**
|
|
622
659
|
* Creates a date column.
|
|
623
660
|
* @returns A new {@link Column} instance for dates.
|
|
624
661
|
* @remarks This column type is used for storing date values.
|
|
625
662
|
*/
|
|
626
|
-
readonly date: () => Column<Date>;
|
|
663
|
+
readonly date: () => Column<Date, "date">;
|
|
627
664
|
/**
|
|
628
665
|
* Creates an object column.
|
|
629
666
|
* @returns A new {@link Column} instance for objects.
|
|
630
667
|
* @remarks This column type is used for storing generic objects with string keys.
|
|
631
668
|
*/
|
|
632
|
-
readonly object: <Obj extends GenericObject>() => Column<Obj>;
|
|
669
|
+
readonly object: <Obj extends GenericObject>() => Column<Obj, "object">;
|
|
633
670
|
/**
|
|
634
671
|
* Creates an array column.
|
|
635
672
|
* @returns A new {@link Column} instance for arrays.
|
|
636
673
|
* @remarks This column type is used for storing arrays of any type.
|
|
637
674
|
*/
|
|
638
|
-
readonly array: <T = any>() => Column<T[]>;
|
|
675
|
+
readonly array: <T = any>() => Column<T[], "array">;
|
|
639
676
|
/**
|
|
640
677
|
* Creates a list column.
|
|
641
678
|
* @returns A new {@link Column} instance for lists.
|
|
642
679
|
* @remarks This column type is used for storing lists of any type.
|
|
643
680
|
*/
|
|
644
|
-
readonly list: <T = any>() => Column<List<T
|
|
681
|
+
readonly list: <T = any>() => Column<List<T>, "list">;
|
|
645
682
|
/**
|
|
646
683
|
* Creates a tuple column.
|
|
647
684
|
* @returns A new {@link Column} instance for tuples.
|
|
648
685
|
* @remarks This column type is used for storing fixed-size arrays (tuples) of any type.
|
|
649
686
|
*/
|
|
650
|
-
readonly tuple: <T = any>() => Column<Tuple<T
|
|
687
|
+
readonly tuple: <T = any>() => Column<Tuple<T>, "tuple">;
|
|
651
688
|
/**
|
|
652
689
|
* Creates a set column.
|
|
653
690
|
* @returns A new {@link Column} instance for sets.
|
|
654
691
|
* @remarks This column type is used for storing unique collections of any type.
|
|
655
692
|
*/
|
|
656
|
-
readonly set: <T = any>() => Column<Set<T
|
|
693
|
+
readonly set: <T = any>() => Column<Set<T>, "set">;
|
|
657
694
|
/**
|
|
658
695
|
* Creates a map column.
|
|
659
696
|
* @returns A new {@link Column} instance for maps.
|
|
660
697
|
* @remarks This column type is used for storing key-value pairs of any type.
|
|
661
698
|
*/
|
|
662
|
-
readonly map: <K = any, V = any>() => Column<Map<K, V
|
|
699
|
+
readonly map: <K = any, V = any>() => Column<Map<K, V>, "map">;
|
|
663
700
|
/**
|
|
664
701
|
* Creates a custom column.
|
|
665
702
|
* @returns A new {@link Column} instance for custom data types.
|
|
@@ -668,7 +705,7 @@ declare const column: {
|
|
|
668
705
|
* - You can specify the type when creating the column.
|
|
669
706
|
* - No built-in serialization/deserialization is provided; you must handle it yourself.
|
|
670
707
|
*/
|
|
671
|
-
readonly custom: <T = any>() => Column<T>;
|
|
708
|
+
readonly custom: <T = any>() => Column<T, "custom">;
|
|
672
709
|
};
|
|
673
710
|
//#endregion
|
|
674
711
|
//#region src/utils.d.ts
|
|
@@ -685,5 +722,20 @@ declare function uuidV4(uppercase?: boolean): UUID<'v4'>;
|
|
|
685
722
|
* @return Timestamp string in ISO 8601 format
|
|
686
723
|
*/
|
|
687
724
|
declare function getTimestamp(value?: string | number | Date): Timestamp;
|
|
725
|
+
/**
|
|
726
|
+
* * Check if a value is a valid Timestamp string in ISO 8601 format
|
|
727
|
+
* @param value The value to check
|
|
728
|
+
* @returns `true` if the value is a valid Timestamp, otherwise `false`
|
|
729
|
+
*/
|
|
730
|
+
declare function isTimestamp(value: unknown): value is Timestamp;
|
|
731
|
+
//#endregion
|
|
732
|
+
//#region src/validators.d.ts
|
|
733
|
+
/**
|
|
734
|
+
* * Validate if a value matches the specified column data type
|
|
735
|
+
* @param type The column data type
|
|
736
|
+
* @param value The value to validate
|
|
737
|
+
* @returns `null` if valid, otherwise an error message string
|
|
738
|
+
*/
|
|
739
|
+
declare function validateColumnType<T extends TypeName>(type: T, value: unknown): string | null;
|
|
688
740
|
//#endregion
|
|
689
|
-
export { $InferAutoInc, $InferDefault, $InferOptional, $InferPkField, $InferRow, $InferTimestamp, $InferUUID, $UUID, $UUIDVersion, $UnionToIntersection, AdvancedTypes, ArrayToTuple, AsyncFunction, BasicPrimitive, Branded, type Column, ColumnDefinition, Constructor, DateLike, GenericFn, GenericObject, InferInsertType, InferSelectType, InferUpdateType, List, Locality, LocalityConfig, LooseLiteral, MapObjectValues, NestedPrimitiveKey, NormalPrimitive, Prettify, Primitive, SchemaDefinition, SelectFields, SortDirection, StoreConfig, type Table, Timestamp, Tuple, UUID, UUIDVersion, VoidFn, column, defineSchema, getTimestamp, openDBWithStores, table, uuidV4 };
|
|
741
|
+
export { $InferAutoInc, $InferDefault, $InferOptional, $InferPkField, $InferRow, $InferTimestamp, $InferUUID, $UUID, $UUIDVersion, $UnionToIntersection, AdvancedTypes, ArrayToTuple, AsyncFunction, BasicPrimitive, Branded, type Column, ColumnDefinition, ColumnRecord, Constructor, DateLike, FirstOverloadParams, GenericFn, GenericObject, InferInsertType, InferSelectType, InferUpdateType, List, Locality, LocalityConfig, LooseLiteral, MapObjectValues, NestedPrimitiveKey, NormalPrimitive, Numeric, Prettify, Primitive, SchemaDefinition, SchemaRecord, SelectFields, SortDirection, StoreConfig, type Table, Timestamp, Tuple, TypeName, UUID, UUIDVersion, VoidFn, column, defineSchema, getTimestamp, isTimestamp, openDBWithStores, table, uuidV4, validateColumnType };
|