remult 3.4.0 → 3.4.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.
@@ -102,7 +102,7 @@ class KnexEntityDataProvider {
102
102
  this.dp = dp;
103
103
  }
104
104
  async groupBy(options) {
105
- return groupByImpl(options, await dbNamesOf(this.entity, this.dp.wrapIdentifier), this.dp.createCommand(), false, (limit, offset) => this.knex.client.config.client?.includes('mssql')
105
+ return groupByImpl(options, await dbNamesOfWithForceSqlExpression(this.entity, this.dp.wrapIdentifier, true), this.dp.createCommand(), false, (limit, offset) => this.knex.client.config.client?.includes('mssql')
106
106
  ? ' offset ' + offset + ' rows fetch next ' + limit + ' rows only'
107
107
  : ' limit ' + limit + ' offset ' + offset, this.dp.jsonColumnStorage);
108
108
  }
@@ -183,7 +183,7 @@ class KnexEntityDataProvider {
183
183
  });
184
184
  }
185
185
  async init() {
186
- const r = (await dbNamesOfWithForceSqlExpression(this.entity, (x) => x));
186
+ const r = (await dbNamesOfWithForceSqlExpression(this.entity, (x) => x, true));
187
187
  return {
188
188
  $dbNameOf: (f) => {
189
189
  let fm = f;
@@ -1,6 +1,6 @@
1
1
  import { ObjectId, } from 'mongodb';
2
2
  import { Filter } from './index.js';
3
- import { dbNamesOf, dbNamesOfWithForceSqlExpression, } from './src/filter/filter-consumer-bridge-to-sql-request.js';
3
+ import { dbNamesOfWithForceSqlExpression, } from './src/filter/filter-consumer-bridge-to-sql-request.js';
4
4
  import { remult as remultContext } from './src/remult-proxy.js';
5
5
  import { getRepository } from './src/remult3/RepositoryImplementation.js';
6
6
  import { getRepositoryInternals } from './src/remult3/repository-internals.js';
@@ -295,7 +295,7 @@ class MongoEntityDataProvider {
295
295
  return result;
296
296
  }
297
297
  async collection() {
298
- const e = await dbNamesOf(this.entity);
298
+ const e = await dbNamesOfWithForceSqlExpression(this.entity, undefined, true);
299
299
  const collection = this.db.collection(e.$entityName);
300
300
  return { e, collection };
301
301
  }
@@ -324,7 +324,7 @@ class ActualSQLEntityDataProvider {
324
324
  this.strategy = strategy;
325
325
  }
326
326
  async init() {
327
- let dbNameProvider = await dbNamesOfWithForceSqlExpression(this.entity, (x) => this.sql.wrapIdentifier(x));
327
+ let dbNameProvider = await dbNamesOfWithForceSqlExpression(this.entity, (x) => this.sql.wrapIdentifier(x), true);
328
328
  await this.iAmUsed(dbNameProvider);
329
329
  return dbNameProvider;
330
330
  }
@@ -1,17 +1,13 @@
1
- export async function entityDbName(metadata, wrapIdentifier = (x) => x) {
1
+ import { isSqlExpressionInProgress, runSqlExpression, } from './sqlExpressionInProgress.js';
2
+ export async function entityDbName(metadata, wrapIdentifier = (x) => x, forceSqlExpression = false) {
2
3
  if (metadata.options.sqlExpression) {
3
4
  if (typeof metadata.options.sqlExpression === 'string')
4
5
  return metadata.options.sqlExpression;
5
6
  else if (typeof metadata.options.sqlExpression === 'function') {
6
- const prev = metadata.options.sqlExpression;
7
- try {
8
- metadata.options.sqlExpression =
9
- "recursive sqlExpression call for entity '" + metadata.key + "'. ";
10
- return await prev(metadata);
11
- }
12
- finally {
13
- metadata.options.sqlExpression = prev;
14
- }
7
+ if (isSqlExpressionInProgress(metadata) && !forceSqlExpression)
8
+ return "recursive sqlExpression call for entity '" + metadata.key + "'. ";
9
+ const { sqlExpression } = metadata.options;
10
+ return await runSqlExpression(metadata, () => sqlExpression(metadata));
15
11
  }
16
12
  }
17
13
  return wrapIdentifier(metadata.dbName);
@@ -1,26 +1,20 @@
1
1
  import { getRelationFieldInfo } from '../remult3/relationInfoMember.js';
2
- const sqlExpressionInProgressKey = Symbol.for(`sqlExpressionInProgressKey`);
2
+ import { isSqlExpressionInProgress, runSqlExpression, } from './sqlExpressionInProgress.js';
3
3
  export const originalSqlExpressionKey = Symbol.for(`originalSqlExpressionKey`);
4
4
  export async function fieldDbName(f, meta, wrapIdentifier = (x) => x, forceSqlExpression = false) {
5
5
  try {
6
6
  if (f.options.sqlExpression) {
7
7
  let result;
8
8
  if (typeof f.options.sqlExpression === 'function') {
9
- if (f[sqlExpressionInProgressKey] && !forceSqlExpression) {
9
+ if (isSqlExpressionInProgress(f) && !forceSqlExpression) {
10
10
  return "recursive sqlExpression call for field '" + f.key + "'. \0";
11
11
  }
12
- try {
13
- ;
14
- f[sqlExpressionInProgressKey] = true;
15
- if (!f[originalSqlExpressionKey])
16
- f[originalSqlExpressionKey] = f.options.sqlExpression;
17
- result = await f.options.sqlExpression(meta, undefined, undefined);
18
- if (!result.includes('\0'))
19
- f.options.sqlExpression = () => result;
20
- }
21
- finally {
22
- delete f[sqlExpressionInProgressKey];
23
- }
12
+ const { sqlExpression } = f.options;
13
+ if (!f[originalSqlExpressionKey])
14
+ f[originalSqlExpressionKey] = sqlExpression;
15
+ result = await runSqlExpression(f, () => sqlExpression(meta, undefined, undefined));
16
+ if (!result.includes('\0'))
17
+ f.options.sqlExpression = () => result;
24
18
  }
25
19
  else
26
20
  result = f.options.sqlExpression;
@@ -223,10 +223,10 @@ export function shouldCreateEntity(entity, e) {
223
223
  export async function dbNamesOf(repo, wrapIdentifierOrOptions) {
224
224
  return internalDbNamesOf(repo, wrapIdentifierOrOptions);
225
225
  }
226
- export async function dbNamesOfWithForceSqlExpression(repo, wrapIdentifierOrOptions) {
227
- return internalDbNamesOf(repo, wrapIdentifierOrOptions, true);
226
+ export async function dbNamesOfWithForceSqlExpression(repo, wrapIdentifierOrOptions, forceEntitySqlExpression = false) {
227
+ return internalDbNamesOf(repo, wrapIdentifierOrOptions, true, forceEntitySqlExpression);
228
228
  }
229
- async function internalDbNamesOf(repo, wrapIdentifierOrOptions, forceSqlExpression = false) {
229
+ async function internalDbNamesOf(repo, wrapIdentifierOrOptions, forceSqlExpression = false, forceEntitySqlExpression = false) {
230
230
  let options = typeof wrapIdentifierOrOptions === 'function'
231
231
  ? { wrapIdentifier: wrapIdentifierOrOptions }
232
232
  : wrapIdentifierOrOptions || {};
@@ -237,7 +237,7 @@ async function internalDbNamesOf(repo, wrapIdentifierOrOptions, forceSqlExpressi
237
237
  if (!options.wrapIdentifier)
238
238
  options.wrapIdentifier = (x) => x;
239
239
  const result = {
240
- $entityName: await entityDbName(meta, options.wrapIdentifier),
240
+ $entityName: await entityDbName(meta, options.wrapIdentifier, forceEntitySqlExpression),
241
241
  toString: () => result.$entityName,
242
242
  $dbNameOf: (field) => {
243
243
  var key;
@@ -0,0 +1,14 @@
1
+ const sqlExpressionInProgressKey = Symbol.for(`sqlExpressionInProgressKey`);
2
+ export function isSqlExpressionInProgress(owner) {
3
+ return owner[sqlExpressionInProgressKey];
4
+ }
5
+ export async function runSqlExpression(owner, sqlExpression) {
6
+ try {
7
+ ;
8
+ owner[sqlExpressionInProgressKey] = true;
9
+ return await sqlExpression();
10
+ }
11
+ finally {
12
+ delete owner[sqlExpressionInProgressKey];
13
+ }
14
+ }
@@ -124,10 +124,10 @@ export class RemultProxy {
124
124
  .remultFactory()
125
125
  .repo(...args)
126
126
  .updateMany(...args2),
127
- find: (options) => self
127
+ find: (...args2) => self
128
128
  .remultFactory()
129
129
  .repo(...args)
130
- .find(options),
130
+ .find(...args2),
131
131
  groupBy: (...args2) => self
132
132
  .remultFactory()
133
133
  .repo(...args)
@@ -138,14 +138,14 @@ export class RemultProxy {
138
138
  .repo(...args)
139
139
  //@ts-ignore
140
140
  .aggregate(...args2),
141
- findFirst: (where, options) => self
141
+ findFirst: (...args2) => self
142
142
  .remultFactory()
143
143
  .repo(...args)
144
- .findFirst(where, options),
145
- findOne: (options) => self
144
+ .findFirst(...args2),
145
+ findOne: (...args2) => self
146
146
  .remultFactory()
147
147
  .repo(...args)
148
- .findOne(options),
148
+ .findOne(...args2),
149
149
  findId: (a, b) => self
150
150
  .remultFactory()
151
151
  .repo(...args)
@@ -26,6 +26,7 @@ export class QueryResultImpl {
26
26
  page: page,
27
27
  load: this.options.load,
28
28
  include: this.options.include,
29
+ args: this.options.args,
29
30
  });
30
31
  }
31
32
  async count() {
@@ -51,6 +52,7 @@ export class QueryResultImpl {
51
52
  limit: this.options.pageSize,
52
53
  load: this.options.load,
53
54
  include: this.options.include,
55
+ args: this.options.args,
54
56
  };
55
57
  let getItems = () => this.repo.find(options);
56
58
  if (this._aggregates === undefined &&
@@ -41,18 +41,6 @@ let classValidatorValidate = undefined;
41
41
  // })
42
42
  // .catch(() => {
43
43
  // });
44
- // Assigning a `toOne` also writes its `field`/`fields`, which would wipe the FK of a row whose
45
- // target is missing.
46
- function setMissingRelationToNull(row, key) {
47
- const ref = getEntityRef(row);
48
- ref._skipRelationFieldSync = true;
49
- try {
50
- row[key] = null;
51
- }
52
- finally {
53
- ref._skipRelationFieldSync = false;
54
- }
55
- }
56
44
  export class RepositoryImplementation {
57
45
  _entity;
58
46
  _remult;
@@ -744,12 +732,10 @@ export class RepositoryImplementation {
744
732
  for (const row of result) {
745
733
  let { findOptions, returnNull, returnUndefined } = this._findOptionsBasedOnRelation(rel, col, incl, row, otherRepo);
746
734
  const colKey = col.key;
747
- if (returnNull || returnUndefined) {
748
- if (rel.type === 'toMany')
749
- row[colKey] = (returnNull ? null : undefined);
750
- else
751
- setMissingRelationToNull(row, colKey);
752
- }
735
+ if (returnNull)
736
+ row[colKey] = null;
737
+ else if (returnUndefined)
738
+ row[colKey] = undefined;
753
739
  else {
754
740
  const entityType = rel.toEntity;
755
741
  const toRepo = otherRepo;
@@ -760,12 +746,14 @@ export class RepositoryImplementation {
760
746
  metadata: toRepo.metadata,
761
747
  }, findOptions)
762
748
  .then((result) => {
763
- if (rel.type === 'toMany')
764
- row[colKey] = result;
765
- else if (result.length == 0)
766
- setMissingRelationToNull(row, colKey);
767
- else
768
- row[colKey] = result[0];
749
+ if (result.length == 0 && rel.type == 'toOne')
750
+ return;
751
+ row[colKey] =
752
+ rel.type !== 'toMany'
753
+ ? result.length == 0
754
+ ? null
755
+ : result[0]
756
+ : result;
769
757
  });
770
758
  }
771
759
  }
@@ -1201,7 +1189,7 @@ class rowHelperBase {
1201
1189
  },
1202
1190
  set: (newVal) => {
1203
1191
  val = newVal;
1204
- if (newVal === undefined || this._skipRelationFieldSync)
1192
+ if (newVal === undefined)
1205
1193
  return;
1206
1194
  const op = col.options;
1207
1195
  if (op.field) {
@@ -1226,7 +1214,6 @@ class rowHelperBase {
1226
1214
  }
1227
1215
  }
1228
1216
  }
1229
- _skipRelationFieldSync = false;
1230
1217
  _subscribers;
1231
1218
  subscribe(listener) {
1232
1219
  this.initSubscribers();
@@ -1685,9 +1672,7 @@ export class rowHelperImplementation extends rowHelperBase {
1685
1672
  await listener.saved?.(this.instance, true);
1686
1673
  }
1687
1674
  }
1688
- this.repo._remult.liveQueryPublisher.itemChanged(this.repo.metadata.key, [
1689
- { id: this.getId(), oldId: this.getOriginalId(), deleted: false },
1690
- ]);
1675
+ this.repo._remult.liveQueryPublisher.itemChanged(this.repo.metadata.key, [{ id: this.getId(), oldId: this.getOriginalId(), deleted: false }]);
1691
1676
  this.saveOriginalData();
1692
1677
  this._isNew = false;
1693
1678
  return this.instance;
@@ -1814,7 +1799,8 @@ export class rowHelperImplementation extends rowHelperBase {
1814
1799
  if (!this.repo._dataProvider.isProxy)
1815
1800
  //y2 should be changed to be based on data provider - consider naming
1816
1801
  for (const col of this.info.fieldsMetadata) {
1817
- if (col.options.serverExpression) {
1802
+ if (col.options.serverExpression &&
1803
+ !this._fieldsExcludedBySelect?.has(col.key)) {
1818
1804
  const result = (await col.options.serverExpression(this.instance));
1819
1805
  if (result !== undefined)
1820
1806
  this.instance[col.key] = result;
package/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import type { ClassType } from './classType.js';
2
2
  import type { DataProvider } from './src/data-interfaces.js';
3
3
  export { ArrayEntityDataProvider } from './src/data-providers/array-entity-data-provider.js';
4
4
  export type { ClassType } from './classType.js';
5
- export type { ValidateFieldEvent, MembersOnly, NumericKeys, FieldsMetadata, FieldRef, IdFieldRef, FieldsRef, EntityMetadata, EntityOrderBy, EntityFilter, FindOptions, FindOptionsBase, QueryResult, QueryOptions, UpsertOptions, Repository, GroupByOptions, GroupByResult, FindFirstOptions, ComparisonValueFilter, ValueFilter, IdFilter, ContainsStringValueFilter, EntityRef, SortSegments, Paginator, LiveQuery, LiveQueryChangeInfo, Subscribable, RefSubscriber, RefSubscriberBase, RelationOptions, ObjectMembersOnly, MembersToInclude, Loaded, RepositoryRelations, EntityIdFields, EntitySelectFields, InsertOrUpdateOptions, ClassFieldDecorator, ClassFieldDecoratorContextStub, //n1 consider removing in ts5
5
+ export type { ValidateFieldEvent, MembersOnly, NumericKeys, FieldsMetadata, FieldRef, IdFieldRef, FieldsRef, EntityMetadata, EntityOrderBy, EntityFilter, FindOptions, FindOptionsBase, QueryResult, QueryOptions, UpsertOptions, Repository, GroupByOptions, GroupByResult, FindFirstOptions, ComparisonValueFilter, ValueFilter, IdFilter, ContainsStringValueFilter, EntityRef, SortSegments, Paginator, LiveQuery, LiveQueryChangeInfo, Subscribable, RefSubscriber, RefSubscriberBase, RelationOptions, ObjectMembersOnly, MembersToInclude, RepositoryRelations, EntityIdFields, EntitySelectFields, InsertOrUpdateOptions, ClassFieldDecorator, ClassFieldDecoratorContextStub, //n1 consider removing in ts5
6
6
  LifecycleEvent, FieldsRefBase, FieldsRefForEntityBase, RepositoryRelationsForEntityBase, ControllerRefForControllerBase, ControllerRefBase, ControllerRef, EntityRefForEntityBase, IdMetadata, FindFirstOptionsBase, } from './src/remult3/remult3.js';
7
7
  export { standardSchema } from './src/standard-schema/index.js';
8
8
  export { EntityBase, ControllerBase, FieldType, getFields, ValueListFieldType, getValueList, ValueListInfo, } from './src/remult3/RepositoryImplementation.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remult",
3
- "version": "3.4.0",
3
+ "version": "3.4.2",
4
4
  "description": "A CRUD framework for full-stack TypeScript",
5
5
  "homepage": "https://remult.dev",
6
6
  "repository": {
@@ -185,7 +185,7 @@ var KnexEntityDataProvider = /** @class */ (function () {
185
185
  case 0:
186
186
  _a = sql_database_js_1.groupByImpl;
187
187
  _b = [options];
188
- return [4 /*yield*/, (0, filter_consumer_bridge_to_sql_request_js_2.dbNamesOf)(this.entity, this.dp.wrapIdentifier)];
188
+ return [4 /*yield*/, (0, filter_consumer_bridge_to_sql_request_js_1.dbNamesOfWithForceSqlExpression)(this.entity, this.dp.wrapIdentifier, true)];
189
189
  case 1: return [2 /*return*/, _a.apply(void 0, _b.concat([_c.sent(), this.dp.createCommand(),
190
190
  false,
191
191
  function (limit, offset) {
@@ -320,7 +320,7 @@ var KnexEntityDataProvider = /** @class */ (function () {
320
320
  var _this = this;
321
321
  return tslib_1.__generator(this, function (_a) {
322
322
  switch (_a.label) {
323
- case 0: return [4 /*yield*/, (0, filter_consumer_bridge_to_sql_request_js_1.dbNamesOfWithForceSqlExpression)(this.entity, function (x) { return x; })];
323
+ case 0: return [4 /*yield*/, (0, filter_consumer_bridge_to_sql_request_js_1.dbNamesOfWithForceSqlExpression)(this.entity, function (x) { return x; }, true)];
324
324
  case 1:
325
325
  r = (_a.sent());
326
326
  return [2 /*return*/, {
package/remult-mongo.js CHANGED
@@ -619,7 +619,7 @@ var MongoEntityDataProvider = /** @class */ (function () {
619
619
  var e, collection;
620
620
  return tslib_1.__generator(this, function (_a) {
621
621
  switch (_a.label) {
622
- case 0: return [4 /*yield*/, (0, filter_consumer_bridge_to_sql_request_js_1.dbNamesOf)(this.entity)];
622
+ case 0: return [4 /*yield*/, (0, filter_consumer_bridge_to_sql_request_js_1.dbNamesOfWithForceSqlExpression)(this.entity, undefined, true)];
623
623
  case 1:
624
624
  e = _a.sent();
625
625
  collection = this.db.collection(e.$entityName);
@@ -475,9 +475,7 @@ var ActualSQLEntityDataProvider = /** @class */ (function () {
475
475
  var _this = this;
476
476
  return tslib_1.__generator(this, function (_a) {
477
477
  switch (_a.label) {
478
- case 0: return [4 /*yield*/, (0, filter_consumer_bridge_to_sql_request_js_1.dbNamesOfWithForceSqlExpression)(this.entity, function (x) {
479
- return _this.sql.wrapIdentifier(x);
480
- })];
478
+ case 0: return [4 /*yield*/, (0, filter_consumer_bridge_to_sql_request_js_1.dbNamesOfWithForceSqlExpression)(this.entity, function (x) { return _this.sql.wrapIdentifier(x); }, true)];
481
479
  case 1:
482
480
  dbNameProvider = _a.sent();
483
481
  return [4 /*yield*/, this.iAmUsed(dbNameProvider)];
@@ -1,2 +1,2 @@
1
1
  import type { EntityMetadata } from '../remult3/remult3.js';
2
- export declare function entityDbName(metadata: EntityMetadata, wrapIdentifier?: (name: string) => string): Promise<string>;
2
+ export declare function entityDbName(metadata: EntityMetadata, wrapIdentifier?: (name: string) => string, forceSqlExpression?: boolean): Promise<string>;
@@ -2,30 +2,28 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.entityDbName = entityDbName;
4
4
  var tslib_1 = require("tslib");
5
+ var sqlExpressionInProgress_js_1 = require("./sqlExpressionInProgress.js");
5
6
  function entityDbName(metadata_1) {
6
- return tslib_1.__awaiter(this, arguments, void 0, function (metadata, wrapIdentifier) {
7
- var prev;
7
+ return tslib_1.__awaiter(this, arguments, void 0, function (metadata, wrapIdentifier, forceSqlExpression) {
8
+ var sqlExpression_1;
8
9
  if (wrapIdentifier === void 0) { wrapIdentifier = function (x) { return x; }; }
10
+ if (forceSqlExpression === void 0) { forceSqlExpression = false; }
9
11
  return tslib_1.__generator(this, function (_a) {
10
12
  switch (_a.label) {
11
13
  case 0:
12
- if (!metadata.options.sqlExpression) return [3 /*break*/, 5];
14
+ if (!metadata.options.sqlExpression) return [3 /*break*/, 3];
13
15
  if (!(typeof metadata.options.sqlExpression === 'string')) return [3 /*break*/, 1];
14
16
  return [2 /*return*/, metadata.options.sqlExpression];
15
17
  case 1:
16
- if (!(typeof metadata.options.sqlExpression === 'function')) return [3 /*break*/, 5];
17
- prev = metadata.options.sqlExpression;
18
- _a.label = 2;
19
- case 2:
20
- _a.trys.push([2, , 4, 5]);
21
- metadata.options.sqlExpression =
22
- "recursive sqlExpression call for entity '" + metadata.key + "'. ";
23
- return [4 /*yield*/, prev(metadata)];
24
- case 3: return [2 /*return*/, _a.sent()];
25
- case 4:
26
- metadata.options.sqlExpression = prev;
27
- return [7 /*endfinally*/];
28
- case 5: return [2 /*return*/, wrapIdentifier(metadata.dbName)];
18
+ if (!(typeof metadata.options.sqlExpression === 'function')) return [3 /*break*/, 3];
19
+ if ((0, sqlExpressionInProgress_js_1.isSqlExpressionInProgress)(metadata) && !forceSqlExpression)
20
+ return [2 /*return*/, "recursive sqlExpression call for entity '" + metadata.key + "'. "];
21
+ sqlExpression_1 = metadata.options.sqlExpression;
22
+ return [4 /*yield*/, (0, sqlExpressionInProgress_js_1.runSqlExpression)(metadata, function () {
23
+ return sqlExpression_1(metadata);
24
+ })];
25
+ case 2: return [2 /*return*/, _a.sent()];
26
+ case 3: return [2 /*return*/, wrapIdentifier(metadata.dbName)];
29
27
  }
30
28
  });
31
29
  });
@@ -4,47 +4,41 @@ exports.originalSqlExpressionKey = void 0;
4
4
  exports.fieldDbName = fieldDbName;
5
5
  var tslib_1 = require("tslib");
6
6
  var relationInfoMember_js_1 = require("../remult3/relationInfoMember.js");
7
- var sqlExpressionInProgressKey = Symbol.for("sqlExpressionInProgressKey");
7
+ var sqlExpressionInProgress_js_1 = require("./sqlExpressionInProgress.js");
8
8
  exports.originalSqlExpressionKey = Symbol.for("originalSqlExpressionKey");
9
9
  function fieldDbName(f_1, meta_1) {
10
10
  return tslib_1.__awaiter(this, arguments, void 0, function (f, meta, wrapIdentifier, forceSqlExpression) {
11
- var result_1, rel, field, fInfo;
11
+ var result_1, sqlExpression_1, rel, field, fInfo;
12
12
  if (wrapIdentifier === void 0) { wrapIdentifier = function (x) { return x; }; }
13
13
  if (forceSqlExpression === void 0) { forceSqlExpression = false; }
14
14
  return tslib_1.__generator(this, function (_a) {
15
15
  switch (_a.label) {
16
16
  case 0:
17
- _a.trys.push([0, , 8, 9]);
18
- if (!f.options.sqlExpression) return [3 /*break*/, 7];
19
- if (!(typeof f.options.sqlExpression === 'function')) return [3 /*break*/, 5];
20
- if (f[sqlExpressionInProgressKey] && !forceSqlExpression) {
17
+ _a.trys.push([0, , 5, 6]);
18
+ if (!f.options.sqlExpression) return [3 /*break*/, 4];
19
+ if (!(typeof f.options.sqlExpression === 'function')) return [3 /*break*/, 2];
20
+ if ((0, sqlExpressionInProgress_js_1.isSqlExpressionInProgress)(f) && !forceSqlExpression) {
21
21
  return [2 /*return*/, "recursive sqlExpression call for field '" + f.key + "'. \0"];
22
22
  }
23
- _a.label = 1;
24
- case 1:
25
- _a.trys.push([1, , 3, 4]);
26
- ;
27
- f[sqlExpressionInProgressKey] = true;
23
+ sqlExpression_1 = f.options.sqlExpression;
28
24
  if (!f[exports.originalSqlExpressionKey])
29
- f[exports.originalSqlExpressionKey] = f.options.sqlExpression;
30
- return [4 /*yield*/, f.options.sqlExpression(meta, undefined, undefined)];
31
- case 2:
25
+ f[exports.originalSqlExpressionKey] = sqlExpression_1;
26
+ return [4 /*yield*/, (0, sqlExpressionInProgress_js_1.runSqlExpression)(f, function () {
27
+ return sqlExpression_1(meta, undefined, undefined);
28
+ })];
29
+ case 1:
32
30
  result_1 = _a.sent();
33
31
  if (!result_1.includes('\0'))
34
32
  f.options.sqlExpression = function () { return result_1; };
35
- return [3 /*break*/, 4];
36
- case 3:
37
- delete f[sqlExpressionInProgressKey];
38
- return [7 /*endfinally*/];
39
- case 4: return [3 /*break*/, 6];
40
- case 5:
33
+ return [3 /*break*/, 3];
34
+ case 2:
41
35
  result_1 = f.options.sqlExpression;
42
- _a.label = 6;
43
- case 6:
36
+ _a.label = 3;
37
+ case 3:
44
38
  if (!result_1)
45
39
  return [2 /*return*/, f.dbName];
46
40
  return [2 /*return*/, result_1];
47
- case 7:
41
+ case 4:
48
42
  rel = (0, relationInfoMember_js_1.getRelationFieldInfo)(f);
49
43
  field = (rel === null || rel === void 0 ? void 0 : rel.type) === 'toOne' &&
50
44
  f.options.field;
@@ -54,8 +48,8 @@ function fieldDbName(f_1, meta_1) {
54
48
  return [2 /*return*/, fieldDbName(fInfo, meta, wrapIdentifier, forceSqlExpression)];
55
49
  }
56
50
  return [2 /*return*/, wrapIdentifier(f.dbName)];
57
- case 8: return [7 /*endfinally*/];
58
- case 9: return [2 /*return*/];
51
+ case 5: return [7 /*endfinally*/];
52
+ case 6: return [2 /*return*/];
59
53
  }
60
54
  });
61
55
  });
@@ -88,5 +88,5 @@ export interface dbNamesOfOptions {
88
88
  tableName?: boolean | string;
89
89
  }
90
90
  export declare function dbNamesOf<entityType>(repo: EntityMetadataOverloads<entityType>, wrapIdentifierOrOptions?: ((name: string) => string) | dbNamesOfOptions): Promise<EntityDbNames<entityType>>;
91
- export declare function dbNamesOfWithForceSqlExpression<entityType>(repo: EntityMetadataOverloads<entityType>, wrapIdentifierOrOptions?: ((name: string) => string) | dbNamesOfOptions): Promise<EntityDbNames<entityType>>;
91
+ export declare function dbNamesOfWithForceSqlExpression<entityType>(repo: EntityMetadataOverloads<entityType>, wrapIdentifierOrOptions?: ((name: string) => string) | dbNamesOfOptions, forceEntitySqlExpression?: boolean): Promise<EntityDbNames<entityType>>;
92
92
  export declare function toDbSql(r: SqlCommandWithParameters, field: FieldMetadata, val: any): string;
@@ -347,18 +347,20 @@ function dbNamesOf(repo, wrapIdentifierOrOptions) {
347
347
  });
348
348
  });
349
349
  }
350
- function dbNamesOfWithForceSqlExpression(repo, wrapIdentifierOrOptions) {
351
- return tslib_1.__awaiter(this, void 0, void 0, function () {
350
+ function dbNamesOfWithForceSqlExpression(repo_1, wrapIdentifierOrOptions_1) {
351
+ return tslib_1.__awaiter(this, arguments, void 0, function (repo, wrapIdentifierOrOptions, forceEntitySqlExpression) {
352
+ if (forceEntitySqlExpression === void 0) { forceEntitySqlExpression = false; }
352
353
  return tslib_1.__generator(this, function (_a) {
353
- return [2 /*return*/, internalDbNamesOf(repo, wrapIdentifierOrOptions, true)];
354
+ return [2 /*return*/, internalDbNamesOf(repo, wrapIdentifierOrOptions, true, forceEntitySqlExpression)];
354
355
  });
355
356
  });
356
357
  }
357
358
  function internalDbNamesOf(repo_1, wrapIdentifierOrOptions_1) {
358
- return tslib_1.__awaiter(this, arguments, void 0, function (repo, wrapIdentifierOrOptions, forceSqlExpression) {
359
+ return tslib_1.__awaiter(this, arguments, void 0, function (repo, wrapIdentifierOrOptions, forceSqlExpression, forceEntitySqlExpression) {
359
360
  var options, meta, result, _a, _b, field, r, e_3_1;
360
361
  var _c, e_3, _d;
361
362
  if (forceSqlExpression === void 0) { forceSqlExpression = false; }
363
+ if (forceEntitySqlExpression === void 0) { forceEntitySqlExpression = false; }
362
364
  return tslib_1.__generator(this, function (_e) {
363
365
  switch (_e.label) {
364
366
  case 0:
@@ -372,7 +374,7 @@ function internalDbNamesOf(repo_1, wrapIdentifierOrOptions_1) {
372
374
  if (!options.wrapIdentifier)
373
375
  options.wrapIdentifier = function (x) { return x; };
374
376
  _c = {};
375
- return [4 /*yield*/, (0, entityDbName_js_1.entityDbName)(meta, options.wrapIdentifier)];
377
+ return [4 /*yield*/, (0, entityDbName_js_1.entityDbName)(meta, options.wrapIdentifier, forceEntitySqlExpression)];
376
378
  case 1:
377
379
  result = (_c.$entityName = _e.sent(),
378
380
  _c.toString = function () { return result.$entityName; },
@@ -0,0 +1,2 @@
1
+ export declare function isSqlExpressionInProgress(owner: object): boolean;
2
+ export declare function runSqlExpression<T>(owner: object, sqlExpression: () => T | Promise<T>): Promise<T>;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isSqlExpressionInProgress = isSqlExpressionInProgress;
4
+ exports.runSqlExpression = runSqlExpression;
5
+ var tslib_1 = require("tslib");
6
+ var sqlExpressionInProgressKey = Symbol.for("sqlExpressionInProgressKey");
7
+ function isSqlExpressionInProgress(owner) {
8
+ return owner[sqlExpressionInProgressKey];
9
+ }
10
+ function runSqlExpression(owner, sqlExpression) {
11
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
12
+ return tslib_1.__generator(this, function (_a) {
13
+ switch (_a.label) {
14
+ case 0:
15
+ _a.trys.push([0, , 2, 3]);
16
+ ;
17
+ owner[sqlExpressionInProgressKey] = true;
18
+ return [4 /*yield*/, sqlExpression()];
19
+ case 1: return [2 /*return*/, _a.sent()];
20
+ case 2:
21
+ delete owner[sqlExpressionInProgressKey];
22
+ return [7 /*endfinally*/];
23
+ case 3: return [2 /*return*/];
24
+ }
25
+ });
26
+ });
27
+ }
@@ -112,11 +112,16 @@ var RemultProxy = /** @class */ (function () {
112
112
  .repo.apply(_b, tslib_1.__spreadArray([], tslib_1.__read(args), false)))
113
113
  .updateMany.apply(_a, tslib_1.__spreadArray([], tslib_1.__read(args2), false));
114
114
  },
115
- _a.find = function (options) {
116
- var _a;
117
- return (_a = self
115
+ _a.find = function () {
116
+ var _a, _b;
117
+ var args2 = [];
118
+ for (var _i = 0; _i < arguments.length; _i++) {
119
+ args2[_i] = arguments[_i];
120
+ }
121
+ return (_a = (_b = self
118
122
  .remultFactory())
119
- .repo.apply(_a, tslib_1.__spreadArray([], tslib_1.__read(args), false)).find(options);
123
+ .repo.apply(_b, tslib_1.__spreadArray([], tslib_1.__read(args), false)))
124
+ .find.apply(_a, tslib_1.__spreadArray([], tslib_1.__read(args2), false));
120
125
  },
121
126
  _a.groupBy = function () {
122
127
  var _a, _b;
@@ -140,17 +145,27 @@ var RemultProxy = /** @class */ (function () {
140
145
  .repo.apply(_b, tslib_1.__spreadArray([], tslib_1.__read(args), false)))
141
146
  .aggregate.apply(_a, tslib_1.__spreadArray([], tslib_1.__read(args2), false));
142
147
  },
143
- _a.findFirst = function (where, options) {
144
- var _a;
145
- return (_a = self
148
+ _a.findFirst = function () {
149
+ var _a, _b;
150
+ var args2 = [];
151
+ for (var _i = 0; _i < arguments.length; _i++) {
152
+ args2[_i] = arguments[_i];
153
+ }
154
+ return (_a = (_b = self
146
155
  .remultFactory())
147
- .repo.apply(_a, tslib_1.__spreadArray([], tslib_1.__read(args), false)).findFirst(where, options);
156
+ .repo.apply(_b, tslib_1.__spreadArray([], tslib_1.__read(args), false)))
157
+ .findFirst.apply(_a, tslib_1.__spreadArray([], tslib_1.__read(args2), false));
148
158
  },
149
- _a.findOne = function (options) {
150
- var _a;
151
- return (_a = self
159
+ _a.findOne = function () {
160
+ var _a, _b;
161
+ var args2 = [];
162
+ for (var _i = 0; _i < arguments.length; _i++) {
163
+ args2[_i] = arguments[_i];
164
+ }
165
+ return (_a = (_b = self
152
166
  .remultFactory())
153
- .repo.apply(_a, tslib_1.__spreadArray([], tslib_1.__read(args), false)).findOne(options);
167
+ .repo.apply(_b, tslib_1.__spreadArray([], tslib_1.__read(args), false)))
168
+ .findOne.apply(_a, tslib_1.__spreadArray([], tslib_1.__read(args2), false));
154
169
  },
155
170
  _a.findId = function (a, b) {
156
171
  var _a;
@@ -29,6 +29,7 @@ var QueryResultImpl = /** @class */ (function () {
29
29
  page: page,
30
30
  load: this.options.load,
31
31
  include: this.options.include,
32
+ args: this.options.args,
32
33
  })];
33
34
  });
34
35
  });
@@ -115,6 +116,7 @@ var QueryResultImpl = /** @class */ (function () {
115
116
  limit: this.options.pageSize,
116
117
  load: this.options.load,
117
118
  include: this.options.include,
119
+ args: this.options.args,
118
120
  };
119
121
  getItems = function () { return _this.repo.find(options); };
120
122
  if (this._aggregates === undefined &&
@@ -106,7 +106,6 @@ declare abstract class rowHelperBase<T> {
106
106
  * must not be serialized by {@link toApiJson}. */
107
107
  _fieldsExcludedBySelect?: Set<string>;
108
108
  constructor(fieldsMetadata: FieldMetadata[], instance: T, remult: Remult, isNewRow: boolean, excludeRelationMembers?: Set<string>);
109
- _skipRelationFieldSync: boolean;
110
109
  _subscribers?: SubscribableImp;
111
110
  subscribe(listener: RefSubscriber): Unsubscribe;
112
111
  _isLoading: boolean;
@@ -57,18 +57,6 @@ var classValidatorValidate = undefined;
57
57
  // })
58
58
  // .catch(() => {
59
59
  // });
60
- // Assigning a `toOne` also writes its `field`/`fields`, which would wipe the FK of a row whose
61
- // target is missing.
62
- function setMissingRelationToNull(row, key) {
63
- var ref = (0, getEntityRef_js_1.getEntityRef)(row);
64
- ref._skipRelationFieldSync = true;
65
- try {
66
- row[key] = null;
67
- }
68
- finally {
69
- ref._skipRelationFieldSync = false;
70
- }
71
- }
72
60
  var RepositoryImplementation = /** @class */ (function () {
73
61
  function RepositoryImplementation(_entity, _remult, _dataProvider, _info, _defaultFindOptions) {
74
62
  this._entity = _entity;
@@ -1239,12 +1227,10 @@ var RepositoryImplementation = /** @class */ (function () {
1239
1227
  var _loop_2 = function (row) {
1240
1228
  var _e = this_1._findOptionsBasedOnRelation(rel, col, incl, row, otherRepo), findOptions = _e.findOptions, returnNull = _e.returnNull, returnUndefined = _e.returnUndefined;
1241
1229
  var colKey = col.key;
1242
- if (returnNull || returnUndefined) {
1243
- if (rel.type === 'toMany')
1244
- row[colKey] = (returnNull ? null : undefined);
1245
- else
1246
- setMissingRelationToNull(row, colKey);
1247
- }
1230
+ if (returnNull)
1231
+ row[colKey] = null;
1232
+ else if (returnUndefined)
1233
+ row[colKey] = undefined;
1248
1234
  else {
1249
1235
  var entityType = rel.toEntity;
1250
1236
  var toRepo_1 = otherRepo;
@@ -1259,12 +1245,14 @@ var RepositoryImplementation = /** @class */ (function () {
1259
1245
  metadata: toRepo_1.metadata,
1260
1246
  }, findOptions)
1261
1247
  .then(function (result) {
1262
- if (rel.type === 'toMany')
1263
- row[colKey] = result;
1264
- else if (result.length == 0)
1265
- setMissingRelationToNull(row, colKey);
1266
- else
1267
- row[colKey] = result[0];
1248
+ if (result.length == 0 && rel.type == 'toOne')
1249
+ return;
1250
+ row[colKey] =
1251
+ rel.type !== 'toMany'
1252
+ ? result.length == 0
1253
+ ? null
1254
+ : result[0]
1255
+ : result;
1268
1256
  });
1269
1257
  }
1270
1258
  };
@@ -1908,7 +1896,6 @@ var rowHelperBase = /** @class */ (function () {
1908
1896
  this.instance = instance;
1909
1897
  this.remult = remult;
1910
1898
  this.isNewRow = isNewRow;
1911
- this._skipRelationFieldSync = false;
1912
1899
  this._isLoading = false;
1913
1900
  this.lookups = new Map();
1914
1901
  this.originalValues = {};
@@ -1968,7 +1955,7 @@ var rowHelperBase = /** @class */ (function () {
1968
1955
  },
1969
1956
  set: function (newVal) {
1970
1957
  val_1 = newVal;
1971
- if (newVal === undefined || _this._skipRelationFieldSync)
1958
+ if (newVal === undefined)
1972
1959
  return;
1973
1960
  var op = col.options;
1974
1961
  if (op.field) {
@@ -2819,9 +2806,7 @@ var rowHelperImplementation = /** @class */ (function (_super) {
2819
2806
  finally { if (e_41) throw e_41.error; }
2820
2807
  return [7 /*endfinally*/];
2821
2808
  case 12:
2822
- this.repo._remult.liveQueryPublisher.itemChanged(this.repo.metadata.key, [
2823
- { id: this.getId(), oldId: this.getOriginalId(), deleted: false },
2824
- ]);
2809
+ this.repo._remult.liveQueryPublisher.itemChanged(this.repo.metadata.key, [{ id: this.getId(), oldId: this.getOriginalId(), deleted: false }]);
2825
2810
  this.saveOriginalData();
2826
2811
  this._isNew = false;
2827
2812
  return [2 /*return*/, this.instance];
@@ -3107,31 +3092,33 @@ var rowHelperImplementation = /** @class */ (function (_super) {
3107
3092
  return tslib_1.__awaiter(this, void 0, void 0, function () {
3108
3093
  var _a, _b, col, result, e_46_1;
3109
3094
  var e_46, _c;
3110
- return tslib_1.__generator(this, function (_d) {
3111
- switch (_d.label) {
3095
+ var _d;
3096
+ return tslib_1.__generator(this, function (_e) {
3097
+ switch (_e.label) {
3112
3098
  case 0:
3113
3099
  if (!!this.repo._dataProvider.isProxy) return [3 /*break*/, 8];
3114
- _d.label = 1;
3100
+ _e.label = 1;
3115
3101
  case 1:
3116
- _d.trys.push([1, 6, 7, 8]);
3102
+ _e.trys.push([1, 6, 7, 8]);
3117
3103
  _a = tslib_1.__values(this.info.fieldsMetadata), _b = _a.next();
3118
- _d.label = 2;
3104
+ _e.label = 2;
3119
3105
  case 2:
3120
3106
  if (!!_b.done) return [3 /*break*/, 5];
3121
3107
  col = _b.value;
3122
- if (!col.options.serverExpression) return [3 /*break*/, 4];
3108
+ if (!(col.options.serverExpression &&
3109
+ !((_d = this._fieldsExcludedBySelect) === null || _d === void 0 ? void 0 : _d.has(col.key)))) return [3 /*break*/, 4];
3123
3110
  return [4 /*yield*/, col.options.serverExpression(this.instance)];
3124
3111
  case 3:
3125
- result = (_d.sent());
3112
+ result = (_e.sent());
3126
3113
  if (result !== undefined)
3127
3114
  this.instance[col.key] = result;
3128
- _d.label = 4;
3115
+ _e.label = 4;
3129
3116
  case 4:
3130
3117
  _b = _a.next();
3131
3118
  return [3 /*break*/, 2];
3132
3119
  case 5: return [3 /*break*/, 8];
3133
3120
  case 6:
3134
- e_46_1 = _d.sent();
3121
+ e_46_1 = _e.sent();
3135
3122
  e_46 = { error: e_46_1 };
3136
3123
  return [3 /*break*/, 8];
3137
3124
  case 7:
@@ -395,10 +395,6 @@ export type GroupByResult<entityType, groupByFields extends (keyof entityType)[]
395
395
  };
396
396
  /** used to perform CRUD operations on an `entityType` */
397
397
  export interface Repository<entityType> {
398
- /** returns an array based on the provided options. Included relations drop their `?`, see {@link Loaded} */
399
- find<const include extends MembersToInclude<entityType>>(options: FindOptions<entityType> & {
400
- include: include;
401
- }): Promise<Loaded<entityType, include>[]>;
402
398
  /** returns an array based on the provided options */
403
399
  find(options?: FindOptions<entityType>): Promise<entityType[]>;
404
400
  /** Using the same options as the {@link find} method, but subscribing to entity changes.
@@ -414,9 +410,6 @@ export interface Repository<entityType> {
414
410
  * @example
415
411
  * await taskRepo.findFirst({ completed:false },{ createIfNotFound: true })
416
412
  * */
417
- findFirst<const include extends MembersToInclude<entityType>>(where: EntityFilter<entityType> | undefined, options: FindFirstOptions<entityType> & {
418
- include: include;
419
- }): Promise<Loaded<entityType, include> | undefined>;
420
413
  findFirst(where?: EntityFilter<entityType>, options?: FindFirstOptions<entityType>): Promise<entityType | undefined>;
421
414
  /** returns the first item that matchers the `where` condition
422
415
  * @example
@@ -424,14 +417,8 @@ export interface Repository<entityType> {
424
417
  * @example
425
418
  * await taskRepo.findFirst({ where:{ completed:false }, createIfNotFound: true })
426
419
  * */
427
- findOne<const include extends MembersToInclude<entityType>>(options: FindFirstOptions<entityType> & {
428
- include: include;
429
- }): Promise<Loaded<entityType, include> | undefined>;
430
420
  findOne(options?: FindFirstOptions<entityType>): Promise<entityType | undefined>;
431
421
  /** returns the items that matches the id. If id is undefined | null, returns null */
432
- findId<const include extends MembersToInclude<entityType>>(id: idType<entityType>, options: FindFirstOptionsBase<entityType> & {
433
- include: include;
434
- }): Promise<Loaded<entityType, include> | undefined | null>;
435
422
  findId(id: idType<entityType>, options?: FindFirstOptionsBase<entityType>): Promise<entityType | undefined | null>;
436
423
  /**
437
424
  * Performs an aggregation on the repository's entity type based on the specified options.
@@ -1196,29 +1183,6 @@ export type ObjectMembersOnly<T> = MembersOnly<{
1196
1183
  export type MembersToInclude<T> = {
1197
1184
  [K in keyof ObjectMembersOnly<T>]?: boolean | (NonNullable<T[K]> extends Array<any> ? FindOptions<NonNullable<T[K]>[number]> : FindFirstOptions<NonNullable<T[K]>>);
1198
1185
  };
1199
- type LoadedTarget<target, include> = include extends {
1200
- include: infer nested;
1201
- } ? Loaded<target, nested> : target;
1202
- type LoadedRelation<value, include> = NonNullable<value> extends (infer target)[] ? LoadedTarget<target, include>[] : null extends value ? LoadedTarget<NonNullable<value>, include> | null : LoadedTarget<NonNullable<value>, include>;
1203
- type LoadedKeys<entityType, include> = {
1204
- [K in keyof include & keyof entityType]-?: [include[K]] extends [
1205
- true | object
1206
- ] ? K : never;
1207
- }[keyof include & keyof entityType];
1208
- /**
1209
- * The entity type `find` returns for a given `include`.
1210
- * Included relations drop their `?`, and nested `include`s work the same way.
1211
- * A relation declared `| null` stays nullable.
1212
- * A relation included with `false` or a widened `boolean` keeps its declared type.
1213
- * An included relation whose target row is missing loads as `null`.
1214
- * Declare it `| null` when that can happen, e.g. an optional FK or a target a `backendPrefilter` can hide.
1215
- * @example
1216
- * const tasks = await repo(Task).find({ include: { category: true } })
1217
- * tasks[0].category.name // `category` is loaded, no `?.` needed
1218
- */
1219
- export type Loaded<entityType, include> = 0 extends 1 & (entityType | include) ? entityType : [LoadedKeys<entityType, include>] extends [never] ? entityType : Omit<entityType, LoadedKeys<entityType, include>> & {
1220
- [K in LoadedKeys<entityType, include>]-?: LoadedRelation<Exclude<entityType[K], undefined>, include[K]>;
1221
- };
1222
1186
  export type RepositoryRelations<entityType> = {
1223
1187
  [K in keyof ObjectMembersOnly<entityType>]-?: NonNullable<entityType[K]> extends Array<infer R> ? Repository<R> : entityType[K] extends infer R ? {
1224
1188
  findOne: (options?: FindOptionsBase<R>) => Promise<R>;
@@ -1265,4 +1229,3 @@ export declare const flags: {
1265
1229
  /** Version poll while SSE is stale */
1266
1230
  liveQueryPollWhenStaleMs: number;
1267
1231
  };
1268
- export {};