remult 0.25.7-exp.0 → 0.25.7-exp.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.
Files changed (37) hide show
  1. package/esm/postgres/postgres-data-provider.js +3 -0
  2. package/esm/postgres/schema-builder.js +3 -3
  3. package/esm/remult-sql-js.js +3 -0
  4. package/esm/src/data-api.js +57 -12
  5. package/esm/src/data-providers/array-entity-data-provider.js +15 -19
  6. package/esm/src/data-providers/in-memory-database.js +9 -2
  7. package/esm/src/data-providers/json-data-provider.js +1 -1
  8. package/esm/src/data-providers/rest-data-provider.js +29 -8
  9. package/esm/src/data-providers/sql-database.js +14 -6
  10. package/esm/src/data-providers/web-sql-data-provider.js +3 -0
  11. package/esm/src/filter/filter-consumer-bridge-to-sql-request.js +10 -5
  12. package/esm/src/remult3/RepositoryImplementation.js +89 -11
  13. package/esm/src/remult3/remult3.js +22 -7
  14. package/esm/src/validators.js +1 -1
  15. package/package.json +1 -1
  16. package/postgres/postgres-data-provider.js +3 -0
  17. package/postgres/schema-builder.js +3 -3
  18. package/remult-sql-js.js +3 -0
  19. package/src/data-api.d.ts +5 -0
  20. package/src/data-api.js +222 -45
  21. package/src/data-interfaces.d.ts +5 -0
  22. package/src/data-providers/array-entity-data-provider.d.ts +2 -1
  23. package/src/data-providers/array-entity-data-provider.js +14 -17
  24. package/src/data-providers/in-memory-database.js +15 -3
  25. package/src/data-providers/json-data-provider.js +1 -1
  26. package/src/data-providers/rest-data-provider.d.ts +6 -2
  27. package/src/data-providers/rest-data-provider.js +42 -9
  28. package/src/data-providers/sql-database.js +13 -9
  29. package/src/data-providers/web-sql-data-provider.js +3 -0
  30. package/src/filter/filter-consumer-bridge-to-sql-request.d.ts +3 -1
  31. package/src/filter/filter-consumer-bridge-to-sql-request.js +10 -7
  32. package/src/remult3/RepositoryImplementation.d.ts +8 -0
  33. package/src/remult3/RepositoryImplementation.js +475 -241
  34. package/src/remult3/remult3.d.ts +8 -0
  35. package/src/remult3/remult3.js +22 -7
  36. package/src/sql-command.d.ts +2 -0
  37. package/src/validators.js +1 -1
@@ -80,6 +80,9 @@ class PostgresBridgeToSQLCommand {
80
80
  }
81
81
  values = [];
82
82
  addParameterAndReturnSqlToken(val) {
83
+ return this.param(val);
84
+ }
85
+ param(val) {
83
86
  if (Array.isArray(val))
84
87
  val = JSON.stringify(val);
85
88
  this.values.push(val);
@@ -65,9 +65,9 @@ export class PostgresSchemaBuilder {
65
65
  }
66
66
  const where = [];
67
67
  if (schema) {
68
- where.push(`table_schema=${cmd.addParameterAndReturnSqlToken(this.removeQuotes(schema))}`);
68
+ where.push(`table_schema=${cmd.param(this.removeQuotes(schema))}`);
69
69
  }
70
- where.push(`table_name=${cmd.addParameterAndReturnSqlToken(this.removeQuotes(table))}`);
70
+ where.push(`table_name=${cmd.param(this.removeQuotes(table))}`);
71
71
  return where.join(' AND ');
72
72
  }
73
73
  schemaAndName(e) {
@@ -162,7 +162,7 @@ CREATE table ${this.schemaAndName(e)} (${result}\r\n)`;
162
162
  const colName = e.$dbNameOf(c(entity));
163
163
  if ((await cmd.execute(`SELECT 1 FROM information_schema.columns WHERE ` +
164
164
  `${this.whereTableAndSchema(cmd, e)} ` +
165
- `AND column_name=${cmd.addParameterAndReturnSqlToken(colName.toLocaleLowerCase())}`)).rows.length == 0) {
165
+ `AND column_name=${cmd.param(colName.toLocaleLowerCase())}`)).rows.length == 0) {
166
166
  let sql = `ALTER table ${this.schemaAndName(e)} ` +
167
167
  `ADD column ${postgresColumnSyntax(c(entity), colName)}`;
168
168
  if (PostgresSchemaBuilder.logToConsole)
@@ -92,6 +92,9 @@ class SqlJsCommand {
92
92
  return new SqlJsSqlResult((await this.db).exec(sql, this.values));
93
93
  }
94
94
  addParameterAndReturnSqlToken(val) {
95
+ return this.param(val);
96
+ }
97
+ param(val) {
95
98
  if (val instanceof Date)
96
99
  val = val.valueOf();
97
100
  const key = ':' + ++this.i;
@@ -30,6 +30,10 @@ export class DataApi {
30
30
  return this.getArray(res, req, body);
31
31
  case 'count':
32
32
  return this.count(res, req, body);
33
+ case 'deleteMany':
34
+ return this.deleteMany(res, req, body);
35
+ case 'updateMany':
36
+ return this.updateMany(res, req, body);
33
37
  case 'endLiveQuery':
34
38
  await this.remult.liveQueryStorage.remove(body.id);
35
39
  res.success('ok');
@@ -60,6 +64,24 @@ export class DataApi {
60
64
  response.error(err);
61
65
  }
62
66
  }
67
+ async deleteMany(response, request, filterBody) {
68
+ try {
69
+ return await doTransaction(this.remult, async () => {
70
+ let deleted = 0;
71
+ for await (const x of this.repository.query({
72
+ where: await this.buildWhere(request, filterBody),
73
+ include: this.includeNone(),
74
+ })) {
75
+ await this.actualDelete(x);
76
+ deleted++;
77
+ }
78
+ response.success({ deleted });
79
+ });
80
+ }
81
+ catch (err) {
82
+ response.error(err);
83
+ }
84
+ }
63
85
  async getArrayImpl(response, request, filterBody) {
64
86
  let findOptions = {
65
87
  load: () => [],
@@ -219,25 +241,48 @@ export class DataApi {
219
241
  response.error(err);
220
242
  }
221
243
  }
244
+ async updateMany(response, request, body) {
245
+ try {
246
+ return await doTransaction(this.remult, async () => {
247
+ let updated = 0;
248
+ for await (const x of this.repository.query({
249
+ where: await this.buildWhere(request, body.where),
250
+ include: this.includeNone(),
251
+ })) {
252
+ await this.actualUpdate(x, body.set);
253
+ updated++;
254
+ }
255
+ response.success({ updated });
256
+ });
257
+ }
258
+ catch (err) {
259
+ response.error(err);
260
+ }
261
+ }
262
+ async actualUpdate(row, body) {
263
+ let ref = this.repository.getEntityRef(row);
264
+ await ref._updateEntityBasedOnApi(body);
265
+ if (!ref.apiUpdateAllowed) {
266
+ throw new ForbiddenError();
267
+ }
268
+ await ref.save();
269
+ return ref;
270
+ }
222
271
  async put(response, id, body) {
223
272
  await this.doOnId(response, id, async (row) => {
224
- let ref = this.repository.getEntityRef(row);
225
- await ref._updateEntityBasedOnApi(body);
226
- if (!ref.apiUpdateAllowed) {
227
- response.forbidden();
228
- return;
229
- }
230
- await ref.save();
273
+ const ref = await this.actualUpdate(row, body);
231
274
  response.success(ref.toApiJson());
232
275
  });
233
276
  }
277
+ async actualDelete(row) {
278
+ if (!this.repository.getEntityRef(row).apiDeleteAllowed) {
279
+ throw new ForbiddenError();
280
+ }
281
+ await this.repository.getEntityRef(row).delete();
282
+ }
234
283
  async delete(response, id) {
235
284
  await this.doOnId(response, id, async (row) => {
236
- if (!this.repository.getEntityRef(row).apiDeleteAllowed) {
237
- response.forbidden();
238
- return;
239
- }
240
- await this.repository.getEntityRef(row).delete();
285
+ await this.actualDelete(row);
241
286
  response.deleted();
242
287
  });
243
288
  }
@@ -3,6 +3,7 @@ import { dbNamesOf, isDbReadonly, } from '../filter/filter-consumer-bridge-to-sq
3
3
  import { Filter, customDatabaseFilterToken, } from '../filter/filter-interfaces.js';
4
4
  export class ArrayEntityDataProvider {
5
5
  entity;
6
+ rows;
6
7
  static rawFilter(filter) {
7
8
  return {
8
9
  [customDatabaseFilterToken]: {
@@ -10,14 +11,9 @@ export class ArrayEntityDataProvider {
10
11
  },
11
12
  };
12
13
  }
13
- //@internal
14
- rows;
15
14
  constructor(entity, rows) {
16
15
  this.entity = entity;
17
- if (rows === undefined)
18
- this.rows = [];
19
- else
20
- this.rows = rows;
16
+ this.rows = rows;
21
17
  }
22
18
  //@internal
23
19
  __names;
@@ -26,7 +22,7 @@ export class ArrayEntityDataProvider {
26
22
  if (this.__names)
27
23
  return this.__names;
28
24
  this.__names = await dbNamesOf(this.entity, (x) => x);
29
- for (const r of this.rows) {
25
+ for (const r of this.rows()) {
30
26
  this.verifyThatRowHasAllNotNullColumns(r, this.__names);
31
27
  }
32
28
  return this.__names;
@@ -53,7 +49,7 @@ export class ArrayEntityDataProvider {
53
49
  }
54
50
  }
55
51
  async count(where) {
56
- let rows = this.rows;
52
+ let rows = this.rows();
57
53
  const names = await this.init();
58
54
  let j = 0;
59
55
  for (let i = 0; i < rows.length; i++) {
@@ -70,7 +66,7 @@ export class ArrayEntityDataProvider {
70
66
  return j;
71
67
  }
72
68
  async find(options) {
73
- let rows = this.rows;
69
+ let rows = this.rows();
74
70
  const dbNames = await this.init();
75
71
  if (options) {
76
72
  if (options.where) {
@@ -122,8 +118,8 @@ export class ArrayEntityDataProvider {
122
118
  const names = await this.init();
123
119
  let idMatches = this.idMatches(id, names);
124
120
  let keys = Object.keys(data);
125
- for (let i = 0; i < this.rows.length; i++) {
126
- let r = this.rows[i];
121
+ for (let i = 0; i < this.rows().length; i++) {
122
+ let r = this.rows()[i];
127
123
  if (idMatches(r)) {
128
124
  let newR = { ...r };
129
125
  for (const f of this.entity.fields) {
@@ -134,8 +130,8 @@ export class ArrayEntityDataProvider {
134
130
  }
135
131
  }
136
132
  this.verifyThatRowHasAllNotNullColumns(newR, names);
137
- this.rows[i] = newR;
138
- return Promise.resolve(this.translateFromJson(this.rows[i], names));
133
+ this.rows()[i] = newR;
134
+ return Promise.resolve(this.translateFromJson(this.rows()[i], names));
139
135
  }
140
136
  }
141
137
  throw new Error("couldn't find id to update: " + id);
@@ -143,9 +139,9 @@ export class ArrayEntityDataProvider {
143
139
  async delete(id) {
144
140
  const names = await this.init();
145
141
  let idMatches = this.idMatches(id, names);
146
- for (let i = 0; i < this.rows.length; i++) {
147
- if (idMatches(this.rows[i])) {
148
- this.rows.splice(i, 1);
142
+ for (let i = 0; i < this.rows().length; i++) {
143
+ if (idMatches(this.rows()[i])) {
144
+ this.rows().splice(i, 1);
149
145
  return Promise.resolve();
150
146
  }
151
147
  }
@@ -158,19 +154,19 @@ export class ArrayEntityDataProvider {
158
154
  if (!(idf instanceof CompoundIdField)) {
159
155
  if (idf.valueConverter.fieldTypeInDb === 'autoincrement') {
160
156
  j[idf.key] = 1;
161
- for (const row of this.rows) {
157
+ for (const row of this.rows()) {
162
158
  if (row[idf.key] >= j[idf.key])
163
159
  j[idf.key] = row[idf.key] + 1;
164
160
  }
165
161
  }
166
162
  if (j[idf.key])
167
- this.rows.forEach((i) => {
163
+ this.rows().forEach((i) => {
168
164
  if (j[idf.key] == i[idf.key])
169
165
  throw Error('id already exists');
170
166
  });
171
167
  }
172
168
  this.verifyThatRowHasAllNotNullColumns(j, names);
173
- this.rows.push(j);
169
+ this.rows().push(j);
174
170
  return Promise.resolve(this.translateFromJson(j, names));
175
171
  }
176
172
  }
@@ -1,14 +1,21 @@
1
1
  import { ArrayEntityDataProvider } from './array-entity-data-provider.js';
2
2
  export class InMemoryDataProvider {
3
3
  async transaction(action) {
4
- await action(this);
4
+ let before = JSON.stringify(this.rows);
5
+ try {
6
+ await action(this);
7
+ }
8
+ catch (e) {
9
+ this.rows = JSON.parse(before);
10
+ throw e;
11
+ }
5
12
  }
6
13
  rows = {};
7
14
  getEntityDataProvider(entity) {
8
15
  let name = entity.key;
9
16
  if (!this.rows[name])
10
17
  this.rows[name] = [];
11
- return new ArrayEntityDataProvider(entity, this.rows[name]);
18
+ return new ArrayEntityDataProvider(entity, () => this.rows[name]);
12
19
  }
13
20
  toString() {
14
21
  return 'InMemoryDataProvider';
@@ -24,7 +24,7 @@ class JsonEntityDataProvider {
24
24
  let s = await this.helper.getItem(dbName);
25
25
  if (s)
26
26
  data = JSON.parse(s);
27
- let dp = new ArrayEntityDataProvider(this.entity, data);
27
+ let dp = new ArrayEntityDataProvider(this.entity, () => data);
28
28
  return what(dp, async () => await this.helper.setItem(dbName, JSON.stringify(data, undefined, 2)));
29
29
  }
30
30
  p = Promise.resolve();
@@ -119,18 +119,27 @@ export class RestEntityDataProvider {
119
119
  const { run } = this.buildFindRequest({ where });
120
120
  return run('count').then((r) => +r.count);
121
121
  }
122
+ async deleteMany(where) {
123
+ const { run } = this.buildFindRequest({ where }, true);
124
+ return run('deleteMany').then((r) => +r.deleted);
125
+ }
126
+ async updateMany(where, data) {
127
+ const { run } = this.buildFindRequest({ where }, true);
128
+ return run('updateMany', { set: this.toJsonOfIncludedKeys(data) }).then((r) => +r.updated);
129
+ }
122
130
  find(options) {
123
131
  let { run } = this.buildFindRequest(options);
124
132
  return run().then((x) => x.map((y) => this.translateFromJson(y)));
125
133
  }
126
134
  //@internal
127
- buildFindRequest(options) {
135
+ buildFindRequest(options, forcePost = false) {
128
136
  let url = new UrlBuilder(this.url());
129
137
  let filterObject;
130
138
  if (options) {
131
139
  if (options.where) {
132
140
  filterObject = options.where.toJson(); // options.where.__applyToConsumer(new FilterConsumnerBridgeToUrlBuilder(url));
133
- if (addFilterToUrlAndReturnTrueIfSuccessful(filterObject, url))
141
+ if (!forcePost &&
142
+ addFilterToUrlAndReturnTrueIfSuccessful(filterObject, url))
134
143
  filterObject = undefined;
135
144
  }
136
145
  if (options.orderBy && options.orderBy.Segments) {
@@ -157,15 +166,19 @@ export class RestEntityDataProvider {
157
166
  if (options.page)
158
167
  url.add('_page', options.page);
159
168
  }
160
- const run = (action) => {
169
+ const run = (action, body) => {
161
170
  let u = new UrlBuilder(url.url);
162
171
  if (!action && filterObject) {
163
172
  action = 'get';
164
173
  }
165
174
  if (action)
166
175
  u.add('__action', action);
167
- if (filterObject) {
168
- return this.http().post(u.url, filterObject);
176
+ if (filterObject || forcePost) {
177
+ if (!body)
178
+ body = filterObject;
179
+ else
180
+ body = { ...body, where: filterObject };
181
+ return this.http().post(u.url, body);
169
182
  }
170
183
  else
171
184
  return this.http().get(u.url);
@@ -187,15 +200,18 @@ export class RestEntityDataProvider {
187
200
  };
188
201
  }
189
202
  update(id, data) {
203
+ return this.http()
204
+ .put(this.url() + '/' + encodeURIComponent(id), this.toJsonOfIncludedKeys(data))
205
+ .then((y) => this.translateFromJson(y));
206
+ }
207
+ toJsonOfIncludedKeys(data) {
190
208
  let result = {};
191
209
  let keys = Object.keys(data);
192
210
  for (const col of this.entity.fields) {
193
211
  if (keys.includes(col.key))
194
212
  result[col.key] = col.valueConverter.toJson(data[col.key]);
195
213
  }
196
- return this.http()
197
- .put(this.url() + '/' + encodeURIComponent(id), result)
198
- .then((y) => this.translateFromJson(y));
214
+ return result;
199
215
  }
200
216
  delete(id) {
201
217
  return this.http().delete(this.url() + '/' + encodeURIComponent(id));
@@ -205,6 +221,11 @@ export class RestEntityDataProvider {
205
221
  .post(this.url(), this.translateToJson(data))
206
222
  .then((y) => this.translateFromJson(y));
207
223
  }
224
+ insertMany(data) {
225
+ return this.http()
226
+ .post(this.url(), data.map((data) => this.translateToJson(data)))
227
+ .then((y) => y.map((y) => this.translateFromJson(y)));
228
+ }
208
229
  }
209
230
  export class RestDataProviderHttpProviderUsingFetch {
210
231
  fetch;
@@ -58,7 +58,10 @@ export class SqlDatabase {
58
58
  createCommand: () => {
59
59
  let c = x.createCommand();
60
60
  return {
61
- addParameterAndReturnSqlToken: (x) => c.addParameterAndReturnSqlToken(x),
61
+ addParameterAndReturnSqlToken: (val) => {
62
+ return c.param(val);
63
+ },
64
+ param: (x) => c.param(x),
62
65
  execute: async (sql) => {
63
66
  if (completed)
64
67
  throw "can't run a command after the transaction was completed";
@@ -139,7 +142,10 @@ class LogSQLCommand {
139
142
  }
140
143
  args = {};
141
144
  addParameterAndReturnSqlToken(val) {
142
- let r = this.origin.addParameterAndReturnSqlToken(val);
145
+ return this.param(val);
146
+ }
147
+ param(val, name) {
148
+ let r = this.origin.param(val);
143
149
  this.args[r] = val;
144
150
  return r;
145
151
  }
@@ -321,8 +327,7 @@ class ActualSQLServerDataProvider {
321
327
  added = true;
322
328
  else
323
329
  statement += ', ';
324
- statement +=
325
- e.$dbNameOf(x) + ' = ' + r.addParameterAndReturnSqlToken(v);
330
+ statement += e.$dbNameOf(x) + ' = ' + r.param(v);
326
331
  }
327
332
  }
328
333
  }
@@ -364,7 +369,7 @@ class ActualSQLServerDataProvider {
364
369
  vals += ', ';
365
370
  }
366
371
  cols += e.$dbNameOf(x);
367
- vals += r.addParameterAndReturnSqlToken(v);
372
+ vals += r.param(v);
368
373
  }
369
374
  }
370
375
  }
@@ -382,6 +387,9 @@ class myDummySQLCommand {
382
387
  throw new Error('Method not implemented.');
383
388
  }
384
389
  addParameterAndReturnSqlToken(val) {
390
+ return this.param(val);
391
+ }
392
+ param(val) {
385
393
  if (val === null)
386
394
  return 'null';
387
395
  if (val instanceof Date)
@@ -410,7 +418,7 @@ async function bulkInsert(array, db) {
410
418
  sql += items
411
419
  .map((row) => '(' +
412
420
  row.$.toArray()
413
- .map((f) => c.addParameterAndReturnSqlToken(f.metadata.valueConverter.toDb(f.value)))
421
+ .map((f) => c.param(f.metadata.valueConverter.toDb(f.value)))
414
422
  .join(', ') +
415
423
  ')')
416
424
  .join(',');
@@ -101,6 +101,9 @@ class WebSqlBridgeToSQLCommand {
101
101
  }
102
102
  values = [];
103
103
  addParameterAndReturnSqlToken(val) {
104
+ return this.param(val);
105
+ }
106
+ param(val) {
104
107
  this.values.push(val);
105
108
  return '~' + this.values.length + '~';
106
109
  }
@@ -61,7 +61,7 @@ export class FilterConsumerBridgeToSqlRequest {
61
61
  this.addToWhere(this.nameProvider.$dbNameOf(col) +
62
62
  ' in (' +
63
63
  val
64
- .map((x) => this.r.addParameterAndReturnSqlToken(col.valueConverter.toDb(x)))
64
+ .map((x) => this.r.param(col.valueConverter.toDb(x)))
65
65
  .join(',') +
66
66
  ')');
67
67
  else
@@ -110,7 +110,7 @@ export class FilterConsumerBridgeToSqlRequest {
110
110
  ' ' +
111
111
  operator +
112
112
  ' ' +
113
- this.r.addParameterAndReturnSqlToken(col.valueConverter.toDb(val));
113
+ this.r.param(col.valueConverter.toDb(val));
114
114
  this.addToWhere(x);
115
115
  })());
116
116
  }
@@ -141,10 +141,15 @@ export class CustomSqlFilterBuilder {
141
141
  this.r = r;
142
142
  }
143
143
  sql = '';
144
- addParameterAndReturnSqlToken(val, field) {
145
- if (field)
144
+ /** @deprecated @deprecated use `param` instead*/
145
+ addParameterAndReturnSqlToken(val) {
146
+ return this.param(val);
147
+ }
148
+ param(val, field) {
149
+ if (typeof field === 'object' && field.valueConverter.toDb) {
146
150
  val = field.valueConverter.toDb(val);
147
- return this.r.addParameterAndReturnSqlToken(val);
151
+ }
152
+ return this.r.param(val);
148
153
  }
149
154
  async filterToRaw(repo, condition) {
150
155
  return SqlDatabase.filterToRaw(repo, condition, this);
@@ -39,6 +39,12 @@ export class RepositoryImplementation {
39
39
  dataProvider;
40
40
  _info;
41
41
  defaultFindOptions;
42
+ notFoundError(id) {
43
+ return {
44
+ message: `id ${id} not found in entity ${this.metadata.key}`,
45
+ httpStatusCode: 404,
46
+ };
47
+ }
42
48
  [getInternalKey]() {
43
49
  return this;
44
50
  }
@@ -191,8 +197,9 @@ export class RepositoryImplementation {
191
197
  return this.edp.delete(item);
192
198
  else {
193
199
  let ref2 = await this.findId(item);
194
- if (ref2)
195
- return await getEntityRef(ref2).delete();
200
+ if (!ref2)
201
+ throw this.notFoundError(item);
202
+ return await getEntityRef(ref2).delete();
196
203
  }
197
204
  let ref2 = this.getRefForExistingRow(item, undefined);
198
205
  if (!this.dataProvider.isProxy)
@@ -201,11 +208,30 @@ export class RepositoryImplementation {
201
208
  }
202
209
  async insert(entity) {
203
210
  if (Array.isArray(entity)) {
204
- let r = [];
205
- for (const item of entity) {
206
- r.push(await this.insert(item));
211
+ if (this.dataProvider.isProxy) {
212
+ let refs = [];
213
+ let raw = [];
214
+ for (const item of entity) {
215
+ let ref = getEntityRef(entity, false);
216
+ if (ref) {
217
+ if (!ref.isNew())
218
+ throw 'Item is not new';
219
+ }
220
+ else {
221
+ ref = (await this.getEntityRef(this.create(item)));
222
+ }
223
+ refs.push(ref);
224
+ raw.push(await ref.buildDtoForInsert());
225
+ }
226
+ return Promise.all((await this.edp.insertMany(raw)).map((item, i) => refs[i].processInsertResponseDto(item)));
227
+ }
228
+ else {
229
+ let r = [];
230
+ for (const item of entity) {
231
+ r.push(await this.insert(item));
232
+ }
233
+ return r;
207
234
  }
208
- return r;
209
235
  }
210
236
  else {
211
237
  let ref = getEntityRef(entity, false);
@@ -243,6 +269,20 @@ export class RepositoryImplementation {
243
269
  }
244
270
  }
245
271
  }
272
+ async updateMany(where, set) {
273
+ if (this.dataProvider.isProxy) {
274
+ return this.edp.updateMany(await this.translateWhereToFilter(where), set);
275
+ }
276
+ else {
277
+ let updated = 0;
278
+ for await (const item of this.query({ where })) {
279
+ assign(item, set);
280
+ await getEntityRef(item).save();
281
+ updated++;
282
+ }
283
+ return updated;
284
+ }
285
+ }
246
286
  async update(id, entity) {
247
287
  {
248
288
  let ref = getEntityRef(entity, false);
@@ -269,7 +309,7 @@ export class RepositoryImplementation {
269
309
  else {
270
310
  const r = await ref.reload();
271
311
  if (!r)
272
- throw new Error('Not Found');
312
+ throw this.notFoundError(ref.id);
273
313
  for (const key in entity) {
274
314
  if (Object.prototype.hasOwnProperty.call(entity, key)) {
275
315
  let f = ref.fields[key];
@@ -595,6 +635,19 @@ export class RepositoryImplementation {
595
635
  async count(where) {
596
636
  return this.edp.count(await this.translateWhereToFilter(where));
597
637
  }
638
+ async deleteMany(where) {
639
+ if (this.dataProvider.isProxy) {
640
+ return this.edp.deleteMany(await this.translateWhereToFilter(where));
641
+ }
642
+ else {
643
+ let deleted = 0;
644
+ for await (const item of this.query({ where })) {
645
+ await getEntityRef(item).delete();
646
+ deleted++;
647
+ }
648
+ return deleted;
649
+ }
650
+ }
598
651
  cache = new Map();
599
652
  async findOne(options, skipOrderByAndLimit = false) {
600
653
  let r;
@@ -1147,7 +1200,11 @@ export class rowHelperImplementation extends rowHelperBase {
1147
1200
  this.__clearErrorsAndReportChanged();
1148
1201
  }
1149
1202
  async reload() {
1150
- await this.edp.find({ where: this.getIdFilter() }).then(async (newData) => {
1203
+ await this.edp
1204
+ .find({ where: await this.getIdFilter() })
1205
+ .then(async (newData) => {
1206
+ if (newData.length === 0)
1207
+ throw this.repository.notFoundError(this.id);
1151
1208
  await this.loadDataFrom(newData[0]);
1152
1209
  this.saveOriginalData();
1153
1210
  });
@@ -1232,7 +1289,7 @@ export class rowHelperImplementation extends rowHelperBase {
1232
1289
  if (!wasChanged)
1233
1290
  return this.instance;
1234
1291
  if (doNotSave) {
1235
- updatedRow = (await this.edp.find({ where: this.getIdFilter() }))[0];
1292
+ updatedRow = (await this.edp.find({ where: await this.getIdFilter() }))[0];
1236
1293
  }
1237
1294
  else {
1238
1295
  updatedRow = await this.edp.update(this.id, changesOnly);
@@ -1262,6 +1319,27 @@ export class rowHelperImplementation extends rowHelperBase {
1262
1319
  this._saving = false;
1263
1320
  }
1264
1321
  }
1322
+ async processInsertResponseDto(updatedRow) {
1323
+ await this.loadDataFrom(updatedRow);
1324
+ this.saveOriginalData();
1325
+ this._isNew = false;
1326
+ return this.instance;
1327
+ }
1328
+ async buildDtoForInsert() {
1329
+ await this.__validateEntity();
1330
+ this.__assertValidity();
1331
+ let d = this.copyDataToObject(this.isNew());
1332
+ let ignoreKeys = [];
1333
+ for (const field of this.metadata.fields) {
1334
+ if (field.dbReadOnly) {
1335
+ d[field.key] = undefined;
1336
+ ignoreKeys.push(field.key);
1337
+ let f = this.fields.find(field);
1338
+ f.value = f.originalValue;
1339
+ }
1340
+ }
1341
+ return d;
1342
+ }
1265
1343
  buildLifeCycleEvent(preventDefault = () => { }) {
1266
1344
  const self = this;
1267
1345
  return {
@@ -1275,8 +1353,8 @@ export class rowHelperImplementation extends rowHelperBase {
1275
1353
  relations: self.repository.relations(self.instance),
1276
1354
  };
1277
1355
  }
1278
- getIdFilter() {
1279
- return Filter.fromEntityFilter(this.metadata, this.repository.metadata.idMetadata.getIdFilter(this.id));
1356
+ async getIdFilter() {
1357
+ return await this.repository.translateWhereToFilter(this.repository.metadata.idMetadata.getIdFilter(this.id));
1280
1358
  }
1281
1359
  async delete() {
1282
1360
  this.__clearErrorsAndReportChanged();