remult 0.14.7 → 0.14.8

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 (152) hide show
  1. package/LICENSE +21 -0
  2. package/esm/assign.d.ts +1 -0
  3. package/esm/assign.js +5 -0
  4. package/esm/classType.d.ts +3 -0
  5. package/esm/classType.js +1 -0
  6. package/esm/graphql.d.ts +5 -0
  7. package/esm/graphql.js +102 -0
  8. package/esm/index.d.ts +36 -0
  9. package/esm/index.js +30 -0
  10. package/esm/inputTypes.d.ts +9 -0
  11. package/esm/inputTypes.js +9 -0
  12. package/esm/postgres/index.d.ts +2 -0
  13. package/esm/postgres/index.js +2 -0
  14. package/esm/postgres/postgres-data-provider.d.ts +28 -0
  15. package/esm/postgres/postgres-data-provider.js +97 -0
  16. package/esm/postgres/schema-builder.d.ts +15 -0
  17. package/esm/postgres/schema-builder.js +128 -0
  18. package/esm/remult-express.d.ts +5 -0
  19. package/esm/remult-express.js +16 -0
  20. package/esm/remult-knex/index.d.ts +51 -0
  21. package/esm/remult-knex/index.js +381 -0
  22. package/esm/remult-middleware.d.ts +2 -0
  23. package/esm/remult-middleware.js +63 -0
  24. package/esm/remult-mongo.d.ts +9 -0
  25. package/esm/remult-mongo.js +220 -0
  26. package/esm/server/JsonEntityFileStorage.d.ts +7 -0
  27. package/esm/server/JsonEntityFileStorage.js +20 -0
  28. package/esm/server/expressBridge.d.ts +140 -0
  29. package/esm/server/expressBridge.js +668 -0
  30. package/esm/server/index.d.ts +4 -0
  31. package/esm/server/index.js +4 -0
  32. package/esm/server/register-actions-on-server.d.ts +3 -0
  33. package/esm/server/register-actions-on-server.js +24 -0
  34. package/esm/server/register-entities-on-server.d.ts +3 -0
  35. package/esm/server/register-entities-on-server.js +15 -0
  36. package/esm/src/__EntityValueProvider.d.ts +10 -0
  37. package/esm/src/__EntityValueProvider.js +1 -0
  38. package/esm/src/__RowsOfDataForTesting.d.ts +3 -0
  39. package/esm/src/__RowsOfDataForTesting.js +1 -0
  40. package/esm/src/backend-tests/backend-database-test-setup.backend-spec.d.ts +5 -0
  41. package/esm/src/backend-tests/backend-database-test-setup.backend-spec.js +113 -0
  42. package/esm/src/backend-tests/my-test.backend-spec.d.ts +1 -0
  43. package/esm/src/backend-tests/my-test.backend-spec.js +49 -0
  44. package/esm/src/column-interfaces.d.ts +95 -0
  45. package/esm/src/column-interfaces.js +7 -0
  46. package/esm/src/column.d.ts +49 -0
  47. package/esm/src/column.js +133 -0
  48. package/esm/src/context.d.ts +124 -0
  49. package/esm/src/context.js +285 -0
  50. package/esm/src/data-api.d.ts +33 -0
  51. package/esm/src/data-api.js +204 -0
  52. package/esm/src/data-interfaces.d.ts +37 -0
  53. package/esm/src/data-interfaces.js +12 -0
  54. package/esm/src/data-providers/array-entity-data-provider.d.ts +22 -0
  55. package/esm/src/data-providers/array-entity-data-provider.js +264 -0
  56. package/esm/src/data-providers/in-memory-database.d.ts +9 -0
  57. package/esm/src/data-providers/in-memory-database.js +16 -0
  58. package/esm/src/data-providers/json-data-provider.d.ts +12 -0
  59. package/esm/src/data-providers/json-data-provider.js +52 -0
  60. package/esm/src/data-providers/rest-data-provider.d.ts +35 -0
  61. package/esm/src/data-providers/rest-data-provider.js +188 -0
  62. package/esm/src/data-providers/sql-database.d.ts +16 -0
  63. package/esm/src/data-providers/sql-database.js +261 -0
  64. package/esm/src/data-providers/web-sql-data-provider.d.ts +18 -0
  65. package/esm/src/data-providers/web-sql-data-provider.js +121 -0
  66. package/esm/src/entity.d.ts +82 -0
  67. package/esm/src/entity.js +1 -0
  68. package/esm/src/filter/filter-consumer-bridge-to-sql-request.d.ts +50 -0
  69. package/esm/src/filter/filter-consumer-bridge-to-sql-request.js +139 -0
  70. package/esm/src/filter/filter-consumer-bridge-to-url-builder.d.ts +1 -0
  71. package/esm/src/filter/filter-consumer-bridge-to-url-builder.js +1 -0
  72. package/esm/src/filter/filter-interfaces.d.ts +85 -0
  73. package/esm/src/filter/filter-interfaces.js +467 -0
  74. package/esm/src/id-entity.d.ts +4 -0
  75. package/esm/src/id-entity.js +8 -0
  76. package/esm/src/remult3/RepositoryImplementation.d.ts +326 -0
  77. package/esm/src/remult3/RepositoryImplementation.js +1806 -0
  78. package/esm/src/remult3/index.d.ts +2 -0
  79. package/esm/src/remult3/index.js +2 -0
  80. package/esm/src/remult3/remult3.d.ts +312 -0
  81. package/esm/src/remult3/remult3.js +1 -0
  82. package/esm/src/server-action.d.ts +70 -0
  83. package/esm/src/server-action.js +365 -0
  84. package/esm/src/shared-tests/db-tests-setup.d.ts +23 -0
  85. package/esm/src/shared-tests/db-tests-setup.js +66 -0
  86. package/esm/src/shared-tests/db-tests.db-tests.d.ts +26 -0
  87. package/esm/src/shared-tests/db-tests.db-tests.js +723 -0
  88. package/esm/src/shared-tests/deleteAll.d.ts +2 -0
  89. package/esm/src/shared-tests/deleteAll.js +4 -0
  90. package/esm/src/shared-tests/entityWithValidations.d.ts +14 -0
  91. package/esm/src/shared-tests/entityWithValidations.js +53 -0
  92. package/esm/src/shared-tests/index.d.ts +4 -0
  93. package/esm/src/shared-tests/index.js +4 -0
  94. package/esm/src/shared-tests/test-custom-id-column.spec.d.ts +1 -0
  95. package/esm/src/shared-tests/test-custom-id-column.spec.js +62 -0
  96. package/esm/src/shared-tests/test-special-value.spec.d.ts +10 -0
  97. package/esm/src/shared-tests/test-special-value.spec.js +88 -0
  98. package/esm/src/shared-tests/test-update-with-null.spec.d.ts +1 -0
  99. package/esm/src/shared-tests/test-update-with-null.spec.js +47 -0
  100. package/esm/src/sort.d.ts +15 -0
  101. package/esm/src/sort.js +82 -0
  102. package/esm/src/sql-command.d.ts +15 -0
  103. package/esm/src/sql-command.js +1 -0
  104. package/esm/src/tests/Done.d.ts +5 -0
  105. package/esm/src/tests/Done.js +11 -0
  106. package/esm/src/tests/TestDataApiResponse.d.ts +10 -0
  107. package/esm/src/tests/TestDataApiResponse.js +22 -0
  108. package/esm/src/tests/c.d.ts +8 -0
  109. package/esm/src/tests/c.js +22 -0
  110. package/esm/src/tests/createData.d.ts +7 -0
  111. package/esm/src/tests/createData.js +22 -0
  112. package/esm/src/tests/d.d.ts +6 -0
  113. package/esm/src/tests/d.js +19 -0
  114. package/esm/src/tests/dWithPrefilter.d.ts +7 -0
  115. package/esm/src/tests/dWithPrefilter.js +32 -0
  116. package/esm/src/tests/entityForCustomFilter.d.ts +16 -0
  117. package/esm/src/tests/entityForCustomFilter.js +44 -0
  118. package/esm/src/tests/entityWithValidationsOnColumn.d.ts +5 -0
  119. package/esm/src/tests/entityWithValidationsOnColumn.js +21 -0
  120. package/esm/src/tests/frontend-database-tests-setup.spec.d.ts +4 -0
  121. package/esm/src/tests/frontend-database-tests-setup.spec.js +38 -0
  122. package/esm/src/tests/h.d.ts +6 -0
  123. package/esm/src/tests/h.js +35 -0
  124. package/esm/src/tests/remult-3-entities.d.ts +23 -0
  125. package/esm/src/tests/remult-3-entities.js +72 -0
  126. package/esm/src/tests/tasks.d.ts +6 -0
  127. package/esm/src/tests/tasks.js +24 -0
  128. package/esm/src/tests/testHelper.spec.d.ts +34 -0
  129. package/esm/src/tests/testHelper.spec.js +217 -0
  130. package/esm/src/tests/testModel/models.d.ts +16 -0
  131. package/esm/src/tests/testModel/models.js +31 -0
  132. package/esm/src/validators.d.ts +14 -0
  133. package/esm/src/validators.js +33 -0
  134. package/esm/urlBuilder.d.ts +6 -0
  135. package/esm/urlBuilder.js +19 -0
  136. package/esm/valueConverters.d.ts +12 -0
  137. package/esm/valueConverters.js +169 -0
  138. package/index.d.ts +1 -0
  139. package/index.js +1 -0
  140. package/package.json +22 -1
  141. package/postgres/index.d.ts +1 -0
  142. package/postgres/index.js +1 -0
  143. package/postgres/postgres-data-provider.d.ts +1 -13
  144. package/postgres/postgres-data-provider.js +28 -262
  145. package/postgres/schema-builder.d.ts +15 -0
  146. package/postgres/schema-builder.js +270 -0
  147. package/readme.md +68 -30
  148. package/src/data-providers/web-sql-data-provider.js +4 -3
  149. package/src/entity.d.ts +9 -2
  150. package/src/remult3/RepositoryImplementation.js +11 -3
  151. package/src/shared-tests/test-update-with-null.spec.js +38 -0
  152. package/valueConverters.js +4 -0
@@ -0,0 +1,1806 @@
1
+ import { CompoundIdField, LookupColumn, makeTitle } from '../column';
2
+ import { allEntities, Remult, isBackend, queryConfig as queryConfig, setControllerSettings } from "../context";
3
+ import { entityFilterToJson, Filter } from "../filter/filter-interfaces";
4
+ import { Sort } from "../sort";
5
+ import { v4 as uuid } from 'uuid';
6
+ import { ValueConverters } from "../../valueConverters";
7
+ import { filterHelper } from "../filter/filter-interfaces";
8
+ import { assign } from "../../assign";
9
+ let classValidatorValidate = undefined;
10
+ // import("class-validator".toString())
11
+ // .then((v) => {
12
+ // classValidatorValidate = (item, ref) => {
13
+ // return v.validate(item).then(errors => {
14
+ // for (const err of errors) {
15
+ // for (const key in err.constraints) {
16
+ // if (Object.prototype.hasOwnProperty.call(err.constraints, key)) {
17
+ // const element = err.constraints[key];
18
+ // ref.fields.find(err.property).error = element;
19
+ // }
20
+ // }
21
+ // }
22
+ // });
23
+ // }
24
+ // })
25
+ // .catch(() => {
26
+ // });
27
+ export class RepositoryImplementation {
28
+ constructor(entity, remult, dataProvider) {
29
+ this.entity = entity;
30
+ this.remult = remult;
31
+ this.dataProvider = dataProvider;
32
+ this.idCache = new Map();
33
+ this.cache = new Map();
34
+ this._info = createOldEntity(entity, remult);
35
+ }
36
+ async createAfterFilter(orderBy, lastRow) {
37
+ let values = new Map();
38
+ for (const s of Sort.translateOrderByToSort(this.metadata, orderBy).Segments) {
39
+ let existingVal = lastRow[s.field.key];
40
+ // if (typeof existingVal !== "string" && typeof existingVal !== "number") {
41
+ // }
42
+ // else {
43
+ // let ei = getEntitySettings(s.field.valueType, false);
44
+ // if (ei) {
45
+ // existingVal = await this.remult.repo(s.field.valueType).findId(existingVal);
46
+ // }
47
+ // }
48
+ values.set(s.field.key, existingVal);
49
+ }
50
+ let r = { $or: [] };
51
+ let equalToColumn = [];
52
+ for (const s of Sort.translateOrderByToSort(this.metadata, orderBy).Segments) {
53
+ let ff = new filterHelper(s.field);
54
+ let f = {};
55
+ for (const c of equalToColumn) {
56
+ f[c.key] = values.get(c.key);
57
+ }
58
+ equalToColumn.push(s.field);
59
+ if (s.isDescending) {
60
+ f[s.field.key] = { $lt: values.get(s.field.key) };
61
+ }
62
+ else
63
+ f[s.field.key] = { $gt: values.get(s.field.key) };
64
+ r.$or.push(f);
65
+ }
66
+ return r;
67
+ }
68
+ get edp() {
69
+ return this.__edp ? this.__edp : this.__edp = this.dataProvider.getEntityDataProvider(this.metadata);
70
+ }
71
+ getCachedById(id) {
72
+ id = id + '';
73
+ this.getCachedByIdAsync(id);
74
+ let r = this.idCache.get(id);
75
+ if (r instanceof Promise)
76
+ return undefined;
77
+ return r;
78
+ }
79
+ async getCachedByIdAsync(id) {
80
+ id = id + '';
81
+ let r = this.idCache.get(id);
82
+ if (r instanceof Promise)
83
+ return await r;
84
+ if (this.idCache.has(id)) {
85
+ return r;
86
+ }
87
+ this.idCache.set(id, undefined);
88
+ let row = this.findId(id).then(row => {
89
+ if (row === undefined) {
90
+ r = null;
91
+ }
92
+ else
93
+ r = row;
94
+ this.idCache.set(id, r);
95
+ return r;
96
+ });
97
+ this.idCache.set(id, row);
98
+ return await row;
99
+ }
100
+ addToCache(item) {
101
+ if (item)
102
+ this.idCache.set(this.getEntityRef(item).getId() + '', item);
103
+ }
104
+ get metadata() { return this._info; }
105
+ ;
106
+ addEventListener(listener) {
107
+ if (!this.listeners)
108
+ this.listeners = [];
109
+ this.listeners.push(listener);
110
+ return () => {
111
+ this.listeners.splice(this.listeners.indexOf(listener), 1);
112
+ };
113
+ }
114
+ query(options) {
115
+ return new QueryResultImpl(options, this);
116
+ }
117
+ getEntityRef(entity) {
118
+ let x = entity[entityMember];
119
+ if (!x) {
120
+ x = new rowHelperImplementation(this._info, entity, this, this.edp, this.remult, true);
121
+ Object.defineProperty(entity, entityMember, {
122
+ get: () => x
123
+ });
124
+ x.saveOriginalData();
125
+ }
126
+ return x;
127
+ }
128
+ async delete(item) {
129
+ if (typeof item === "string" || typeof item === "number")
130
+ return this.edp.delete(item);
131
+ else {
132
+ return this.getRefForExistingRow(item, undefined).delete();
133
+ }
134
+ }
135
+ async insert(entity) {
136
+ if (Array.isArray(entity)) {
137
+ let r = [];
138
+ for (const item of entity) {
139
+ r.push(await this.insert(item));
140
+ }
141
+ return r;
142
+ }
143
+ else {
144
+ let ref = getEntityRef(entity, false);
145
+ if (ref) {
146
+ if (!ref.isNew())
147
+ throw "Item is not new";
148
+ return await ref.save();
149
+ }
150
+ else {
151
+ return await this.getEntityRef(this.create(entity)).save();
152
+ }
153
+ }
154
+ }
155
+ async update(id, entity) {
156
+ let ref = this.getRefForExistingRow(entity, id);
157
+ return (await ref.save());
158
+ }
159
+ getRefForExistingRow(entity, id) {
160
+ let ref = getEntityRef(entity, false);
161
+ if (!ref) {
162
+ const instance = new this.entity(this.remult);
163
+ for (const field of this.fieldsOf(entity)) {
164
+ instance[field.key] = entity[field.key];
165
+ }
166
+ let row = new rowHelperImplementation(this._info, instance, this, this.edp, this.remult, false);
167
+ if (id)
168
+ row.id = id;
169
+ else
170
+ row.id = row.getId();
171
+ ref = row;
172
+ Object.defineProperty(instance, entityMember, {
173
+ get: () => row
174
+ });
175
+ }
176
+ return ref;
177
+ }
178
+ async save(entity) {
179
+ if (Array.isArray(entity)) {
180
+ return Promise.all(entity.map(x => this.save(x)));
181
+ }
182
+ else {
183
+ let ref = getEntityRef(entity, false);
184
+ if (ref)
185
+ return await ref.save();
186
+ else if (entity instanceof EntityBase) {
187
+ return await this.getEntityRef(entity).save();
188
+ }
189
+ else {
190
+ let id = entity[this.metadata.idMetadata.field.key];
191
+ if (id === undefined)
192
+ return this.insert(entity);
193
+ return this.update(id, entity);
194
+ }
195
+ }
196
+ }
197
+ async find(options) {
198
+ Remult.onFind(this._info, options);
199
+ let opt = {};
200
+ if (!options)
201
+ options = {};
202
+ opt = {};
203
+ if (!options.orderBy || Object.keys(options.orderBy).length === 0) {
204
+ options.orderBy = this._info.entityInfo.defaultOrderBy;
205
+ }
206
+ opt.where = await this.translateWhereToFilter(options.where);
207
+ opt.orderBy = Sort.translateOrderByToSort(this.metadata, options.orderBy);
208
+ opt.limit = options.limit;
209
+ opt.page = options.page;
210
+ let rawRows = await this.edp.find(opt);
211
+ let loadFields = undefined;
212
+ if (options.load)
213
+ loadFields = options.load(this.metadata.fields);
214
+ for (const col of this.metadata.fields) {
215
+ let ei = getEntitySettings(col.valueType, false);
216
+ if (ei) {
217
+ let load = !col.options.lazy;
218
+ if (loadFields !== undefined)
219
+ load = loadFields.includes(col);
220
+ if (load) {
221
+ let repo = this.remult.repo(col.valueType);
222
+ let toLoad = [];
223
+ for (const r of rawRows) {
224
+ let val = r[col.key];
225
+ if (val !== undefined && val !== null && !toLoad.includes(val) && !repo.idCache.has(val)) {
226
+ toLoad.push(val);
227
+ }
228
+ }
229
+ if (toLoad.length > 0) {
230
+ await loadManyToOne(repo, toLoad);
231
+ }
232
+ }
233
+ }
234
+ }
235
+ let result = await Promise.all(rawRows.map(async (r) => await this.mapRawDataToResult(r, loadFields)));
236
+ return result;
237
+ async function loadManyToOne(repo, toLoad) {
238
+ let rows = await repo.find({ where: repo.metadata.idMetadata.getIdFilter(...toLoad) });
239
+ for (const r of rows) {
240
+ repo.addToCache(r);
241
+ }
242
+ }
243
+ }
244
+ async mapRawDataToResult(r, loadFields) {
245
+ if (!r)
246
+ return undefined;
247
+ let x = new this.entity(this.remult);
248
+ let helper = new rowHelperImplementation(this._info, x, this, this.edp, this.remult, false);
249
+ Object.defineProperty(x, entityMember, {
250
+ get: () => helper
251
+ });
252
+ await helper.loadDataFrom(r, loadFields);
253
+ helper.saveOriginalData();
254
+ return x;
255
+ }
256
+ async count(where) {
257
+ return this.edp.count(await this.translateWhereToFilter(where));
258
+ }
259
+ async findFirst(where, options) {
260
+ if (!options)
261
+ options = {};
262
+ if (where) {
263
+ if (options.where) {
264
+ let w = options.where;
265
+ options.where = {
266
+ $and: [
267
+ w,
268
+ where
269
+ ]
270
+ };
271
+ }
272
+ else
273
+ options.where = where;
274
+ }
275
+ let r;
276
+ let cacheInfo;
277
+ if (options.useCache) {
278
+ let f = await entityFilterToJson(this.metadata, options.where);
279
+ let key = JSON.stringify(f);
280
+ cacheInfo = this.cache.get(key);
281
+ if (cacheInfo !== undefined) {
282
+ if (cacheInfo.value && this.getEntityRef(cacheInfo.value).wasDeleted()) {
283
+ cacheInfo = undefined;
284
+ this.cache.delete(key);
285
+ }
286
+ else
287
+ return this.cache.get(key).promise;
288
+ }
289
+ else {
290
+ cacheInfo = {
291
+ value: undefined,
292
+ promise: undefined
293
+ };
294
+ this.cache.set(key, cacheInfo);
295
+ }
296
+ }
297
+ r = this.find({ ...options, limit: 1 }).then(async (items) => {
298
+ let r = undefined;
299
+ if (items.length > 0)
300
+ r = items[0];
301
+ if (!r && options.createIfNotFound) {
302
+ r = this.create();
303
+ if (options.where) {
304
+ await __updateEntityBasedOnWhere(this.metadata, options.where, r);
305
+ }
306
+ }
307
+ return r;
308
+ });
309
+ if (cacheInfo) {
310
+ cacheInfo.promise = r = r.then(r => {
311
+ cacheInfo.value = r;
312
+ return r;
313
+ });
314
+ }
315
+ return r;
316
+ }
317
+ fieldsOf(item) {
318
+ let keys = Object.keys(item);
319
+ return this.metadata.fields.toArray().filter(x => keys.includes(x.key));
320
+ }
321
+ create(item) {
322
+ let r = new this.entity(this.remult);
323
+ if (item)
324
+ for (const field of this.fieldsOf(item)) {
325
+ r[field.key] = item[field.key];
326
+ }
327
+ let z = this.getEntityRef(r);
328
+ return r;
329
+ }
330
+ async fromJson(json, newRow) {
331
+ let obj = {};
332
+ for (const col of this.fieldsOf(json)) {
333
+ if (json[col.key] !== undefined) {
334
+ obj[col.key] = col.valueConverter.fromJson(json[col.key]);
335
+ }
336
+ }
337
+ if (newRow) {
338
+ let r = this.create();
339
+ let helper = this.getEntityRef(r);
340
+ await helper.loadDataFrom(obj);
341
+ return r;
342
+ }
343
+ else
344
+ return this.mapRawDataToResult(obj, undefined);
345
+ }
346
+ findId(id, options) {
347
+ if (id === null || id === undefined)
348
+ return null;
349
+ if (typeof id !== "string" && typeof id !== "number")
350
+ throw new Error("id can be either number or string, but got: " + typeof (id));
351
+ return this.findFirst({}, {
352
+ useCache: true,
353
+ ...options,
354
+ where: this.metadata.idMetadata.getIdFilter(id),
355
+ });
356
+ }
357
+ async translateWhereToFilter(where) {
358
+ if (this.metadata.options.backendPrefilter && isBackend()) {
359
+ let z = where;
360
+ where = {
361
+ $and: [
362
+ z, await Filter.resolve(this.metadata.options.backendPrefilter)
363
+ ]
364
+ };
365
+ }
366
+ let r = await Filter.fromEntityFilter(this.metadata, where);
367
+ if (r && !this.dataProvider.supportsCustomFilter) {
368
+ r = await Filter.translateCustomWhere(r, this.metadata, this.remult);
369
+ }
370
+ return r;
371
+ }
372
+ }
373
+ export function __updateEntityBasedOnWhere(entityDefs, where, r) {
374
+ let w = Filter.fromEntityFilter(entityDefs, where);
375
+ const emptyFunction = () => { };
376
+ if (w) {
377
+ w.__applyToConsumer({
378
+ custom: emptyFunction,
379
+ databaseCustom: emptyFunction,
380
+ containsCaseInsensitive: emptyFunction,
381
+ isDifferentFrom: emptyFunction,
382
+ isEqualTo: (col, val) => {
383
+ r[col.key] = val;
384
+ },
385
+ isGreaterOrEqualTo: emptyFunction,
386
+ isGreaterThan: emptyFunction,
387
+ isIn: emptyFunction,
388
+ isLessOrEqualTo: emptyFunction,
389
+ isLessThan: emptyFunction,
390
+ isNotNull: emptyFunction,
391
+ isNull: emptyFunction,
392
+ or: emptyFunction
393
+ });
394
+ }
395
+ }
396
+ export const entityInfo = Symbol("entityInfo");
397
+ export const entityInfo_key = Symbol("entityInfo_key");
398
+ const entityMember = Symbol("entityMember");
399
+ export function getEntitySettings(entity, throwError = true) {
400
+ if (entity === undefined)
401
+ if (throwError) {
402
+ throw new Error("Undefined is not an entity :)");
403
+ }
404
+ else
405
+ return undefined;
406
+ let info = Reflect.getMetadata(entityInfo, entity);
407
+ if (!info && throwError)
408
+ throw new Error(entity.prototype.constructor.name + " is not a known entity, did you forget to set @Entity() or did you forget to add the '@' before the call to Entity?");
409
+ return info;
410
+ }
411
+ export function getEntityKey(entity) {
412
+ return Reflect.getMetadata(entityInfo_key, entity);
413
+ }
414
+ export const columnsOfType = new Map();
415
+ export function createOldEntity(entity, remult) {
416
+ let r = columnsOfType.get(entity);
417
+ if (!r)
418
+ columnsOfType.set(entity, r = []);
419
+ let info = getEntitySettings(entity)(remult);
420
+ let key = getEntityKey(entity);
421
+ let base = Object.getPrototypeOf(entity);
422
+ while (base != null) {
423
+ let baseCols = columnsOfType.get(base);
424
+ if (baseCols) {
425
+ r.unshift(...baseCols.filter(x => !r.find(y => y.key == x.key)));
426
+ }
427
+ let baseSettingsFactory = getEntitySettings(base, false);
428
+ if (baseSettingsFactory) {
429
+ let baseSettings = baseSettingsFactory(remult);
430
+ info = { ...baseSettings, ...info };
431
+ let functions = ["saving", "saved", "deleting", "deleted", "validation"];
432
+ for (const key of functions) {
433
+ if (baseSettings[key] && baseSettings[key] !== info[key]) {
434
+ let x = info[key];
435
+ info[key] = async (a, b) => {
436
+ await x(a, b);
437
+ await baseSettings[key](a, b);
438
+ };
439
+ }
440
+ }
441
+ }
442
+ base = Object.getPrototypeOf(base);
443
+ }
444
+ return new EntityFullInfo(prepareColumnInfo(r, remult), info, remult, entity, key);
445
+ }
446
+ class rowHelperBase {
447
+ constructor(columnsInfo, instance, remult) {
448
+ this.columnsInfo = columnsInfo;
449
+ this.instance = instance;
450
+ this.remult = remult;
451
+ this._isLoading = false;
452
+ this.lookups = new Map();
453
+ this.originalValues = {};
454
+ for (const col of columnsInfo) {
455
+ let ei = getEntitySettings(col.valueType, false);
456
+ if (ei && remult) {
457
+ let lookup = new LookupColumn(remult.repo(col.valueType), undefined);
458
+ this.lookups.set(col.key, lookup);
459
+ let val = instance[col.key];
460
+ let refImpl;
461
+ Object.defineProperty(instance, col.key, {
462
+ get: () => {
463
+ if (this._subscribers) {
464
+ this._subscribers.reportObserved();
465
+ if (!refImpl) {
466
+ refImpl = this.fields.find(col.key);
467
+ if (!refImpl._subscribers) {
468
+ refImpl._subscribers = new SubscribableImp();
469
+ }
470
+ }
471
+ refImpl._subscribers.reportObserved();
472
+ }
473
+ return lookup.item;
474
+ },
475
+ set: (val) => {
476
+ lookup.set(val);
477
+ this._subscribers?.reportChanged();
478
+ if (!refImpl) {
479
+ refImpl = this.fields.find(col.key);
480
+ if (!refImpl._subscribers) {
481
+ refImpl._subscribers = new SubscribableImp();
482
+ }
483
+ }
484
+ refImpl._subscribers.reportChanged();
485
+ },
486
+ enumerable: true
487
+ });
488
+ lookup.set(val);
489
+ }
490
+ else {
491
+ }
492
+ }
493
+ }
494
+ get error() {
495
+ this._subscribers?.reportObserved();
496
+ return this._error;
497
+ }
498
+ set error(val) {
499
+ this._error = val;
500
+ this._subscribers?.reportChanged();
501
+ }
502
+ subscribe(listener) {
503
+ this.initSubscribers();
504
+ return this._subscribers.subscribe(listener);
505
+ }
506
+ initSubscribers() {
507
+ if (!this._subscribers) {
508
+ this._subscribers = new SubscribableImp();
509
+ ;
510
+ for (const col of this.columnsInfo) {
511
+ let ei = getEntitySettings(col.valueType, false);
512
+ let refImpl = this.fields.find(col.key);
513
+ refImpl._subscribers = new SubscribableImp();
514
+ if (ei && this.remult) {
515
+ }
516
+ else {
517
+ let val = this.instance[col.key];
518
+ Object.defineProperty(this.instance, col.key, {
519
+ get: () => {
520
+ this._subscribers.reportObserved();
521
+ refImpl._subscribers.reportObserved();
522
+ return val;
523
+ },
524
+ set: (value) => {
525
+ val = value;
526
+ this._subscribers.reportChanged();
527
+ refImpl._subscribers.reportChanged();
528
+ },
529
+ enumerable: true
530
+ });
531
+ }
532
+ }
533
+ }
534
+ }
535
+ get isLoading() {
536
+ this._subscribers?.reportObserved();
537
+ return this._isLoading;
538
+ }
539
+ set isLoading(val) {
540
+ this._isLoading = val;
541
+ this._subscribers?.reportChanged();
542
+ }
543
+ async waitLoad() {
544
+ await Promise.all([...this.lookups.values()].map(x => x.waitLoad()));
545
+ }
546
+ __assertValidity() {
547
+ if (!this.hasErrors()) {
548
+ let error = {
549
+ modelState: Object.assign({}, this.errors),
550
+ message: this.error
551
+ };
552
+ if (!error.message) {
553
+ for (const col of this.columnsInfo) {
554
+ if (this.errors[col.key]) {
555
+ error.message = this.fields[col.key].metadata.caption + ": " + this.errors[col.key];
556
+ this.error = error.message;
557
+ break;
558
+ }
559
+ }
560
+ }
561
+ throw error;
562
+ }
563
+ }
564
+ catchSaveErrors(err) {
565
+ let e = err;
566
+ if (e instanceof Promise) {
567
+ return e.then(x => this.catchSaveErrors(x));
568
+ }
569
+ if (e.error) {
570
+ e = e.error;
571
+ }
572
+ if (e.message)
573
+ this.error = e.message;
574
+ else if (e.Message)
575
+ this.error = e.Message;
576
+ else
577
+ this.error = e;
578
+ let s = e.modelState;
579
+ if (!s)
580
+ s = e.ModelState;
581
+ if (s) {
582
+ this.errors = s;
583
+ }
584
+ throw err;
585
+ }
586
+ __clearErrorsAndReportChanged() {
587
+ this.errors = undefined;
588
+ this.error = undefined;
589
+ this._reportChangedToEntityAndFields();
590
+ }
591
+ _reportChangedToEntityAndFields() {
592
+ if (this._subscribers) {
593
+ this._subscribers.reportChanged();
594
+ for (const field of this.fields) {
595
+ let ref = field;
596
+ ref._subscribers.reportChanged();
597
+ }
598
+ }
599
+ }
600
+ hasErrors() {
601
+ this._subscribers?.reportObserved();
602
+ return !!!this.error && this.errors == undefined;
603
+ }
604
+ copyDataToObject() {
605
+ let d = {};
606
+ for (const col of this.columnsInfo) {
607
+ let lu = this.lookups.get(col.key);
608
+ let val = undefined;
609
+ if (lu)
610
+ val = lu.id;
611
+ else
612
+ val = this.instance[col.key];
613
+ if (val !== undefined) {
614
+ val = col.valueConverter.toJson(val);
615
+ if (val !== undefined && val !== null)
616
+ val = col.valueConverter.fromJson(JSON.parse(JSON.stringify(val)));
617
+ }
618
+ d[col.key] = val;
619
+ }
620
+ return d;
621
+ }
622
+ saveOriginalData() {
623
+ this.originalValues = this.copyDataToObject();
624
+ }
625
+ async validate() {
626
+ this.__clearErrorsAndReportChanged();
627
+ if (classValidatorValidate)
628
+ await classValidatorValidate(this.instance, this);
629
+ await this.__performColumnAndEntityValidations();
630
+ let r = this.hasErrors();
631
+ return r;
632
+ }
633
+ async __validateEntity() {
634
+ this.__clearErrorsAndReportChanged();
635
+ if (classValidatorValidate)
636
+ await classValidatorValidate(this.instance, this);
637
+ await this.__performColumnAndEntityValidations();
638
+ this.__assertValidity();
639
+ }
640
+ async __performColumnAndEntityValidations() {
641
+ }
642
+ toApiJson() {
643
+ let result = {};
644
+ for (const col of this.columnsInfo) {
645
+ if (!this.remult || col.includeInApi === undefined || this.remult.isAllowed(col.includeInApi)) {
646
+ let val;
647
+ let lu = this.lookups.get(col.key);
648
+ if (lu)
649
+ val = lu.id;
650
+ else {
651
+ val = this.instance[col.key];
652
+ if (!this.remult) {
653
+ if (val) {
654
+ let eo = getEntitySettings(val.constructor, false);
655
+ if (eo) {
656
+ val = getEntityRef(val).getId();
657
+ }
658
+ }
659
+ }
660
+ }
661
+ result[col.key] = col.valueConverter.toJson(val);
662
+ }
663
+ }
664
+ return result;
665
+ }
666
+ async _updateEntityBasedOnApi(body) {
667
+ let keys = Object.keys(body);
668
+ for (const col of this.columnsInfo) {
669
+ if (keys.includes(col.key))
670
+ if (col.includeInApi === undefined || this.remult.isAllowed(col.includeInApi)) {
671
+ if (!this.remult || col.allowApiUpdate === undefined || this.remult.isAllowedForInstance(this.instance, col.allowApiUpdate)) {
672
+ let lu = this.lookups.get(col.key);
673
+ if (lu)
674
+ lu.id = body[col.key];
675
+ else
676
+ this.instance[col.key] = col.valueConverter.fromJson(body[col.key]);
677
+ }
678
+ }
679
+ }
680
+ await Promise.all([...this.fields].map(x => x.load()));
681
+ }
682
+ }
683
+ export class rowHelperImplementation extends rowHelperBase {
684
+ constructor(info, instance, repository, edp, remult, _isNew) {
685
+ super(info.columnsInfo, instance, remult);
686
+ this.info = info;
687
+ this.repository = repository;
688
+ this.edp = edp;
689
+ this._isNew = _isNew;
690
+ this._wasDeleted = false;
691
+ this._saving = false;
692
+ this.metadata = info;
693
+ if (_isNew) {
694
+ for (const col of info.columnsInfo) {
695
+ if (col.defaultValue) {
696
+ if (typeof col.defaultValue === "function") {
697
+ instance[col.key] = col.defaultValue(instance);
698
+ }
699
+ else if (!instance[col.key])
700
+ instance[col.key] = col.defaultValue;
701
+ }
702
+ }
703
+ }
704
+ if (this.info.options.entityRefInit)
705
+ this.info.options.entityRefInit(this, instance);
706
+ if (Remult.entityRefInit)
707
+ Remult.entityRefInit(this, instance);
708
+ }
709
+ get apiUpdateAllowed() { return this.remult.isAllowedForInstance(this.instance, this.metadata.options.allowApiUpdate); }
710
+ get apiDeleteAllowed() { return this.remult.isAllowedForInstance(this.instance, this.metadata.options.allowApiDelete); }
711
+ get apiInsertAllowed() { return this.remult.isAllowedForInstance(this.instance, this.metadata.options.allowApiInsert); }
712
+ getId() {
713
+ if (this.info.idMetadata.field instanceof CompoundIdField)
714
+ return this.info.idMetadata.field.getId(this.instance);
715
+ else
716
+ return this.instance[this.info.idMetadata.field.key];
717
+ }
718
+ wasDeleted() {
719
+ this._subscribers?.reportObserved();
720
+ return this._wasDeleted;
721
+ }
722
+ undoChanges() {
723
+ this.loadDataFrom(this.originalValues);
724
+ this.__clearErrorsAndReportChanged();
725
+ }
726
+ async reload() {
727
+ await this.edp.find({ where: this.getIdFilter() }).then(async (newData) => {
728
+ await this.loadDataFrom(newData[0]);
729
+ this.saveOriginalData();
730
+ });
731
+ this._reportChangedToEntityAndFields();
732
+ return this.instance;
733
+ }
734
+ get fields() {
735
+ if (!this._columns) {
736
+ let _items = [];
737
+ let r = {
738
+ find: (c) => r[typeof c === "string" ? c : c.key],
739
+ [Symbol.iterator]: () => _items[Symbol.iterator](),
740
+ toArray: () => _items
741
+ };
742
+ for (const c of this.info.columnsInfo) {
743
+ _items.push(r[c.key] = new FieldRefImplementation(c, this.info.fields[c.key], this.instance, this, this));
744
+ }
745
+ this._columns = r;
746
+ }
747
+ return this._columns;
748
+ }
749
+ async save() {
750
+ try {
751
+ if (this._saving)
752
+ throw new Error("cannot save while entity is already saving");
753
+ this._saving = true;
754
+ if (this.wasDeleted())
755
+ throw new Error("cannot save a deleted row");
756
+ this.isLoading = true;
757
+ await this.__validateEntity();
758
+ let doNotSave = false;
759
+ for (const col of this.fields) {
760
+ if (col.metadata.options.saving)
761
+ await col.metadata.options.saving(this.instance, col);
762
+ }
763
+ if (this.info.entityInfo.saving) {
764
+ await this.info.entityInfo.saving(this.instance, () => doNotSave = true);
765
+ }
766
+ this.__assertValidity();
767
+ let d = this.copyDataToObject();
768
+ let ignoreKeys = [];
769
+ for (const field of this.metadata.fields) {
770
+ if (field.dbReadOnly) {
771
+ d[field.key] = undefined;
772
+ ignoreKeys.push(field.key);
773
+ let f = this.fields.find(field);
774
+ f.value = f.originalValue;
775
+ }
776
+ }
777
+ if (this.info.idMetadata.field instanceof CompoundIdField)
778
+ delete (d.id);
779
+ let updatedRow;
780
+ try {
781
+ this._subscribers?.reportChanged();
782
+ if (this.isNew()) {
783
+ updatedRow = await this.edp.insert(d);
784
+ }
785
+ else {
786
+ let changesOnly = {};
787
+ let wasChanged = false;
788
+ for (const key in d) {
789
+ if (Object.prototype.hasOwnProperty.call(d, key)) {
790
+ const element = d[key];
791
+ if (this.fields.find(key).valueChanged() && !ignoreKeys.includes(key)) {
792
+ changesOnly[key] = element;
793
+ wasChanged = true;
794
+ }
795
+ }
796
+ }
797
+ if (!wasChanged)
798
+ return this.instance;
799
+ if (doNotSave) {
800
+ updatedRow = (await this.edp.find({ where: this.getIdFilter() }))[0];
801
+ }
802
+ else {
803
+ updatedRow = await this.edp.update(this.id, changesOnly);
804
+ }
805
+ }
806
+ await this.loadDataFrom(updatedRow);
807
+ if (this.info.entityInfo.saved)
808
+ await this.info.entityInfo.saved(this.instance);
809
+ this.saveOriginalData();
810
+ this._isNew = false;
811
+ return this.instance;
812
+ }
813
+ catch (err) {
814
+ await this.catchSaveErrors(err);
815
+ }
816
+ }
817
+ finally {
818
+ this.isLoading = false;
819
+ this._reportChangedToEntityAndFields();
820
+ this._saving = false;
821
+ }
822
+ }
823
+ getIdFilter() {
824
+ return Filter.fromEntityFilter(this.metadata, this.repository.metadata.idMetadata.getIdFilter(this.id));
825
+ }
826
+ async delete() {
827
+ this.__clearErrorsAndReportChanged();
828
+ if (this.info.entityInfo.deleting)
829
+ await this.info.entityInfo.deleting(this.instance);
830
+ this.__assertValidity();
831
+ try {
832
+ await this.edp.delete(this.id);
833
+ if (this.info.entityInfo.deleted)
834
+ await this.info.entityInfo.deleted(this.instance);
835
+ if (this.repository.listeners)
836
+ for (const listener of this.repository.listeners.filter(x => x.deleted)) {
837
+ await listener.deleted(this.instance);
838
+ }
839
+ this._wasDeleted = true;
840
+ }
841
+ catch (err) {
842
+ await this.catchSaveErrors(err);
843
+ }
844
+ }
845
+ async loadDataFrom(data, loadItems) {
846
+ for (const col of this.info.fields) {
847
+ let lu = this.lookups.get(col.key);
848
+ if (lu) {
849
+ lu.id = data[col.key];
850
+ if (loadItems === undefined) {
851
+ if (!col.options.lazy)
852
+ await lu.waitLoad();
853
+ }
854
+ else {
855
+ if (loadItems.includes(col))
856
+ await lu.waitLoad();
857
+ }
858
+ }
859
+ else
860
+ this.instance[col.key] = data[col.key];
861
+ }
862
+ await this.calcServerExpression();
863
+ if (this.repository.metadata.idMetadata.field instanceof CompoundIdField) {
864
+ this.id = this.repository.metadata.idMetadata.field.getId(this.instance);
865
+ }
866
+ else
867
+ this.id = data[this.repository.metadata.idMetadata.field.key];
868
+ }
869
+ getOriginalId() {
870
+ return this.id;
871
+ }
872
+ async calcServerExpression() {
873
+ if (isBackend())
874
+ for (const col of this.info.columnsInfo) {
875
+ if (col.serverExpression) {
876
+ this.instance[col.key] = await col.serverExpression(this.instance);
877
+ }
878
+ }
879
+ }
880
+ isNew() {
881
+ this._subscribers?.reportObserved();
882
+ return this._isNew;
883
+ }
884
+ wasChanged() {
885
+ this._subscribers?.reportObserved();
886
+ for (const col of this.fields) {
887
+ if (col.valueChanged())
888
+ return true;
889
+ }
890
+ return false;
891
+ }
892
+ async __performColumnAndEntityValidations() {
893
+ for (const c of this.columnsInfo) {
894
+ if (c.validate) {
895
+ let col = new FieldRefImplementation(c, this.info.fields[c.key], this.instance, this, this);
896
+ await col.__performValidation();
897
+ }
898
+ }
899
+ if (this.info.entityInfo.validation)
900
+ await this.info.entityInfo.validation(this.instance, this);
901
+ if (this.repository.listeners)
902
+ for (const listener of this.repository.listeners.filter(x => x.validating)) {
903
+ await listener.validating(this.instance);
904
+ }
905
+ }
906
+ }
907
+ const controllerColumns = Symbol("controllerColumns");
908
+ function prepareColumnInfo(r, remult) {
909
+ return r.map(x => decorateColumnSettings(x.settings(remult), remult));
910
+ }
911
+ export function getFields(container, remult) {
912
+ return getControllerRef(container, remult).fields;
913
+ }
914
+ export function getControllerRef(container, remult) {
915
+ let result = container[controllerColumns];
916
+ if (!result)
917
+ result = container[entityMember];
918
+ if (!result) {
919
+ let columnSettings = columnsOfType.get(container.constructor);
920
+ if (!columnSettings)
921
+ columnsOfType.set(container.constructor, columnSettings = []);
922
+ let base = Object.getPrototypeOf(container.constructor);
923
+ while (base != null) {
924
+ let baseCols = columnsOfType.get(base);
925
+ if (baseCols) {
926
+ columnSettings.unshift(...baseCols.filter(x => !columnSettings.find(y => y.key == x.key)));
927
+ }
928
+ base = Object.getPrototypeOf(base);
929
+ }
930
+ container[controllerColumns] = result = new controllerRefImpl(prepareColumnInfo(columnSettings, remult), container, remult);
931
+ }
932
+ return result;
933
+ }
934
+ export class controllerRefImpl extends rowHelperBase {
935
+ constructor(columnsInfo, instance, remult) {
936
+ super(columnsInfo, instance, remult);
937
+ let _items = [];
938
+ let r = {
939
+ find: (c) => r[typeof c === "string" ? c : c.key],
940
+ [Symbol.iterator]: () => _items[Symbol.iterator](),
941
+ toArray: () => _items
942
+ };
943
+ for (const col of columnsInfo) {
944
+ _items.push(r[col.key] = new FieldRefImplementation(col, new columnDefsImpl(col, undefined, remult), instance, undefined, this));
945
+ }
946
+ this.fields = r;
947
+ }
948
+ async __performColumnAndEntityValidations() {
949
+ for (const col of this.fields) {
950
+ if (col instanceof FieldRefImplementation) {
951
+ await col.__performValidation();
952
+ }
953
+ }
954
+ }
955
+ }
956
+ export class FieldRefImplementation {
957
+ constructor(settings, metadata, container, helper, rowBase) {
958
+ this.settings = settings;
959
+ this.metadata = metadata;
960
+ this.container = container;
961
+ this.helper = helper;
962
+ this.rowBase = rowBase;
963
+ this.target = this.settings.target;
964
+ this.entityRef = this.helper;
965
+ }
966
+ subscribe(listener) {
967
+ if (!this._subscribers) {
968
+ this.rowBase.initSubscribers();
969
+ }
970
+ return this._subscribers.subscribe(listener);
971
+ }
972
+ valueIsNull() {
973
+ this.reportObserved();
974
+ let lu = this.rowBase.lookups.get(this.metadata.key);
975
+ if (lu) {
976
+ return lu.id === undefined || lu.id === null;
977
+ }
978
+ return this.value === null;
979
+ }
980
+ originalValueIsNull() {
981
+ this.reportObserved();
982
+ let lu = this.rowBase.lookups.get(this.metadata.key);
983
+ return this.rawOriginalValue() === null;
984
+ }
985
+ async load() {
986
+ let lu = this.rowBase.lookups.get(this.metadata.key);
987
+ if (lu) {
988
+ if (this.valueChanged()) {
989
+ await lu.waitLoadOf(this.rawOriginalValue());
990
+ }
991
+ return await lu.waitLoad();
992
+ }
993
+ return this.value;
994
+ }
995
+ reportObserved() {
996
+ this._subscribers?.reportObserved();
997
+ this.rowBase._subscribers?.reportObserved();
998
+ }
999
+ reportChanged() {
1000
+ this._subscribers?.reportChanged();
1001
+ this.rowBase._subscribers?.reportChanged();
1002
+ }
1003
+ get error() {
1004
+ this.reportObserved();
1005
+ if (!this.rowBase.errors)
1006
+ return undefined;
1007
+ return this.rowBase.errors[this.metadata.key];
1008
+ }
1009
+ set error(error) {
1010
+ if (!this.rowBase.errors)
1011
+ this.rowBase.errors = {};
1012
+ this.rowBase.errors[this.metadata.key] = error;
1013
+ this.reportChanged();
1014
+ }
1015
+ get displayValue() {
1016
+ this.reportObserved();
1017
+ if (this.value != undefined) {
1018
+ if (this.settings.displayValue)
1019
+ return this.settings.displayValue(this.container, this.value);
1020
+ else if (this.metadata.valueConverter.displayValue)
1021
+ return this.metadata.valueConverter.displayValue(this.value);
1022
+ else
1023
+ return this.value.toString();
1024
+ }
1025
+ return "";
1026
+ }
1027
+ ;
1028
+ get value() { return this.container[this.metadata.key]; }
1029
+ ;
1030
+ set value(value) { this.container[this.metadata.key] = value; }
1031
+ ;
1032
+ get originalValue() {
1033
+ this.reportObserved();
1034
+ let lu = this.rowBase.lookups.get(this.metadata.key);
1035
+ if (lu)
1036
+ return lu.get(this.rawOriginalValue());
1037
+ return this.rowBase.originalValues[this.metadata.key];
1038
+ }
1039
+ ;
1040
+ rawOriginalValue() {
1041
+ return this.rowBase.originalValues[this.metadata.key];
1042
+ }
1043
+ setId(id) {
1044
+ this.value = id;
1045
+ }
1046
+ getId() {
1047
+ let lu = this.rowBase.lookups.get(this.metadata.key);
1048
+ if (lu)
1049
+ return lu.id != undefined ? lu.id : null;
1050
+ return this.value;
1051
+ }
1052
+ get inputValue() {
1053
+ this.reportObserved();
1054
+ let lu = this.rowBase.lookups.get(this.metadata.key);
1055
+ if (lu)
1056
+ return lu.id != undefined ? lu.id.toString() : null;
1057
+ return this.metadata.valueConverter.toInput(this.value, this.settings.inputType);
1058
+ }
1059
+ set inputValue(val) {
1060
+ let lu = this.rowBase.lookups.get(this.metadata.key);
1061
+ if (lu) {
1062
+ lu.setId(val);
1063
+ }
1064
+ else
1065
+ this.value = this.metadata.valueConverter.fromInput(val, this.settings.inputType);
1066
+ }
1067
+ ;
1068
+ valueChanged() {
1069
+ this.reportObserved();
1070
+ let val = this.value;
1071
+ let lu = this.rowBase.lookups.get(this.metadata.key);
1072
+ if (lu) {
1073
+ val = lu.id;
1074
+ }
1075
+ return JSON.stringify(this.metadata.valueConverter.toJson(this.rowBase.originalValues[this.metadata.key])) != JSON.stringify(this.metadata.valueConverter.toJson(val));
1076
+ }
1077
+ async __performValidation() {
1078
+ try {
1079
+ let x = typeof (this.settings.validate);
1080
+ if (Array.isArray(this.settings.validate)) {
1081
+ for (const v of this.settings.validate) {
1082
+ await v(this.container, this);
1083
+ }
1084
+ }
1085
+ else if (typeof this.settings.validate === 'function')
1086
+ await this.settings.validate(this.container, this);
1087
+ }
1088
+ catch (error) {
1089
+ if (typeof error === "string")
1090
+ this.error = error;
1091
+ else
1092
+ this.error = error.message;
1093
+ }
1094
+ }
1095
+ async validate() {
1096
+ await this.__performValidation();
1097
+ return !!!this.error;
1098
+ }
1099
+ }
1100
+ export function getEntityRef(entity, throwException = true) {
1101
+ let x = entity[entityMember];
1102
+ if (!x && throwException)
1103
+ throw new Error("item " + entity.constructor.name + " was not initialized using a context");
1104
+ return x;
1105
+ }
1106
+ export const CaptionTransformer = {
1107
+ transformCaption: (remult, key, caption) => caption
1108
+ };
1109
+ export function buildCaption(caption, key, remult) {
1110
+ let result;
1111
+ if (typeof (caption) === "function") {
1112
+ if (remult)
1113
+ result = caption(remult);
1114
+ }
1115
+ else if (caption)
1116
+ result = caption;
1117
+ result = CaptionTransformer.transformCaption(remult, key, result);
1118
+ if (result)
1119
+ return result;
1120
+ if (key)
1121
+ return makeTitle(key);
1122
+ return '';
1123
+ }
1124
+ export class columnDefsImpl {
1125
+ constructor(settings, entityDefs, remult) {
1126
+ this.settings = settings;
1127
+ this.entityDefs = entityDefs;
1128
+ this.options = this.settings;
1129
+ this.target = this.settings.target;
1130
+ this.valueConverter = this.settings.valueConverter;
1131
+ this.allowNull = !!this.settings.allowNull;
1132
+ this.inputType = this.settings.inputType;
1133
+ this.key = this.settings.key;
1134
+ this.valueType = this.settings.valueType;
1135
+ if (settings.serverExpression)
1136
+ this.isServerExpression = true;
1137
+ if (typeof (this.settings.allowApiUpdate) === "boolean")
1138
+ this.readonly = this.settings.allowApiUpdate;
1139
+ if (!this.inputType)
1140
+ this.inputType = this.valueConverter.inputType;
1141
+ this.caption = buildCaption(settings.caption, settings.key, remult);
1142
+ }
1143
+ getDbName() {
1144
+ if (this.dbNamePromise)
1145
+ return this.dbNamePromise;
1146
+ this.dbNamePromise = (async () => {
1147
+ if (this.settings.sqlExpression) {
1148
+ if (typeof this.settings.sqlExpression === "function") {
1149
+ return this.settings.sqlExpression(this.entityDefs);
1150
+ }
1151
+ else
1152
+ return this.settings.sqlExpression;
1153
+ }
1154
+ return this.settings.dbName;
1155
+ })().then(x => {
1156
+ if (x)
1157
+ return x;
1158
+ return this.settings.dbName;
1159
+ });
1160
+ return this.dbNamePromise;
1161
+ }
1162
+ get dbName() {
1163
+ let result;
1164
+ if (this.settings.sqlExpression) {
1165
+ if (typeof this.settings.sqlExpression === "function") {
1166
+ result = this.settings.sqlExpression(this.entityDefs);
1167
+ }
1168
+ else
1169
+ result = this.settings.sqlExpression;
1170
+ }
1171
+ if (result)
1172
+ return result;
1173
+ return this.settings.dbName;
1174
+ }
1175
+ get dbReadOnly() {
1176
+ return this.settings.dbReadOnly;
1177
+ }
1178
+ ;
1179
+ }
1180
+ class EntityFullInfo {
1181
+ constructor(columnsInfo, entityInfo, remult, entityType, key) {
1182
+ this.columnsInfo = columnsInfo;
1183
+ this.entityInfo = entityInfo;
1184
+ this.remult = remult;
1185
+ this.entityType = entityType;
1186
+ this.key = key;
1187
+ this.options = this.entityInfo;
1188
+ this.idMetadata = {
1189
+ field: undefined,
1190
+ createIdInFilter: (items) => {
1191
+ if (items.length > 0)
1192
+ return {
1193
+ $or: items.map(x => this.idMetadata.getIdFilter(getEntityRef(x).getId()))
1194
+ };
1195
+ },
1196
+ isIdField: (col) => {
1197
+ return col.key == this.idMetadata.field.key;
1198
+ },
1199
+ getIdFilter: (...ids) => {
1200
+ if (this.idMetadata.field instanceof CompoundIdField) {
1201
+ let field = this.idMetadata.field;
1202
+ return {
1203
+ $or: ids.map(x => field.isEqualTo(x))
1204
+ };
1205
+ }
1206
+ if (ids.length == 1)
1207
+ return {
1208
+ [this.idMetadata.field.key]: ids[0]
1209
+ };
1210
+ else
1211
+ return {
1212
+ [this.idMetadata.field.key]: ids
1213
+ };
1214
+ }
1215
+ };
1216
+ if (this.options.allowApiCrud !== undefined) {
1217
+ if (this.options.allowApiDelete === undefined)
1218
+ this.options.allowApiDelete = this.options.allowApiCrud;
1219
+ if (this.options.allowApiInsert === undefined)
1220
+ this.options.allowApiInsert = this.options.allowApiCrud;
1221
+ if (this.options.allowApiUpdate === undefined)
1222
+ this.options.allowApiUpdate = this.options.allowApiCrud;
1223
+ if (this.options.allowApiRead === undefined)
1224
+ this.options.allowApiRead = this.options.allowApiCrud;
1225
+ }
1226
+ if (this.options.allowApiRead === undefined)
1227
+ this.options.allowApiRead = true;
1228
+ if (!this.key)
1229
+ this.key = entityType.name;
1230
+ if (!entityInfo.dbName)
1231
+ entityInfo.dbName = this.key;
1232
+ let _items = [];
1233
+ let r = {
1234
+ find: (c) => r[typeof c === "string" ? c : c.key],
1235
+ [Symbol.iterator]: () => _items[Symbol.iterator](),
1236
+ toArray: () => _items
1237
+ };
1238
+ for (const x of columnsInfo) {
1239
+ _items.push(r[x.key] = new columnDefsImpl(x, this, remult));
1240
+ }
1241
+ this.fields = r;
1242
+ this.caption = buildCaption(entityInfo.caption, this.key, remult);
1243
+ if (entityInfo.id) {
1244
+ let r = entityInfo.id(this.fields);
1245
+ if (Array.isArray(r)) {
1246
+ if (r.length > 1)
1247
+ this.idMetadata.field = new CompoundIdField(...r);
1248
+ else if (r.length == 1)
1249
+ this.idMetadata.field = r[0];
1250
+ }
1251
+ else
1252
+ this.idMetadata.field = r;
1253
+ }
1254
+ else {
1255
+ if (this.fields["id"])
1256
+ this.idMetadata.field = this.fields["id"];
1257
+ else
1258
+ this.idMetadata.field = [...this.fields][0];
1259
+ }
1260
+ }
1261
+ get apiUpdateAllowed() { return this.remult.isAllowedForInstance(undefined, this.options.allowApiUpdate); }
1262
+ get apiReadAllowed() { return this.remult.isAllowed(this.options.allowApiRead); }
1263
+ get apiDeleteAllowed() { return this.remult.isAllowedForInstance(undefined, this.options.allowApiDelete); }
1264
+ get apiInsertAllowed() { return this.remult.isAllowedForInstance(undefined, this.options.allowApiInsert); }
1265
+ getDbName() {
1266
+ if (this.dbNamePromise)
1267
+ return this.dbNamePromise;
1268
+ if (!this.options.sqlExpression) {
1269
+ this.dbNamePromise = Promise.resolve(this.options.dbName);
1270
+ }
1271
+ if (typeof this.options.sqlExpression === "string")
1272
+ this.dbNamePromise = Promise.resolve(this.options.sqlExpression);
1273
+ else if (typeof this.options.sqlExpression === "function") {
1274
+ let r = this.options.sqlExpression(this.fields);
1275
+ if (r instanceof Promise)
1276
+ this.dbNamePromise = r;
1277
+ else if (r)
1278
+ this.dbNamePromise = Promise.resolve(r);
1279
+ }
1280
+ this.dbNamePromise = this.dbNamePromise.then(x => {
1281
+ if (!x)
1282
+ return this.options.dbName;
1283
+ return x;
1284
+ });
1285
+ return this.dbNamePromise;
1286
+ }
1287
+ }
1288
+ export function FieldType(...options) {
1289
+ return target => {
1290
+ if (!options) {
1291
+ options = [];
1292
+ }
1293
+ options.splice(0, 0, { valueType: target });
1294
+ Reflect.defineMetadata(storableMember, options, target);
1295
+ return target;
1296
+ };
1297
+ }
1298
+ export class Fields {
1299
+ static object(...options) {
1300
+ return Field(undefined, ...options);
1301
+ }
1302
+ static dateOnly(...options) {
1303
+ return Field(() => Date, {
1304
+ valueConverter: ValueConverters.DateOnly
1305
+ }, ...options);
1306
+ }
1307
+ static date(...options) {
1308
+ return Field(() => Date, ...options);
1309
+ }
1310
+ static integer(...options) {
1311
+ return Field(() => Number, {
1312
+ valueConverter: ValueConverters.Integer
1313
+ }, ...options);
1314
+ }
1315
+ static autoIncrement(...options) {
1316
+ return Field(() => Number, {
1317
+ allowApiUpdate: false,
1318
+ dbReadOnly: true,
1319
+ valueConverter: { ...ValueConverters.Integer, fieldTypeInDb: 'autoincrement' }
1320
+ }, ...options);
1321
+ }
1322
+ static number(...options) {
1323
+ return Field(() => Number, ...options);
1324
+ }
1325
+ static uuid(...options) {
1326
+ return Field(() => String, {
1327
+ allowApiUpdate: false,
1328
+ defaultValue: () => uuid()
1329
+ }, ...options);
1330
+ }
1331
+ static string(...options) {
1332
+ return Field(() => String, ...options);
1333
+ }
1334
+ static boolean(...options) {
1335
+ return Field(() => Boolean, ...options);
1336
+ }
1337
+ }
1338
+ export function isAutoIncrement(f) {
1339
+ return f.options?.valueConverter?.fieldTypeInDb === 'autoincrement';
1340
+ }
1341
+ export function ValueListFieldType(...options) {
1342
+ return (type) => {
1343
+ FieldType(o => {
1344
+ o.valueConverter = ValueListInfo.get(type),
1345
+ o.displayValue = (item, val) => val.caption;
1346
+ }, ...options)(type);
1347
+ };
1348
+ }
1349
+ export class ValueListInfo {
1350
+ constructor(valueListType) {
1351
+ this.valueListType = valueListType;
1352
+ this.byIdMap = new Map();
1353
+ this.values = [];
1354
+ this.isNumeric = false;
1355
+ for (let member in this.valueListType) {
1356
+ let s = this.valueListType[member];
1357
+ if (s instanceof this.valueListType) {
1358
+ if (s.id === undefined)
1359
+ s.id = member;
1360
+ if (typeof s.id === 'number')
1361
+ this.isNumeric = true;
1362
+ if (s.caption === undefined)
1363
+ s.caption = makeTitle(s.id !== undefined ? s.id.toString() : member);
1364
+ this.byIdMap.set(s.id, s);
1365
+ this.values.push(s);
1366
+ }
1367
+ }
1368
+ if (this.isNumeric) {
1369
+ this.fieldTypeInDb = 'integer';
1370
+ }
1371
+ var options = Reflect.getMetadata(storableMember, this.valueListType);
1372
+ if (options) {
1373
+ for (const op of options) {
1374
+ if (op?.getValues) {
1375
+ this.values.splice(0, this.values.length, ...op.getValues());
1376
+ this.byIdMap.clear();
1377
+ this.values.forEach(s => {
1378
+ if (s.caption === undefined && s.id !== undefined)
1379
+ s.caption = makeTitle(s.id);
1380
+ this.byIdMap.set(s.id, s);
1381
+ });
1382
+ }
1383
+ }
1384
+ if (this.values.find(s => s.id === undefined))
1385
+ throw new Error(`ValueType ${this.valueListType} has values without an id`);
1386
+ }
1387
+ else
1388
+ throw new Error(`ValueType not yet initialized, did you forget to call @ValueListFieldType on ` + valueListType);
1389
+ }
1390
+ static get(type) {
1391
+ let r = typeCache.get(type);
1392
+ if (!r) {
1393
+ r = new ValueListInfo(type);
1394
+ typeCache.set(type, r);
1395
+ }
1396
+ return r;
1397
+ }
1398
+ getValues() {
1399
+ return this.values;
1400
+ }
1401
+ byId(key) {
1402
+ if (this.isNumeric)
1403
+ key = +key;
1404
+ return this.byIdMap.get(key);
1405
+ }
1406
+ fromJson(val) {
1407
+ return this.byId(val);
1408
+ }
1409
+ toJson(val) {
1410
+ if (!val)
1411
+ return undefined;
1412
+ return val.id;
1413
+ }
1414
+ fromDb(val) {
1415
+ return this.fromJson(val);
1416
+ }
1417
+ toDb(val) {
1418
+ return this.toJson(val);
1419
+ }
1420
+ toInput(val, inputType) {
1421
+ return this.toJson(val);
1422
+ }
1423
+ fromInput(val, inputType) {
1424
+ return this.fromJson(val);
1425
+ }
1426
+ displayValue(val) {
1427
+ if (!val)
1428
+ return '';
1429
+ return val.caption;
1430
+ }
1431
+ }
1432
+ const typeCache = new Map();
1433
+ export function getValueList(type) {
1434
+ {
1435
+ const fr = type?.metadata?.valueType;
1436
+ if (fr)
1437
+ return ValueListInfo.get(fr).getValues();
1438
+ }
1439
+ {
1440
+ const fr = type?.valueType;
1441
+ if (fr)
1442
+ return ValueListInfo.get(fr).getValues();
1443
+ }
1444
+ return ValueListInfo.get(type).getValues();
1445
+ }
1446
+ /**Decorates fields that should be used as fields.
1447
+ * for more info see: [Field Types](https://remult.dev/docs/field-types.html)
1448
+ *
1449
+ * FieldOptions can be set in two ways:
1450
+ * @example
1451
+ * // as an object
1452
+ * @Fields.string({ includeInApi:false })
1453
+ * title='';
1454
+ * @example
1455
+ * // as an arrow function that receives `remult` as a parameter
1456
+ * @Fields.string((options,remult) => options.includeInApi = true)
1457
+ * title='';
1458
+ */
1459
+ export function Field(valueType, ...options) {
1460
+ return (target, key, c) => {
1461
+ let factory = (remult) => {
1462
+ let r = buildOptions(options, remult);
1463
+ if (!r.valueType && valueType) {
1464
+ r.valueType = valueType();
1465
+ }
1466
+ if (!r.key) {
1467
+ r.key = key;
1468
+ }
1469
+ if (!r.dbName)
1470
+ r.dbName = r.key;
1471
+ let type = r.valueType;
1472
+ if (!type) {
1473
+ type = Reflect.getMetadata("design:type", target, key);
1474
+ r.valueType = type;
1475
+ }
1476
+ if (!r.target)
1477
+ r.target = target;
1478
+ return r;
1479
+ };
1480
+ let names = columnsOfType.get(target.constructor);
1481
+ if (!names) {
1482
+ names = [];
1483
+ columnsOfType.set(target.constructor, names);
1484
+ }
1485
+ let set = names.find(x => x.key == key);
1486
+ if (!set)
1487
+ names.push({
1488
+ key,
1489
+ settings: factory,
1490
+ });
1491
+ else {
1492
+ let prev = set.settings;
1493
+ set.settings = (c) => {
1494
+ let prevO = prev(c);
1495
+ let curr = factory(c);
1496
+ return Object.assign(prevO, curr);
1497
+ };
1498
+ }
1499
+ };
1500
+ }
1501
+ export const storableMember = Symbol("storableMember");
1502
+ function buildOptions(options, remult) {
1503
+ let r = {};
1504
+ for (const o of options) {
1505
+ if (o) {
1506
+ if (typeof o === "function")
1507
+ o(r, remult);
1508
+ else
1509
+ Object.assign(r, o);
1510
+ }
1511
+ }
1512
+ return r;
1513
+ }
1514
+ export function decorateColumnSettings(settings, remult) {
1515
+ if (settings.valueType) {
1516
+ let settingsOnTypeLevel = Reflect.getMetadata(storableMember, settings.valueType);
1517
+ if (settingsOnTypeLevel) {
1518
+ settings = {
1519
+ ...buildOptions(settingsOnTypeLevel, remult),
1520
+ ...settings
1521
+ };
1522
+ }
1523
+ }
1524
+ if (settings.valueType == String) {
1525
+ let x = settings;
1526
+ if (!settings.valueConverter)
1527
+ x.valueConverter = {
1528
+ toJson: x => x,
1529
+ fromJson: x => x
1530
+ };
1531
+ }
1532
+ if (settings.valueType == Number) {
1533
+ let x = settings;
1534
+ if (!settings.valueConverter)
1535
+ x.valueConverter = ValueConverters.Number;
1536
+ }
1537
+ if (settings.valueType == Date) {
1538
+ let x = settings;
1539
+ if (!settings.valueConverter) {
1540
+ x.valueConverter = ValueConverters.Date;
1541
+ }
1542
+ }
1543
+ if (settings.valueType == Boolean) {
1544
+ let x = settings;
1545
+ if (!x.valueConverter)
1546
+ x.valueConverter = ValueConverters.Boolean;
1547
+ }
1548
+ if (!settings.valueConverter) {
1549
+ let ei = getEntitySettings(settings.valueType, false);
1550
+ if (ei) {
1551
+ settings.valueConverter = {
1552
+ toDb: x => x,
1553
+ fromDb: x => x
1554
+ };
1555
+ }
1556
+ else
1557
+ settings.valueConverter = ValueConverters.Default;
1558
+ }
1559
+ if (!settings.valueConverter.toJson) {
1560
+ settings.valueConverter.toJson = x => x;
1561
+ }
1562
+ if (!settings.valueConverter.fromJson) {
1563
+ settings.valueConverter.fromJson = x => x;
1564
+ }
1565
+ if (!settings.valueConverter.toDb) {
1566
+ settings.valueConverter.toDb = x => settings.valueConverter.toJson(x);
1567
+ }
1568
+ if (!settings.valueConverter.fromDb) {
1569
+ settings.valueConverter.fromDb = x => settings.valueConverter.fromJson(x);
1570
+ }
1571
+ if (!settings.valueConverter.toInput) {
1572
+ settings.valueConverter.toInput = x => settings.valueConverter.toJson(x);
1573
+ }
1574
+ if (!settings.valueConverter.fromInput) {
1575
+ settings.valueConverter.fromInput = x => settings.valueConverter.fromJson(x);
1576
+ }
1577
+ return settings;
1578
+ }
1579
+ export function BuildEntity(c, key, fields, ...options) {
1580
+ Entity(key, ...options)(c);
1581
+ for (const fieldKey in fields) {
1582
+ if (Object.prototype.hasOwnProperty.call(fields, fieldKey)) {
1583
+ const element = fields[fieldKey];
1584
+ element(c.prototype, fieldKey);
1585
+ }
1586
+ }
1587
+ }
1588
+ /**Decorates classes that should be used as entities.
1589
+ * Receives a key and an array of EntityOptions.
1590
+ * @example
1591
+ * import { Entity, Fields } from "remult";
1592
+ * @Entity("tasks", {
1593
+ * allowApiCrud: true
1594
+ * })
1595
+ * export class Task {
1596
+ * @Fields.uuid()
1597
+ * id!: string;
1598
+ * @Fields.string()
1599
+ * title = '';
1600
+ * @Fields.boolean()
1601
+ * completed = false;
1602
+ * }
1603
+ * @note
1604
+ * EntityOptions can be set in two ways:
1605
+ * @example
1606
+ * // as an object
1607
+ * @Entity("tasks",{ allowApiCrud:true })
1608
+ * @example
1609
+ * // as an arrow function that receives `remult` as a parameter
1610
+ * @Entity("tasks", (options,remult) => options.allowApiCrud = true)
1611
+ */
1612
+ export function Entity(key, ...options) {
1613
+ return target => {
1614
+ for (const customFilterMember in target) {
1615
+ if (Object.prototype.hasOwnProperty.call(target, customFilterMember)) {
1616
+ const element = target[customFilterMember];
1617
+ if (element?.customFilterInfo?.customFilterTranslator) {
1618
+ if (!element.customFilterInfo.key)
1619
+ element.customFilterInfo.key = customFilterMember;
1620
+ }
1621
+ }
1622
+ }
1623
+ let factory = remult => {
1624
+ let r = {};
1625
+ for (const o of options) {
1626
+ if (o) {
1627
+ if (typeof o === "function")
1628
+ o(r, remult);
1629
+ else
1630
+ Object.assign(r, o);
1631
+ }
1632
+ }
1633
+ let base = Object.getPrototypeOf(target);
1634
+ if (base) {
1635
+ let baseFactory = getEntitySettings(base, false);
1636
+ if (baseFactory) {
1637
+ let opt = baseFactory(remult);
1638
+ if (opt) {
1639
+ r = {
1640
+ ...opt,
1641
+ ...r
1642
+ };
1643
+ }
1644
+ }
1645
+ }
1646
+ return r;
1647
+ };
1648
+ allEntities.push(target);
1649
+ setControllerSettings(target, { key });
1650
+ Reflect.defineMetadata(entityInfo, factory, target);
1651
+ Reflect.defineMetadata(entityInfo_key, key, target);
1652
+ return target;
1653
+ };
1654
+ }
1655
+ export class EntityBase {
1656
+ get _() { return getEntityRef(this); }
1657
+ save() { return this._.save(); }
1658
+ assign(values) {
1659
+ assign(this, values);
1660
+ return this;
1661
+ }
1662
+ delete() { return this._.delete(); }
1663
+ isNew() { return this._.isNew(); }
1664
+ get $() { return this._.fields; }
1665
+ }
1666
+ export class ControllerBase {
1667
+ constructor(remult) {
1668
+ this.remult = remult;
1669
+ }
1670
+ assign(values) {
1671
+ assign(this, values);
1672
+ return this;
1673
+ }
1674
+ get $() { return getFields(this); }
1675
+ get _() { return getControllerRef(this); }
1676
+ }
1677
+ class QueryResultImpl {
1678
+ constructor(options, repo) {
1679
+ this.options = options;
1680
+ this.repo = repo;
1681
+ this._count = undefined;
1682
+ if (!this.options)
1683
+ this.options = {};
1684
+ if (!this.options.pageSize) {
1685
+ this.options.pageSize = queryConfig.defaultPageSize;
1686
+ }
1687
+ }
1688
+ async getPage(page) {
1689
+ if (page < 1)
1690
+ page = 1;
1691
+ return this.repo.find({
1692
+ where: this.options.where,
1693
+ orderBy: this.options.orderBy,
1694
+ limit: this.options.pageSize,
1695
+ page: page,
1696
+ load: this.options.load
1697
+ });
1698
+ }
1699
+ async count() {
1700
+ if (this._count === undefined)
1701
+ this._count = await this.repo.count(this.options.where);
1702
+ return this._count;
1703
+ }
1704
+ async forEach(what) {
1705
+ let i = 0;
1706
+ for await (const x of this) {
1707
+ await what(x);
1708
+ i++;
1709
+ }
1710
+ return i;
1711
+ }
1712
+ async paginator(pNextPageFilter) {
1713
+ this.options.orderBy = Sort.createUniqueEntityOrderBy(this.repo.metadata, this.options.orderBy);
1714
+ let items = await this.repo.find({
1715
+ where: { $and: [this.options.where, pNextPageFilter] },
1716
+ orderBy: this.options.orderBy,
1717
+ limit: this.options.pageSize,
1718
+ load: this.options.load
1719
+ });
1720
+ let nextPage = undefined;
1721
+ let hasNextPage = items.length == this.options.pageSize;
1722
+ if (hasNextPage) {
1723
+ let nextPageFilter = await this.repo.createAfterFilter(this.options.orderBy, items[items.length - 1]);
1724
+ nextPage = () => this.paginator(nextPageFilter);
1725
+ }
1726
+ return {
1727
+ count: () => this.count(),
1728
+ hasNextPage,
1729
+ items,
1730
+ nextPage
1731
+ };
1732
+ }
1733
+ [Symbol.asyncIterator]() {
1734
+ if (!this.options.where) {
1735
+ this.options.where = {};
1736
+ }
1737
+ let ob = this.options.orderBy;
1738
+ this.options.orderBy = Sort.createUniqueEntityOrderBy(this.repo.metadata, ob);
1739
+ let itemIndex = -1;
1740
+ let currentPage = undefined;
1741
+ let itStrategy;
1742
+ let j = 0;
1743
+ itStrategy = async () => {
1744
+ if (this.options.progress) {
1745
+ this.options.progress.progress(j++ / await this.count());
1746
+ }
1747
+ if (currentPage === undefined || itemIndex == currentPage.items.length) {
1748
+ if (currentPage && !currentPage.hasNextPage)
1749
+ return { value: undefined, done: true };
1750
+ let prev = currentPage;
1751
+ if (currentPage)
1752
+ currentPage = await currentPage.nextPage();
1753
+ else
1754
+ currentPage = await this.paginator();
1755
+ itemIndex = 0;
1756
+ if (currentPage.items.length == 0) {
1757
+ return { value: undefined, done: true };
1758
+ }
1759
+ else {
1760
+ if (prev?.items.length > 0) {
1761
+ if (this.repo.getEntityRef(prev.items[0]).getId() == this.repo.getEntityRef(currentPage.items[0]).getId())
1762
+ throw new Error("pagination failure, returned same first row");
1763
+ }
1764
+ }
1765
+ }
1766
+ if (itemIndex < currentPage.items.length)
1767
+ return { value: currentPage.items[itemIndex++], done: false };
1768
+ };
1769
+ return {
1770
+ next: async () => {
1771
+ let r = itStrategy();
1772
+ return r;
1773
+ }
1774
+ };
1775
+ }
1776
+ }
1777
+ class cacheEntityInfo {
1778
+ constructor() {
1779
+ this.value = {};
1780
+ }
1781
+ }
1782
+ class SubscribableImp {
1783
+ reportChanged() {
1784
+ if (this._subscribers)
1785
+ this._subscribers.forEach(x => x.reportChanged());
1786
+ }
1787
+ reportObserved() {
1788
+ if (this._subscribers)
1789
+ this._subscribers.forEach(x => x.reportObserved());
1790
+ }
1791
+ subscribe(listener) {
1792
+ let list;
1793
+ if (typeof listener === "function")
1794
+ list = {
1795
+ reportChanged: () => listener(),
1796
+ reportObserved: () => { }
1797
+ };
1798
+ else
1799
+ list = listener;
1800
+ if (!this._subscribers) {
1801
+ this._subscribers = [];
1802
+ }
1803
+ this._subscribers.push(list);
1804
+ return () => this._subscribers = this._subscribers.filter(x => x != list);
1805
+ }
1806
+ }