arkormx 2.0.0-next.23 → 2.0.0-next.25

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/dist/index.cjs CHANGED
@@ -7593,12 +7593,14 @@ var QueryBuilder = class QueryBuilder {
7593
7593
  * @returns
7594
7594
  */
7595
7595
  async updateOrInsert(attributes, values = {}) {
7596
- if (typeof values !== "function" && this.adapter?.capabilities?.upsert && typeof this.requireAdapter().upsert === "function") {
7596
+ if (typeof values !== "function" && this.adapter?.capabilities?.upsert && typeof this.requireAdapter().upsert === "function") try {
7597
7597
  await this.executeUpsertRows([{
7598
7598
  ...attributes,
7599
7599
  ...values
7600
7600
  }], Object.keys(attributes), Object.keys(values));
7601
7601
  return true;
7602
+ } catch (error) {
7603
+ if (!this.shouldFallbackUpdateOrInsertUpsert(error)) throw error;
7602
7604
  }
7603
7605
  const exists = await this.clone().where(attributes).first() != null;
7604
7606
  const resolvedValues = typeof values === "function" ? await values(exists) : values;
@@ -7611,6 +7613,13 @@ var QueryBuilder = class QueryBuilder {
7611
7613
  }
7612
7614
  return await this.clone().where(attributes).update(resolvedValues) != null;
7613
7615
  }
7616
+ shouldFallbackUpdateOrInsertUpsert(error) {
7617
+ if (!(error instanceof QueryExecutionException)) return false;
7618
+ const cause = error.cause;
7619
+ const code = typeof cause?.code === "string" ? cause.code : void 0;
7620
+ const message = typeof cause?.message === "string" ? cause.message : error.message;
7621
+ return code === "42P10" || message.includes("there is no unique or exclusion constraint matching the ON CONFLICT specification");
7622
+ }
7614
7623
  /**
7615
7624
  * Insert new records or update existing records by one or more unique keys.
7616
7625
  *
@@ -7639,8 +7648,8 @@ var QueryBuilder = class QueryBuilder {
7639
7648
  return affected;
7640
7649
  }
7641
7650
  /**
7642
- * Deletes records matching the current query constraints and returns
7643
- * the deleted record(s) as model instance(s).
7651
+ * Deletes the first record matching the current query constraints and returns
7652
+ * it as a hydrated model instance. Returns null when no record matches.
7644
7653
  *
7645
7654
  * @returns
7646
7655
  */
@@ -7654,13 +7663,26 @@ var QueryBuilder = class QueryBuilder {
7654
7663
  const adapter = this.requireAdapter();
7655
7664
  if (!this.isUniqueWhere(where) && directSpec && typeof adapter.deleteFirst === "function") {
7656
7665
  const deleted = await adapter.deleteFirst(directSpec);
7657
- if (!deleted) throw new ModelNotFoundException(this.model.name, "Record not found for delete operation.", { operation: "delete" });
7666
+ if (!deleted) return null;
7658
7667
  return this.model.hydrate(deleted);
7659
7668
  }
7660
- const uniqueWhere = await this.resolveUniqueWhere(where);
7661
- const deleted = await this.executeDeleteRow(uniqueWhere);
7669
+ const uniqueWhere = await this.resolveUniqueWhere(where, false);
7670
+ if (!uniqueWhere) return null;
7671
+ const deleted = await this.executeDeleteRow(uniqueWhere, false);
7672
+ if (!deleted) return null;
7662
7673
  return this.model.hydrate(deleted);
7663
7674
  }
7675
+ /**
7676
+ * Deletes the first record matching the current query constraints and throws
7677
+ * when no record matches.
7678
+ *
7679
+ * @returns
7680
+ */
7681
+ async deleteOrFail() {
7682
+ const deleted = await this.delete();
7683
+ if (!deleted) throw new ModelNotFoundException(this.model.name, "Record not found for delete operation.", { operation: "delete" });
7684
+ return deleted;
7685
+ }
7664
7686
  tryBuildInsertSpec(values) {
7665
7687
  return {
7666
7688
  target: this.buildQueryTarget(),
@@ -8434,7 +8456,7 @@ var QueryBuilder = class QueryBuilder {
8434
8456
  }
8435
8457
  return updated;
8436
8458
  }
8437
- async executeDeleteRow(where) {
8459
+ async executeDeleteRow(where, failIfMissing = true) {
8438
8460
  const adapter = this.requireAdapter();
8439
8461
  const spec = this.tryBuildDeleteSpec(where);
8440
8462
  if (!spec) throw new UnsupportedAdapterFeatureException("Delete could not be compiled into an Arkorm delete specification.", {
@@ -8442,7 +8464,9 @@ var QueryBuilder = class QueryBuilder {
8442
8464
  model: this.model.name
8443
8465
  });
8444
8466
  const deleted = await adapter.delete(spec);
8445
- if (!deleted) throw new ModelNotFoundException(this.model.name, "Record not found for delete operation.", { operation: "delete" });
8467
+ if (!deleted) return failIfMissing ? (() => {
8468
+ throw new ModelNotFoundException(this.model.name, "Record not found for delete operation.", { operation: "delete" });
8469
+ })() : null;
8446
8470
  return deleted;
8447
8471
  }
8448
8472
  /**
@@ -8471,7 +8495,7 @@ var QueryBuilder = class QueryBuilder {
8471
8495
  * @param where
8472
8496
  * @returns
8473
8497
  */
8474
- async resolveUniqueWhere(where) {
8498
+ async resolveUniqueWhere(where, failIfMissing = true) {
8475
8499
  if (this.isUniqueWhere(where)) return where;
8476
8500
  const condition = this.tryBuildQueryCondition(where);
8477
8501
  if (!condition) throw new UniqueConstraintResolutionException("Unable to resolve a unique identifier for update/delete operation from the current query shape.", {
@@ -8485,10 +8509,12 @@ var QueryBuilder = class QueryBuilder {
8485
8509
  where: condition,
8486
8510
  limit: 1
8487
8511
  });
8488
- if (!row) throw new ModelNotFoundException(this.model.name, "Record not found for update/delete operation.", {
8489
- operation: "resolveUniqueWhere",
8490
- meta: { where }
8491
- });
8512
+ if (!row) return failIfMissing ? (() => {
8513
+ throw new ModelNotFoundException(this.model.name, "Record not found for update/delete operation.", {
8514
+ operation: "resolveUniqueWhere",
8515
+ meta: { where }
8516
+ });
8517
+ })() : null;
8492
8518
  const primaryKey = this.model.getPrimaryKey();
8493
8519
  if (!Object.prototype.hasOwnProperty.call(row, primaryKey)) throw new UniqueConstraintResolutionException(`Unable to resolve a unique identifier for update/delete operation. Include [${primaryKey}] in the query constraints.`, {
8494
8520
  operation: "resolveUniqueWhere",
@@ -10682,7 +10708,7 @@ var Model = class Model {
10682
10708
  await Model.dispatchEvent(constructor, "deleted", this);
10683
10709
  return this;
10684
10710
  }
10685
- const deleted = await constructor.query().where({ [primaryKey]: identifier }).delete();
10711
+ const deleted = await constructor.query().where({ [primaryKey]: identifier }).deleteOrFail();
10686
10712
  this.fill(deleted.getRawAttributes());
10687
10713
  this.syncChanges(previousOriginal);
10688
10714
  this.syncOriginal();
@@ -10711,7 +10737,7 @@ var Model = class Model {
10711
10737
  const previousOriginal = this.getOriginal();
10712
10738
  await Model.dispatchEvent(constructor, "forceDeleting", this);
10713
10739
  await Model.dispatchEvent(constructor, "deleting", this);
10714
- const deleted = await constructor.query().withTrashed().where({ [primaryKey]: identifier }).delete();
10740
+ const deleted = await constructor.query().withTrashed().where({ [primaryKey]: identifier }).deleteOrFail();
10715
10741
  this.fill(deleted.getRawAttributes());
10716
10742
  this.syncChanges(previousOriginal);
10717
10743
  this.syncOriginal();
package/dist/index.d.cts CHANGED
@@ -2687,6 +2687,7 @@ declare class QueryBuilder<TModel, TDelegate extends PrismaDelegateLike = Prisma
2687
2687
  * @returns
2688
2688
  */
2689
2689
  updateOrInsert(attributes: Record<string, unknown>, values?: Record<string, unknown> | ((exists: boolean) => Record<string, unknown> | Promise<Record<string, unknown>>)): Promise<boolean>;
2690
+ private shouldFallbackUpdateOrInsertUpsert;
2690
2691
  /**
2691
2692
  * Insert new records or update existing records by one or more unique keys.
2692
2693
  *
@@ -2697,12 +2698,19 @@ declare class QueryBuilder<TModel, TDelegate extends PrismaDelegateLike = Prisma
2697
2698
  */
2698
2699
  upsert(values: Array<Record<string, unknown>>, uniqueBy: string | string[], update?: string[] | null): Promise<number>;
2699
2700
  /**
2700
- * Deletes records matching the current query constraints and returns
2701
- * the deleted record(s) as model instance(s).
2701
+ * Deletes the first record matching the current query constraints and returns
2702
+ * it as a hydrated model instance. Returns null when no record matches.
2702
2703
  *
2703
2704
  * @returns
2704
2705
  */
2705
- delete(): Promise<TModel>;
2706
+ delete(): Promise<TModel | null>;
2707
+ /**
2708
+ * Deletes the first record matching the current query constraints and throws
2709
+ * when no record matches.
2710
+ *
2711
+ * @returns
2712
+ */
2713
+ deleteOrFail(): Promise<TModel>;
2706
2714
  private tryBuildInsertSpec;
2707
2715
  private tryBuildInsertManySpec;
2708
2716
  private tryBuildUpsertSpec;
package/dist/index.d.mts CHANGED
@@ -2687,6 +2687,7 @@ declare class QueryBuilder<TModel, TDelegate extends PrismaDelegateLike = Prisma
2687
2687
  * @returns
2688
2688
  */
2689
2689
  updateOrInsert(attributes: Record<string, unknown>, values?: Record<string, unknown> | ((exists: boolean) => Record<string, unknown> | Promise<Record<string, unknown>>)): Promise<boolean>;
2690
+ private shouldFallbackUpdateOrInsertUpsert;
2690
2691
  /**
2691
2692
  * Insert new records or update existing records by one or more unique keys.
2692
2693
  *
@@ -2697,12 +2698,19 @@ declare class QueryBuilder<TModel, TDelegate extends PrismaDelegateLike = Prisma
2697
2698
  */
2698
2699
  upsert(values: Array<Record<string, unknown>>, uniqueBy: string | string[], update?: string[] | null): Promise<number>;
2699
2700
  /**
2700
- * Deletes records matching the current query constraints and returns
2701
- * the deleted record(s) as model instance(s).
2701
+ * Deletes the first record matching the current query constraints and returns
2702
+ * it as a hydrated model instance. Returns null when no record matches.
2702
2703
  *
2703
2704
  * @returns
2704
2705
  */
2705
- delete(): Promise<TModel>;
2706
+ delete(): Promise<TModel | null>;
2707
+ /**
2708
+ * Deletes the first record matching the current query constraints and throws
2709
+ * when no record matches.
2710
+ *
2711
+ * @returns
2712
+ */
2713
+ deleteOrFail(): Promise<TModel>;
2706
2714
  private tryBuildInsertSpec;
2707
2715
  private tryBuildInsertManySpec;
2708
2716
  private tryBuildUpsertSpec;
package/dist/index.mjs CHANGED
@@ -7564,12 +7564,14 @@ var QueryBuilder = class QueryBuilder {
7564
7564
  * @returns
7565
7565
  */
7566
7566
  async updateOrInsert(attributes, values = {}) {
7567
- if (typeof values !== "function" && this.adapter?.capabilities?.upsert && typeof this.requireAdapter().upsert === "function") {
7567
+ if (typeof values !== "function" && this.adapter?.capabilities?.upsert && typeof this.requireAdapter().upsert === "function") try {
7568
7568
  await this.executeUpsertRows([{
7569
7569
  ...attributes,
7570
7570
  ...values
7571
7571
  }], Object.keys(attributes), Object.keys(values));
7572
7572
  return true;
7573
+ } catch (error) {
7574
+ if (!this.shouldFallbackUpdateOrInsertUpsert(error)) throw error;
7573
7575
  }
7574
7576
  const exists = await this.clone().where(attributes).first() != null;
7575
7577
  const resolvedValues = typeof values === "function" ? await values(exists) : values;
@@ -7582,6 +7584,13 @@ var QueryBuilder = class QueryBuilder {
7582
7584
  }
7583
7585
  return await this.clone().where(attributes).update(resolvedValues) != null;
7584
7586
  }
7587
+ shouldFallbackUpdateOrInsertUpsert(error) {
7588
+ if (!(error instanceof QueryExecutionException)) return false;
7589
+ const cause = error.cause;
7590
+ const code = typeof cause?.code === "string" ? cause.code : void 0;
7591
+ const message = typeof cause?.message === "string" ? cause.message : error.message;
7592
+ return code === "42P10" || message.includes("there is no unique or exclusion constraint matching the ON CONFLICT specification");
7593
+ }
7585
7594
  /**
7586
7595
  * Insert new records or update existing records by one or more unique keys.
7587
7596
  *
@@ -7610,8 +7619,8 @@ var QueryBuilder = class QueryBuilder {
7610
7619
  return affected;
7611
7620
  }
7612
7621
  /**
7613
- * Deletes records matching the current query constraints and returns
7614
- * the deleted record(s) as model instance(s).
7622
+ * Deletes the first record matching the current query constraints and returns
7623
+ * it as a hydrated model instance. Returns null when no record matches.
7615
7624
  *
7616
7625
  * @returns
7617
7626
  */
@@ -7625,13 +7634,26 @@ var QueryBuilder = class QueryBuilder {
7625
7634
  const adapter = this.requireAdapter();
7626
7635
  if (!this.isUniqueWhere(where) && directSpec && typeof adapter.deleteFirst === "function") {
7627
7636
  const deleted = await adapter.deleteFirst(directSpec);
7628
- if (!deleted) throw new ModelNotFoundException(this.model.name, "Record not found for delete operation.", { operation: "delete" });
7637
+ if (!deleted) return null;
7629
7638
  return this.model.hydrate(deleted);
7630
7639
  }
7631
- const uniqueWhere = await this.resolveUniqueWhere(where);
7632
- const deleted = await this.executeDeleteRow(uniqueWhere);
7640
+ const uniqueWhere = await this.resolveUniqueWhere(where, false);
7641
+ if (!uniqueWhere) return null;
7642
+ const deleted = await this.executeDeleteRow(uniqueWhere, false);
7643
+ if (!deleted) return null;
7633
7644
  return this.model.hydrate(deleted);
7634
7645
  }
7646
+ /**
7647
+ * Deletes the first record matching the current query constraints and throws
7648
+ * when no record matches.
7649
+ *
7650
+ * @returns
7651
+ */
7652
+ async deleteOrFail() {
7653
+ const deleted = await this.delete();
7654
+ if (!deleted) throw new ModelNotFoundException(this.model.name, "Record not found for delete operation.", { operation: "delete" });
7655
+ return deleted;
7656
+ }
7635
7657
  tryBuildInsertSpec(values) {
7636
7658
  return {
7637
7659
  target: this.buildQueryTarget(),
@@ -8405,7 +8427,7 @@ var QueryBuilder = class QueryBuilder {
8405
8427
  }
8406
8428
  return updated;
8407
8429
  }
8408
- async executeDeleteRow(where) {
8430
+ async executeDeleteRow(where, failIfMissing = true) {
8409
8431
  const adapter = this.requireAdapter();
8410
8432
  const spec = this.tryBuildDeleteSpec(where);
8411
8433
  if (!spec) throw new UnsupportedAdapterFeatureException("Delete could not be compiled into an Arkorm delete specification.", {
@@ -8413,7 +8435,9 @@ var QueryBuilder = class QueryBuilder {
8413
8435
  model: this.model.name
8414
8436
  });
8415
8437
  const deleted = await adapter.delete(spec);
8416
- if (!deleted) throw new ModelNotFoundException(this.model.name, "Record not found for delete operation.", { operation: "delete" });
8438
+ if (!deleted) return failIfMissing ? (() => {
8439
+ throw new ModelNotFoundException(this.model.name, "Record not found for delete operation.", { operation: "delete" });
8440
+ })() : null;
8417
8441
  return deleted;
8418
8442
  }
8419
8443
  /**
@@ -8442,7 +8466,7 @@ var QueryBuilder = class QueryBuilder {
8442
8466
  * @param where
8443
8467
  * @returns
8444
8468
  */
8445
- async resolveUniqueWhere(where) {
8469
+ async resolveUniqueWhere(where, failIfMissing = true) {
8446
8470
  if (this.isUniqueWhere(where)) return where;
8447
8471
  const condition = this.tryBuildQueryCondition(where);
8448
8472
  if (!condition) throw new UniqueConstraintResolutionException("Unable to resolve a unique identifier for update/delete operation from the current query shape.", {
@@ -8456,10 +8480,12 @@ var QueryBuilder = class QueryBuilder {
8456
8480
  where: condition,
8457
8481
  limit: 1
8458
8482
  });
8459
- if (!row) throw new ModelNotFoundException(this.model.name, "Record not found for update/delete operation.", {
8460
- operation: "resolveUniqueWhere",
8461
- meta: { where }
8462
- });
8483
+ if (!row) return failIfMissing ? (() => {
8484
+ throw new ModelNotFoundException(this.model.name, "Record not found for update/delete operation.", {
8485
+ operation: "resolveUniqueWhere",
8486
+ meta: { where }
8487
+ });
8488
+ })() : null;
8463
8489
  const primaryKey = this.model.getPrimaryKey();
8464
8490
  if (!Object.prototype.hasOwnProperty.call(row, primaryKey)) throw new UniqueConstraintResolutionException(`Unable to resolve a unique identifier for update/delete operation. Include [${primaryKey}] in the query constraints.`, {
8465
8491
  operation: "resolveUniqueWhere",
@@ -10653,7 +10679,7 @@ var Model = class Model {
10653
10679
  await Model.dispatchEvent(constructor, "deleted", this);
10654
10680
  return this;
10655
10681
  }
10656
- const deleted = await constructor.query().where({ [primaryKey]: identifier }).delete();
10682
+ const deleted = await constructor.query().where({ [primaryKey]: identifier }).deleteOrFail();
10657
10683
  this.fill(deleted.getRawAttributes());
10658
10684
  this.syncChanges(previousOriginal);
10659
10685
  this.syncOriginal();
@@ -10682,7 +10708,7 @@ var Model = class Model {
10682
10708
  const previousOriginal = this.getOriginal();
10683
10709
  await Model.dispatchEvent(constructor, "forceDeleting", this);
10684
10710
  await Model.dispatchEvent(constructor, "deleting", this);
10685
- const deleted = await constructor.query().withTrashed().where({ [primaryKey]: identifier }).delete();
10711
+ const deleted = await constructor.query().withTrashed().where({ [primaryKey]: identifier }).deleteOrFail();
10686
10712
  this.fill(deleted.getRawAttributes());
10687
10713
  this.syncChanges(previousOriginal);
10688
10714
  this.syncOriginal();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arkormx",
3
- "version": "2.0.0-next.23",
3
+ "version": "2.0.0-next.25",
4
4
  "description": "Modern TypeScript-first ORM for Node.js.",
5
5
  "keywords": [
6
6
  "orm",