@bjnstnkvc/db 1.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -91
- package/dist/main.cjs +23 -57
- package/dist/main.d.cts +30 -13
- package/dist/main.d.ts +30 -13
- package/dist/main.js +23 -57
- package/package.json +9 -3
package/README.md
CHANGED
|
@@ -16,7 +16,8 @@ The method names and their semantics follow Laravel closely enough that the docs
|
|
|
16
16
|
- [Grouping](#grouping)
|
|
17
17
|
- [Query plans](#query-plans)
|
|
18
18
|
- [Transactions](#transactions)
|
|
19
|
-
- [Events
|
|
19
|
+
- [Events](#events)
|
|
20
|
+
- [Query log](#query-log)
|
|
20
21
|
- [Multiple tabs](#multiple-tabs)
|
|
21
22
|
- [Connections](#connections)
|
|
22
23
|
- [Storage quota](#storage-quota)
|
|
@@ -94,13 +95,13 @@ await DB.migrate('app');
|
|
|
94
95
|
and every example below passes it as `DB.table<User>('users')` so the builder can type its
|
|
95
96
|
constraints, its return values and its aggregate keys.
|
|
96
97
|
|
|
97
|
-
| Option
|
|
98
|
-
|
|
99
|
-
| `default`
|
|
100
|
-
| `connections[name].database`
|
|
101
|
-
| `connections[name].migrations` | Ordered migration classes. Their order **is** the schema version.
|
|
102
|
-
| `connections[name].seeders`
|
|
103
|
-
| `connections[name].strict`
|
|
98
|
+
| Option | Meaning |
|
|
99
|
+
|--------------------------------|---------------------------------------------------------------------------------------------------------|
|
|
100
|
+
| `default` | The connection used when none is named |
|
|
101
|
+
| `connections[name].database` | The IndexedDB database name |
|
|
102
|
+
| `connections[name].migrations` | Ordered migration classes. Their order **is** the schema version. |
|
|
103
|
+
| `connections[name].seeders` | Ordered seeder classes, run by `DB.seed(name)`. See [Seeding](#seeding). |
|
|
104
|
+
| `connections[name].strict` | Defaults to `true`. Nullability violations and uncoercible values throw. `false` writes `null` instead. |
|
|
104
105
|
|
|
105
106
|
`DB.migrate(name)` is idempotent. It opens the database at the version your migrations ask for, and
|
|
106
107
|
when that already matches, nothing runs. Calling it on every boot is the intended usage, and there
|
|
@@ -144,8 +145,10 @@ start over, `DB.fresh(name)` deletes the database and replays every migration.
|
|
|
144
145
|
Migrations may only ever be **appended**. Reordering them, or removing one that already ran, throws
|
|
145
146
|
`MigrationMismatchException` rather than corrupting the schema.
|
|
146
147
|
|
|
147
|
-
The recorded name defaults to the class name
|
|
148
|
-
|
|
148
|
+
The recorded name defaults to the class name in snake case, the way Laravel names a migration file,
|
|
149
|
+
so `CreateUsersTable` is recorded as `create_users_table`. Because it is derived from the class name,
|
|
150
|
+
a bundler that mangles class names will look like a reordered list. If you minify with class-name
|
|
151
|
+
mangling, override `name()`:
|
|
149
152
|
|
|
150
153
|
```ts
|
|
151
154
|
class CreateUsersTable extends Migration {
|
|
@@ -184,15 +187,15 @@ Resolves to one entry per registered migration:
|
|
|
184
187
|
|
|
185
188
|
```
|
|
186
189
|
[
|
|
187
|
-
{ migration: '
|
|
188
|
-
{ migration: '
|
|
190
|
+
{ migration: 'create_users_table', ran: true, at: '2026-08-27T21:00:00.000Z' },
|
|
191
|
+
{ migration: 'add_role_to_users_table', ran: false, at: null }
|
|
189
192
|
]
|
|
190
193
|
```
|
|
191
194
|
|
|
192
195
|
`DB.status(name)` never migrates as a side effect, so you can call it before `DB.migrate(name)` to
|
|
193
196
|
see what is pending.
|
|
194
197
|
|
|
195
|
-
>
|
|
198
|
+
> Modeled on Laravel's [Migrations](https://laravel.com/docs/12.x/migrations). These only run
|
|
196
199
|
> forward, and they are registered in the connection config rather than discovered from a directory.
|
|
197
200
|
|
|
198
201
|
### Seeding
|
|
@@ -478,7 +481,7 @@ await DB.fresh('app');
|
|
|
478
481
|
await DB.fresh('app', { seed: true });
|
|
479
482
|
```
|
|
480
483
|
|
|
481
|
-
>
|
|
484
|
+
> Modeled on Laravel's [Database: Seeding](https://laravel.com/docs/12.x/seeding), down to the
|
|
482
485
|
> seeded connection standing in as the default for the duration of the run.
|
|
483
486
|
|
|
484
487
|
### Defining a schema
|
|
@@ -486,21 +489,21 @@ await DB.fresh('app', { seed: true });
|
|
|
486
489
|
IndexedDB stores whole objects and enforces only a key path, `autoIncrement` and indexes. Column
|
|
487
490
|
types are recorded as metadata and enforced by this package at write time.
|
|
488
491
|
|
|
489
|
-
| Blueprint
|
|
490
|
-
|
|
491
|
-
| `table.id()`
|
|
492
|
-
| `table.uuid('id').primary()`
|
|
493
|
-
| `table.string` / `integer` / `float` / `boolean` / `date` / `datetime` / `json` | Column metadata
|
|
494
|
-
| `table.decimal('price', 2)`
|
|
495
|
-
| `table.enum('role', Role)`
|
|
496
|
-
| `.nullable()`
|
|
497
|
-
| `.default(value)`
|
|
498
|
-
| `.primary()`
|
|
499
|
-
| `.index()`
|
|
500
|
-
| `.unique()`
|
|
501
|
-
| `table.index(['a', 'b'])`
|
|
502
|
-
| `.multiEntry()`
|
|
503
|
-
| `table.timestamps()`
|
|
492
|
+
| Blueprint | Effect |
|
|
493
|
+
|---------------------------------------------------------------------------------|------------------------------------------------------------------------------------|
|
|
494
|
+
| `table.id()` | `keyPath: 'id'`, `autoIncrement: true` |
|
|
495
|
+
| `table.uuid('id').primary()` | `keyPath: 'id'`, no autoIncrement |
|
|
496
|
+
| `table.string` / `integer` / `float` / `boolean` / `date` / `datetime` / `json` | Column metadata |
|
|
497
|
+
| `table.decimal('price', 2)` | Column metadata, stored as a whole number of the smallest unit |
|
|
498
|
+
| `table.enum('role', Role)` | Column metadata, checked at write time. Takes a list, an enum or a constant object |
|
|
499
|
+
| `.nullable()` | Metadata, enforced at write time |
|
|
500
|
+
| `.default(value)` | Applied at write time, and backfilled when added to an existing table |
|
|
501
|
+
| `.primary()` | Makes the column the key path. At most one per table. |
|
|
502
|
+
| `.index()` | `createIndex('users_name_index', 'name')` |
|
|
503
|
+
| `.unique()` | `createIndex('users_email_unique', 'email', { unique: true })` |
|
|
504
|
+
| `table.index(['a', 'b'])` | Compound index |
|
|
505
|
+
| `.multiEntry()` | One index entry per array element |
|
|
506
|
+
| `table.timestamps()` | Nullable `created_at` / `updated_at`, filled automatically |
|
|
504
507
|
|
|
505
508
|
Altering a table also supports `dropColumn`, `renameColumn`, `dropIndex` and `Schema.rename`. The key
|
|
506
509
|
path may not be dropped or renamed, because IndexedDB fixes it when the store is created.
|
|
@@ -665,7 +668,7 @@ await Schema.getIndexes('users');
|
|
|
665
668
|
await Schema.connection('reporting').hasTable('reports');
|
|
666
669
|
```
|
|
667
670
|
|
|
668
|
-
>
|
|
671
|
+
> Modeled on Laravel's [Migrations: Tables](https://laravel.com/docs/12.x/migrations#tables).
|
|
669
672
|
> Column types are metadata this package enforces at write time, since IndexedDB stores whole objects
|
|
670
673
|
> and checks nothing itself.
|
|
671
674
|
|
|
@@ -771,22 +774,22 @@ await DB.table<User>('users').min('age');
|
|
|
771
774
|
await DB.table<User>('users').max('age');
|
|
772
775
|
```
|
|
773
776
|
|
|
774
|
-
| Terminal
|
|
775
|
-
|
|
776
|
-
| `get()`
|
|
777
|
-
| `first()`
|
|
778
|
-
| `firstOrFail()`
|
|
779
|
-
| `find(key)`
|
|
780
|
-
| `findOrFail(key)`
|
|
781
|
-
| `value(column)`
|
|
782
|
-
| `pluck(column)`
|
|
783
|
-
| `pluck(column, key)`
|
|
784
|
-
| `exists()` / `doesntExist()`
|
|
785
|
-
| `count()`
|
|
786
|
-
| `sum(column)`
|
|
787
|
-
| `avg(column)` / `min(column)` / `max(column)` | `number` or `null` when nothing matched
|
|
788
|
-
| `sole()`
|
|
789
|
-
| `paginate(page?, perPage?)`
|
|
777
|
+
| Terminal | Resolves to |
|
|
778
|
+
|-----------------------------------------------|-----------------------------------------------------------------------------|
|
|
779
|
+
| `get()` | `T[]` |
|
|
780
|
+
| `first()` | `T` or `null` |
|
|
781
|
+
| `firstOrFail()` | `T`, or throws `RecordsNotFoundException` |
|
|
782
|
+
| `find(key)` | `T` or `null`, by point lookup on the key path |
|
|
783
|
+
| `findOrFail(key)` | `T`, or throws `RecordsNotFoundException` |
|
|
784
|
+
| `value(column)` | The column of the first matching record, or `null` |
|
|
785
|
+
| `pluck(column)` | `V[]` in result order |
|
|
786
|
+
| `pluck(column, key)` | `Record<string, V>`, keyed by a second column |
|
|
787
|
+
| `exists()` / `doesntExist()` | `boolean` |
|
|
788
|
+
| `count()` | `number` |
|
|
789
|
+
| `sum(column)` | `number` |
|
|
790
|
+
| `avg(column)` / `min(column)` / `max(column)` | `number` or `null` when nothing matched |
|
|
791
|
+
| `sole()` | `T`, or throws `RecordsNotFoundException` / `MultipleRecordsFoundException` |
|
|
792
|
+
| `paginate(page?, perPage?)` | `{ data, total, perPage, currentPage, lastPage }` |
|
|
790
793
|
|
|
791
794
|
`min` and `max` read the answer straight off the index when the column has one and the query is
|
|
792
795
|
unconstrained, so they cost one cursor rather than a full scan.
|
|
@@ -852,7 +855,7 @@ The key path may not be updated, so `update`, `upsert` and `increment` all refus
|
|
|
852
855
|
when an index drives the query and key order otherwise. Pair them with an indexed `orderBy` if you
|
|
853
856
|
need a defined order.
|
|
854
857
|
|
|
855
|
-
>
|
|
858
|
+
> Modeled on Laravel's [Database: Query Builder](https://laravel.com/docs/12.x/queries). The method
|
|
856
859
|
> names and their semantics match, and every terminal is asynchronous because IndexedDB is.
|
|
857
860
|
|
|
858
861
|
### Joins
|
|
@@ -959,7 +962,7 @@ covers it, and `chunk` slices the materialised result rather than walking keys.
|
|
|
959
962
|
await DB.table('users').whereColumn('updated_at', '>', 'created_at').get();
|
|
960
963
|
```
|
|
961
964
|
|
|
962
|
-
>
|
|
965
|
+
> Modeled on Laravel's [Query Builder: Joins](https://laravel.com/docs/12.x/queries#joins). Rows
|
|
963
966
|
> stay flat as they do in Laravel, and the join itself runs in memory because IndexedDB has none.
|
|
964
967
|
|
|
965
968
|
### Grouping
|
|
@@ -994,13 +997,13 @@ Because the alias is an object key rather than a string inside an expression, th
|
|
|
994
997
|
inferred rather than cast. That row is typed `{ role: string; total: number; oldest: number | null }`,
|
|
995
998
|
and reading a column you did not group or aggregate is a compile error.
|
|
996
999
|
|
|
997
|
-
| Aggregate
|
|
998
|
-
|
|
999
|
-
| `{ count: '*' }`
|
|
1000
|
-
| `{ count: 'column' }`
|
|
1001
|
-
| `{ sum: 'column' }`
|
|
1002
|
-
| `{ avg: 'column' }`
|
|
1003
|
-
| `{ min: 'column' }` / `{ max: 'column' }` | The extreme, `null` for a group with no values
|
|
1000
|
+
| Aggregate | Meaning |
|
|
1001
|
+
|-------------------------------------------|-------------------------------------------------------|
|
|
1002
|
+
| `{ count: '*' }` | The number of records in the group, always a `number` |
|
|
1003
|
+
| `{ count: 'column' }` | The number of records whose column is not null |
|
|
1004
|
+
| `{ sum: 'column' }` | The total, `0` for a group with no values |
|
|
1005
|
+
| `{ avg: 'column' }` | The mean, `null` for a group with no values |
|
|
1006
|
+
| `{ min: 'column' }` / `{ max: 'column' }` | The extreme, `null` for a group with no values |
|
|
1004
1007
|
|
|
1005
1008
|
Group by several columns by passing several names:
|
|
1006
1009
|
|
|
@@ -1032,7 +1035,7 @@ await DB.table<User>('users')
|
|
|
1032
1035
|
Grouping happens in memory after the records are fetched, so the planner still applies to the
|
|
1033
1036
|
`where` clauses that select them, and a grouped query reports the plan of that underlying fetch.
|
|
1034
1037
|
|
|
1035
|
-
>
|
|
1038
|
+
> Modeled on Laravel's [Query Builder: Grouping](https://laravel.com/docs/12.x/queries#groupby-having),
|
|
1036
1039
|
> with the aggregates named in a typed object instead of raw SQL.
|
|
1037
1040
|
|
|
1038
1041
|
### Query plans
|
|
@@ -1092,32 +1095,52 @@ commits behind your back the first time you await anything outside it, so offeri
|
|
|
1092
1095
|
offering a trap. The same rule as migrations applies here: the callback may only await operations
|
|
1093
1096
|
from this package.
|
|
1094
1097
|
|
|
1095
|
-
>
|
|
1098
|
+
> Modeled on Laravel's [Database: Transactions](https://laravel.com/docs/12.x/database#database-transactions).
|
|
1096
1099
|
> The tables have to be declared up front, because an IndexedDB transaction fixes its scope when it
|
|
1097
1100
|
> opens.
|
|
1098
1101
|
|
|
1099
|
-
### Events
|
|
1102
|
+
### Events
|
|
1100
1103
|
|
|
1101
|
-
|
|
1102
|
-
DB.onQueryExecuted((event: QueryExecuted): void => {
|
|
1103
|
-
console.log(event.plan, event.duration, event.records);
|
|
1104
|
-
});
|
|
1104
|
+
Listen for an event by its key, and the listener receives an instance of the class it maps to:
|
|
1105
1105
|
|
|
1106
|
+
```ts
|
|
1106
1107
|
DB.listen('migration-started', (event: MigrationStarted): void => console.log(event.migration));
|
|
1107
1108
|
DB.listen('query', listener, { once: true });
|
|
1108
1109
|
DB.forget('query', listener);
|
|
1109
1110
|
```
|
|
1110
1111
|
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1112
|
+
Every event also has a shortcut named after its class, which takes the same options:
|
|
1113
|
+
|
|
1114
|
+
```ts
|
|
1115
|
+
DB.onQueryExecuted((event: QueryExecuted): void => {
|
|
1116
|
+
console.log(event.plan, event.duration, event.records);
|
|
1117
|
+
});
|
|
1118
|
+
```
|
|
1119
|
+
|
|
1120
|
+
| Key | Class | Carries |
|
|
1121
|
+
|---------------------------|-------------------------|----------------------------------------------------------------------------------------|
|
|
1122
|
+
| `query` | `QueryExecuted` | `connection`, `table`, `plan`, `constraints`, `orders`, `limit`, `duration`, `records` |
|
|
1123
|
+
| `transaction-beginning` | `TransactionBeginning` | `connection` |
|
|
1124
|
+
| `transaction-committed` | `TransactionCommitted` | `connection` |
|
|
1125
|
+
| `transaction-rolled-back` | `TransactionRolledBack` | `connection`, `reason` |
|
|
1126
|
+
| `migrations-started` | `MigrationsStarted` | `connection`, `migrations` |
|
|
1127
|
+
| `migration-started` | `MigrationStarted` | `migration` |
|
|
1128
|
+
| `migration-ended` | `MigrationEnded` | `migration` |
|
|
1129
|
+
| `migrations-ended` | `MigrationsEnded` | `connection`, `migrations` |
|
|
1130
|
+
| `no-pending-migrations` | `NoPendingMigrations` | `connection` |
|
|
1131
|
+
| `seeding-started` | `SeedingStarted` | `connection`, `seeders` |
|
|
1132
|
+
| `seeder-started` | `SeederStarted` | `seeder` |
|
|
1133
|
+
| `seeder-ended` | `SeederEnded` | `seeder` |
|
|
1134
|
+
| `seeding-ended` | `SeedingEnded` | `connection`, `seeders` |
|
|
1135
|
+
| `database-blocked` | `DatabaseBlocked` | `database` |
|
|
1115
1136
|
|
|
1116
1137
|
A connection with no seeders announces nothing, so `seeding-started` firing always means at least
|
|
1117
1138
|
one seeder is about to run.
|
|
1118
1139
|
|
|
1119
|
-
|
|
1120
|
-
|
|
1140
|
+
> Modeled on Laravel's [Migrations: Events](https://laravel.com/docs/12.x/migrations#events), with
|
|
1141
|
+
> each event dispatched as a browser event and listened for by key.
|
|
1142
|
+
|
|
1143
|
+
### Query log
|
|
1121
1144
|
|
|
1122
1145
|
```ts
|
|
1123
1146
|
DB.enableQueryLog();
|
|
@@ -1127,7 +1150,7 @@ await DB.table<User>('users').where('role', 'admin').get();
|
|
|
1127
1150
|
DB.getQueryLog();
|
|
1128
1151
|
```
|
|
1129
1152
|
|
|
1130
|
-
Resolves to one entry per query
|
|
1153
|
+
Resolves to one entry per `query` event dispatched while the log was enabled:
|
|
1131
1154
|
|
|
1132
1155
|
```
|
|
1133
1156
|
[
|
|
@@ -1148,7 +1171,7 @@ DB.disableQueryLog();
|
|
|
1148
1171
|
|
|
1149
1172
|
`DB.logging()` then returns `false`, and `DB.getQueryLog()` an empty array.
|
|
1150
1173
|
|
|
1151
|
-
>
|
|
1174
|
+
> Modeled on Laravel's [Database: Listening for Query Events](https://laravel.com/docs/12.x/database#listening-for-query-events),
|
|
1152
1175
|
> with the same enable, get and flush surface, dispatched as a browser event.
|
|
1153
1176
|
|
|
1154
1177
|
### Multiple tabs
|
|
@@ -1171,14 +1194,14 @@ DB.disconnect('app');
|
|
|
1171
1194
|
DB.purge('app');
|
|
1172
1195
|
```
|
|
1173
1196
|
|
|
1174
|
-
| Call
|
|
1175
|
-
|
|
1176
|
-
| `connection()`
|
|
1177
|
-
| `connection(name)` | A named connection, cached after the first resolve
|
|
1197
|
+
| Call | Effect |
|
|
1198
|
+
|--------------------|----------------------------------------------------------------------------------|
|
|
1199
|
+
| `connection()` | The default connection |
|
|
1200
|
+
| `connection(name)` | A named connection, cached after the first resolve |
|
|
1178
1201
|
| `disconnect(name)` | Close the handle, leaving the connection registered so the next query reopens it |
|
|
1179
|
-
| `purge(name)`
|
|
1202
|
+
| `purge(name)` | Close it and drop it, so the next resolve rebuilds it from configuration |
|
|
1180
1203
|
|
|
1181
|
-
>
|
|
1204
|
+
> Modeled on Laravel's [Database: Multiple Connections](https://laravel.com/docs/12.x/database#using-multiple-database-connections),
|
|
1182
1205
|
> resolved by name and cached, with one IndexedDB database behind each.
|
|
1183
1206
|
|
|
1184
1207
|
### Storage quota
|
|
@@ -1233,21 +1256,21 @@ memory, so writes inside a narrowed transaction still get their defaults.
|
|
|
1233
1256
|
Every exception extends `Error` and sets its own `name`, so `instanceof` and the stack both read
|
|
1234
1257
|
true. All of them are exported from the package root.
|
|
1235
1258
|
|
|
1236
|
-
| Exception
|
|
1237
|
-
|
|
1238
|
-
| `CheckConstraintViolationException`
|
|
1239
|
-
| `ConnectionNotConfiguredException`
|
|
1240
|
-
| `DatabaseBlockedException`
|
|
1241
|
-
| `MigrationMismatchException`
|
|
1242
|
-
| `MigrationTransactionClosedException` | A migration awaited something outside this package, letting the versionchange transaction commit early
|
|
1243
|
-
| `MultipleRecordsFoundException`
|
|
1244
|
-
| `NotNullConstraintViolationException` | A non-nullable column is written as null, or is absent with no default
|
|
1245
|
-
| `QuotaExceededException`
|
|
1246
|
-
| `RecordsNotFoundException`
|
|
1247
|
-
| `ReservedTableException`
|
|
1248
|
-
| `SchemaException`
|
|
1249
|
-
| `TableNotFoundException`
|
|
1250
|
-
| `UniqueConstraintViolationException`
|
|
1259
|
+
| Exception | Thrown when |
|
|
1260
|
+
|---------------------------------------|-------------------------------------------------------------------------------------------------------------|
|
|
1261
|
+
| `CheckConstraintViolationException` | A write gives an enumerated column a value it does not accept |
|
|
1262
|
+
| `ConnectionNotConfiguredException` | A connection is resolved under a name `DB.configure` never declared |
|
|
1263
|
+
| `DatabaseBlockedException` | Another tab holds the database open at an older version, so the upgrade cannot start |
|
|
1264
|
+
| `MigrationMismatchException` | The recorded migration list is not a prefix of the registered one, so one was removed, renamed or reordered |
|
|
1265
|
+
| `MigrationTransactionClosedException` | A migration awaited something outside this package, letting the versionchange transaction commit early |
|
|
1266
|
+
| `MultipleRecordsFoundException` | `sole()` matched more than one record |
|
|
1267
|
+
| `NotNullConstraintViolationException` | A non-nullable column is written as null, or is absent with no default |
|
|
1268
|
+
| `QuotaExceededException` | The origin's storage quota stopped the operation |
|
|
1269
|
+
| `RecordsNotFoundException` | `firstOrFail()`, `sole()` or `findOrFail()` matched nothing |
|
|
1270
|
+
| `ReservedTableException` | A migration tries to create `migrations` or `schema` |
|
|
1271
|
+
| `SchemaException` | A schema or query call the shape of the database cannot support |
|
|
1272
|
+
| `TableNotFoundException` | A query or schema read names a table the database does not have |
|
|
1273
|
+
| `UniqueConstraintViolationException` | A write collides with a unique index, named in the message |
|
|
1251
1274
|
|
|
1252
1275
|
`SchemaException` is the broad one, so here is every case that raises it:
|
|
1253
1276
|
|
package/dist/main.cjs
CHANGED
|
@@ -1170,7 +1170,7 @@ var Request = class {
|
|
|
1170
1170
|
};
|
|
1171
1171
|
|
|
1172
1172
|
// src/schema/Coercer.ts
|
|
1173
|
-
var FALSY = ["false", "0"];
|
|
1173
|
+
var FALSY = /* @__PURE__ */ new Set(["false", "0"]);
|
|
1174
1174
|
var Coercer = class {
|
|
1175
1175
|
/**
|
|
1176
1176
|
* Coerce a value into its declared column type.
|
|
@@ -1187,7 +1187,7 @@ var Coercer = class {
|
|
|
1187
1187
|
case "float":
|
|
1188
1188
|
return this.#numeric(value, strict, false);
|
|
1189
1189
|
case "boolean":
|
|
1190
|
-
return typeof value === "string" && FALSY.
|
|
1190
|
+
return typeof value === "string" && FALSY.has(value) ? false : Boolean(value);
|
|
1191
1191
|
case "decimal":
|
|
1192
1192
|
return this.#scaled(value, strict);
|
|
1193
1193
|
case "enum":
|
|
@@ -1435,15 +1435,9 @@ var Join = class {
|
|
|
1435
1435
|
* The conditions the tables are joined on.
|
|
1436
1436
|
*/
|
|
1437
1437
|
#conditions = [];
|
|
1438
|
-
/**
|
|
1439
|
-
* Join on a pair of columns.
|
|
1440
|
-
*/
|
|
1441
1438
|
on(first, operator, second) {
|
|
1442
1439
|
return this.#condition("and", first, operator, second);
|
|
1443
1440
|
}
|
|
1444
|
-
/**
|
|
1445
|
-
* Join on a pair of columns, disjunctively.
|
|
1446
|
-
*/
|
|
1447
1441
|
orOn(first, operator, second) {
|
|
1448
1442
|
return this.#condition("or", first, operator, second);
|
|
1449
1443
|
}
|
|
@@ -1488,7 +1482,7 @@ var Predicate = class {
|
|
|
1488
1482
|
if (index === 0 || constraint.conjunction === "or") {
|
|
1489
1483
|
groups.push([]);
|
|
1490
1484
|
}
|
|
1491
|
-
groups
|
|
1485
|
+
groups.at(-1)?.push(constraint);
|
|
1492
1486
|
}
|
|
1493
1487
|
return groups;
|
|
1494
1488
|
}
|
|
@@ -1748,7 +1742,7 @@ var Joiner = class {
|
|
|
1748
1742
|
};
|
|
1749
1743
|
|
|
1750
1744
|
// src/query/Planner.ts
|
|
1751
|
-
var RANGEABLE = ["=", "==", "===", ">", ">=", "<", "<="];
|
|
1745
|
+
var RANGEABLE = /* @__PURE__ */ new Set(["=", "==", "===", ">", ">=", "<", "<="]);
|
|
1752
1746
|
var Planner = class {
|
|
1753
1747
|
/**
|
|
1754
1748
|
* Compile the constraints and orders into an execution plan.
|
|
@@ -1838,7 +1832,7 @@ var Planner = class {
|
|
|
1838
1832
|
}
|
|
1839
1833
|
return { constraint, ...target, range: IDBKeyRange.bound(constraint.from, constraint.to, false, false), values: null };
|
|
1840
1834
|
}
|
|
1841
|
-
if (!RANGEABLE.
|
|
1835
|
+
if (!RANGEABLE.has(constraint.operator) || !this.#keyable(constraint.value)) {
|
|
1842
1836
|
return null;
|
|
1843
1837
|
}
|
|
1844
1838
|
return { constraint, ...target, range: this.#range(constraint.operator, constraint.value), values: null };
|
|
@@ -1914,7 +1908,7 @@ var Signature = class {
|
|
|
1914
1908
|
* Build a signature identifying a record by every column it holds.
|
|
1915
1909
|
*/
|
|
1916
1910
|
static of(record) {
|
|
1917
|
-
return Object.keys(record).sort().map((column) => this.#segment(column) + this.#segment(this.value(record[column]))).join("");
|
|
1911
|
+
return Object.keys(record).sort((a, b) => a < b ? -1 : 1).map((column) => this.#segment(column) + this.#segment(this.value(record[column]))).join("");
|
|
1918
1912
|
}
|
|
1919
1913
|
/**
|
|
1920
1914
|
* Build a signature identifying an ordered list of values.
|
|
@@ -1997,17 +1991,11 @@ var Grouping = class _Grouping {
|
|
|
1997
1991
|
grouping.#offset = this.#offset;
|
|
1998
1992
|
return grouping;
|
|
1999
1993
|
}
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
*/
|
|
2003
|
-
having(column, operator, value) {
|
|
2004
|
-
return this.#constrain("and", column, operator, value);
|
|
1994
|
+
having(column, ...parameters) {
|
|
1995
|
+
return this.#constrain("and", column, parameters);
|
|
2005
1996
|
}
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
*/
|
|
2009
|
-
orHaving(column, operator, value) {
|
|
2010
|
-
return this.#constrain("or", column, operator, value);
|
|
1997
|
+
orHaving(column, ...parameters) {
|
|
1998
|
+
return this.#constrain("or", column, parameters);
|
|
2011
1999
|
}
|
|
2012
2000
|
/**
|
|
2013
2001
|
* Sort the groups by a column or an aggregate.
|
|
@@ -2117,8 +2105,8 @@ var Grouping = class _Grouping {
|
|
|
2117
2105
|
/**
|
|
2118
2106
|
* Add a constraint on the groups the query returns.
|
|
2119
2107
|
*/
|
|
2120
|
-
#constrain(conjunction, column,
|
|
2121
|
-
const resolved =
|
|
2108
|
+
#constrain(conjunction, column, parameters) {
|
|
2109
|
+
const resolved = parameters.length < 2 ? { operator: "=", value: parameters[0] } : { operator: parameters[0], value: parameters[1] };
|
|
2122
2110
|
this.#constraints.push({ type: "basic", column, operator: resolved.operator, value: resolved.value, conjunction, not: false });
|
|
2123
2111
|
return this;
|
|
2124
2112
|
}
|
|
@@ -2186,23 +2174,14 @@ var Builder = class _Builder {
|
|
|
2186
2174
|
get table() {
|
|
2187
2175
|
return this.#table;
|
|
2188
2176
|
}
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
*/
|
|
2192
|
-
where(column, operator, value) {
|
|
2193
|
-
return this.#constrain("and", false, column, operator, value);
|
|
2177
|
+
where(column, ...parameters) {
|
|
2178
|
+
return this.#constrain("and", false, column, parameters);
|
|
2194
2179
|
}
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
*/
|
|
2198
|
-
orWhere(column, operator, value) {
|
|
2199
|
-
return this.#constrain("or", false, column, operator, value);
|
|
2180
|
+
orWhere(column, ...parameters) {
|
|
2181
|
+
return this.#constrain("or", false, column, parameters);
|
|
2200
2182
|
}
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
*/
|
|
2204
|
-
whereNot(column, operator, value) {
|
|
2205
|
-
return this.#constrain("and", true, column, operator, value);
|
|
2183
|
+
whereNot(column, ...parameters) {
|
|
2184
|
+
return this.#constrain("and", true, column, parameters);
|
|
2206
2185
|
}
|
|
2207
2186
|
/**
|
|
2208
2187
|
* Constrain a column to one of the given values.
|
|
@@ -2327,21 +2306,12 @@ var Builder = class _Builder {
|
|
|
2327
2306
|
whereDay(column, value) {
|
|
2328
2307
|
return this.#part("and", column, "day", value);
|
|
2329
2308
|
}
|
|
2330
|
-
/**
|
|
2331
|
-
* Join another table, keeping only the rows that match.
|
|
2332
|
-
*/
|
|
2333
2309
|
join(table, first, operator, second) {
|
|
2334
2310
|
return this.#join("inner", table, first, operator, second);
|
|
2335
2311
|
}
|
|
2336
|
-
/**
|
|
2337
|
-
* Join another table, keeping every row of this one.
|
|
2338
|
-
*/
|
|
2339
2312
|
leftJoin(table, first, operator, second) {
|
|
2340
2313
|
return this.#join("left", table, first, operator, second);
|
|
2341
2314
|
}
|
|
2342
|
-
/**
|
|
2343
|
-
* Join another table, keeping every row of it.
|
|
2344
|
-
*/
|
|
2345
2315
|
rightJoin(table, first, operator, second) {
|
|
2346
2316
|
return this.#join("right", table, first, operator, second);
|
|
2347
2317
|
}
|
|
@@ -2352,15 +2322,9 @@ var Builder = class _Builder {
|
|
|
2352
2322
|
this.#joins.push({ table, type: "cross", conditions: [] });
|
|
2353
2323
|
return this;
|
|
2354
2324
|
}
|
|
2355
|
-
/**
|
|
2356
|
-
* Constrain a column against another column of the same row.
|
|
2357
|
-
*/
|
|
2358
2325
|
whereColumn(column, operator, other) {
|
|
2359
2326
|
return this.#compared("and", column, operator, other);
|
|
2360
2327
|
}
|
|
2361
|
-
/**
|
|
2362
|
-
* Constrain a column against another column of the same row, disjunctively.
|
|
2363
|
-
*/
|
|
2364
2328
|
orWhereColumn(column, operator, other) {
|
|
2365
2329
|
return this.#compared("or", column, operator, other);
|
|
2366
2330
|
}
|
|
@@ -2983,7 +2947,7 @@ var Builder = class _Builder {
|
|
|
2983
2947
|
/**
|
|
2984
2948
|
* Add a constraint of the given shape to the query.
|
|
2985
2949
|
*/
|
|
2986
|
-
#constrain(conjunction, not, column,
|
|
2950
|
+
#constrain(conjunction, not, column, parameters) {
|
|
2987
2951
|
if (typeof column === "function") {
|
|
2988
2952
|
const nested = new _Builder(this.#connection, this.#table, this.#transaction);
|
|
2989
2953
|
column(nested);
|
|
@@ -3000,7 +2964,7 @@ var Builder = class _Builder {
|
|
|
3000
2964
|
}));
|
|
3001
2965
|
return this.#push({ type: "nested", constraints, conjunction, not });
|
|
3002
2966
|
}
|
|
3003
|
-
const resolved =
|
|
2967
|
+
const resolved = parameters.length < 2 ? { operator: "=", value: parameters[0] } : { operator: parameters[0], value: parameters[1] };
|
|
3004
2968
|
return this.#push({ type: "basic", column, operator: resolved.operator, value: resolved.value, conjunction, not });
|
|
3005
2969
|
}
|
|
3006
2970
|
/**
|
|
@@ -3060,6 +3024,8 @@ var Builder = class _Builder {
|
|
|
3060
3024
|
const clause = new Join();
|
|
3061
3025
|
if (typeof first === "function") {
|
|
3062
3026
|
first(clause);
|
|
3027
|
+
} else if (second === void 0) {
|
|
3028
|
+
clause.on(first, operator);
|
|
3063
3029
|
} else {
|
|
3064
3030
|
clause.on(first, operator, second);
|
|
3065
3031
|
}
|
|
@@ -4141,7 +4107,7 @@ var Migration = class {
|
|
|
4141
4107
|
* Get the name of the migration.
|
|
4142
4108
|
*/
|
|
4143
4109
|
name() {
|
|
4144
|
-
return this.constructor.name;
|
|
4110
|
+
return this.constructor.name.replace(/([a-z\d])([A-Z])/g, "$1_$2").replace(/([A-Z])([A-Z][a-z])/g, "$1_$2").toLowerCase();
|
|
4145
4111
|
}
|
|
4146
4112
|
};
|
|
4147
4113
|
|
package/dist/main.d.cts
CHANGED
|
@@ -302,11 +302,13 @@ declare class Join {
|
|
|
302
302
|
/**
|
|
303
303
|
* Join on a pair of columns.
|
|
304
304
|
*/
|
|
305
|
-
on(first: string,
|
|
305
|
+
on(first: string, second: string): this;
|
|
306
|
+
on(first: string, operator: Operator, second: string): this;
|
|
306
307
|
/**
|
|
307
308
|
* Join on a pair of columns, disjunctively.
|
|
308
309
|
*/
|
|
309
|
-
orOn(first: string,
|
|
310
|
+
orOn(first: string, second: string): this;
|
|
311
|
+
orOn(first: string, operator: Operator, second: string): this;
|
|
310
312
|
/**
|
|
311
313
|
* Get the conditions the tables are joined on.
|
|
312
314
|
*/
|
|
@@ -327,11 +329,13 @@ declare class Grouping<T, G extends (keyof T & string)[], A extends Aggregations
|
|
|
327
329
|
/**
|
|
328
330
|
* Constrain the groups the query returns.
|
|
329
331
|
*/
|
|
330
|
-
having(column: Key<Grouped<T, G, A>>,
|
|
332
|
+
having(column: Key<Grouped<T, G, A>>, value: unknown): this;
|
|
333
|
+
having(column: Key<Grouped<T, G, A>>, operator: Operator, value: unknown): this;
|
|
331
334
|
/**
|
|
332
335
|
* Add a disjunctive constraint on the groups the query returns.
|
|
333
336
|
*/
|
|
334
|
-
orHaving(column: Key<Grouped<T, G, A>>,
|
|
337
|
+
orHaving(column: Key<Grouped<T, G, A>>, value: unknown): this;
|
|
338
|
+
orHaving(column: Key<Grouped<T, G, A>>, operator: Operator, value: unknown): this;
|
|
335
339
|
/**
|
|
336
340
|
* Sort the groups by a column or an aggregate.
|
|
337
341
|
*/
|
|
@@ -518,7 +522,6 @@ declare class Connection {
|
|
|
518
522
|
|
|
519
523
|
type Nested<T> = (query: Builder<T>) => void;
|
|
520
524
|
type Joining = (join: Join) => void;
|
|
521
|
-
type Column<T> = Key<T> | Partial<T> | Nested<T>;
|
|
522
525
|
declare class Builder<T = Record<string, unknown>> {
|
|
523
526
|
#private;
|
|
524
527
|
/**
|
|
@@ -532,15 +535,21 @@ declare class Builder<T = Record<string, unknown>> {
|
|
|
532
535
|
/**
|
|
533
536
|
* Add a constraint to the query.
|
|
534
537
|
*/
|
|
535
|
-
where(column:
|
|
538
|
+
where(column: Partial<T> | Nested<T>): this;
|
|
539
|
+
where(column: Key<T>, value: unknown): this;
|
|
540
|
+
where(column: Key<T>, operator: Operator, value: unknown): this;
|
|
536
541
|
/**
|
|
537
542
|
* Add a disjunctive constraint to the query.
|
|
538
543
|
*/
|
|
539
|
-
orWhere(column:
|
|
544
|
+
orWhere(column: Partial<T> | Nested<T>): this;
|
|
545
|
+
orWhere(column: Key<T>, value: unknown): this;
|
|
546
|
+
orWhere(column: Key<T>, operator: Operator, value: unknown): this;
|
|
540
547
|
/**
|
|
541
548
|
* Add a negated constraint to the query.
|
|
542
549
|
*/
|
|
543
|
-
whereNot(column:
|
|
550
|
+
whereNot(column: Partial<T> | Nested<T>): this;
|
|
551
|
+
whereNot(column: Key<T>, value: unknown): this;
|
|
552
|
+
whereNot(column: Key<T>, operator: Operator, value: unknown): this;
|
|
544
553
|
/**
|
|
545
554
|
* Constrain a column to one of the given values.
|
|
546
555
|
*/
|
|
@@ -624,15 +633,21 @@ declare class Builder<T = Record<string, unknown>> {
|
|
|
624
633
|
/**
|
|
625
634
|
* Join another table, keeping only the rows that match.
|
|
626
635
|
*/
|
|
627
|
-
join<R = Record<string, unknown>>(table: string, first:
|
|
636
|
+
join<R = Record<string, unknown>>(table: string, first: Joining): Builder<R>;
|
|
637
|
+
join<R = Record<string, unknown>>(table: string, first: string, second: string): Builder<R>;
|
|
638
|
+
join<R = Record<string, unknown>>(table: string, first: string, operator: Operator, second: string): Builder<R>;
|
|
628
639
|
/**
|
|
629
640
|
* Join another table, keeping every row of this one.
|
|
630
641
|
*/
|
|
631
|
-
leftJoin<R = Record<string, unknown>>(table: string, first:
|
|
642
|
+
leftJoin<R = Record<string, unknown>>(table: string, first: Joining): Builder<R>;
|
|
643
|
+
leftJoin<R = Record<string, unknown>>(table: string, first: string, second: string): Builder<R>;
|
|
644
|
+
leftJoin<R = Record<string, unknown>>(table: string, first: string, operator: Operator, second: string): Builder<R>;
|
|
632
645
|
/**
|
|
633
646
|
* Join another table, keeping every row of it.
|
|
634
647
|
*/
|
|
635
|
-
rightJoin<R = Record<string, unknown>>(table: string, first:
|
|
648
|
+
rightJoin<R = Record<string, unknown>>(table: string, first: Joining): Builder<R>;
|
|
649
|
+
rightJoin<R = Record<string, unknown>>(table: string, first: string, second: string): Builder<R>;
|
|
650
|
+
rightJoin<R = Record<string, unknown>>(table: string, first: string, operator: Operator, second: string): Builder<R>;
|
|
636
651
|
/**
|
|
637
652
|
* Pair every row of this table with every row of another.
|
|
638
653
|
*/
|
|
@@ -640,11 +655,13 @@ declare class Builder<T = Record<string, unknown>> {
|
|
|
640
655
|
/**
|
|
641
656
|
* Constrain a column against another column of the same row.
|
|
642
657
|
*/
|
|
643
|
-
whereColumn(column: Key<T>,
|
|
658
|
+
whereColumn(column: Key<T>, other: string): this;
|
|
659
|
+
whereColumn(column: Key<T>, operator: Operator, other: string): this;
|
|
644
660
|
/**
|
|
645
661
|
* Constrain a column against another column of the same row, disjunctively.
|
|
646
662
|
*/
|
|
647
|
-
orWhereColumn(column: Key<T>,
|
|
663
|
+
orWhereColumn(column: Key<T>, other: string): this;
|
|
664
|
+
orWhereColumn(column: Key<T>, operator: Operator, other: string): this;
|
|
648
665
|
/**
|
|
649
666
|
* Project only the given columns, which may alias what they select.
|
|
650
667
|
*/
|
package/dist/main.d.ts
CHANGED
|
@@ -302,11 +302,13 @@ declare class Join {
|
|
|
302
302
|
/**
|
|
303
303
|
* Join on a pair of columns.
|
|
304
304
|
*/
|
|
305
|
-
on(first: string,
|
|
305
|
+
on(first: string, second: string): this;
|
|
306
|
+
on(first: string, operator: Operator, second: string): this;
|
|
306
307
|
/**
|
|
307
308
|
* Join on a pair of columns, disjunctively.
|
|
308
309
|
*/
|
|
309
|
-
orOn(first: string,
|
|
310
|
+
orOn(first: string, second: string): this;
|
|
311
|
+
orOn(first: string, operator: Operator, second: string): this;
|
|
310
312
|
/**
|
|
311
313
|
* Get the conditions the tables are joined on.
|
|
312
314
|
*/
|
|
@@ -327,11 +329,13 @@ declare class Grouping<T, G extends (keyof T & string)[], A extends Aggregations
|
|
|
327
329
|
/**
|
|
328
330
|
* Constrain the groups the query returns.
|
|
329
331
|
*/
|
|
330
|
-
having(column: Key<Grouped<T, G, A>>,
|
|
332
|
+
having(column: Key<Grouped<T, G, A>>, value: unknown): this;
|
|
333
|
+
having(column: Key<Grouped<T, G, A>>, operator: Operator, value: unknown): this;
|
|
331
334
|
/**
|
|
332
335
|
* Add a disjunctive constraint on the groups the query returns.
|
|
333
336
|
*/
|
|
334
|
-
orHaving(column: Key<Grouped<T, G, A>>,
|
|
337
|
+
orHaving(column: Key<Grouped<T, G, A>>, value: unknown): this;
|
|
338
|
+
orHaving(column: Key<Grouped<T, G, A>>, operator: Operator, value: unknown): this;
|
|
335
339
|
/**
|
|
336
340
|
* Sort the groups by a column or an aggregate.
|
|
337
341
|
*/
|
|
@@ -518,7 +522,6 @@ declare class Connection {
|
|
|
518
522
|
|
|
519
523
|
type Nested<T> = (query: Builder<T>) => void;
|
|
520
524
|
type Joining = (join: Join) => void;
|
|
521
|
-
type Column<T> = Key<T> | Partial<T> | Nested<T>;
|
|
522
525
|
declare class Builder<T = Record<string, unknown>> {
|
|
523
526
|
#private;
|
|
524
527
|
/**
|
|
@@ -532,15 +535,21 @@ declare class Builder<T = Record<string, unknown>> {
|
|
|
532
535
|
/**
|
|
533
536
|
* Add a constraint to the query.
|
|
534
537
|
*/
|
|
535
|
-
where(column:
|
|
538
|
+
where(column: Partial<T> | Nested<T>): this;
|
|
539
|
+
where(column: Key<T>, value: unknown): this;
|
|
540
|
+
where(column: Key<T>, operator: Operator, value: unknown): this;
|
|
536
541
|
/**
|
|
537
542
|
* Add a disjunctive constraint to the query.
|
|
538
543
|
*/
|
|
539
|
-
orWhere(column:
|
|
544
|
+
orWhere(column: Partial<T> | Nested<T>): this;
|
|
545
|
+
orWhere(column: Key<T>, value: unknown): this;
|
|
546
|
+
orWhere(column: Key<T>, operator: Operator, value: unknown): this;
|
|
540
547
|
/**
|
|
541
548
|
* Add a negated constraint to the query.
|
|
542
549
|
*/
|
|
543
|
-
whereNot(column:
|
|
550
|
+
whereNot(column: Partial<T> | Nested<T>): this;
|
|
551
|
+
whereNot(column: Key<T>, value: unknown): this;
|
|
552
|
+
whereNot(column: Key<T>, operator: Operator, value: unknown): this;
|
|
544
553
|
/**
|
|
545
554
|
* Constrain a column to one of the given values.
|
|
546
555
|
*/
|
|
@@ -624,15 +633,21 @@ declare class Builder<T = Record<string, unknown>> {
|
|
|
624
633
|
/**
|
|
625
634
|
* Join another table, keeping only the rows that match.
|
|
626
635
|
*/
|
|
627
|
-
join<R = Record<string, unknown>>(table: string, first:
|
|
636
|
+
join<R = Record<string, unknown>>(table: string, first: Joining): Builder<R>;
|
|
637
|
+
join<R = Record<string, unknown>>(table: string, first: string, second: string): Builder<R>;
|
|
638
|
+
join<R = Record<string, unknown>>(table: string, first: string, operator: Operator, second: string): Builder<R>;
|
|
628
639
|
/**
|
|
629
640
|
* Join another table, keeping every row of this one.
|
|
630
641
|
*/
|
|
631
|
-
leftJoin<R = Record<string, unknown>>(table: string, first:
|
|
642
|
+
leftJoin<R = Record<string, unknown>>(table: string, first: Joining): Builder<R>;
|
|
643
|
+
leftJoin<R = Record<string, unknown>>(table: string, first: string, second: string): Builder<R>;
|
|
644
|
+
leftJoin<R = Record<string, unknown>>(table: string, first: string, operator: Operator, second: string): Builder<R>;
|
|
632
645
|
/**
|
|
633
646
|
* Join another table, keeping every row of it.
|
|
634
647
|
*/
|
|
635
|
-
rightJoin<R = Record<string, unknown>>(table: string, first:
|
|
648
|
+
rightJoin<R = Record<string, unknown>>(table: string, first: Joining): Builder<R>;
|
|
649
|
+
rightJoin<R = Record<string, unknown>>(table: string, first: string, second: string): Builder<R>;
|
|
650
|
+
rightJoin<R = Record<string, unknown>>(table: string, first: string, operator: Operator, second: string): Builder<R>;
|
|
636
651
|
/**
|
|
637
652
|
* Pair every row of this table with every row of another.
|
|
638
653
|
*/
|
|
@@ -640,11 +655,13 @@ declare class Builder<T = Record<string, unknown>> {
|
|
|
640
655
|
/**
|
|
641
656
|
* Constrain a column against another column of the same row.
|
|
642
657
|
*/
|
|
643
|
-
whereColumn(column: Key<T>,
|
|
658
|
+
whereColumn(column: Key<T>, other: string): this;
|
|
659
|
+
whereColumn(column: Key<T>, operator: Operator, other: string): this;
|
|
644
660
|
/**
|
|
645
661
|
* Constrain a column against another column of the same row, disjunctively.
|
|
646
662
|
*/
|
|
647
|
-
orWhereColumn(column: Key<T>,
|
|
663
|
+
orWhereColumn(column: Key<T>, other: string): this;
|
|
664
|
+
orWhereColumn(column: Key<T>, operator: Operator, other: string): this;
|
|
648
665
|
/**
|
|
649
666
|
* Project only the given columns, which may alias what they select.
|
|
650
667
|
*/
|
package/dist/main.js
CHANGED
|
@@ -1106,7 +1106,7 @@ var Request = class {
|
|
|
1106
1106
|
};
|
|
1107
1107
|
|
|
1108
1108
|
// src/schema/Coercer.ts
|
|
1109
|
-
var FALSY = ["false", "0"];
|
|
1109
|
+
var FALSY = /* @__PURE__ */ new Set(["false", "0"]);
|
|
1110
1110
|
var Coercer = class {
|
|
1111
1111
|
/**
|
|
1112
1112
|
* Coerce a value into its declared column type.
|
|
@@ -1123,7 +1123,7 @@ var Coercer = class {
|
|
|
1123
1123
|
case "float":
|
|
1124
1124
|
return this.#numeric(value, strict, false);
|
|
1125
1125
|
case "boolean":
|
|
1126
|
-
return typeof value === "string" && FALSY.
|
|
1126
|
+
return typeof value === "string" && FALSY.has(value) ? false : Boolean(value);
|
|
1127
1127
|
case "decimal":
|
|
1128
1128
|
return this.#scaled(value, strict);
|
|
1129
1129
|
case "enum":
|
|
@@ -1371,15 +1371,9 @@ var Join = class {
|
|
|
1371
1371
|
* The conditions the tables are joined on.
|
|
1372
1372
|
*/
|
|
1373
1373
|
#conditions = [];
|
|
1374
|
-
/**
|
|
1375
|
-
* Join on a pair of columns.
|
|
1376
|
-
*/
|
|
1377
1374
|
on(first, operator, second) {
|
|
1378
1375
|
return this.#condition("and", first, operator, second);
|
|
1379
1376
|
}
|
|
1380
|
-
/**
|
|
1381
|
-
* Join on a pair of columns, disjunctively.
|
|
1382
|
-
*/
|
|
1383
1377
|
orOn(first, operator, second) {
|
|
1384
1378
|
return this.#condition("or", first, operator, second);
|
|
1385
1379
|
}
|
|
@@ -1424,7 +1418,7 @@ var Predicate = class {
|
|
|
1424
1418
|
if (index === 0 || constraint.conjunction === "or") {
|
|
1425
1419
|
groups.push([]);
|
|
1426
1420
|
}
|
|
1427
|
-
groups
|
|
1421
|
+
groups.at(-1)?.push(constraint);
|
|
1428
1422
|
}
|
|
1429
1423
|
return groups;
|
|
1430
1424
|
}
|
|
@@ -1684,7 +1678,7 @@ var Joiner = class {
|
|
|
1684
1678
|
};
|
|
1685
1679
|
|
|
1686
1680
|
// src/query/Planner.ts
|
|
1687
|
-
var RANGEABLE = ["=", "==", "===", ">", ">=", "<", "<="];
|
|
1681
|
+
var RANGEABLE = /* @__PURE__ */ new Set(["=", "==", "===", ">", ">=", "<", "<="]);
|
|
1688
1682
|
var Planner = class {
|
|
1689
1683
|
/**
|
|
1690
1684
|
* Compile the constraints and orders into an execution plan.
|
|
@@ -1774,7 +1768,7 @@ var Planner = class {
|
|
|
1774
1768
|
}
|
|
1775
1769
|
return { constraint, ...target, range: IDBKeyRange.bound(constraint.from, constraint.to, false, false), values: null };
|
|
1776
1770
|
}
|
|
1777
|
-
if (!RANGEABLE.
|
|
1771
|
+
if (!RANGEABLE.has(constraint.operator) || !this.#keyable(constraint.value)) {
|
|
1778
1772
|
return null;
|
|
1779
1773
|
}
|
|
1780
1774
|
return { constraint, ...target, range: this.#range(constraint.operator, constraint.value), values: null };
|
|
@@ -1850,7 +1844,7 @@ var Signature = class {
|
|
|
1850
1844
|
* Build a signature identifying a record by every column it holds.
|
|
1851
1845
|
*/
|
|
1852
1846
|
static of(record) {
|
|
1853
|
-
return Object.keys(record).sort().map((column) => this.#segment(column) + this.#segment(this.value(record[column]))).join("");
|
|
1847
|
+
return Object.keys(record).sort((a, b) => a < b ? -1 : 1).map((column) => this.#segment(column) + this.#segment(this.value(record[column]))).join("");
|
|
1854
1848
|
}
|
|
1855
1849
|
/**
|
|
1856
1850
|
* Build a signature identifying an ordered list of values.
|
|
@@ -1933,17 +1927,11 @@ var Grouping = class _Grouping {
|
|
|
1933
1927
|
grouping.#offset = this.#offset;
|
|
1934
1928
|
return grouping;
|
|
1935
1929
|
}
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
*/
|
|
1939
|
-
having(column, operator, value) {
|
|
1940
|
-
return this.#constrain("and", column, operator, value);
|
|
1930
|
+
having(column, ...parameters) {
|
|
1931
|
+
return this.#constrain("and", column, parameters);
|
|
1941
1932
|
}
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
*/
|
|
1945
|
-
orHaving(column, operator, value) {
|
|
1946
|
-
return this.#constrain("or", column, operator, value);
|
|
1933
|
+
orHaving(column, ...parameters) {
|
|
1934
|
+
return this.#constrain("or", column, parameters);
|
|
1947
1935
|
}
|
|
1948
1936
|
/**
|
|
1949
1937
|
* Sort the groups by a column or an aggregate.
|
|
@@ -2053,8 +2041,8 @@ var Grouping = class _Grouping {
|
|
|
2053
2041
|
/**
|
|
2054
2042
|
* Add a constraint on the groups the query returns.
|
|
2055
2043
|
*/
|
|
2056
|
-
#constrain(conjunction, column,
|
|
2057
|
-
const resolved =
|
|
2044
|
+
#constrain(conjunction, column, parameters) {
|
|
2045
|
+
const resolved = parameters.length < 2 ? { operator: "=", value: parameters[0] } : { operator: parameters[0], value: parameters[1] };
|
|
2058
2046
|
this.#constraints.push({ type: "basic", column, operator: resolved.operator, value: resolved.value, conjunction, not: false });
|
|
2059
2047
|
return this;
|
|
2060
2048
|
}
|
|
@@ -2122,23 +2110,14 @@ var Builder = class _Builder {
|
|
|
2122
2110
|
get table() {
|
|
2123
2111
|
return this.#table;
|
|
2124
2112
|
}
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
*/
|
|
2128
|
-
where(column, operator, value) {
|
|
2129
|
-
return this.#constrain("and", false, column, operator, value);
|
|
2113
|
+
where(column, ...parameters) {
|
|
2114
|
+
return this.#constrain("and", false, column, parameters);
|
|
2130
2115
|
}
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
*/
|
|
2134
|
-
orWhere(column, operator, value) {
|
|
2135
|
-
return this.#constrain("or", false, column, operator, value);
|
|
2116
|
+
orWhere(column, ...parameters) {
|
|
2117
|
+
return this.#constrain("or", false, column, parameters);
|
|
2136
2118
|
}
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
*/
|
|
2140
|
-
whereNot(column, operator, value) {
|
|
2141
|
-
return this.#constrain("and", true, column, operator, value);
|
|
2119
|
+
whereNot(column, ...parameters) {
|
|
2120
|
+
return this.#constrain("and", true, column, parameters);
|
|
2142
2121
|
}
|
|
2143
2122
|
/**
|
|
2144
2123
|
* Constrain a column to one of the given values.
|
|
@@ -2263,21 +2242,12 @@ var Builder = class _Builder {
|
|
|
2263
2242
|
whereDay(column, value) {
|
|
2264
2243
|
return this.#part("and", column, "day", value);
|
|
2265
2244
|
}
|
|
2266
|
-
/**
|
|
2267
|
-
* Join another table, keeping only the rows that match.
|
|
2268
|
-
*/
|
|
2269
2245
|
join(table, first, operator, second) {
|
|
2270
2246
|
return this.#join("inner", table, first, operator, second);
|
|
2271
2247
|
}
|
|
2272
|
-
/**
|
|
2273
|
-
* Join another table, keeping every row of this one.
|
|
2274
|
-
*/
|
|
2275
2248
|
leftJoin(table, first, operator, second) {
|
|
2276
2249
|
return this.#join("left", table, first, operator, second);
|
|
2277
2250
|
}
|
|
2278
|
-
/**
|
|
2279
|
-
* Join another table, keeping every row of it.
|
|
2280
|
-
*/
|
|
2281
2251
|
rightJoin(table, first, operator, second) {
|
|
2282
2252
|
return this.#join("right", table, first, operator, second);
|
|
2283
2253
|
}
|
|
@@ -2288,15 +2258,9 @@ var Builder = class _Builder {
|
|
|
2288
2258
|
this.#joins.push({ table, type: "cross", conditions: [] });
|
|
2289
2259
|
return this;
|
|
2290
2260
|
}
|
|
2291
|
-
/**
|
|
2292
|
-
* Constrain a column against another column of the same row.
|
|
2293
|
-
*/
|
|
2294
2261
|
whereColumn(column, operator, other) {
|
|
2295
2262
|
return this.#compared("and", column, operator, other);
|
|
2296
2263
|
}
|
|
2297
|
-
/**
|
|
2298
|
-
* Constrain a column against another column of the same row, disjunctively.
|
|
2299
|
-
*/
|
|
2300
2264
|
orWhereColumn(column, operator, other) {
|
|
2301
2265
|
return this.#compared("or", column, operator, other);
|
|
2302
2266
|
}
|
|
@@ -2919,7 +2883,7 @@ var Builder = class _Builder {
|
|
|
2919
2883
|
/**
|
|
2920
2884
|
* Add a constraint of the given shape to the query.
|
|
2921
2885
|
*/
|
|
2922
|
-
#constrain(conjunction, not, column,
|
|
2886
|
+
#constrain(conjunction, not, column, parameters) {
|
|
2923
2887
|
if (typeof column === "function") {
|
|
2924
2888
|
const nested = new _Builder(this.#connection, this.#table, this.#transaction);
|
|
2925
2889
|
column(nested);
|
|
@@ -2936,7 +2900,7 @@ var Builder = class _Builder {
|
|
|
2936
2900
|
}));
|
|
2937
2901
|
return this.#push({ type: "nested", constraints, conjunction, not });
|
|
2938
2902
|
}
|
|
2939
|
-
const resolved =
|
|
2903
|
+
const resolved = parameters.length < 2 ? { operator: "=", value: parameters[0] } : { operator: parameters[0], value: parameters[1] };
|
|
2940
2904
|
return this.#push({ type: "basic", column, operator: resolved.operator, value: resolved.value, conjunction, not });
|
|
2941
2905
|
}
|
|
2942
2906
|
/**
|
|
@@ -2996,6 +2960,8 @@ var Builder = class _Builder {
|
|
|
2996
2960
|
const clause = new Join();
|
|
2997
2961
|
if (typeof first === "function") {
|
|
2998
2962
|
first(clause);
|
|
2963
|
+
} else if (second === void 0) {
|
|
2964
|
+
clause.on(first, operator);
|
|
2999
2965
|
} else {
|
|
3000
2966
|
clause.on(first, operator, second);
|
|
3001
2967
|
}
|
|
@@ -4077,7 +4043,7 @@ var Migration = class {
|
|
|
4077
4043
|
* Get the name of the migration.
|
|
4078
4044
|
*/
|
|
4079
4045
|
name() {
|
|
4080
|
-
return this.constructor.name;
|
|
4046
|
+
return this.constructor.name.replace(/([a-z\d])([A-Z])/g, "$1_$2").replace(/([A-Z])([A-Z][a-z])/g, "$1_$2").toLowerCase();
|
|
4081
4047
|
}
|
|
4082
4048
|
};
|
|
4083
4049
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bjnstnkvc/db",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "TypeScript database layer for IndexedDB with an API modeled on Laravel.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/main.cjs",
|
|
@@ -8,8 +8,14 @@
|
|
|
8
8
|
"types": "./dist/main.d.ts",
|
|
9
9
|
"exports": {
|
|
10
10
|
".": {
|
|
11
|
-
"import": {
|
|
12
|
-
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/main.d.ts",
|
|
13
|
+
"default": "./dist/main.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/main.d.cts",
|
|
17
|
+
"default": "./dist/main.cjs"
|
|
18
|
+
}
|
|
13
19
|
}
|
|
14
20
|
},
|
|
15
21
|
"files": [
|