pqb 0.32.0 → 0.33.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/dist/index.js CHANGED
@@ -881,6 +881,25 @@ const make = (_op) => {
881
881
  return setQueryOperators(this, boolean);
882
882
  },
883
883
  {
884
+ // function to turn the operator expression into SQL
885
+ _op
886
+ }
887
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
888
+ );
889
+ };
890
+ const makeVarArg = (_op) => {
891
+ return Object.assign(
892
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
893
+ function(...args) {
894
+ var _a, _b, _c;
895
+ ((_b = (_a = this.q).chain) != null ? _b : _a.chain = []).push(_op, args);
896
+ if ((_c = this.q.parsers) == null ? void 0 : _c[orchidCore.getValueKey]) {
897
+ this.q.parsers[orchidCore.getValueKey] = void 0;
898
+ }
899
+ return setQueryOperators(this, boolean);
900
+ },
901
+ {
902
+ // function to turn the operator expression into SQL
884
903
  _op
885
904
  }
886
905
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -963,15 +982,51 @@ const text = __spreadProps$7(__spreadValues$f({}, base), {
963
982
  (key, value, ctx, quotedAs) => `${key} LIKE '%' || ${quoteValue$1(value, ctx, quotedAs)}`
964
983
  )
965
984
  });
985
+ const encodeJsonPath = (ctx, path) => orchidCore.addValue(ctx.values, `{${Array.isArray(path) ? path.join(", ") : path}}`);
986
+ const jsonPathQueryOp = (key, [path, options], ctx) => `jsonb_path_query_first(${key}, ${orchidCore.addValue(ctx.values, path)}${(options == null ? void 0 : options.vars) ? `, ${orchidCore.addValue(ctx.values, JSON.stringify(options.vars))}${options.silent ? ", true" : ""}` : (options == null ? void 0 : options.silent) ? ", NULL, true" : ""})`;
966
987
  const json = __spreadProps$7(__spreadValues$f({}, base), {
967
- jsonPath: make(
968
- (key, [path, op, value], ctx, quotedAs) => `jsonb_path_query_first(${key}, '${path}') #>> '{}' ${op} ${value === null ? "null" : quoteValue$1(value, ctx, quotedAs, true)}`
988
+ jsonPathQueryFirst: Object.assign(
989
+ function(path, options) {
990
+ var _a, _b, _c, _d, _e;
991
+ ((_b = (_a = this.q).chain) != null ? _b : _a.chain = []).push(jsonPathQueryOp, [path, options]);
992
+ if ((_c = this.q.parsers) == null ? void 0 : _c[orchidCore.getValueKey]) {
993
+ this.q.parsers[orchidCore.getValueKey] = void 0;
994
+ }
995
+ if (options == null ? void 0 : options.type) {
996
+ const parse = options.type(this.columnTypes).parseFn;
997
+ if (parse)
998
+ ((_e = (_d = this.q).parsers) != null ? _e : _d.parsers = {})[orchidCore.getValueKey] = parse;
999
+ }
1000
+ return this;
1001
+ },
1002
+ { _op: jsonPathQueryOp }
969
1003
  ),
970
1004
  jsonSupersetOf: make(
971
1005
  (key, value, ctx, quotedAs) => `${key} @> ${quoteValue$1(value, ctx, quotedAs, true)}`
972
1006
  ),
973
1007
  jsonSubsetOf: make(
974
1008
  (key, value, ctx, quotedAs) => `${key} <@ ${quoteValue$1(value, ctx, quotedAs, true)}`
1009
+ ),
1010
+ jsonSet: makeVarArg(
1011
+ (key, [path, value], ctx) => `jsonb_set(${key}, ${encodeJsonPath(ctx, path)}, ${orchidCore.addValue(
1012
+ ctx.values,
1013
+ JSON.stringify(value)
1014
+ )})`
1015
+ ),
1016
+ jsonReplace: makeVarArg(
1017
+ (key, [path, value], ctx) => `jsonb_set(${key}, ${encodeJsonPath(ctx, path)}, ${orchidCore.addValue(
1018
+ ctx.values,
1019
+ JSON.stringify(value)
1020
+ )}, false)`
1021
+ ),
1022
+ jsonInsert: makeVarArg(
1023
+ (key, [path, value, options], ctx) => `jsonb_insert(${key}, ${encodeJsonPath(ctx, path)}, ${orchidCore.addValue(
1024
+ ctx.values,
1025
+ JSON.stringify(value)
1026
+ )}${(options == null ? void 0 : options.after) ? ", true" : ""})`
1027
+ ),
1028
+ jsonRemove: makeVarArg(
1029
+ (key, [path], ctx) => `(${key} #- ${encodeJsonPath(ctx, path)})`
975
1030
  )
976
1031
  });
977
1032
  const Operators = {
@@ -2077,9 +2132,13 @@ const processWhere = (ands, ctx, table, query, data, quotedAs) => {
2077
2132
  if ("prototype" in data || "baseQuery" in data) {
2078
2133
  const query2 = data;
2079
2134
  if (query2.q.expr) {
2080
- const q = joinSubQuery(table, query2);
2081
- q.q.select = [query2.q.expr];
2082
- ands.push(`(${getSqlText(makeSQL(q, ctx))})`);
2135
+ if (query2.q.subQuery === 1) {
2136
+ ands.push(selectToSql(ctx, table, query2.q, quotedAs));
2137
+ } else {
2138
+ const q = joinSubQuery(table, query2);
2139
+ q.q.select = [query2.q.expr];
2140
+ ands.push(`(${getSqlText(makeSQL(q, ctx))})`);
2141
+ }
2083
2142
  } else {
2084
2143
  pushWhereToSql(
2085
2144
  ands,
@@ -3306,9 +3365,7 @@ const then = async (q, adapter, trx, beforeHooks, afterHooks, afterCommitHooks,
3306
3365
  result = filterResult(q, returnType, queryResult, hookSelect, result);
3307
3366
  }
3308
3367
  if (query.transform) {
3309
- for (const fn of query.transform) {
3310
- result = fn(result);
3311
- }
3368
+ result = orchidCore.applyTransforms(returnType, query.transform, result);
3312
3369
  }
3313
3370
  return resolve == null ? void 0 : resolve(result);
3314
3371
  } catch (err) {
@@ -3526,10 +3583,8 @@ const addParserForSelectItem = (q, as, key, arg) => {
3526
3583
  orchidCore.setParserToQuery(q.q, key, (item) => {
3527
3584
  const t = query.returnType || "all";
3528
3585
  subQueryResult.rows = t === "value" || t === "valueOrThrow" ? [[item]] : t === "one" || t === "oneOrThrow" ? [item] : item;
3529
- return orchidCore.applyTransforms(
3530
- query.transform,
3531
- query.handleResult(arg, t, subQueryResult, true)
3532
- );
3586
+ const result = query.handleResult(arg, t, subQueryResult, true);
3587
+ return query.transform ? orchidCore.applyTransforms(t, query.transform, result) : result;
3533
3588
  });
3534
3589
  }
3535
3590
  if (query.returnType === "valueOrThrow" || query.returnType === "oneOrThrow") {
@@ -3610,7 +3665,7 @@ const processSelectArg = (q, as, arg, columnAs) => {
3610
3665
  (q2) => q2,
3611
3666
  key
3612
3667
  );
3613
- } else if (((_d = value.q) == null ? void 0 : _d.isSubQuery) && value.q.expr) {
3668
+ } else if (((_d = value.q) == null ? void 0 : _d.subQuery) && value.q.expr) {
3614
3669
  value = value.q.expr;
3615
3670
  }
3616
3671
  }
@@ -3785,7 +3840,7 @@ class SelectItemExpression extends orchidCore.Expression {
3785
3840
  // except that it will use non-aliasing `columnToSql` when `ctx.aliasValue` is true,
3786
3841
  // it is needed for relation sub-queries that returns a single column.
3787
3842
  makeSQL(ctx, quotedAs) {
3788
- return typeof this.item === "string" ? this.item === "*" ? selectAllSql(this.query, this.q, quotedAs) : ctx.aliasValue ? columnToSql(ctx, this.q, this.q.shape, this.item, quotedAs, true) : columnToSqlWithAs(ctx, this.q, this.item, quotedAs, true) : selectedObjectToSQL(ctx, this.query, quotedAs, this.item);
3843
+ return typeof this.item === "string" ? this.item === "*" ? selectAllSql(this.query, this.q, quotedAs) : ctx.aliasValue ? columnToSql(ctx, this.q, this.q.shape, this.item, quotedAs, true) : columnToSqlWithAs(ctx, this.q, this.item, quotedAs, true) : selectedObjectToSQL(ctx, quotedAs, this.item);
3789
3844
  }
3790
3845
  }
3791
3846
 
@@ -3993,50 +4048,6 @@ function queryJson(self, coalesce) {
3993
4048
  return q;
3994
4049
  }
3995
4050
 
3996
- const jsonColumnOrMethodToSql = (ctx, table, column, values, quotedAs) => {
3997
- return typeof column === "string" ? columnToSql(ctx, table.q, table.q.shape, column, quotedAs) : jsonToSql(ctx, table, column, values, quotedAs);
3998
- };
3999
- const jsonToSql = (ctx, table, item, values, quotedAs) => {
4000
- const json = item.__json;
4001
- if (json[0] === "pathQuery") {
4002
- const [, , , column, path, options] = json;
4003
- return `jsonb_path_query(${jsonColumnOrMethodToSql(
4004
- ctx,
4005
- table,
4006
- column,
4007
- values,
4008
- quotedAs
4009
- )}, ${orchidCore.addValue(values, path)}${(options == null ? void 0 : options.vars) ? `, ${orchidCore.addValue(values, options.vars)}` : ""}${(options == null ? void 0 : options.silent) ? ", true" : ""})`;
4010
- } else if (json[0] === "set") {
4011
- const [, , , column, path, value, options] = json;
4012
- return `jsonb_set(${jsonColumnOrMethodToSql(
4013
- ctx,
4014
- table,
4015
- column,
4016
- values,
4017
- quotedAs
4018
- )}, '{${path.join(", ")}}', ${orchidCore.addValue(values, JSON.stringify(value))}${(options == null ? void 0 : options.createIfMissing) ? ", true" : ""})`;
4019
- } else if (json[0] === "insert") {
4020
- const [, , , column, path, value, options] = json;
4021
- return `jsonb_insert(${jsonColumnOrMethodToSql(
4022
- ctx,
4023
- table,
4024
- column,
4025
- values,
4026
- quotedAs
4027
- )}, '{${path.join(", ")}}', ${orchidCore.addValue(values, JSON.stringify(value))}${(options == null ? void 0 : options.insertAfter) ? ", true" : ""})`;
4028
- } else if (json[0] === "remove") {
4029
- const [, , , column, path] = json;
4030
- return `${jsonColumnOrMethodToSql(
4031
- ctx,
4032
- table,
4033
- column,
4034
- values,
4035
- quotedAs
4036
- )} #- '{${path.join(", ")}}'`;
4037
- }
4038
- return "";
4039
- };
4040
4051
  const pushSelectSql = (ctx, table, query, quotedAs) => {
4041
4052
  ctx.sql.push(selectToSql(ctx, table, query, quotedAs));
4042
4053
  };
@@ -4070,7 +4081,7 @@ const selectToSql = (ctx, table, query, quotedAs) => {
4070
4081
  }
4071
4082
  }
4072
4083
  } else {
4073
- list.push(selectedObjectToSQL(ctx, table, quotedAs, item));
4084
+ list.push(selectedObjectToSQL(ctx, quotedAs, item));
4074
4085
  }
4075
4086
  }
4076
4087
  return list.join(", ");
@@ -4078,10 +4089,7 @@ const selectToSql = (ctx, table, query, quotedAs) => {
4078
4089
  return selectAllSql(table, query, quotedAs);
4079
4090
  };
4080
4091
  const selectedStringToSQL = (ctx, table, query, quotedAs, item) => item === "*" ? selectAllSql(table, query, quotedAs) : columnToSqlWithAs(ctx, table.q, item, quotedAs, true);
4081
- function selectedObjectToSQL(ctx, table, quotedAs, item) {
4082
- if ("__json" in item) {
4083
- return `${jsonToSql(ctx, table, item, ctx.values, quotedAs)} "${item.__json[1]}"`;
4084
- }
4092
+ function selectedObjectToSQL(ctx, quotedAs, item) {
4085
4093
  const sql = item.toSQL(ctx, quotedAs);
4086
4094
  return ctx.aliasValue ? `${sql} r` : sql;
4087
4095
  }
@@ -4771,11 +4779,12 @@ const processData = (ctx, table, set, data, quotedAs) => {
4771
4779
  };
4772
4780
  const processValue = (ctx, table, QueryClass, key, value, quotedAs) => {
4773
4781
  if (value && typeof value === "object") {
4774
- if (value.__json) {
4775
- return jsonToSql(ctx, table, value, ctx.values, quotedAs);
4776
- } else if (orchidCore.isExpression(value)) {
4782
+ if (orchidCore.isExpression(value)) {
4777
4783
  return value.toSQL(ctx, quotedAs);
4778
4784
  } else if (value instanceof QueryClass) {
4785
+ if (value.q.subQuery === 1) {
4786
+ return selectToSql(ctx, table, value.q, quotedAs);
4787
+ }
4779
4788
  return `(${getSqlText(
4780
4789
  joinSubQuery(table, value).toSQL(ctx)
4781
4790
  )})`;
@@ -5201,11 +5210,11 @@ const makeRegexToFindInSql = (value) => {
5201
5210
  return new RegExp(`${value}(?=(?:[^']*'[^']*')*[^']*$)`, "g");
5202
5211
  };
5203
5212
  const resolveSubQueryCallback = (q, cb) => {
5204
- const { isSubQuery, relChain } = q.q;
5205
- q.q.isSubQuery = true;
5213
+ const { subQuery, relChain } = q.q;
5214
+ q.q.subQuery = 1;
5206
5215
  q.q.relChain = void 0;
5207
5216
  const result = cb(q);
5208
- q.q.isSubQuery = isSubQuery;
5217
+ q.q.subQuery = subQuery;
5209
5218
  q.q.relChain = relChain;
5210
5219
  return result;
5211
5220
  };
@@ -6655,7 +6664,7 @@ class Create {
6655
6664
  * const createdCount = await db.table.insertMany([data, data, data]);
6656
6665
  * ```
6657
6666
  *
6658
- * Because of a limitation of Postgres protocol, queries having more than **65536** are going to fail in runtime.
6667
+ * Because of a limitation of Postgres protocol, queries having more than **65535** of values are going to fail in runtime.
6659
6668
  * To solve this seamlessly, OrchidORM will automatically batch such queries, and wrap them into a transaction, unless they are already in a transaction.
6660
6669
  *
6661
6670
  * ```ts
@@ -6700,7 +6709,10 @@ class Create {
6700
6709
  * @param args - object with columns list and raw SQL for values
6701
6710
  */
6702
6711
  createRaw(...args) {
6703
- return _queryCreateRaw(this.clone(), args);
6712
+ return _queryCreateRaw(
6713
+ this.clone(),
6714
+ args
6715
+ );
6704
6716
  }
6705
6717
  /**
6706
6718
  * Works exactly as {@link createRaw}, except that it returns inserted row count by default.
@@ -6708,7 +6720,10 @@ class Create {
6708
6720
  * @param args - object with columns list and raw SQL for values
6709
6721
  */
6710
6722
  insertRaw(...args) {
6711
- return _queryInsertRaw(this.clone(), args);
6723
+ return _queryInsertRaw(
6724
+ this.clone(),
6725
+ args
6726
+ );
6712
6727
  }
6713
6728
  /**
6714
6729
  * `createManyRaw` and `insertManyRaw` are for creating many record with raw SQL expressions.
@@ -6729,7 +6744,10 @@ class Create {
6729
6744
  * @param args - object with columns list and array of raw SQL for values
6730
6745
  */
6731
6746
  createManyRaw(...args) {
6732
- return _queryCreateManyRaw(this.clone(), args);
6747
+ return _queryCreateManyRaw(
6748
+ this.clone(),
6749
+ args
6750
+ );
6733
6751
  }
6734
6752
  /**
6735
6753
  * Works exactly as {@link createManyRaw}, except that it returns inserted row count by default.
@@ -6737,7 +6755,10 @@ class Create {
6737
6755
  * @param args - object with columns list and array of raw SQL for values
6738
6756
  */
6739
6757
  insertManyRaw(...args) {
6740
- return _queryInsertManyRaw(this.clone(), args);
6758
+ return _queryInsertManyRaw(
6759
+ this.clone(),
6760
+ args
6761
+ );
6741
6762
  }
6742
6763
  /**
6743
6764
  * These methods are for creating a single record, for batch creating see {@link createManyFrom}.
@@ -6779,7 +6800,11 @@ class Create {
6779
6800
  * @param data - additionally you can set some columns
6780
6801
  */
6781
6802
  createFrom(query, data) {
6782
- return _queryCreateFrom(this.clone(), query, data);
6803
+ return _queryCreateFrom(
6804
+ this.clone(),
6805
+ query,
6806
+ data
6807
+ );
6783
6808
  }
6784
6809
  /**
6785
6810
  * Works exactly as {@link createFrom}, except that it returns inserted row count by default.
@@ -6788,7 +6813,11 @@ class Create {
6788
6813
  * @param data - additionally you can set some columns
6789
6814
  */
6790
6815
  insertFrom(query, data) {
6791
- return _queryInsertFrom(this.clone(), query, data);
6816
+ return _queryInsertFrom(
6817
+ this.clone(),
6818
+ query,
6819
+ data
6820
+ );
6792
6821
  }
6793
6822
  /**
6794
6823
  * Similar to `createFrom`, but intended to create many records.
@@ -6804,7 +6833,10 @@ class Create {
6804
6833
  * @param query - query to create new records from
6805
6834
  */
6806
6835
  createManyFrom(query) {
6807
- return _queryCreateManyFrom(this.clone(), query);
6836
+ return _queryCreateManyFrom(
6837
+ this.clone(),
6838
+ query
6839
+ );
6808
6840
  }
6809
6841
  /**
6810
6842
  * Works exactly as {@link createManyFrom}, except that it returns inserted row count by default.
@@ -6812,7 +6844,10 @@ class Create {
6812
6844
  * @param query - query to create new records from
6813
6845
  */
6814
6846
  insertManyFrom(query) {
6815
- return _queryInsertManyFrom(this.clone(), query);
6847
+ return _queryInsertManyFrom(
6848
+ this.clone(),
6849
+ query
6850
+ );
6816
6851
  }
6817
6852
  /**
6818
6853
  * `defaults` allows setting values that will be used later in `create`.
@@ -6837,7 +6872,10 @@ class Create {
6837
6872
  * @param data - default values for `create` and `createMany` which will follow `defaults`
6838
6873
  */
6839
6874
  defaults(data) {
6840
- return _queryDefaults(this.clone(), data);
6875
+ return _queryDefaults(
6876
+ this.clone(),
6877
+ data
6878
+ );
6841
6879
  }
6842
6880
  /**
6843
6881
  * By default, violating unique constraint will cause the creative query to throw,
@@ -7299,9 +7337,7 @@ class Having {
7299
7337
  return pushQueryValue(
7300
7338
  q,
7301
7339
  "having",
7302
- args.map(
7303
- (arg) => arg(q).q.expr
7304
- )
7340
+ args.map((arg) => arg(q).q.expr)
7305
7341
  );
7306
7342
  }
7307
7343
  /**
@@ -8277,183 +8313,6 @@ class OnMethods {
8277
8313
  }
8278
8314
  }
8279
8315
 
8280
- class JsonModifiers {
8281
- /**
8282
- * Return a JSON value/object/array where a given value is set at the given path.
8283
- * The path is an array of keys to access the value.
8284
- *
8285
- * Can be used in `update` callback.
8286
- *
8287
- * ```ts
8288
- * const result = await db.table.jsonSet('data', ['name'], 'new value').take();
8289
- *
8290
- * expect(result.data).toEqual({ name: 'new value' });
8291
- * ```
8292
- *
8293
- * Optionally takes parameters of type `{ as?: string, createIfMissing?: boolean }`
8294
- *
8295
- * ```ts
8296
- * await db.table.jsonSet('data', ['name'], 'new value', {
8297
- * as: 'alias', // select data as `alias`
8298
- * createIfMissing: true, // ignored if missing by default
8299
- * });
8300
- * ```
8301
- *
8302
- * @param column - name of JSON column, or a result of a nested json method
8303
- * @param path - path to value inside the json
8304
- * @param value - value to set into the json
8305
- * @param options - `as` to alias the json value when selecting, `createIfMissing: true` will create a new JSON property if it didn't exist before
8306
- */
8307
- jsonSet(column, path, value, options) {
8308
- var _a;
8309
- const q = this.clone();
8310
- const json = {
8311
- __json: [
8312
- "set",
8313
- (_a = options == null ? void 0 : options.as) != null ? _a : typeof column === "string" ? column : column.__json[1],
8314
- typeof column === "string" ? q.q.shape[column] : column.__json[2],
8315
- column,
8316
- path,
8317
- value,
8318
- options
8319
- ]
8320
- };
8321
- return Object.assign(pushQueryValue(q, "select", json), json);
8322
- }
8323
- /**
8324
- * Return a JSON value/object/array where a given value is inserted at the given JSON path. Value can be a single value or JSON object. If a value exists at the given path, the value is not replaced.
8325
- *
8326
- * Can be used in `update` callback.
8327
- *
8328
- * ```ts
8329
- * // imagine user has data = { tags: ['two'] }
8330
- * const result = await db.table.jsonInsert('data', ['tags', 0], 'one').take();
8331
- *
8332
- * // 'one' is inserted to 0 position
8333
- * expect(result.data).toEqual({ tags: ['one', 'two'] });
8334
- * ```
8335
- *
8336
- * Optionally takes parameters of type `{ as?: string, insertAfter?: boolean }`
8337
- *
8338
- * ```ts
8339
- * // imagine user has data = { tags: ['one'] }
8340
- * const result = await db.table
8341
- * .jsonInsert('data', ['tags', 0], 'two', {
8342
- * as: 'alias', // select as an alias
8343
- * insertAfter: true, // insert after the specified position
8344
- * })
8345
- * .take();
8346
- *
8347
- * // 'one' is inserted to 0 position
8348
- * expect(result.alias).toEqual({ tags: ['one', 'two'] });
8349
- * ```
8350
- * @param column - name of JSON column, or a result of a nested json method
8351
- * @param path - path to the array inside the json, last path element is index to insert into
8352
- * @param value - value to insert into the json array
8353
- * @param options - `as` to alias the json value when selecting, `insertAfter: true` to insert after the specified position
8354
- */
8355
- jsonInsert(column, path, value, options) {
8356
- var _a;
8357
- const q = this.clone();
8358
- const json = {
8359
- __json: [
8360
- "insert",
8361
- (_a = options == null ? void 0 : options.as) != null ? _a : typeof column === "string" ? column : column.__json[1],
8362
- typeof column === "string" ? q.q.shape[column] : column.__json[2],
8363
- column,
8364
- path,
8365
- value,
8366
- options
8367
- ]
8368
- };
8369
- return Object.assign(pushQueryValue(q, "select", json), json);
8370
- }
8371
- /**
8372
- * Return a JSON value/object/array where a given value is removed at the given JSON path.
8373
- *
8374
- * Can be used in `update` callback.
8375
- *
8376
- * ```ts
8377
- * // imagine a user has data = { tags: ['one', 'two'] }
8378
- * const result = await db.table
8379
- * .jsonRemove(
8380
- * 'data',
8381
- * ['tags', 0],
8382
- * // optional parameters:
8383
- * {
8384
- * as: 'alias', // select as an alias
8385
- * },
8386
- * )
8387
- * .take();
8388
- *
8389
- * expect(result.alias).toEqual({ tags: ['two'] });
8390
- * ```
8391
- *
8392
- * @param column - name of JSON column, or a result of a nested json method
8393
- * @param path - path to the array inside the json, last path element is index to remove this element
8394
- * @param options - `as` to alias the json value when selecting
8395
- */
8396
- jsonRemove(column, path, options) {
8397
- var _a;
8398
- const q = this.clone();
8399
- const json = {
8400
- __json: [
8401
- "remove",
8402
- (_a = options == null ? void 0 : options.as) != null ? _a : typeof column === "string" ? column : column.__json[1],
8403
- typeof column === "string" ? q.q.shape[column] : column.__json[2],
8404
- column,
8405
- path
8406
- ]
8407
- };
8408
- return Object.assign(pushQueryValue(q, "select", json), json);
8409
- }
8410
- /**
8411
- * Selects a value from JSON data using a JSON path.
8412
- *
8413
- * ```ts
8414
- * import { columnTypes } from 'orchid-orm';
8415
- *
8416
- * db.table.jsonPathQuery(
8417
- * columnTypes.text(3, 100), // type of the value
8418
- * 'data', // name of the JSON column
8419
- * '$.name', // JSON path
8420
- * 'name', // select value as name
8421
- *
8422
- * // Optionally supports `vars` and `silent` options
8423
- * // check Postgres docs for jsonb_path_query for details
8424
- * {
8425
- * vars: 'vars',
8426
- * silent: true,
8427
- * },
8428
- * );
8429
- * ```
8430
- *
8431
- * Nested JSON operations can be used in place of JSON column name:
8432
- *
8433
- * ```ts
8434
- * db.table.jsonPathQuery(
8435
- * columnTypes.text(3, 100),
8436
- * // Available: .jsonSet, .jsonInsert, .jsonRemove
8437
- * db.table.jsonSet('data', ['key'], 'value'),
8438
- * '$.name',
8439
- * 'name',
8440
- * );
8441
- * ```
8442
- *
8443
- * @param type - provide a column type to have a correct result type
8444
- * @param column - name of JSON column, or a result of a nested json method
8445
- * @param path - special JSON path string to reference a JSON value
8446
- * @param as - optional alias for the selected value
8447
- * @param options - supports `vars` and `silent`, check Postgres docs of `json_path_query` for these
8448
- */
8449
- jsonPathQuery(type, column, path, as, options) {
8450
- const q = this.clone();
8451
- const json = {
8452
- __json: ["pathQuery", as, type, column, path, options]
8453
- };
8454
- return Object.assign(pushQueryValue(q, "select", json), json);
8455
- }
8456
- }
8457
8316
  class JsonMethods {
8458
8317
  /**
8459
8318
  * Wraps the query in a way to select a single JSON string.
@@ -8829,7 +8688,7 @@ const resolveCallbacksInArgs = (q, args) => {
8829
8688
  const qb = Object.create(q);
8830
8689
  qb.q = getClonedQueryData(q.q);
8831
8690
  qb.q.and = qb.q.or = qb.q.scopes = void 0;
8832
- qb.q.isSubQuery = true;
8691
+ qb.q.subQuery = 1;
8833
8692
  args[i] = resolveSubQueryCallback(qb, arg);
8834
8693
  }
8835
8694
  }
@@ -10528,6 +10387,8 @@ class TransformMethods {
10528
10387
  *
10529
10388
  * `transform` method should be called in the last order, other methods can't be chained after calling it.
10530
10389
  *
10390
+ * It is meant to transform the whole result of a query, for transforming individual records consider using {@link QueryMap.map}.
10391
+ *
10531
10392
  * The [hooks](/guide/hooks.html) that are going to run after the query will receive the query result **before** transferring.
10532
10393
  *
10533
10394
  * Consider the following example of a cursor-based pagination by `id`:
@@ -10579,6 +10440,52 @@ class TransformMethods {
10579
10440
  }
10580
10441
  }
10581
10442
 
10443
+ class QueryMap {
10444
+ /**
10445
+ * Use `map` to transform individual records of a query result.
10446
+ *
10447
+ * It accepts a single record and should return a single transformed record.
10448
+ *
10449
+ * For transforming the whole result of a query, consider using [transform](#transform) instead.
10450
+ *
10451
+ * The [hooks](/guide/hooks) that are going to run after the query will receive the query result **before** transformation.
10452
+ *
10453
+ * ```ts
10454
+ * // add a `titleLength` to every post
10455
+ * const posts = await db.post.limit(10).map((post) => ({
10456
+ * ...post,
10457
+ * titleLength: post.title.length,
10458
+ * }));
10459
+ *
10460
+ * posts[0].titleLength; // number
10461
+ *
10462
+ * // using the exact same `map` function to transform a single post
10463
+ * const singlePost = await db.post.find(id).map((post) => ({
10464
+ * ...post,
10465
+ * titleLength: post.title.length,
10466
+ * }));
10467
+ *
10468
+ * singlePost.titleLength; // number
10469
+ *
10470
+ * // can be used in sub-queries
10471
+ * const postsWithComments = await db.post.select('title', {
10472
+ * comments: (q) =>
10473
+ * q.comments.map((comment) => ({
10474
+ * ...comment,
10475
+ * truncatedContent: comment.content.slice(0, 100),
10476
+ * })),
10477
+ * });
10478
+ *
10479
+ * postsWithComments[0].comments[0].truncatedContent; // string
10480
+ * ```
10481
+ *
10482
+ * @param fn - function to transform an individual record
10483
+ */
10484
+ map(fn) {
10485
+ return pushQueryValue(this.clone(), "transform", { map: fn });
10486
+ }
10487
+ }
10488
+
10582
10489
  class ScopeMethods {
10583
10490
  /**
10584
10491
  * See {@link ScopeMethods}
@@ -11542,7 +11449,6 @@ orchidCore.applyMixins(QueryMethods, [
11542
11449
  OnMethods,
11543
11450
  WithMethods,
11544
11451
  Union,
11545
- JsonModifiers,
11546
11452
  JsonMethods,
11547
11453
  Create,
11548
11454
  Update,
@@ -11561,6 +11467,7 @@ orchidCore.applyMixins(QueryMethods, [
11561
11467
  MergeQueryMethods,
11562
11468
  SqlMethod,
11563
11469
  TransformMethods,
11470
+ QueryMap,
11564
11471
  ScopeMethods,
11565
11472
  SoftDeleteMethods,
11566
11473
  ExpressionMethods
@@ -12181,7 +12088,6 @@ exports.JSONColumn = JSONColumn;
12181
12088
  exports.JSONTextColumn = JSONTextColumn;
12182
12089
  exports.Join = Join;
12183
12090
  exports.JsonMethods = JsonMethods;
12184
- exports.JsonModifiers = JsonModifiers;
12185
12091
  exports.LimitedTextBaseColumn = LimitedTextBaseColumn;
12186
12092
  exports.LineColumn = LineColumn;
12187
12093
  exports.LsegColumn = LsegColumn;