@bjnstnkvc/db 2.0.1 → 2.0.2

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
@@ -835,6 +835,7 @@ await DB.table<User>('users').where('id', 1).increment('visits');
835
835
  await DB.table<User>('users').where('id', 1).decrement('credits', 5);
836
836
 
837
837
  await DB.table<User>('users').where('role', 'guest').delete();
838
+ await DB.table<User>('users').oldest('created_at').limit(100).delete();
838
839
  await DB.table<User>('users').truncate();
839
840
  ```
840
841
 
@@ -851,9 +852,10 @@ enforce anything else. Any other column throws `SchemaException`.
851
852
 
852
853
  The key path may not be updated, so `update`, `upsert` and `increment` all refuse it.
853
854
 
854
- `update` and `delete` honour `limit` and `offset` in the order the plan scans, which is index order
855
- when an index drives the query and key order otherwise. Pair them with an indexed `orderBy` if you
856
- need a defined order.
855
+ `update`, `delete`, `increment` and `decrement` honor `orderBy` together with `limit` and
856
+ `offset`, so they touch the same records a read of the query would return, whether or not an index
857
+ serves the order. Without an `orderBy`, they follow the order the plan scans, which is index order
858
+ when an index drives the query and key order otherwise.
857
859
 
858
860
  > Modeled on Laravel's [Database: Query Builder](https://laravel.com/docs/12.x/queries). The method
859
861
  > names and their semantics match, and every terminal is asynchronous because IndexedDB is.
package/dist/main.cjs CHANGED
@@ -2910,7 +2910,7 @@ var Builder = class _Builder {
2910
2910
  }
2911
2911
  }
2912
2912
  /**
2913
- * Apply a change to every record matching the query, in the order the plan scans them.
2913
+ * Apply a change to every record matching the query, in the order the query asks for.
2914
2914
  */
2915
2915
  async #modify(apply) {
2916
2916
  const schema = await this.#connection.schema(this.#table);
@@ -2919,8 +2919,20 @@ var Builder = class _Builder {
2919
2919
  const started = performance.now();
2920
2920
  const matches = Predicate.compile(plan.residual);
2921
2921
  const ceiling = this.#limit === null ? null : this.#offset + this.#limit;
2922
+ const collects = !plan.ordered && this.#orders.length > 0 && (this.#limit !== null || this.#offset > 0);
2922
2923
  let seen = 0;
2923
2924
  let affected = 0;
2925
+ if (collects) {
2926
+ const collected = plan.values === null ? await this.#cursored(store, plan, matches) : await this.#points(store, plan, matches);
2927
+ for (const entry of this.#paged(this.#sorted(collected))) {
2928
+ await Request.walk(store.openCursor(IDBKeyRange.only(entry.key)), (cursor) => {
2929
+ apply(cursor);
2930
+ affected++;
2931
+ });
2932
+ }
2933
+ this.#emit(Planner.describe(plan), started, affected);
2934
+ return affected;
2935
+ }
2924
2936
  const visit = (cursor) => {
2925
2937
  if (!matches(cursor.value)) {
2926
2938
  return true;
@@ -2937,6 +2949,9 @@ var Builder = class _Builder {
2937
2949
  await Request.walk(source.openCursor(plan.range, plan.direction), visit);
2938
2950
  } else {
2939
2951
  for (const value of plan.values) {
2952
+ if (ceiling !== null && seen >= ceiling) {
2953
+ break;
2954
+ }
2940
2955
  const source = plan.index === null ? store : store.index(plan.index);
2941
2956
  await Request.walk(source.openCursor(IDBKeyRange.only(value)), visit);
2942
2957
  }
package/dist/main.js CHANGED
@@ -2846,7 +2846,7 @@ var Builder = class _Builder {
2846
2846
  }
2847
2847
  }
2848
2848
  /**
2849
- * Apply a change to every record matching the query, in the order the plan scans them.
2849
+ * Apply a change to every record matching the query, in the order the query asks for.
2850
2850
  */
2851
2851
  async #modify(apply) {
2852
2852
  const schema = await this.#connection.schema(this.#table);
@@ -2855,8 +2855,20 @@ var Builder = class _Builder {
2855
2855
  const started = performance.now();
2856
2856
  const matches = Predicate.compile(plan.residual);
2857
2857
  const ceiling = this.#limit === null ? null : this.#offset + this.#limit;
2858
+ const collects = !plan.ordered && this.#orders.length > 0 && (this.#limit !== null || this.#offset > 0);
2858
2859
  let seen = 0;
2859
2860
  let affected = 0;
2861
+ if (collects) {
2862
+ const collected = plan.values === null ? await this.#cursored(store, plan, matches) : await this.#points(store, plan, matches);
2863
+ for (const entry of this.#paged(this.#sorted(collected))) {
2864
+ await Request.walk(store.openCursor(IDBKeyRange.only(entry.key)), (cursor) => {
2865
+ apply(cursor);
2866
+ affected++;
2867
+ });
2868
+ }
2869
+ this.#emit(Planner.describe(plan), started, affected);
2870
+ return affected;
2871
+ }
2860
2872
  const visit = (cursor) => {
2861
2873
  if (!matches(cursor.value)) {
2862
2874
  return true;
@@ -2873,6 +2885,9 @@ var Builder = class _Builder {
2873
2885
  await Request.walk(source.openCursor(plan.range, plan.direction), visit);
2874
2886
  } else {
2875
2887
  for (const value of plan.values) {
2888
+ if (ceiling !== null && seen >= ceiling) {
2889
+ break;
2890
+ }
2876
2891
  const source = plan.index === null ? store : store.index(plan.index);
2877
2892
  await Request.walk(source.openCursor(IDBKeyRange.only(value)), visit);
2878
2893
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bjnstnkvc/db",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "description": "TypeScript database layer for IndexedDB with an API modeled on Laravel.",
5
5
  "type": "module",
6
6
  "main": "./dist/main.cjs",