@bjnstnkvc/db 0.1.0 → 1.0.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # DB
2
2
 
3
- A database layer for IndexedDB, with an API modelled on [Laravel's](https://laravel.com/docs/12.x/database): a `DB` class, a fluent query builder, a schema builder and forward-only migrations that run when your app boots.
3
+ A database layer for IndexedDB, with an API modeled on [Laravel's](https://laravel.com/docs/12.x/database): a `DB` class, a fluent query builder, a schema builder and forward-only migrations that run when your app boots.
4
4
 
5
5
  The method names and their semantics follow Laravel closely enough that the docs are worth reading side by side, and each section below links the page it draws from. It is not a port: IndexedDB is a key-value store with no query language, so the places where behaviour has to differ are called out where they arise. This project is not affiliated with the Laravel project.
6
6
 
@@ -192,7 +192,7 @@ Resolves to one entry per registered migration:
192
192
  `DB.status(name)` never migrates as a side effect, so you can call it before `DB.migrate(name)` to
193
193
  see what is pending.
194
194
 
195
- > Modelled on Laravel's [Migrations](https://laravel.com/docs/12.x/migrations). These only run
195
+ > modeled on Laravel's [Migrations](https://laravel.com/docs/12.x/migrations). These only run
196
196
  > forward, and they are registered in the connection config rather than discovered from a directory.
197
197
 
198
198
  ### Seeding
@@ -478,7 +478,7 @@ await DB.fresh('app');
478
478
  await DB.fresh('app', { seed: true });
479
479
  ```
480
480
 
481
- > Modelled on Laravel's [Database: Seeding](https://laravel.com/docs/12.x/seeding), down to the
481
+ > modeled on Laravel's [Database: Seeding](https://laravel.com/docs/12.x/seeding), down to the
482
482
  > seeded connection standing in as the default for the duration of the run.
483
483
 
484
484
  ### Defining a schema
@@ -665,7 +665,7 @@ await Schema.getIndexes('users');
665
665
  await Schema.connection('reporting').hasTable('reports');
666
666
  ```
667
667
 
668
- > Modelled on Laravel's [Migrations: Tables](https://laravel.com/docs/12.x/migrations#tables).
668
+ > modeled on Laravel's [Migrations: Tables](https://laravel.com/docs/12.x/migrations#tables).
669
669
  > Column types are metadata this package enforces at write time, since IndexedDB stores whole objects
670
670
  > and checks nothing itself.
671
671
 
@@ -852,7 +852,7 @@ The key path may not be updated, so `update`, `upsert` and `increment` all refus
852
852
  when an index drives the query and key order otherwise. Pair them with an indexed `orderBy` if you
853
853
  need a defined order.
854
854
 
855
- > Modelled on Laravel's [Database: Query Builder](https://laravel.com/docs/12.x/queries). The method
855
+ > modeled on Laravel's [Database: Query Builder](https://laravel.com/docs/12.x/queries). The method
856
856
  > names and their semantics match, and every terminal is asynchronous because IndexedDB is.
857
857
 
858
858
  ### Joins
@@ -959,7 +959,7 @@ covers it, and `chunk` slices the materialised result rather than walking keys.
959
959
  await DB.table('users').whereColumn('updated_at', '>', 'created_at').get();
960
960
  ```
961
961
 
962
- > Modelled on Laravel's [Query Builder: Joins](https://laravel.com/docs/12.x/queries#joins). Rows
962
+ > modeled on Laravel's [Query Builder: Joins](https://laravel.com/docs/12.x/queries#joins). Rows
963
963
  > stay flat as they do in Laravel, and the join itself runs in memory because IndexedDB has none.
964
964
 
965
965
  ### Grouping
@@ -1032,7 +1032,7 @@ await DB.table<User>('users')
1032
1032
  Grouping happens in memory after the records are fetched, so the planner still applies to the
1033
1033
  `where` clauses that select them, and a grouped query reports the plan of that underlying fetch.
1034
1034
 
1035
- > Modelled on Laravel's [Query Builder: Grouping](https://laravel.com/docs/12.x/queries#groupby-having),
1035
+ > modeled on Laravel's [Query Builder: Grouping](https://laravel.com/docs/12.x/queries#groupby-having),
1036
1036
  > with the aggregates named in a typed object instead of raw SQL.
1037
1037
 
1038
1038
  ### Query plans
@@ -1092,7 +1092,7 @@ commits behind your back the first time you await anything outside it, so offeri
1092
1092
  offering a trap. The same rule as migrations applies here: the callback may only await operations
1093
1093
  from this package.
1094
1094
 
1095
- > Modelled on Laravel's [Database: Transactions](https://laravel.com/docs/12.x/database#database-transactions).
1095
+ > modeled on Laravel's [Database: Transactions](https://laravel.com/docs/12.x/database#database-transactions).
1096
1096
  > The tables have to be declared up front, because an IndexedDB transaction fixes its scope when it
1097
1097
  > opens.
1098
1098
 
@@ -1148,7 +1148,7 @@ DB.disableQueryLog();
1148
1148
 
1149
1149
  `DB.logging()` then returns `false`, and `DB.getQueryLog()` an empty array.
1150
1150
 
1151
- > Modelled on Laravel's [Database: Listening for Query Events](https://laravel.com/docs/12.x/database#listening-for-query-events),
1151
+ > modeled on Laravel's [Database: Listening for Query Events](https://laravel.com/docs/12.x/database#listening-for-query-events),
1152
1152
  > with the same enable, get and flush surface, dispatched as a browser event.
1153
1153
 
1154
1154
  ### Multiple tabs
@@ -1178,7 +1178,7 @@ DB.purge('app');
1178
1178
  | `disconnect(name)` | Close the handle, leaving the connection registered so the next query reopens it |
1179
1179
  | `purge(name)` | Close it and drop it, so the next resolve rebuilds it from configuration |
1180
1180
 
1181
- > Modelled on Laravel's [Database: Multiple Connections](https://laravel.com/docs/12.x/database#using-multiple-database-connections),
1181
+ > modeled on Laravel's [Database: Multiple Connections](https://laravel.com/docs/12.x/database#using-multiple-database-connections),
1182
1182
  > resolved by name and cached, with one IndexedDB database behind each.
1183
1183
 
1184
1184
  ### Storage quota
package/dist/main.cjs CHANGED
@@ -1162,7 +1162,7 @@ var Request = class {
1162
1162
  * Name the failure, where the platform reports one this package can say more about.
1163
1163
  */
1164
1164
  static translate(error) {
1165
- if (error !== null && error.name === "QuotaExceededError") {
1165
+ if (error?.name === "QuotaExceededError") {
1166
1166
  return new QuotaExceededException();
1167
1167
  }
1168
1168
  return error;
@@ -1591,13 +1591,13 @@ var Predicate = class {
1591
1591
  let resume = 0;
1592
1592
  while (index < subject.length) {
1593
1593
  const current = tokens[token];
1594
- if (current !== void 0 && current.kind === "any") {
1594
+ if (current?.kind === "any") {
1595
1595
  wildcard = token;
1596
1596
  resume = index;
1597
1597
  token++;
1598
1598
  continue;
1599
1599
  }
1600
- if (current !== void 0 && (current.kind === "one" || current.value === subject[index].toLowerCase())) {
1600
+ if (current?.kind === "one" || current?.value === subject[index].toLowerCase()) {
1601
1601
  token++;
1602
1602
  index++;
1603
1603
  continue;
@@ -1695,7 +1695,7 @@ var Joiner = class {
1695
1695
  */
1696
1696
  static #hashable(clause) {
1697
1697
  const condition = clause.conditions[0];
1698
- return clause.conditions.length === 1 && condition !== void 0 && condition.operator === "=";
1698
+ return clause.conditions.length === 1 && condition?.operator === "=";
1699
1699
  }
1700
1700
  /**
1701
1701
  * Index the other side by the value its join column holds.
@@ -1871,7 +1871,7 @@ var Planner = class {
1871
1871
  return null;
1872
1872
  }
1873
1873
  const column = schema.columns.find((candidate) => candidate.name === order.column);
1874
- if (column !== void 0 && column.nullable) {
1874
+ if (column?.nullable) {
1875
1875
  return null;
1876
1876
  }
1877
1877
  return { constraint: { type: "null", column: order.column, conjunction: "and", not: false }, ...target, range: null, values: null };
@@ -3751,17 +3751,26 @@ var Connection = class {
3751
3751
  let runner = null;
3752
3752
  let failure = null;
3753
3753
  request.onupgradeneeded = (event) => {
3754
+ const transaction = request.transaction;
3755
+ let live = true;
3756
+ const closed = () => {
3757
+ live = false;
3758
+ };
3759
+ transaction.addEventListener("complete", closed);
3760
+ transaction.addEventListener("abort", closed);
3754
3761
  runner = Migrator.run(
3755
3762
  this.#name,
3756
3763
  request.result,
3757
- request.transaction,
3764
+ transaction,
3758
3765
  migrations,
3759
3766
  Migrator.pending(event.oldVersion),
3760
3767
  /* @__PURE__ */ new Date()
3761
3768
  );
3762
3769
  runner.catch((error) => {
3763
3770
  failure = error;
3764
- request.transaction?.abort();
3771
+ if (live) {
3772
+ transaction.abort();
3773
+ }
3765
3774
  });
3766
3775
  };
3767
3776
  request.onblocked = () => {
package/dist/main.js CHANGED
@@ -1098,7 +1098,7 @@ var Request = class {
1098
1098
  * Name the failure, where the platform reports one this package can say more about.
1099
1099
  */
1100
1100
  static translate(error) {
1101
- if (error !== null && error.name === "QuotaExceededError") {
1101
+ if (error?.name === "QuotaExceededError") {
1102
1102
  return new QuotaExceededException();
1103
1103
  }
1104
1104
  return error;
@@ -1527,13 +1527,13 @@ var Predicate = class {
1527
1527
  let resume = 0;
1528
1528
  while (index < subject.length) {
1529
1529
  const current = tokens[token];
1530
- if (current !== void 0 && current.kind === "any") {
1530
+ if (current?.kind === "any") {
1531
1531
  wildcard = token;
1532
1532
  resume = index;
1533
1533
  token++;
1534
1534
  continue;
1535
1535
  }
1536
- if (current !== void 0 && (current.kind === "one" || current.value === subject[index].toLowerCase())) {
1536
+ if (current?.kind === "one" || current?.value === subject[index].toLowerCase()) {
1537
1537
  token++;
1538
1538
  index++;
1539
1539
  continue;
@@ -1631,7 +1631,7 @@ var Joiner = class {
1631
1631
  */
1632
1632
  static #hashable(clause) {
1633
1633
  const condition = clause.conditions[0];
1634
- return clause.conditions.length === 1 && condition !== void 0 && condition.operator === "=";
1634
+ return clause.conditions.length === 1 && condition?.operator === "=";
1635
1635
  }
1636
1636
  /**
1637
1637
  * Index the other side by the value its join column holds.
@@ -1807,7 +1807,7 @@ var Planner = class {
1807
1807
  return null;
1808
1808
  }
1809
1809
  const column = schema.columns.find((candidate) => candidate.name === order.column);
1810
- if (column !== void 0 && column.nullable) {
1810
+ if (column?.nullable) {
1811
1811
  return null;
1812
1812
  }
1813
1813
  return { constraint: { type: "null", column: order.column, conjunction: "and", not: false }, ...target, range: null, values: null };
@@ -3687,17 +3687,26 @@ var Connection = class {
3687
3687
  let runner = null;
3688
3688
  let failure = null;
3689
3689
  request.onupgradeneeded = (event) => {
3690
+ const transaction = request.transaction;
3691
+ let live = true;
3692
+ const closed = () => {
3693
+ live = false;
3694
+ };
3695
+ transaction.addEventListener("complete", closed);
3696
+ transaction.addEventListener("abort", closed);
3690
3697
  runner = Migrator.run(
3691
3698
  this.#name,
3692
3699
  request.result,
3693
- request.transaction,
3700
+ transaction,
3694
3701
  migrations,
3695
3702
  Migrator.pending(event.oldVersion),
3696
3703
  /* @__PURE__ */ new Date()
3697
3704
  );
3698
3705
  runner.catch((error) => {
3699
3706
  failure = error;
3700
- request.transaction?.abort();
3707
+ if (live) {
3708
+ transaction.abort();
3709
+ }
3701
3710
  });
3702
3711
  };
3703
3712
  request.onblocked = () => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bjnstnkvc/db",
3
- "version": "0.1.0",
4
- "description": "TypeScript database layer for IndexedDB with an API modelled on Laravel.",
3
+ "version": "1.0.0",
4
+ "description": "TypeScript database layer for IndexedDB with an API modeled on Laravel.",
5
5
  "type": "module",
6
6
  "main": "./dist/main.cjs",
7
7
  "module": "./dist/main.js",