remult 0.23.0-exp.2 → 0.23.0-exp.21

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.
Files changed (92) hide show
  1. package/README.md +26 -27
  2. package/esm/graphql.js +7 -1
  3. package/esm/index.d.ts +16 -3
  4. package/esm/index.js +17 -2
  5. package/esm/internals.d.ts +2 -1
  6. package/esm/internals.js +1 -1
  7. package/esm/remult-express.js +1 -1
  8. package/esm/remult-knex/index.js +2 -1
  9. package/esm/remult-mongo.js +2 -1
  10. package/esm/server/JsonEntityFileStorage.js +1 -1
  11. package/esm/server/expressBridge.js +1 -1
  12. package/esm/src/CompoundIdField.d.ts +1 -1
  13. package/esm/src/CompoundIdField.js +3 -1
  14. package/esm/src/buildRestDataProvider.d.ts +1 -2
  15. package/esm/src/column-interfaces.d.ts +19 -7
  16. package/esm/src/column.d.ts +4 -18
  17. package/esm/src/column.js +10 -44
  18. package/esm/src/context.d.ts +1 -1
  19. package/esm/src/context.js +5 -1
  20. package/esm/src/data-interfaces.js +1 -2
  21. package/esm/src/data-providers/array-entity-data-provider.d.ts +1 -1
  22. package/esm/src/data-providers/array-entity-data-provider.js +6 -6
  23. package/esm/src/data-providers/sql-database.js +2 -1
  24. package/esm/src/data-providers/web-sql-data-provider.js +3 -3
  25. package/esm/src/entity.d.ts +48 -17
  26. package/esm/src/filter/filter-interfaces.d.ts +2 -16
  27. package/esm/src/filter/filter-interfaces.js +87 -6
  28. package/esm/src/live-query/LiveQueryClient.js +2 -1
  29. package/esm/src/live-query/SubscriptionChannel.js +4 -3
  30. package/esm/src/remult-proxy.js +10 -2
  31. package/esm/src/remult3/Fields.d.ts +140 -21
  32. package/esm/src/remult3/Fields.js +26 -30
  33. package/esm/src/remult3/RepositoryImplementation.d.ts +10 -16
  34. package/esm/src/remult3/RepositoryImplementation.js +165 -48
  35. package/esm/src/remult3/entity.d.ts +1 -1
  36. package/esm/src/remult3/entity.js +0 -1
  37. package/esm/src/remult3/getEntityRef.d.ts +1 -1
  38. package/esm/src/remult3/getEntityRef.js +1 -1
  39. package/esm/src/remult3/relation-loader.js +4 -1
  40. package/esm/src/remult3/remult3.d.ts +132 -7
  41. package/esm/src/remult3/remult3.js +30 -0
  42. package/esm/src/remult3/repository-internals.d.ts +14 -0
  43. package/esm/src/remult3/repository-internals.js +7 -0
  44. package/esm/src/server-action.js +1 -1
  45. package/esm/src/sort.d.ts +3 -3
  46. package/esm/src/sort.js +36 -8
  47. package/graphql.js +10 -2
  48. package/index.d.ts +16 -3
  49. package/index.js +19 -3
  50. package/internals.d.ts +2 -1
  51. package/internals.js +3 -1
  52. package/package.json +1 -1
  53. package/remult-express.js +1 -1
  54. package/remult-knex/index.js +2 -1
  55. package/remult-mongo.js +2 -1
  56. package/server/JsonEntityFileStorage.js +1 -1
  57. package/server/expressBridge.js +1 -1
  58. package/src/CompoundIdField.d.ts +1 -1
  59. package/src/CompoundIdField.js +3 -0
  60. package/src/buildRestDataProvider.d.ts +1 -2
  61. package/src/column-interfaces.d.ts +19 -7
  62. package/src/column.d.ts +4 -18
  63. package/src/column.js +10 -56
  64. package/src/context.d.ts +1 -1
  65. package/src/context.js +5 -1
  66. package/src/data-interfaces.js +1 -2
  67. package/src/data-providers/array-entity-data-provider.d.ts +1 -1
  68. package/src/data-providers/array-entity-data-provider.js +5 -6
  69. package/src/data-providers/sql-database.js +2 -1
  70. package/src/data-providers/web-sql-data-provider.js +3 -3
  71. package/src/entity.d.ts +48 -17
  72. package/src/filter/filter-interfaces.d.ts +2 -16
  73. package/src/filter/filter-interfaces.js +101 -9
  74. package/src/live-query/LiveQueryClient.js +2 -1
  75. package/src/live-query/SubscriptionChannel.js +4 -3
  76. package/src/remult-proxy.js +43 -29
  77. package/src/remult3/Fields.d.ts +140 -21
  78. package/src/remult3/Fields.js +32 -32
  79. package/src/remult3/RepositoryImplementation.d.ts +10 -16
  80. package/src/remult3/RepositoryImplementation.js +286 -163
  81. package/src/remult3/entity.d.ts +1 -1
  82. package/src/remult3/entity.js +0 -1
  83. package/src/remult3/getEntityRef.d.ts +1 -1
  84. package/src/remult3/getEntityRef.js +2 -1
  85. package/src/remult3/relation-loader.js +4 -1
  86. package/src/remult3/remult3.d.ts +132 -7
  87. package/src/remult3/remult3.js +30 -0
  88. package/src/remult3/repository-internals.d.ts +14 -0
  89. package/src/remult3/repository-internals.js +11 -0
  90. package/src/server-action.js +1 -1
  91. package/src/sort.d.ts +3 -3
  92. package/src/sort.js +43 -11
@@ -4,7 +4,6 @@ import { Remult, isBackend, queryConfig, } from '../context';
4
4
  import { Filter } from '../filter/filter-interfaces';
5
5
  import { Sort } from '../sort';
6
6
  import { assign } from '../../assign';
7
- import { filterHelper } from '../filter/filter-interfaces';
8
7
  import { ValueConverters } from '../valueConverters';
9
8
  import { findOptionsToJson } from '../data-providers/rest-data-provider';
10
9
  import { remult as defaultRemult } from '../remult-proxy';
@@ -12,6 +11,7 @@ import { entityMember, getEntityKey, getEntityRef, getEntitySettings, } from './
12
11
  import { __updateEntityBasedOnWhere } from './__updateEntityBasedOnWhere';
13
12
  import { getRelationInfo, relationInfoMember } from './relationInfoMember';
14
13
  import { RelationLoader } from './relation-loader';
14
+ import { getInternalKey } from './repository-internals';
15
15
  //import { remult } from "../remult-proxy";
16
16
  let classValidatorValidate = undefined;
17
17
  // import ("class-validator".toString())
@@ -37,6 +37,9 @@ export class RepositoryImplementation {
37
37
  dataProvider;
38
38
  _info;
39
39
  defaultFindOptions;
40
+ [getInternalKey]() {
41
+ return this;
42
+ }
40
43
  async createAfterFilter(orderBy, lastRow) {
41
44
  let values = new Map();
42
45
  for (const s of Sort.translateOrderByToSort(this.metadata, orderBy)
@@ -56,7 +59,6 @@ export class RepositoryImplementation {
56
59
  let equalToColumn = [];
57
60
  for (const s of Sort.translateOrderByToSort(this.metadata, orderBy)
58
61
  .Segments) {
59
- let ff = new filterHelper(s.field);
60
62
  let f = {};
61
63
  for (const c of equalToColumn) {
62
64
  f[c.key] = values.get(c.key);
@@ -251,6 +253,8 @@ export class RepositoryImplementation {
251
253
  for (const key in entity) {
252
254
  if (Object.prototype.hasOwnProperty.call(entity, key)) {
253
255
  let f = ref.fields[key];
256
+ if (entity[key] === undefined && getRelationInfo(f.metadata.options))
257
+ continue;
254
258
  if (f)
255
259
  r[key] = entity[key];
256
260
  }
@@ -324,7 +328,6 @@ export class RepositoryImplementation {
324
328
  async rawFind(options, skipOrderByAndLimit = false, loader) {
325
329
  if (!options)
326
330
  options = {};
327
- Remult.onFind(this._info, options);
328
331
  if (this.defaultFindOptions) {
329
332
  options = { ...this.defaultFindOptions, ...options };
330
333
  }
@@ -333,6 +336,7 @@ export class RepositoryImplementation {
333
336
  delete opt.orderBy;
334
337
  delete opt.limit;
335
338
  }
339
+ Remult.onFind(this._info, options);
336
340
  const rawRows = await this.edp.find(opt);
337
341
  let result = await this.loadManyToOneForManyRows(rawRows, options, loader);
338
342
  return result;
@@ -350,9 +354,12 @@ export class RepositoryImplementation {
350
354
  options.orderBy = this._info.entityInfo.defaultOrderBy;
351
355
  }
352
356
  opt.where = await this.translateWhereToFilter(options.where);
353
- opt.orderBy = Sort.translateOrderByToSort(this.metadata, options.orderBy);
354
- opt.limit = options.limit;
355
- opt.page = options.page;
357
+ if (options.orderBy !== undefined)
358
+ opt.orderBy = Sort.translateOrderByToSort(this.metadata, options.orderBy);
359
+ if (options.limit !== undefined)
360
+ opt.limit = options.limit;
361
+ if (options.page !== undefined)
362
+ opt.page = options.page;
356
363
  return opt;
357
364
  }
358
365
  async fromJsonArray(jsonItems, loadOptions) {
@@ -376,13 +383,9 @@ export class RepositoryImplementation {
376
383
  if (ei) {
377
384
  let isRelation = col.options?.[relationInfoMember];
378
385
  if (!isRelation) {
379
- let load = isRelation
380
- ? col.options?.defaultIncluded
381
- : !col.options.lazy;
386
+ let load = !col.options.lazy;
382
387
  if (loadFields !== undefined)
383
388
  load = loadFields.includes(col);
384
- if (loadOptions.include)
385
- load = loadOptions.include[col.key];
386
389
  if (load) {
387
390
  let repo = this.remult.repo(col.valueType);
388
391
  let toLoad = [];
@@ -391,7 +394,7 @@ export class RepositoryImplementation {
391
394
  if (val !== undefined &&
392
395
  val !== null &&
393
396
  !toLoad.includes(val) &&
394
- !repo.idCache.has(val)) {
397
+ !repo.idCache.has(val + '')) {
395
398
  toLoad.push(val);
396
399
  }
397
400
  }
@@ -417,7 +420,7 @@ export class RepositoryImplementation {
417
420
  let rel = getRelationInfo(col.options);
418
421
  let incl = col.options
419
422
  .defaultIncluded;
420
- if (loadOptions?.include) {
423
+ if (loadOptions?.include?.[col.key] !== undefined) {
421
424
  incl = loadOptions.include[col.key];
422
425
  }
423
426
  if (rel && incl) {
@@ -439,7 +442,7 @@ export class RepositoryImplementation {
439
442
  row[col.key] =
440
443
  rel.type !== 'toMany'
441
444
  ? result.length == 0
442
- ? undefined
445
+ ? null
443
446
  : result[0]
444
447
  : result;
445
448
  });
@@ -455,7 +458,7 @@ export class RepositoryImplementation {
455
458
  let where = [];
456
459
  let findOptions = {};
457
460
  let findOptionsSources = [];
458
- const options = field.options;
461
+ let options = field.options;
459
462
  if (typeof options.findOptions === 'function') {
460
463
  findOptionsSources.push(options.findOptions(row));
461
464
  }
@@ -477,11 +480,54 @@ export class RepositoryImplementation {
477
480
  findOptions[key] = source[key];
478
481
  }
479
482
  }
483
+ function buildError(what) {
484
+ return Error(`Error for relation: "${field.key}" to "${otherRepo.metadata.key}": ` +
485
+ what);
486
+ }
487
+ let hasFields = () => options.field || options.fields;
488
+ if (rel.type === 'toMany' && !hasFields()) {
489
+ for (const fieldInOtherRepo of otherRepo.fields.toArray()) {
490
+ if (!hasFields()) {
491
+ const reverseRel = getRelationInfo(fieldInOtherRepo.options);
492
+ const relOp = fieldInOtherRepo.options;
493
+ if (reverseRel)
494
+ if (reverseRel.toType() === this.entity)
495
+ if (reverseRel.type === 'reference') {
496
+ options = { ...findOptions, field: fieldInOtherRepo.key };
497
+ }
498
+ else if (reverseRel.type === 'toOne') {
499
+ if (relOp.field) {
500
+ options = { ...options, field: relOp.field };
501
+ }
502
+ else if (relOp.fields) {
503
+ let fields = {};
504
+ for (const key in relOp.fields) {
505
+ if (Object.prototype.hasOwnProperty.call(relOp.fields, key)) {
506
+ const keyInMyTable = relOp.fields[key];
507
+ fields[keyInMyTable] = key;
508
+ }
509
+ }
510
+ options = { ...options, fields };
511
+ }
512
+ }
513
+ }
514
+ }
515
+ if (!hasFields())
516
+ throw buildError(`No matching field found on target. Please specify field/fields`);
517
+ }
518
+ function requireField(field, meta) {
519
+ const result = meta.fields.find(field);
520
+ if (!result)
521
+ throw buildError(`Field "${field}" was not found in "${meta.key}".`);
522
+ return result;
523
+ }
480
524
  if (options.field) {
481
525
  if (rel.type === 'toOne') {
526
+ requireField(options.field, this.metadata);
482
527
  where.push(otherRepo.metadata.idMetadata.getIdFilter(row[options.field]));
483
528
  }
484
529
  else {
530
+ requireField(options.field, otherRepo.metadata);
485
531
  where.push({
486
532
  [options.field]: this.metadata.idMetadata.getId(row),
487
533
  });
@@ -490,13 +536,15 @@ export class RepositoryImplementation {
490
536
  else if (options.fields) {
491
537
  for (const key in options.fields) {
492
538
  if (Object.prototype.hasOwnProperty.call(options.fields, key)) {
539
+ requireField(options.fields[key], this.metadata);
540
+ requireField(key, otherRepo.metadata);
493
541
  where.push({ [key]: row[options.fields[key]] });
494
542
  }
495
543
  }
496
544
  }
497
545
  else if (rel.type === 'toOne' || rel.type === 'reference') {
498
546
  let val = rel.type === 'reference'
499
- ? getEntityRef(row).fields.find(field.key).getId()
547
+ ? getEntityRef(row).fields.find(requireField(field.key, this.metadata)).getId()
500
548
  : row[field.key];
501
549
  if (val === null)
502
550
  returnNull = true;
@@ -741,6 +789,7 @@ class rowHelperBase {
741
789
  columnsInfo;
742
790
  instance;
743
791
  remult;
792
+ isNewRow;
744
793
  _error;
745
794
  get error() {
746
795
  this._subscribers?.reportObserved();
@@ -750,10 +799,11 @@ class rowHelperBase {
750
799
  this._error = val;
751
800
  this._subscribers?.reportChanged();
752
801
  }
753
- constructor(columnsInfo, instance, remult) {
802
+ constructor(columnsInfo, instance, remult, isNewRow) {
754
803
  this.columnsInfo = columnsInfo;
755
804
  this.instance = instance;
756
805
  this.remult = remult;
806
+ this.isNewRow = isNewRow;
757
807
  {
758
808
  let fac = remult;
759
809
  if (fac != null && fac.remultFactory) {
@@ -796,7 +846,38 @@ class rowHelperBase {
796
846
  });
797
847
  lookup.set(val);
798
848
  }
799
- else {
849
+ else if (getRelationInfo(col)?.type === 'toOne') {
850
+ let hasVal = instance.hasOwnProperty(col.key);
851
+ let val = instance[col.key];
852
+ if (isNewRow && !val)
853
+ hasVal = false;
854
+ Object.defineProperty(instance, col.key, {
855
+ get: () => {
856
+ return val;
857
+ },
858
+ set: (newVal) => {
859
+ val = newVal;
860
+ if (newVal === undefined)
861
+ return;
862
+ const op = col;
863
+ if (op.field) {
864
+ this.instance[op.field] = this.remult
865
+ .repo(getRelationInfo(col).toType())
866
+ .metadata.idMetadata.getId(newVal);
867
+ }
868
+ if (op.fields) {
869
+ for (const key in op.fields) {
870
+ if (Object.prototype.hasOwnProperty.call(op.fields, key)) {
871
+ const element = op.fields[key];
872
+ this.instance[element] = newVal[key];
873
+ }
874
+ }
875
+ }
876
+ },
877
+ enumerable: true,
878
+ });
879
+ if (hasVal)
880
+ instance[col.key] = val;
800
881
  }
801
882
  }
802
883
  }
@@ -922,7 +1003,9 @@ class rowHelperBase {
922
1003
  if (val !== undefined && val !== null)
923
1004
  val = col.valueConverter.fromJson(JSON.parse(JSON.stringify(val)));
924
1005
  }
925
- d[col.key] = val;
1006
+ const rel = getRelationInfo(col);
1007
+ if (!rel || rel.type === 'reference')
1008
+ d[col.key] = val;
926
1009
  }
927
1010
  return d;
928
1011
  }
@@ -956,7 +1039,7 @@ class rowHelperBase {
956
1039
  for (const col of this.columnsInfo) {
957
1040
  if (!this.remult ||
958
1041
  col.includeInApi === undefined ||
959
- this.remult.isAllowed(col.includeInApi)) {
1042
+ this.remult.isAllowedForInstance(this.instance, col.includeInApi)) {
960
1043
  let val;
961
1044
  let lu = this.lookups.get(col.key);
962
1045
  let disable = false;
@@ -985,13 +1068,14 @@ class rowHelperBase {
985
1068
  }
986
1069
  return result;
987
1070
  }
988
- async _updateEntityBasedOnApi(body) {
1071
+ async _updateEntityBasedOnApi(body, ignoreApiAllowed = false) {
989
1072
  let keys = Object.keys(body);
990
1073
  for (const col of this.columnsInfo) {
991
1074
  if (keys.includes(col.key))
992
1075
  if (col.includeInApi === undefined ||
993
- this.remult.isAllowed(col.includeInApi)) {
1076
+ this.remult.isAllowedForInstance(this.instance, col.includeInApi)) {
994
1077
  if (!this.remult ||
1078
+ ignoreApiAllowed ||
995
1079
  col.allowApiUpdate === undefined ||
996
1080
  this.remult.isAllowedForInstance(this.instance, col.allowApiUpdate)) {
997
1081
  let lu = this.lookups.get(col.key);
@@ -1011,7 +1095,7 @@ export class rowHelperImplementation extends rowHelperBase {
1011
1095
  edp;
1012
1096
  _isNew;
1013
1097
  constructor(info, instance, repository, edp, remult, _isNew) {
1014
- super(info.columnsInfo, instance, remult);
1098
+ super(info.columnsInfo, instance, remult, _isNew);
1015
1099
  this.info = info;
1016
1100
  this.repository = repository;
1017
1101
  this.edp = edp;
@@ -1033,6 +1117,9 @@ export class rowHelperImplementation extends rowHelperBase {
1033
1117
  if (Remult.entityRefInit)
1034
1118
  Remult.entityRefInit(this, instance);
1035
1119
  }
1120
+ get relations() {
1121
+ return this.repository.relations(this.instance);
1122
+ }
1036
1123
  get apiUpdateAllowed() {
1037
1124
  return this.remult.isAllowedForInstance(this.instance, this.metadata.options.allowApiUpdate);
1038
1125
  }
@@ -1104,12 +1191,15 @@ export class rowHelperImplementation extends rowHelperBase {
1104
1191
  // no need
1105
1192
  await this.__validateEntity();
1106
1193
  let doNotSave = false;
1107
- for (const col of this.fields) {
1108
- if (col.metadata.options.saving)
1109
- await col.metadata.options.saving(this.instance, col);
1110
- }
1111
- if (this.info.entityInfo.saving) {
1112
- await this.info.entityInfo.saving(this.instance, () => (doNotSave = true));
1194
+ let e = this.buildLifeCycleEvent(() => (doNotSave = true));
1195
+ if (!this.remult.dataProvider.isProxy) {
1196
+ for (const col of this.fields) {
1197
+ if (col.metadata.options.saving)
1198
+ await col.metadata.options.saving(this.instance, e, col);
1199
+ }
1200
+ if (this.info.entityInfo.saving) {
1201
+ await this.info.entityInfo.saving(this.instance, e);
1202
+ }
1113
1203
  }
1114
1204
  this.__assertValidity();
1115
1205
  let d = this.copyDataToObject();
@@ -1125,8 +1215,7 @@ export class rowHelperImplementation extends rowHelperBase {
1125
1215
  f.value = f.originalValue;
1126
1216
  }
1127
1217
  }
1128
- if (this.info.idMetadata.field instanceof CompoundIdField)
1129
- delete d.id;
1218
+ //if (this.info.idMetadata.field instanceof CompoundIdField) delete d.id
1130
1219
  let updatedRow;
1131
1220
  let isNew = this.isNew();
1132
1221
  try {
@@ -1157,12 +1246,14 @@ export class rowHelperImplementation extends rowHelperBase {
1157
1246
  }
1158
1247
  }
1159
1248
  await this.loadDataFrom(updatedRow);
1160
- if (this.info.entityInfo.saved)
1161
- await this.info.entityInfo.saved(this.instance);
1162
- if (this.repository.listeners)
1163
- for (const listener of this.repository.listeners.filter((x) => x.saved)) {
1164
- await listener.saved(this.instance, isNew);
1165
- }
1249
+ if (!this.remult.dataProvider.isProxy) {
1250
+ if (this.info.entityInfo.saved)
1251
+ await this.info.entityInfo.saved(this.instance, e);
1252
+ if (this.repository.listeners)
1253
+ for (const listener of this.repository.listeners.filter((x) => x.saved)) {
1254
+ await listener.saved(this.instance, isNew);
1255
+ }
1256
+ }
1166
1257
  await this.repository.remult.liveQueryPublisher.itemChanged(this.repository.metadata.key, [{ id: this.getId(), oldId: this.getOriginalId(), deleted: false }]);
1167
1258
  this.saveOriginalData();
1168
1259
  this._isNew = false;
@@ -1178,18 +1269,36 @@ export class rowHelperImplementation extends rowHelperBase {
1178
1269
  this._saving = false;
1179
1270
  }
1180
1271
  }
1272
+ buildLifeCycleEvent(preventDefault = () => { }) {
1273
+ const self = this;
1274
+ return {
1275
+ isNew: self.isNew(),
1276
+ fields: self.fields,
1277
+ id: self.getId(),
1278
+ originalId: self.getOriginalId(),
1279
+ metadata: self.repository.metadata,
1280
+ repository: self.repository,
1281
+ preventDefault: () => preventDefault(),
1282
+ relations: self.repository.relations(self.instance),
1283
+ };
1284
+ }
1181
1285
  getIdFilter() {
1182
1286
  return Filter.fromEntityFilter(this.metadata, this.repository.metadata.idMetadata.getIdFilter(this.id));
1183
1287
  }
1184
1288
  async delete() {
1185
1289
  this.__clearErrorsAndReportChanged();
1186
- if (this.info.entityInfo.deleting)
1187
- await this.info.entityInfo.deleting(this.instance);
1290
+ let e = this.buildLifeCycleEvent();
1291
+ if (!this.remult.dataProvider.isProxy) {
1292
+ if (this.info.entityInfo.deleting)
1293
+ await this.info.entityInfo.deleting(this.instance, e);
1294
+ }
1188
1295
  this.__assertValidity();
1189
1296
  try {
1190
1297
  await this.edp.delete(this.id);
1191
- if (this.info.entityInfo.deleted)
1192
- await this.info.entityInfo.deleted(this.instance);
1298
+ if (!this.remult.dataProvider.isProxy) {
1299
+ if (this.info.entityInfo.deleted)
1300
+ await this.info.entityInfo.deleted(this.instance, e);
1301
+ }
1193
1302
  if (this.repository.listeners)
1194
1303
  for (const listener of this.repository.listeners.filter((x) => x.deleted)) {
1195
1304
  await listener.deleted(this.instance);
@@ -1228,7 +1337,7 @@ export class rowHelperImplementation extends rowHelperBase {
1228
1337
  }
1229
1338
  async calcServerExpression() {
1230
1339
  if (isBackend())
1231
- //[ ] should be changed to be based on data provider
1340
+ //y2 should be changed to be based on data provider - consider naming
1232
1341
  for (const col of this.info.columnsInfo) {
1233
1342
  if (col.serverExpression) {
1234
1343
  this.instance[col.key] = await col.serverExpression(this.instance);
@@ -1254,8 +1363,10 @@ export class rowHelperImplementation extends rowHelperBase {
1254
1363
  await col.__performValidation();
1255
1364
  }
1256
1365
  }
1257
- if (this.info.entityInfo.validation)
1258
- await this.info.entityInfo.validation(this.instance, this);
1366
+ if (this.info.entityInfo.validation) {
1367
+ let e = this.buildLifeCycleEvent(() => { });
1368
+ await this.info.entityInfo.validation(this.instance, e);
1369
+ }
1259
1370
  if (this.repository.listeners)
1260
1371
  for (const listener of this.repository.listeners.filter((x) => x.validating)) {
1261
1372
  await listener.validating(this.instance);
@@ -1292,7 +1403,7 @@ export function getControllerRef(container, remultArg) {
1292
1403
  }
1293
1404
  export class controllerRefImpl extends rowHelperBase {
1294
1405
  constructor(columnsInfo, instance, remult) {
1295
- super(columnsInfo, instance, remult);
1406
+ super(columnsInfo, instance, remult, false);
1296
1407
  let _items = [];
1297
1408
  let r = {
1298
1409
  find: (c) => r[typeof c === 'string' ? c : c.key],
@@ -1526,10 +1637,10 @@ export class columnDefsImpl {
1526
1637
  .getEntityMetadataWithoutBreakingTheEntity(item)
1527
1638
  .fields.find(this.key).displayValue;
1528
1639
  }
1529
- get includedInApi() {
1640
+ includedInApi(item) {
1530
1641
  if (this.options.includeInApi === undefined)
1531
1642
  return true;
1532
- return this.remult.isAllowed(this.options.includeInApi); //TODO 2- consolidate other code paths to go through here
1643
+ return this.remult.isAllowedForInstance(item, this.options.includeInApi);
1533
1644
  }
1534
1645
  toInput(value, inputType) {
1535
1646
  return this.valueConverter.toInput(value, inputType);
@@ -1629,7 +1740,9 @@ class EntityFullInfo {
1629
1740
  this.fields = r;
1630
1741
  this.caption = buildCaption(entityInfo.caption, this.key, remult);
1631
1742
  if (entityInfo.id) {
1632
- let r = entityInfo.id(this.fields);
1743
+ let r = typeof entityInfo.id === 'function'
1744
+ ? entityInfo.id(this.fields)
1745
+ : Object.keys(entityInfo.id).map((x) => this.fields.find(x));
1633
1746
  if (Array.isArray(r)) {
1634
1747
  if (r.length > 1)
1635
1748
  this.idMetadata.field = new CompoundIdField(...r);
@@ -1703,6 +1816,8 @@ class EntityFullInfo {
1703
1816
  }
1704
1817
  idMetadata = {
1705
1818
  getId: (item) => {
1819
+ if (item === undefined || item === null)
1820
+ return item;
1706
1821
  const ref = getEntityRef(item, false);
1707
1822
  if (ref)
1708
1823
  return ref.getId();
@@ -2031,6 +2146,7 @@ class QueryResultImpl {
2031
2146
  limit: this.options.pageSize,
2032
2147
  page: page,
2033
2148
  load: this.options.load,
2149
+ include: this.options.include,
2034
2150
  });
2035
2151
  }
2036
2152
  async count() {
@@ -2055,6 +2171,7 @@ class QueryResultImpl {
2055
2171
  orderBy: this.options.orderBy,
2056
2172
  limit: this.options.pageSize,
2057
2173
  load: this.options.load,
2174
+ include: this.options.include,
2058
2175
  });
2059
2176
  let nextPage = undefined;
2060
2177
  let hasNextPage = items.length == this.options.pageSize;
@@ -1,6 +1,6 @@
1
1
  import type { Remult } from '../context';
2
2
  import type { EntityOptions } from '../entity';
3
- import type { ClassDecoratorContextStub } from './RepositoryImplementation';
3
+ import type { ClassDecoratorContextStub } from './remult3';
4
4
  /**Decorates classes that should be used as entities.
5
5
  * Receives a key and an array of EntityOptions.
6
6
  * @example
@@ -1,6 +1,5 @@
1
1
  import { allEntities, setControllerSettings } from '../context';
2
2
  import { entityInfo, entityInfo_key, getEntitySettings } from './getEntityRef';
3
- //[ ] YONI - in Typescript 5 I do get the name of the class, what would we like to change because of that?
4
3
  /**Decorates classes that should be used as entities.
5
4
  * Receives a key and an array of EntityOptions.
6
5
  * @example
@@ -5,5 +5,5 @@ export declare function getEntityRef<entityType>(entity: entityType, throwExcept
5
5
  export declare const entityMember: unique symbol;
6
6
  export declare const entityInfo: unique symbol;
7
7
  export declare const entityInfo_key: unique symbol;
8
- export declare function getEntitySettings<T>(entity: ClassType<T>, throwError?: boolean): EntityOptionsFactory;
8
+ export declare function getEntitySettings<T>(entity: ClassType<T>, throwError?: boolean): EntityOptionsFactory | undefined;
9
9
  export declare function getEntityKey(entity: ClassType<any>): string;
@@ -2,7 +2,7 @@ export function getEntityRef(entity, throwException = true) {
2
2
  let x = entity[entityMember];
3
3
  if (!x && throwException)
4
4
  throw new Error('item ' +
5
- entity.constructor.name +
5
+ (entity.constructor?.name || entity) +
6
6
  ' was not initialized using a context');
7
7
  return x;
8
8
  }
@@ -51,7 +51,10 @@ class QueryVariation {
51
51
  let w = this.whereVariations.get(whereKey);
52
52
  if (!w) {
53
53
  const keys = Object.keys(where);
54
- if (keys.length === 1 && typeof where[keys[0]] !== 'object') {
54
+ if (keys.length === 1 &&
55
+ typeof where[keys[0]] !== 'object' &&
56
+ !findOptions.limit // because merging calls in that case may bring non more rows than the limit
57
+ ) {
55
58
  let inVariation = this.pendingInStatements.get(keys[0]);
56
59
  if (!inVariation) {
57
60
  this.pendingInStatements.set(keys[0], (inVariation = new PendingInStatements(this.rel, keys[0], findOptions)));