pqb 0.54.1 → 0.54.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/dist/index.js CHANGED
@@ -432,7 +432,7 @@ class ColumnType extends orchidCore.ColumnTypeBase {
432
432
  return sql2;
433
433
  }
434
434
  });
435
- column.data.readonly = true;
435
+ column.data.readOnly = true;
436
436
  return column;
437
437
  }
438
438
  }
@@ -2158,7 +2158,7 @@ class TsVectorColumn extends ColumnType {
2158
2158
  toSQL,
2159
2159
  toCode
2160
2160
  });
2161
- column.data.readonly = true;
2161
+ column.data.readOnly = true;
2162
2162
  return column;
2163
2163
  }
2164
2164
  }
@@ -2458,8 +2458,7 @@ class VirtualColumn extends ColumnType {
2458
2458
  super(schema, inputSchema);
2459
2459
  this.dataType = "";
2460
2460
  this.operators = Operators.any;
2461
- this.data.explicitSelect = true;
2462
- this.data.insertable = this.data.updatable = false;
2461
+ this.data.explicitSelect = this.data.appReadOnly = this.data.virtual = true;
2463
2462
  }
2464
2463
  toCode() {
2465
2464
  throw new Error(`toCode is not implemented for virtual column`);
@@ -2470,8 +2469,7 @@ const _UnknownColumn = class _UnknownColumn extends VirtualColumn {
2470
2469
  constructor(schema) {
2471
2470
  super(schema, schema.unknown());
2472
2471
  this.selectable = true;
2473
- this.data.explicitSelect = void 0;
2474
- this.data.insertable = this.data.updatable = true;
2472
+ this.data.explicitSelect = this.data.appReadOnly = this.data.virtual = void 0;
2475
2473
  }
2476
2474
  };
2477
2475
  _UnknownColumn.instance = new _UnknownColumn(defaultSchemaConfig);
@@ -2730,8 +2728,9 @@ class NotFoundError extends OrchidOrmError {
2730
2728
  }
2731
2729
  _query = new WeakMap();
2732
2730
  class OrchidOrmInternalError extends Error {
2733
- constructor(query, message) {
2731
+ constructor(query, message, data) {
2734
2732
  super(message);
2733
+ this.data = data;
2735
2734
  // `#query` is private to prevent it from serializing to not cause problems to test runner reports
2736
2735
  __privateAdd(this, _query2);
2737
2736
  __privateSet(this, _query2, query);
@@ -3380,8 +3379,8 @@ const noneMethods = {
3380
3379
  const _queryNone = (q) => {
3381
3380
  if (isQueryNone(q)) return q;
3382
3381
  q = extendQuery(q, noneMethods);
3383
- pushQueryValueImmutable(q, "and", new RawSQL("false"));
3384
- pushQueryValueImmutable(
3382
+ orchidCore.pushQueryValueImmutable(q, "and", new RawSQL("false"));
3383
+ orchidCore.pushQueryValueImmutable(
3385
3384
  q,
3386
3385
  "transform",
3387
3386
  (_, queryData) => noneResult(q, queryData, queryData.returnType)
@@ -3405,11 +3404,7 @@ const resolveCallbacksInArgs = (q, args) => {
3405
3404
  };
3406
3405
  const _queryWhere = (q, args) => {
3407
3406
  resolveCallbacksInArgs(q, args);
3408
- return pushQueryArrayImmutable(
3409
- q,
3410
- "and",
3411
- args
3412
- );
3407
+ return pushQueryArrayImmutable(q, "and", args);
3413
3408
  };
3414
3409
  const _queryFindBy = (q, args) => {
3415
3410
  return _queryTake(_queryWhere(q, args));
@@ -3418,7 +3413,7 @@ const _queryFindByOptional = (q, args) => {
3418
3413
  return _queryTakeOptional(_queryWhere(q, args));
3419
3414
  };
3420
3415
  const _queryWhereSql = (q, args) => {
3421
- return pushQueryValueImmutable(
3416
+ return orchidCore.pushQueryValueImmutable(
3422
3417
  q,
3423
3418
  "and",
3424
3419
  sqlQueryArgsToExpression(args)
@@ -3426,24 +3421,24 @@ const _queryWhereSql = (q, args) => {
3426
3421
  };
3427
3422
  const _queryWhereNot = (q, args) => {
3428
3423
  resolveCallbacksInArgs(q, args);
3429
- return pushQueryValueImmutable(q, "and", {
3424
+ return orchidCore.pushQueryValueImmutable(q, "and", {
3430
3425
  NOT: args
3431
3426
  });
3432
3427
  };
3433
3428
  const _queryWhereNotSql = (q, args) => {
3434
- return pushQueryValueImmutable(q, "and", {
3429
+ return orchidCore.pushQueryValueImmutable(q, "and", {
3435
3430
  NOT: sqlQueryArgsToExpression(args)
3436
3431
  });
3437
3432
  };
3438
3433
  const _queryWhereOneOf = (q, args) => {
3439
3434
  resolveCallbacksInArgs(q, args);
3440
- return pushQueryValueImmutable(q, "and", {
3435
+ return orchidCore.pushQueryValueImmutable(q, "and", {
3441
3436
  OR: args
3442
3437
  });
3443
3438
  };
3444
3439
  const _queryWhereNotOneOf = (q, args) => {
3445
3440
  resolveCallbacksInArgs(q, args);
3446
- return pushQueryValueImmutable(q, "and", {
3441
+ return orchidCore.pushQueryValueImmutable(q, "and", {
3447
3442
  NOT: { OR: args }
3448
3443
  });
3449
3444
  };
@@ -3493,9 +3488,9 @@ const _queryWhereIn = (q, and, arg, values, not) => {
3493
3488
  }
3494
3489
  if (not) item = { NOT: item };
3495
3490
  if (and) {
3496
- pushQueryValueImmutable(q, "and", item);
3491
+ orchidCore.pushQueryValueImmutable(q, "and", item);
3497
3492
  } else {
3498
- pushQueryValueImmutable(q, "or", [item]);
3493
+ orchidCore.pushQueryValueImmutable(q, "or", [item]);
3499
3494
  }
3500
3495
  return q;
3501
3496
  };
@@ -4299,10 +4294,6 @@ const pushQueryArrayImmutable = (q, key, value) => {
4299
4294
  q.q[key] = arr ? [...arr, ...value] : value;
4300
4295
  return q;
4301
4296
  };
4302
- const pushQueryValueImmutable = (q, key, value) => {
4303
- orchidCore.pushOrNewArrayToObjectImmutable(q.q, key, value);
4304
- return q;
4305
- };
4306
4297
  const setQueryObjectValueImmutable = (q, object, key, value) => {
4307
4298
  q.q[object] = {
4308
4299
  ...q.q[object],
@@ -4518,7 +4509,7 @@ const _join = (query, require, type, first, args) => {
4518
4509
  computeds
4519
4510
  );
4520
4511
  }
4521
- pushQueryValueImmutable(query, "join", {
4512
+ orchidCore.pushQueryValueImmutable(query, "join", {
4522
4513
  type,
4523
4514
  args: joinArgs
4524
4515
  });
@@ -4595,7 +4586,7 @@ const _joinLateral = (self, type, arg, as, innerJoinLateral) => {
4595
4586
  }
4596
4587
  as || (as = getQueryAs(arg));
4597
4588
  orchidCore.setObjectValueImmutable(q.q, "joinedComputeds", as, arg.q.computeds);
4598
- pushQueryValueImmutable(q, "join", {
4589
+ orchidCore.pushQueryValueImmutable(q, "join", {
4599
4590
  type: `${type} LATERAL`,
4600
4591
  args: { l: arg, a: as, i: innerJoinLateral }
4601
4592
  });
@@ -4986,7 +4977,7 @@ const applyComputedColumns = (q, fn) => {
4986
4977
  const { data } = col;
4987
4978
  data.computed = item;
4988
4979
  data.explicitSelect = true;
4989
- data.readonly = true;
4980
+ data.readOnly = true;
4990
4981
  addColumnParserToQuery(
4991
4982
  q.q,
4992
4983
  key,
@@ -5800,7 +5791,7 @@ const addParserForSelectItem = (q, as, key, arg, columnAlias, joinQuery) => {
5800
5791
  );
5801
5792
  }
5802
5793
  if (query.hookSelect || query.parsers || query.transform) {
5803
- pushQueryValueImmutable(q, "batchParsers", {
5794
+ orchidCore.pushQueryValueImmutable(q, "batchParsers", {
5804
5795
  path: [key],
5805
5796
  fn: (path, queryResult) => {
5806
5797
  const { rows } = queryResult;
@@ -6544,7 +6535,7 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
6544
6535
  const { from, values: v } = values;
6545
6536
  const q2 = from.clone();
6546
6537
  if (v) {
6547
- pushQueryValueImmutable(
6538
+ orchidCore.pushQueryValueImmutable(
6548
6539
  q2,
6549
6540
  "select",
6550
6541
  new RawSQL(
@@ -8802,7 +8793,7 @@ class WithMethods {
8802
8793
  withSql(name, ...args) {
8803
8794
  const q = _clone(this);
8804
8795
  const [options, shape, sql] = args.length === 2 ? [void 0, args[0], args[1]] : args;
8805
- pushQueryValueImmutable(q, "with", {
8796
+ orchidCore.pushQueryValueImmutable(q, "with", {
8806
8797
  n: name,
8807
8798
  o: options,
8808
8799
  s: sql(q)
@@ -8825,38 +8816,50 @@ const processCreateItem = (q, item, rowIndex, ctx, encoders) => {
8825
8816
  var _a;
8826
8817
  const { shape } = q.q;
8827
8818
  for (const key in item) {
8828
- if (shape[key]?.data.insertable !== false) {
8829
- let value = item[key];
8830
- if (typeof value === "function") {
8831
- value = item[key] = resolveSubQueryCallbackV2(
8832
- q,
8833
- value
8834
- );
8835
- if (value && typeof value === "object" && value instanceof Db) {
8836
- moveQueryValueToWith(
8837
- q,
8838
- (_a = q.q).insertWith ?? (_a.insertWith = {}),
8839
- value,
8840
- item,
8841
- key,
8842
- rowIndex
8843
- );
8844
- }
8845
- }
8846
- if (!ctx.columns.has(key) && (shape[key] && !shape[key].data.readonly || shape === anyShape) && value !== void 0) {
8847
- ctx.columns.set(key, ctx.columns.size);
8848
- encoders[key] = shape[key]?.data.encode;
8849
- }
8850
- } else if (shape[key] instanceof VirtualColumn) {
8851
- shape[key].create?.(
8819
+ const column = shape[key];
8820
+ if (!column) continue;
8821
+ if (column.data.virtual) {
8822
+ column.create?.(
8852
8823
  q,
8853
8824
  ctx,
8854
8825
  item,
8855
8826
  rowIndex
8856
8827
  );
8828
+ continue;
8829
+ }
8830
+ throwOnReadOnly$1(q, column, key);
8831
+ let value = item[key];
8832
+ if (typeof value === "function") {
8833
+ value = item[key] = resolveSubQueryCallbackV2(
8834
+ q,
8835
+ value
8836
+ );
8837
+ if (value && typeof value === "object" && value instanceof Db) {
8838
+ moveQueryValueToWith(
8839
+ q,
8840
+ (_a = q.q).insertWith ?? (_a.insertWith = {}),
8841
+ value,
8842
+ item,
8843
+ key,
8844
+ rowIndex
8845
+ );
8846
+ }
8847
+ }
8848
+ if (!ctx.columns.has(key) && (column && !column.data.readOnly || shape === anyShape) && value !== void 0) {
8849
+ ctx.columns.set(key, ctx.columns.size);
8850
+ encoders[key] = column?.data.encode;
8857
8851
  }
8858
8852
  }
8859
8853
  };
8854
+ const throwOnReadOnly$1 = (q, column, key) => {
8855
+ if (column.data.appReadOnly || column.data.readOnly) {
8856
+ throw new OrchidOrmInternalError(
8857
+ q,
8858
+ "Trying to insert a readonly column",
8859
+ { column: key }
8860
+ );
8861
+ }
8862
+ };
8860
8863
  const createCtx = () => ({
8861
8864
  columns: /* @__PURE__ */ new Map(),
8862
8865
  resultAll: void 0
@@ -8930,7 +8933,7 @@ const insert = (self, {
8930
8933
  }
8931
8934
  return self;
8932
8935
  };
8933
- const getFromSelectColumns = (from, obj, many) => {
8936
+ const getFromSelectColumns = (q, from, obj, many) => {
8934
8937
  if (!many && !queryTypeWithLimitOne[from.q.returnType]) {
8935
8938
  throw new Error(
8936
8939
  "Cannot create based on a query which returns multiple records"
@@ -8948,12 +8951,16 @@ const getFromSelectColumns = (from, obj, many) => {
8948
8951
  if (obj?.columns) {
8949
8952
  queryColumns.push(...obj.columns);
8950
8953
  }
8954
+ for (const key of queryColumns) {
8955
+ const column = q.shape[key];
8956
+ if (column) throwOnReadOnly$1(from, column, key);
8957
+ }
8951
8958
  return queryColumns;
8952
8959
  };
8953
8960
  const insertFromQuery = (q, from, many, data) => {
8954
8961
  const ctx = createCtx();
8955
8962
  const obj = data && handleOneData(q, data, ctx);
8956
- const columns = getFromSelectColumns(from, obj, many);
8963
+ const columns = getFromSelectColumns(q, from, obj, many);
8957
8964
  return insert(
8958
8965
  q,
8959
8966
  {
@@ -8972,7 +8979,7 @@ const _queryInsert = (q, data) => {
8972
8979
  const obj = handleOneData(q, data, ctx);
8973
8980
  const values = q.q.values;
8974
8981
  if (values && "from" in values) {
8975
- obj.columns = getFromSelectColumns(values.from, obj);
8982
+ obj.columns = getFromSelectColumns(q, values.from, obj);
8976
8983
  values.values = obj.values[0];
8977
8984
  obj.values = values;
8978
8985
  }
@@ -9006,7 +9013,7 @@ const _queryDefaults = (q, data) => {
9006
9013
  q.q.defaults = data;
9007
9014
  return q;
9008
9015
  };
9009
- class Create {
9016
+ class QueryCreate {
9010
9017
  /**
9011
9018
  * `create` and `insert` create a single record.
9012
9019
  *
@@ -9410,6 +9417,8 @@ class OnConflictQueryBuilder {
9410
9417
  set(set) {
9411
9418
  let resolved;
9412
9419
  for (const key in set) {
9420
+ const column = this.query.shape[key];
9421
+ if (column) throwOnReadOnly$1(this.query, column, key);
9413
9422
  if (typeof set[key] === "function") {
9414
9423
  if (!resolved) resolved = { ...set };
9415
9424
  resolved[key] = set[key]();
@@ -9679,7 +9688,7 @@ class Having {
9679
9688
  */
9680
9689
  having(...args) {
9681
9690
  const q = _clone(this);
9682
- return pushQueryValueImmutable(
9691
+ return orchidCore.pushQueryValueImmutable(
9683
9692
  q,
9684
9693
  "having",
9685
9694
  args.map((arg) => arg(q).q.expr)
@@ -9695,14 +9704,18 @@ class Having {
9695
9704
  * @param args - SQL expression
9696
9705
  */
9697
9706
  havingSql(...args) {
9698
- return pushQueryValueImmutable(_clone(this), "having", args);
9707
+ return orchidCore.pushQueryValueImmutable(_clone(this), "having", args);
9699
9708
  }
9700
9709
  }
9701
9710
 
9702
- const before = (q, key, cb) => pushQueryValueImmutable(q, `before${key}`, cb);
9711
+ const before = (q, key, cb) => orchidCore.pushQueryValueImmutable(q, `before${key}`, cb);
9703
9712
  const after = (query, key, select, cb, commit) => {
9704
9713
  const q = query;
9705
- pushQueryValueImmutable(q, `after${key}${commit ? "Commit" : ""}`, cb);
9714
+ orchidCore.pushQueryValueImmutable(
9715
+ q,
9716
+ `after${key}${commit ? "Commit" : ""}`,
9717
+ cb
9718
+ );
9706
9719
  const prop = `after${key}Select`;
9707
9720
  const set = q.q[prop] = new Set(q.q[prop]);
9708
9721
  for (const column of select) {
@@ -9711,13 +9724,19 @@ const after = (query, key, select, cb, commit) => {
9711
9724
  return query;
9712
9725
  };
9713
9726
  const _queryHookBeforeQuery = (q, cb) => {
9714
- return pushQueryValueImmutable(q, "before", cb);
9727
+ return orchidCore.pushQueryValueImmutable(q, "before", cb);
9715
9728
  };
9716
9729
  const _queryHookAfterQuery = (q, cb) => {
9717
- return pushQueryValueImmutable(q, "after", cb);
9730
+ return orchidCore.pushQueryValueImmutable(q, "after", cb);
9718
9731
  };
9719
9732
  const _queryHookBeforeCreate = (q, cb) => {
9720
- return before(q, "Create", (q2) => cb(new QueryHookUtils(q2, "hookCreateSet")));
9733
+ return before(
9734
+ q,
9735
+ "Create",
9736
+ (q2) => cb(
9737
+ new orchidCore.QueryHookUtils(q2, q2.q.columns, "hookCreateSet")
9738
+ )
9739
+ );
9721
9740
  };
9722
9741
  const _queryHookAfterCreate = (q, select, cb) => {
9723
9742
  return after(q, "Create", select, cb);
@@ -9726,7 +9745,15 @@ const _queryHookAfterCreateCommit = (q, select, cb) => {
9726
9745
  return after(q, "Create", select, cb, true);
9727
9746
  };
9728
9747
  const _queryHookBeforeUpdate = (q, cb) => {
9729
- return before(q, "Update", (q2) => cb(new QueryHookUtils(q2, "hookUpdateSet")));
9748
+ return before(q, "Update", (q2) => {
9749
+ const columns = [];
9750
+ for (const item of q2.q.updateData) {
9751
+ if (typeof item === "object") {
9752
+ columns.push(...Object.keys(item));
9753
+ }
9754
+ }
9755
+ return cb(new orchidCore.QueryHookUtils(q2, columns, "hookUpdateSet"));
9756
+ });
9730
9757
  };
9731
9758
  const _queryHookAfterUpdate = (q, select, cb) => {
9732
9759
  return after(q, "Update", select, cb);
@@ -9735,11 +9762,7 @@ const _queryHookAfterUpdateCommit = (q, select, cb) => {
9735
9762
  return after(q, "Update", select, cb, true);
9736
9763
  };
9737
9764
  const _queryHookBeforeSave = (q, cb) => {
9738
- return before(
9739
- before(q, "Create", (q2) => cb(new QueryHookUtils(q2, "hookCreateSet"))),
9740
- "Update",
9741
- (q2) => cb(new QueryHookUtils(q2, "hookUpdateSet"))
9742
- );
9765
+ return _queryHookBeforeUpdate(_queryHookBeforeCreate(q, cb), cb);
9743
9766
  };
9744
9767
  const _queryHookAfterSave = (q, select, cb) => {
9745
9768
  return after(after(q, "Create", select, cb), "Update", select, cb);
@@ -9762,21 +9785,6 @@ const _queryHookAfterDelete = (q, select, cb) => {
9762
9785
  const _queryHookAfterDeleteCommit = (q, select, cb) => {
9763
9786
  return after(q, "Delete", select, cb, true);
9764
9787
  };
9765
- class QueryHookUtils {
9766
- constructor(query, key) {
9767
- this.query = query;
9768
- this.key = key;
9769
- this.set = (data) => {
9770
- const set = {};
9771
- for (const key in data) {
9772
- if (data[key] !== void 0) {
9773
- set[key] = data[key];
9774
- }
9775
- }
9776
- pushQueryValueImmutable(this.query, this.key, set);
9777
- };
9778
- }
9779
- }
9780
9788
  class QueryHooks {
9781
9789
  /**
9782
9790
  * Run the function before any kind of query.
@@ -9959,7 +9967,7 @@ class QueryHooks {
9959
9967
  */
9960
9968
  catchAfterCommitError(fn) {
9961
9969
  const q = _clone(this);
9962
- pushQueryValueImmutable(q, "catchAfterCommitErrors", fn);
9970
+ orchidCore.pushQueryValueImmutable(q, "catchAfterCommitErrors", fn);
9963
9971
  return q;
9964
9972
  }
9965
9973
  }
@@ -10641,7 +10649,7 @@ const makeOnItem = (joinTo, joinFrom, args) => ({
10641
10649
  }
10642
10650
  });
10643
10651
  const pushQueryOnForOuter = (q, joinFrom, joinTo, leftColumn, rightColumn) => {
10644
- return pushQueryValueImmutable(q, "and", {
10652
+ return orchidCore.pushQueryValueImmutable(q, "and", {
10645
10653
  ON: {
10646
10654
  joinFrom: joinTo,
10647
10655
  from: leftColumn,
@@ -10652,14 +10660,14 @@ const pushQueryOnForOuter = (q, joinFrom, joinTo, leftColumn, rightColumn) => {
10652
10660
  });
10653
10661
  };
10654
10662
  const pushQueryOn = (q, joinFrom, joinTo, ...on) => {
10655
- return pushQueryValueImmutable(
10663
+ return orchidCore.pushQueryValueImmutable(
10656
10664
  q,
10657
10665
  "and",
10658
10666
  makeOnItem(joinFrom, joinTo, on)
10659
10667
  );
10660
10668
  };
10661
10669
  const pushQueryOrOn = (q, joinFrom, joinTo, ...on) => {
10662
- return pushQueryValueImmutable(q, "or", [
10670
+ return orchidCore.pushQueryValueImmutable(q, "or", [
10663
10671
  makeOnItem(joinFrom, joinTo, on)
10664
10672
  ]);
10665
10673
  };
@@ -10691,7 +10699,7 @@ const _queryJoinOrOn = (q, args) => {
10691
10699
  );
10692
10700
  };
10693
10701
  const _queryJoinOnJsonPathEquals = (q, args) => {
10694
- return pushQueryValueImmutable(q, "and", {
10702
+ return orchidCore.pushQueryValueImmutable(q, "and", {
10695
10703
  ON: args
10696
10704
  });
10697
10705
  };
@@ -10807,6 +10815,15 @@ class MergeQueryMethods {
10807
10815
  }
10808
10816
  }
10809
10817
 
10818
+ const throwOnReadOnly = (q, column, key) => {
10819
+ if (column.data.appReadOnly || column.data.readOnly) {
10820
+ throw new OrchidOrmInternalError(
10821
+ q,
10822
+ "Trying to update a readonly column",
10823
+ { column: key }
10824
+ );
10825
+ }
10826
+ };
10810
10827
  const _queryChangeCounter = (self, op, data) => {
10811
10828
  const q = self.q;
10812
10829
  q.type = "update";
@@ -10823,11 +10840,19 @@ const _queryChangeCounter = (self, op, data) => {
10823
10840
  map = {};
10824
10841
  for (const key in data) {
10825
10842
  map[key] = { op, arg: data[key] };
10843
+ const column = self.shape[key];
10844
+ if (column) {
10845
+ throwOnReadOnly(self, column, key);
10846
+ }
10826
10847
  }
10827
10848
  } else {
10828
10849
  map = { [data]: { op, arg: 1 } };
10850
+ const column = self.shape[data];
10851
+ if (column) {
10852
+ throwOnReadOnly(self, column, data);
10853
+ }
10829
10854
  }
10830
- pushQueryValueImmutable(self, "updateData", map);
10855
+ orchidCore.pushQueryValueImmutable(self, "updateData", map);
10831
10856
  return self;
10832
10857
  };
10833
10858
  const update = (self) => {
@@ -10844,17 +10869,18 @@ const update = (self) => {
10844
10869
  const _queryUpdate = (query, arg) => {
10845
10870
  const { q } = query;
10846
10871
  const set = { ...arg };
10847
- pushQueryValueImmutable(query, "updateData", set);
10872
+ orchidCore.pushQueryValueImmutable(query, "updateData", set);
10848
10873
  const { shape } = q;
10849
10874
  const ctx = {};
10850
10875
  for (const key in arg) {
10851
10876
  const item = shape[key];
10852
- if (item instanceof VirtualColumn && item.update) {
10853
- item.update(query, ctx, set);
10877
+ if (!item && shape !== anyShape) {
10854
10878
  delete set[key];
10855
- } else if ((!shape[key] || shape[key].data.readonly) && shape !== anyShape) {
10879
+ } else if (item.data.virtual) {
10880
+ item.update?.(query, ctx, set);
10856
10881
  delete set[key];
10857
10882
  } else {
10883
+ if (item) throwOnReadOnly(query, item, key);
10858
10884
  let value = set[key];
10859
10885
  if (typeof value === "function") {
10860
10886
  value = resolveSubQueryCallbackV2(
@@ -10880,7 +10906,7 @@ const _queryUpdate = (query, arg) => {
10880
10906
  "with"
10881
10907
  );
10882
10908
  } else {
10883
- const encode = shape[key].data.encode;
10909
+ const encode = item?.data.encode;
10884
10910
  if (encode) set[key] = encode(value);
10885
10911
  }
10886
10912
  }
@@ -11458,9 +11484,9 @@ class SearchMethods {
11458
11484
  }
11459
11485
  setQueryObjectValueImmutable(q, "sources", arg.as, arg);
11460
11486
  if (arg.order) {
11461
- pushQueryValueImmutable(q, "order", arg.as);
11487
+ orchidCore.pushQueryValueImmutable(q, "order", arg.as);
11462
11488
  }
11463
- return pushQueryValueImmutable(q, "and", { SEARCH: arg });
11489
+ return orchidCore.pushQueryValueImmutable(q, "and", { SEARCH: arg });
11464
11490
  }
11465
11491
  }
11466
11492
 
@@ -11550,109 +11576,13 @@ function orCreate(query, data, updateData, mergeData) {
11550
11576
  };
11551
11577
  return query;
11552
11578
  }
11553
- class QueryUpsertOrCreate {
11554
- /**
11555
- * `upsert` tries to update a single record, and then it creates the record if it doesn't yet exist.
11556
- *
11557
- * `find` or `findBy` must precede `upsert` because it does not work with multiple updates.
11558
- *
11559
- * In case more than one row was updated, it will throw `MoreThanOneRowError` and the transaction will be rolled back.
11560
- *
11561
- * It can take `update` and `create` objects, then they are used separately for update and create queries.
11562
- * Or, it can take `data` and `create` objects, `data` will be used for update and be mixed to `create` object.
11563
- *
11564
- * `data` and `update` objects are of the same type that's expected by `update` method, `create` object is of type of `create` method argument.
11565
- *
11566
- * No values are returned by default, place `select` or `selectAll` before `upsert` to specify returning columns.
11567
- *
11568
- * ```ts
11569
- * await User.selectAll()
11570
- * .findBy({ email: 'some@email.com' })
11571
- * .upsert({
11572
- * data: {
11573
- * // update record's name
11574
- * name: 'new name',
11575
- * // supports sql and nested queries
11576
- * fromSQL: () => sql`*SQL expression*`,
11577
- * fromQuery: () => db.someTable.create(data).get('column'),
11578
- * },
11579
- * create: {
11580
- * // create a new record with this email and a name 'new name'
11581
- * email: 'some@email.com',
11582
- * // supports sql and nested queries as well
11583
- * },
11584
- * create: {
11585
- * // create a new record with this email and a name 'new name'
11586
- * email: 'some@email.com',
11587
- * },
11588
- * });
11589
- *
11590
- * // the same as above but using `update` and `create`
11591
- * await User.selectAll()
11592
- * .findBy({ email: 'some@email.com' })
11593
- * .upsert({
11594
- * update: {
11595
- * name: 'updated user',
11596
- * },
11597
- * create: {
11598
- * email: 'some@email.com',
11599
- * // here we use a different name when creating a record
11600
- * name: 'created user',
11601
- * },
11602
- * });
11603
- * ```
11604
- *
11605
- * The data for `create` may be returned from a function, it won't be called if a record was updated:
11606
- *
11607
- * ```ts
11608
- * await User.selectAll()
11609
- * .findBy({ email: 'some@email.com' })
11610
- * .upsert({
11611
- * update: {
11612
- * name: 'updated user',
11613
- * },
11614
- * create: () => ({
11615
- * email: 'some@email.com',
11616
- * name: 'created user',
11617
- * }),
11618
- * });
11619
- *
11620
- * // the same as above using `data`
11621
- * await User.selectAll()
11622
- * .findBy({ email: 'some@email.com' })
11623
- * .upsert({
11624
- * data: {
11625
- * name: 'updated user',
11626
- * },
11627
- * create: () => ({
11628
- * email: 'some@email.com',
11629
- * // name in `create` is overriding the name from `data`
11630
- * name: 'created user',
11631
- * }),
11632
- * });
11633
- * ```
11634
- *
11635
- * Data from `data` or `update` is passed to the `create` function and can be used:
11636
- *
11637
- * ```ts
11638
- * const user = await User.selectAll()
11639
- * .findBy({ email: 'some@email.com' })
11640
- * .upsert({
11641
- * data: {
11642
- * name: 'updated user',
11643
- * },
11644
- * // `updateData` has the exact type of what is passed to `data`
11645
- * create: (updateData) => ({
11646
- * email: `${updateData.name}@email.com`,
11647
- * }),
11648
- * });
11649
- * ```
11650
- *
11651
- * `upsert` works in the exact same way as [orCreate](#orCreate), but with `UPDATE` statement instead of `SELECT`.
11652
- * it also performs a single query if the record exists, and two queries if there is no record yet.
11653
- *
11654
- * @param data - `update` property for the data to update, `create` property for the data to create
11655
- */
11579
+ const QueryOrCreate = {
11580
+ orCreate(data) {
11581
+ return orCreate(_clone(this), data);
11582
+ }
11583
+ };
11584
+
11585
+ const QueryUpsert = {
11656
11586
  upsert(data) {
11657
11587
  const q = _clone(this);
11658
11588
  let updateData;
@@ -11667,75 +11597,7 @@ class QueryUpsertOrCreate {
11667
11597
  }
11668
11598
  return orCreate(q, data.create, updateData, mergeData);
11669
11599
  }
11670
- /**
11671
- * `orCreate` creates a record only if it was not found by conditions.
11672
- *
11673
- * `find` or `findBy` must precede `orCreate`.
11674
- *
11675
- * It is accepting the same argument as `create` commands.
11676
- *
11677
- * No result is returned by default, place `get`, `select`, or `selectAll` before `orCreate` to specify returning columns.
11678
- *
11679
- * ```ts
11680
- * const user = await db.user
11681
- * .selectAll()
11682
- * .findBy({ email: 'some@email.com' })
11683
- * .orCreate({
11684
- * email: 'some@email.com',
11685
- * name: 'created user',
11686
- * // supports sql and nested queries
11687
- * fromSQL: () => sql`*SQL expression*`,
11688
- * fromQuery: () => db.someTable.create(data).get('column'),
11689
- * fromRelated: (q) => q.relatedTable.update(data).get('column'),
11690
- * });
11691
- * ```
11692
- *
11693
- * The data can be returned from a function, it won't be called if the record was found:
11694
- *
11695
- * ```ts
11696
- * const user = await User.selectAll()
11697
- * .findBy({ email: 'some@email.com' })
11698
- * .orCreate(() => ({
11699
- * email: 'some@email.com',
11700
- * name: 'created user',
11701
- * }));
11702
- * ```
11703
- *
11704
- * `orCreate` works by performing just a single query in the case if the record exists, and one additional query when the record does not exist.
11705
- *
11706
- * At first, it performs a "find" query, the query cost is exact same as if you didn't use `orCreate`.
11707
- *
11708
- * Then, if the record wasn't found, it performs a single query with CTE expressions to try finding it again, for the case it was already created just a moment before,
11709
- * and then it creates the record if it's still not found. Using such CTE allows to skip using transactions, while still conforming to atomicity.
11710
- *
11711
- * ```sql
11712
- * -- first query
11713
- * SELECT * FROM "table" WHERE "key" = 'value'
11714
- *
11715
- * -- the record could have been created in between these two queries
11716
- *
11717
- * -- second query
11718
- * WITH find_row AS (
11719
- * SELECT * FROM "table" WHERE "key" = 'value'
11720
- * )
11721
- * WITH insert_row AS (
11722
- * INSERT INTO "table" ("key")
11723
- * SELECT 'value'
11724
- * -- skip the insert if the row already exists
11725
- * WHERE NOT EXISTS (SELECT 1 FROM find_row)
11726
- * RETURNING *
11727
- * )
11728
- * SELECT * FROM find_row
11729
- * UNION ALL
11730
- * SELECT * FROM insert_row
11731
- * ```
11732
- *
11733
- * @param data - the same data as for `create`, it may be returned from a callback
11734
- */
11735
- orCreate(data) {
11736
- return orCreate(_clone(this), data);
11737
- }
11738
- }
11600
+ };
11739
11601
 
11740
11602
  class SqlMethod {
11741
11603
  sql(...args) {
@@ -11800,7 +11662,7 @@ class TransformMethods {
11800
11662
  * @param fn - function to transform query result with
11801
11663
  */
11802
11664
  transform(fn) {
11803
- return pushQueryValueImmutable(_clone(this), "transform", fn);
11665
+ return orchidCore.pushQueryValueImmutable(_clone(this), "transform", fn);
11804
11666
  }
11805
11667
  }
11806
11668
 
@@ -11846,7 +11708,7 @@ class QueryMap {
11846
11708
  * @param fn - function to transform an individual record
11847
11709
  */
11848
11710
  map(fn) {
11849
- return pushQueryValueImmutable(_clone(this), "transform", {
11711
+ return orchidCore.pushQueryValueImmutable(_clone(this), "transform", {
11850
11712
  map: fn
11851
11713
  });
11852
11714
  }
@@ -12475,7 +12337,7 @@ class QueryMethods {
12475
12337
  * @param arg - window config
12476
12338
  */
12477
12339
  window(arg) {
12478
- return pushQueryValueImmutable(_clone(this), "window", arg);
12340
+ return orchidCore.pushQueryValueImmutable(_clone(this), "window", arg);
12479
12341
  }
12480
12342
  wrap(query, as) {
12481
12343
  return queryWrap(this, _clone(query), as);
@@ -12530,7 +12392,7 @@ class QueryMethods {
12530
12392
  * @param args - SQL expression
12531
12393
  */
12532
12394
  orderSql(...args) {
12533
- return pushQueryValueImmutable(
12395
+ return orchidCore.pushQueryValueImmutable(
12534
12396
  _clone(this),
12535
12397
  "order",
12536
12398
  sqlQueryArgsToExpression(args)
@@ -12819,6 +12681,8 @@ class QueryMethods {
12819
12681
  return _chain(this, _clone(rel.query), rel);
12820
12682
  }
12821
12683
  }
12684
+ Object.assign(QueryMethods.prototype, QueryUpsert);
12685
+ Object.assign(QueryMethods.prototype, QueryOrCreate);
12822
12686
  orchidCore.applyMixins(QueryMethods, [
12823
12687
  AsMethods,
12824
12688
  AggregateMethods,
@@ -12829,7 +12693,7 @@ orchidCore.applyMixins(QueryMethods, [
12829
12693
  WithMethods,
12830
12694
  Union,
12831
12695
  JsonMethods,
12832
- Create,
12696
+ QueryCreate,
12833
12697
  Update,
12834
12698
  Delete,
12835
12699
  Transaction,
@@ -12841,7 +12705,6 @@ orchidCore.applyMixins(QueryMethods, [
12841
12705
  Then,
12842
12706
  QueryLog,
12843
12707
  QueryHooks,
12844
- QueryUpsertOrCreate,
12845
12708
  QueryGet,
12846
12709
  MergeQueryMethods,
12847
12710
  SqlMethod,
@@ -13017,6 +12880,7 @@ class Db extends QueryMethods {
13017
12880
  let hasParsers = false;
13018
12881
  let modifyQuery = void 0;
13019
12882
  let prepareSelectAll = false;
12883
+ let hasHookSetters;
13020
12884
  const { snakeCase } = options;
13021
12885
  for (const key in shape) {
13022
12886
  const column = shape[key];
@@ -13052,6 +12916,9 @@ class Db extends QueryMethods {
13052
12916
  column.data.runtimeDefault = encode ? () => encode(def()) : def;
13053
12917
  }
13054
12918
  }
12919
+ if (column.data.setOnCreate || column.data.setOnUpdate || column.data.setOnSave) {
12920
+ hasHookSetters = true;
12921
+ }
13055
12922
  }
13056
12923
  this.q = {
13057
12924
  adapter,
@@ -13126,6 +12993,27 @@ class Db extends QueryMethods {
13126
12993
  if (softDelete) {
13127
12994
  enableSoftDelete(this, table, shape, softDelete, scopes);
13128
12995
  }
12996
+ if (hasHookSetters) {
12997
+ const hooks = {
12998
+ setOnCreate: _queryHookBeforeCreate,
12999
+ setOnUpdate: _queryHookBeforeUpdate,
13000
+ setOnSave: _queryHookBeforeSave
13001
+ };
13002
+ for (const key in shape) {
13003
+ const { data } = shape[key];
13004
+ for (const hookKey in hooks) {
13005
+ const fn = data[hookKey];
13006
+ if (fn) {
13007
+ hooks[hookKey](this, (arg) => {
13008
+ const value = fn(arg);
13009
+ if (value !== void 0) {
13010
+ arg.set({ [key]: value });
13011
+ }
13012
+ });
13013
+ }
13014
+ }
13015
+ }
13016
+ }
13129
13017
  }
13130
13018
  [node_util.inspect.custom]() {
13131
13019
  return `Query<${this.table}>`;
@@ -13478,7 +13366,6 @@ exports.Clear = Clear;
13478
13366
  exports.ColumnRefExpression = ColumnRefExpression;
13479
13367
  exports.ColumnType = ColumnType;
13480
13368
  exports.ComputedColumn = ComputedColumn;
13481
- exports.Create = Create;
13482
13369
  exports.CustomTypeColumn = CustomTypeColumn;
13483
13370
  exports.DateBaseColumn = DateBaseColumn;
13484
13371
  exports.DateColumn = DateColumn;
@@ -13525,13 +13412,13 @@ exports.PathColumn = PathColumn;
13525
13412
  exports.PointColumn = PointColumn;
13526
13413
  exports.PolygonColumn = PolygonColumn;
13527
13414
  exports.PostgisGeographyPointColumn = PostgisGeographyPointColumn;
13415
+ exports.QueryCreate = QueryCreate;
13528
13416
  exports.QueryError = QueryError;
13529
13417
  exports.QueryGet = QueryGet;
13530
- exports.QueryHookUtils = QueryHookUtils;
13531
13418
  exports.QueryHooks = QueryHooks;
13532
13419
  exports.QueryLog = QueryLog;
13533
13420
  exports.QueryMethods = QueryMethods;
13534
- exports.QueryUpsertOrCreate = QueryUpsertOrCreate;
13421
+ exports.QueryUpsert = QueryUpsert;
13535
13422
  exports.RawSQL = RawSQL;
13536
13423
  exports.RealColumn = RealColumn;
13537
13424
  exports.RefExpression = RefExpression;
@@ -13686,7 +13573,6 @@ exports.pushQueryArrayImmutable = pushQueryArrayImmutable;
13686
13573
  exports.pushQueryOn = pushQueryOn;
13687
13574
  exports.pushQueryOnForOuter = pushQueryOnForOuter;
13688
13575
  exports.pushQueryOrOn = pushQueryOrOn;
13689
- exports.pushQueryValueImmutable = pushQueryValueImmutable;
13690
13576
  exports.pushTableDataCode = pushTableDataCode;
13691
13577
  exports.queryFrom = queryFrom;
13692
13578
  exports.queryFromSql = queryFromSql;