remult 0.25.8-exp.2 → 0.25.8-exp.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/esm/graphql.js CHANGED
@@ -904,7 +904,7 @@ export function translateWhereToRestBody(fields, { where }) {
904
904
  }
905
905
  }
906
906
  if (where.OR) {
907
- result.OR = where.OR.map((where) => translateWhereToRestBody(fields, { where }));
907
+ result.OR = where.OR.map((where) => translateWhereToRestBody(fields, { where }).where);
908
908
  }
909
- return result;
909
+ return { where: result };
910
910
  }
@@ -250,8 +250,8 @@ export class RemultServerImplementation {
250
250
  console.info('[remult] ' + myRoute);
251
251
  r.route(myRoute)
252
252
  .get(this.process((c, req, res, orig) => dataApiFactory(c).httpGet(res, req, () => this.serializeContext(c))))
253
- .put(this.process(async (c, req, res, _, __, orig) => dataApiFactory(c).put(res, '', await this.coreOptions.getRequestBody(orig))))
254
- .delete(this.process(async (c, req, res, orig) => dataApiFactory(c).delete(res, '')))
253
+ .put(this.process(async (c, req, res, _, __, orig) => dataApiFactory(c).updateMany(res, req, await this.coreOptions.getRequestBody(orig))))
254
+ .delete(this.process(async (c, req, res, _, __, orig) => dataApiFactory(c).deleteMany(res, req, undefined)))
255
255
  .post(this.process(async (c, req, res, _, __, orig) => dataApiFactory(c).httpPost(res, req, await this.coreOptions.getRequestBody(orig), () => this.serializeContext(c))));
256
256
  r.route(myRoute + '/:id')
257
257
  //@ts-ignore
@@ -467,6 +467,17 @@ export class RemultServerImplementation {
467
467
  return secureBase(condition, def, item);
468
468
  };
469
469
  let apiPath = (spec.paths[this.options.rootPath + '/' + key] = {});
470
+ let itemInBody = {
471
+ requestBody: {
472
+ content: {
473
+ 'application/json': {
474
+ schema: {
475
+ $ref: '#/components/schemas/' + mutationKey,
476
+ },
477
+ },
478
+ },
479
+ },
480
+ };
470
481
  let apiPathWithId = (spec.paths[this.options.rootPath + '/' + key + '/{id}'] = {});
471
482
  //https://github.com/2fd/open-api.d.ts
472
483
  apiPath.get = secure(meta.options.allowApiRead, true, {
@@ -519,6 +530,73 @@ export class RemultServerImplementation {
519
530
  },
520
531
  },
521
532
  });
533
+ apiPath.delete = secure(meta.options.allowApiDelete, true, {
534
+ description: 'deletes row of ' +
535
+ key +
536
+ '. supports filter operators. For more info on filtering [see this article](https://remult.dev/docs/rest-api.html#filter)',
537
+ parameters: [...parameters],
538
+ responses: {
539
+ '400': {
540
+ description: 'Error: Bad Request',
541
+ content: {
542
+ 'application/json': {
543
+ schema: {
544
+ $ref: '#/components/schemas/InvalidResponse',
545
+ },
546
+ },
547
+ },
548
+ },
549
+ '200': {
550
+ description: 'returns the number of deleted rows ' + key,
551
+ content: {
552
+ 'application/json': {
553
+ schema: {
554
+ type: 'object',
555
+ properties: {
556
+ deleted: {
557
+ type: 'number',
558
+ },
559
+ },
560
+ },
561
+ },
562
+ },
563
+ },
564
+ },
565
+ });
566
+ apiPath.put = secure(meta.options.allowApiDelete, true, {
567
+ description: 'updates row of ' +
568
+ key +
569
+ '. supports filter operators. For more info on filtering [see this article](https://remult.dev/docs/rest-api.html#filter)',
570
+ parameters: [...parameters],
571
+ ...itemInBody,
572
+ responses: {
573
+ '400': {
574
+ description: 'Error: Bad Request',
575
+ content: {
576
+ 'application/json': {
577
+ schema: {
578
+ $ref: '#/components/schemas/InvalidResponse',
579
+ },
580
+ },
581
+ },
582
+ },
583
+ '200': {
584
+ description: 'returns the number of updated rows ' + key,
585
+ content: {
586
+ 'application/json': {
587
+ schema: {
588
+ type: 'object',
589
+ properties: {
590
+ updated: {
591
+ type: 'number',
592
+ },
593
+ },
594
+ },
595
+ },
596
+ },
597
+ },
598
+ },
599
+ });
522
600
  let idParameter = {
523
601
  name: 'id',
524
602
  in: 'path',
@@ -526,17 +604,6 @@ export class RemultServerImplementation {
526
604
  required: true,
527
605
  schema: { type: 'string' },
528
606
  };
529
- let itemInBody = {
530
- requestBody: {
531
- content: {
532
- 'application/json': {
533
- schema: {
534
- $ref: '#/components/schemas/' + mutationKey,
535
- },
536
- },
537
- },
538
- },
539
- };
540
607
  apiPath.post = secure(meta.options.allowApiInsert, false, {
541
608
  //"summary": "insert a " + key,
542
609
  //"description": "insert a " + key,
@@ -33,7 +33,7 @@ export class DataApi {
33
33
  case 'deleteMany':
34
34
  return this.deleteMany(res, req, body);
35
35
  case 'updateMany':
36
- return this.updateMany(res, req, body);
36
+ return this.updateManyImplementation(res, req, body);
37
37
  case 'endLiveQuery':
38
38
  await this.remult.liveQueryStorage.remove(body.id);
39
39
  res.success('ok');
@@ -50,26 +50,28 @@ export class DataApi {
50
50
  }
51
51
  await this.doOnId(response, id, async (row) => response.success(this.repository.getEntityRef(row).toApiJson()));
52
52
  }
53
- async count(response, request, filterBody) {
53
+ async count(response, request, body) {
54
54
  if (!this.repository.metadata.apiReadAllowed) {
55
55
  response.forbidden();
56
56
  return;
57
57
  }
58
58
  try {
59
59
  response.success({
60
- count: +(await this.repository.count(await this.buildWhere(request, filterBody))),
60
+ count: +(await this.repository.count(await this.buildWhere(request, body))),
61
61
  });
62
62
  }
63
63
  catch (err) {
64
64
  response.error(err, this.repository.metadata);
65
65
  }
66
66
  }
67
- async deleteMany(response, request, filterBody) {
67
+ async deleteMany(response, request, body) {
68
68
  try {
69
+ let deleted = 0;
70
+ let where = await this.buildWhere(request, body);
71
+ Filter.throwErrorIfFilterIsEmpty(where, 'deleteMany');
69
72
  return await doTransaction(this.remult, async () => {
70
- let deleted = 0;
71
73
  for await (const x of this.repository.query({
72
- where: await this.buildWhere(request, filterBody),
74
+ where,
73
75
  include: this.includeNone(),
74
76
  })) {
75
77
  await this.actualDelete(x);
@@ -82,12 +84,12 @@ export class DataApi {
82
84
  response.error(err, this.repository.metadata);
83
85
  }
84
86
  }
85
- async getArrayImpl(response, request, filterBody) {
87
+ async getArrayImpl(response, request, body) {
86
88
  let findOptions = {
87
89
  load: () => [],
88
90
  include: this.includeNone(),
89
91
  };
90
- findOptions.where = await this.buildWhere(request, filterBody);
92
+ findOptions.where = await this.buildWhere(request, body);
91
93
  if (request) {
92
94
  let sort = request.get('_sort');
93
95
  if (sort != undefined) {
@@ -146,13 +148,13 @@ export class DataApi {
146
148
  }
147
149
  return include;
148
150
  }
149
- async getArray(response, request, filterBody) {
151
+ async getArray(response, request, body) {
150
152
  if (!this.repository.metadata.apiReadAllowed) {
151
153
  response.forbidden();
152
154
  return;
153
155
  }
154
156
  try {
155
- const { r } = await this.getArrayImpl(response, request, filterBody);
157
+ const { r } = await this.getArrayImpl(response, request, body);
156
158
  response.success(r);
157
159
  }
158
160
  catch (err) {
@@ -162,13 +164,13 @@ export class DataApi {
162
164
  response.error(err, this.repository.metadata);
163
165
  }
164
166
  }
165
- async liveQuery(response, request, filterBody, serializeContext, queryChannel) {
167
+ async liveQuery(response, request, body, serializeContext, queryChannel) {
166
168
  if (!this.repository.metadata.apiReadAllowed) {
167
169
  response.forbidden();
168
170
  return;
169
171
  }
170
172
  try {
171
- const r = await this.getArrayImpl(response, request, filterBody);
173
+ const r = await this.getArrayImpl(response, request, body);
172
174
  const data = {
173
175
  requestJson: await serializeContext(),
174
176
  findOptionsJson: findOptionsToJson(r.findOptions, this.repository.metadata),
@@ -188,7 +190,7 @@ export class DataApi {
188
190
  response.error(err, this.repository.metadata);
189
191
  }
190
192
  }
191
- async buildWhere(request, filterBody) {
193
+ async buildWhere(request, body) {
192
194
  var where = [];
193
195
  if (this.repository.metadata.options.apiPrefilter) {
194
196
  if (typeof this.repository.metadata.options.apiPrefilter === 'function')
@@ -208,8 +210,8 @@ export class DataApi {
208
210
  },
209
211
  }));
210
212
  }
211
- if (filterBody)
212
- where.push(Filter.entityFilterFromJson(this.repository.metadata, filterBody));
213
+ if (body?.where)
214
+ where.push(Filter.entityFilterFromJson(this.repository.metadata, body.where));
213
215
  return { $and: where };
214
216
  }
215
217
  async doOnId(response, id, what) {
@@ -245,11 +247,23 @@ export class DataApi {
245
247
  }
246
248
  }
247
249
  async updateMany(response, request, body) {
250
+ const action = request?.get('__action');
251
+ if (action == 'emptyId') {
252
+ return this.put(response, '', body);
253
+ }
254
+ let where = await this.buildWhere(request, body);
255
+ Filter.throwErrorIfFilterIsEmpty(where, 'updateMany');
256
+ return this.updateManyImplementation(response, request, {
257
+ where: undefined,
258
+ set: body,
259
+ });
260
+ }
261
+ async updateManyImplementation(response, request, body) {
248
262
  try {
249
263
  return await doTransaction(this.remult, async () => {
250
264
  let updated = 0;
251
265
  for await (const x of this.repository.query({
252
- where: await this.buildWhere(request, body.where),
266
+ where: await this.buildWhere(request, body),
253
267
  include: this.includeNone(),
254
268
  })) {
255
269
  await this.actualUpdate(x, body.set);
@@ -120,26 +120,27 @@ export class RestEntityDataProvider {
120
120
  return run('count').then((r) => +r.count);
121
121
  }
122
122
  async deleteMany(where) {
123
- const { run } = this.buildFindRequest({ where }, true);
123
+ const { run } = this.buildFindRequest({ where }, 'delete');
124
124
  return run('deleteMany').then((r) => +r.deleted);
125
125
  }
126
126
  async updateMany(where, data) {
127
- const { run } = this.buildFindRequest({ where }, true);
128
- return run('updateMany', { set: this.toJsonOfIncludedKeys(data) }).then((r) => +r.updated);
127
+ const { run } = this.buildFindRequest({ where }, 'put');
128
+ return run('updateMany', this.toJsonOfIncludedKeys(data)).then((r) => +r.updated);
129
129
  }
130
130
  find(options) {
131
131
  let { run } = this.buildFindRequest(options);
132
132
  return run().then((x) => x.map((y) => this.translateFromJson(y)));
133
133
  }
134
134
  //@internal
135
- buildFindRequest(options, forcePost = false) {
135
+ buildFindRequest(options, method) {
136
+ if (!method)
137
+ method = 'get';
136
138
  let url = new UrlBuilder(this.url());
137
139
  let filterObject;
138
140
  if (options) {
139
141
  if (options.where) {
140
142
  filterObject = options.where.toJson(); // options.where.__applyToConsumer(new FilterConsumnerBridgeToUrlBuilder(url));
141
- if (!forcePost &&
142
- addFilterToUrlAndReturnTrueIfSuccessful(filterObject, url))
143
+ if (addFilterToUrlAndReturnTrueIfSuccessful(filterObject, url))
143
144
  filterObject = undefined;
144
145
  }
145
146
  if (options.orderBy && options.orderBy.Segments) {
@@ -173,15 +174,12 @@ export class RestEntityDataProvider {
173
174
  }
174
175
  if (action)
175
176
  u.add('__action', action);
176
- if (filterObject || forcePost) {
177
- if (!body)
178
- body = filterObject;
179
- else
180
- body = { ...body, where: filterObject };
177
+ if (filterObject) {
178
+ body = { set: body, where: filterObject };
181
179
  return this.http().post(u.url, body);
182
180
  }
183
181
  else
184
- return this.http().get(u.url);
182
+ return this.http()[method](u.url, body);
185
183
  };
186
184
  return {
187
185
  createKey: () => JSON.stringify({ url, filterObject }),
@@ -201,7 +199,8 @@ export class RestEntityDataProvider {
201
199
  }
202
200
  update(id, data) {
203
201
  return this.http()
204
- .put(this.url() + '/' + encodeURIComponent(id), this.toJsonOfIncludedKeys(data))
202
+ .put(this.url() +
203
+ (id != '' ? '/' + encodeURIComponent(id) : '?__action=emptyId'), this.toJsonOfIncludedKeys(data))
205
204
  .then((y) => this.translateFromJson(y));
206
205
  }
207
206
  toJsonOfIncludedKeys(data) {
@@ -213,8 +212,11 @@ export class RestEntityDataProvider {
213
212
  }
214
213
  return result;
215
214
  }
216
- delete(id) {
217
- return this.http().delete(this.url() + '/' + encodeURIComponent(id));
215
+ async delete(id) {
216
+ if (id == '')
217
+ await this.deleteMany(Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(id)));
218
+ else
219
+ return this.http().delete(this.url() + '/' + encodeURIComponent(id));
218
220
  }
219
221
  insert(data) {
220
222
  return this.http()
@@ -6,6 +6,37 @@ import { getRelationFieldInfo } from '../remult3/relationInfoMember.js';
6
6
  */
7
7
  export class Filter {
8
8
  apply;
9
+ //@internal
10
+ static throwErrorIfFilterIsEmpty(where, methodName) {
11
+ if (Filter.isFilterEmpty(where)) {
12
+ throw {
13
+ message: `${methodName}: requires a filter to protect against accidental delete/update of all rows`,
14
+ httpStatusCode: 400,
15
+ };
16
+ }
17
+ }
18
+ //@internal
19
+ static isFilterEmpty(where) {
20
+ if (where.$and) {
21
+ for (const a of where.$and) {
22
+ if (!Filter.isFilterEmpty(a)) {
23
+ return false;
24
+ }
25
+ }
26
+ }
27
+ if (where.$or) {
28
+ for (const a of where.$or) {
29
+ if (Filter.isFilterEmpty(a)) {
30
+ return true;
31
+ }
32
+ }
33
+ return false;
34
+ }
35
+ if (Object.keys(where).filter((x) => !['$or', '$and'].includes(x)).length == 0) {
36
+ return true;
37
+ }
38
+ return false;
39
+ }
9
40
  static createCustom(rawFilterTranslator, key = '') {
10
41
  let rawFilterInfo = { key: key, rawFilterTranslator };
11
42
  return Object.assign((x) => {
@@ -270,6 +270,7 @@ export class RepositoryImplementation {
270
270
  }
271
271
  }
272
272
  async updateMany(where, set) {
273
+ Filter.throwErrorIfFilterIsEmpty(where, 'updateMany');
273
274
  if (this._dataProvider.isProxy) {
274
275
  return this._edp.updateMany(await this._translateWhereToFilter(where), set);
275
276
  }
@@ -636,6 +637,7 @@ export class RepositoryImplementation {
636
637
  return this._edp.count(await this._translateWhereToFilter(where));
637
638
  }
638
639
  async deleteMany(where) {
640
+ Filter.throwErrorIfFilterIsEmpty(where, 'deleteMany');
639
641
  if (this._dataProvider.isProxy) {
640
642
  return this._edp.deleteMany(await this._translateWhereToFilter(where));
641
643
  }
@@ -1,16 +1,10 @@
1
1
  export {};
2
+ //y1 - reconsider adding where to all in case of post - it is a breaking change and no longer required
3
+ //y1 - review that with deleteMany, and updateMany I've taken a similar approach to get, that when the filter is complex, we go to post - one reason is that delete doesn't accept a body.
4
+ //y1 - should the remult api be deleteMany({id:[1,2]}) or deleteMany({where:{id:[1,2]}})
2
5
  //p1 - in this video I'll use remult to turn a frontend app to a fullstack app
3
- /*p1 - discuss using delete & put - with url query language for deleteMany and updateMany -
4
- - put & delete, similar to get
5
- - add where to count, deleteMany,updateMany,
6
- - prevent delete all and update all - must have meaningful where.
7
- - try forcing this also in typescript
8
-
9
- - protect against deleting of all rows by mistake
10
- - https://github.com/remult/remult/issues/221#issuecomment-2016519746
11
-
12
- */
13
6
  //y1 - getFields didn't work for kobi in the home component
7
+ //y1 - consider replacing all errors with error classes that extend the base Error class
14
8
  //p1 - document offline support
15
9
  //p1 - add section to Fields doc, explaining field type in db
16
10
  //p1 - add section about union type
@@ -136,7 +136,7 @@ export class ValueConverters {
136
136
  toJson: (value) => ValueConverters.Number.toDb(value),
137
137
  fromInput: (x, type) => {
138
138
  let r = +x;
139
- if (!x)
139
+ if (x === null || x === undefined)
140
140
  return undefined;
141
141
  return r;
142
142
  },
package/graphql.js CHANGED
@@ -1081,10 +1081,8 @@ function translateWhereToRestBody(fields, _a) {
1081
1081
  finally { if (e_7) throw e_7.error; }
1082
1082
  }
1083
1083
  if (where.OR) {
1084
- result.OR = where.OR.map(function (where) {
1085
- return translateWhereToRestBody(fields, { where: where });
1086
- });
1084
+ result.OR = where.OR.map(function (where) { return translateWhereToRestBody(fields, { where: where }).where; });
1087
1085
  }
1088
- return result;
1086
+ return { where: result };
1089
1087
  }
1090
1088
  exports.translateWhereToRestBody = translateWhereToRestBody;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remult",
3
- "version": "0.25.8-exp.2",
3
+ "version": "0.25.8-exp.3",
4
4
  "description": "A CRUD framework for full-stack TypeScript",
5
5
  "homepage": "https://remult.dev",
6
6
  "repository": {
@@ -444,16 +444,16 @@ var RemultServerImplementation = /** @class */ (function () {
444
444
  return tslib_1.__generator(this, function (_d) {
445
445
  switch (_d.label) {
446
446
  case 0:
447
- _b = (_a = dataApiFactory(c)).put;
447
+ _b = (_a = dataApiFactory(c)).updateMany;
448
448
  _c = [res,
449
- ''];
449
+ req];
450
450
  return [4 /*yield*/, this.coreOptions.getRequestBody(orig)];
451
451
  case 1: return [2 /*return*/, _b.apply(_a, _c.concat([_d.sent()]))];
452
452
  }
453
453
  });
454
454
  }); }))
455
- .delete(this.process(function (c, req, res, orig) { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) {
456
- return [2 /*return*/, dataApiFactory(c).delete(res, '')];
455
+ .delete(this.process(function (c, req, res, _, __, orig) { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) {
456
+ return [2 /*return*/, dataApiFactory(c).deleteMany(res, req, undefined)];
457
457
  }); }); }))
458
458
  .post(this.process(function (c, req, res, _, __, orig) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
459
459
  var _a, _b, _c;
@@ -792,6 +792,17 @@ var RemultServerImplementation = /** @class */ (function () {
792
792
  return secureBase(condition, def, item);
793
793
  };
794
794
  var apiPath = (spec.paths[this_2.options.rootPath + '/' + key] = {});
795
+ var itemInBody = {
796
+ requestBody: {
797
+ content: {
798
+ 'application/json': {
799
+ schema: {
800
+ $ref: '#/components/schemas/' + mutationKey,
801
+ },
802
+ },
803
+ },
804
+ },
805
+ };
795
806
  var apiPathWithId = (spec.paths[this_2.options.rootPath + '/' + key + '/{id}'] = {});
796
807
  //https://github.com/2fd/open-api.d.ts
797
808
  apiPath.get = secure(meta.options.allowApiRead, true, {
@@ -843,6 +854,68 @@ var RemultServerImplementation = /** @class */ (function () {
843
854
  },
844
855
  },
845
856
  });
857
+ apiPath.delete = secure(meta.options.allowApiDelete, true, {
858
+ description: 'deletes row of ' +
859
+ key +
860
+ '. supports filter operators. For more info on filtering [see this article](https://remult.dev/docs/rest-api.html#filter)',
861
+ parameters: tslib_1.__spreadArray([], tslib_1.__read(parameters), false),
862
+ responses: {
863
+ '400': {
864
+ description: 'Error: Bad Request',
865
+ content: {
866
+ 'application/json': {
867
+ schema: {
868
+ $ref: '#/components/schemas/InvalidResponse',
869
+ },
870
+ },
871
+ },
872
+ },
873
+ '200': {
874
+ description: 'returns the number of deleted rows ' + key,
875
+ content: {
876
+ 'application/json': {
877
+ schema: {
878
+ type: 'object',
879
+ properties: {
880
+ deleted: {
881
+ type: 'number',
882
+ },
883
+ },
884
+ },
885
+ },
886
+ },
887
+ },
888
+ },
889
+ });
890
+ apiPath.put = secure(meta.options.allowApiDelete, true, tslib_1.__assign(tslib_1.__assign({ description: 'updates row of ' +
891
+ key +
892
+ '. supports filter operators. For more info on filtering [see this article](https://remult.dev/docs/rest-api.html#filter)', parameters: tslib_1.__spreadArray([], tslib_1.__read(parameters), false) }, itemInBody), { responses: {
893
+ '400': {
894
+ description: 'Error: Bad Request',
895
+ content: {
896
+ 'application/json': {
897
+ schema: {
898
+ $ref: '#/components/schemas/InvalidResponse',
899
+ },
900
+ },
901
+ },
902
+ },
903
+ '200': {
904
+ description: 'returns the number of updated rows ' + key,
905
+ content: {
906
+ 'application/json': {
907
+ schema: {
908
+ type: 'object',
909
+ properties: {
910
+ updated: {
911
+ type: 'number',
912
+ },
913
+ },
914
+ },
915
+ },
916
+ },
917
+ },
918
+ } }));
846
919
  var idParameter = {
847
920
  name: 'id',
848
921
  in: 'path',
@@ -850,17 +923,6 @@ var RemultServerImplementation = /** @class */ (function () {
850
923
  required: true,
851
924
  schema: { type: 'string' },
852
925
  };
853
- var itemInBody = {
854
- requestBody: {
855
- content: {
856
- 'application/json': {
857
- schema: {
858
- $ref: '#/components/schemas/' + mutationKey,
859
- },
860
- },
861
- },
862
- },
863
- };
864
926
  apiPath.post = secure(meta.options.allowApiInsert, false, tslib_1.__assign(tslib_1.__assign({
865
927
  //"summary": "insert a " + key,
866
928
  //"description": "insert a " + key,
package/src/context.d.ts CHANGED
@@ -92,6 +92,8 @@ export interface ApiClient {
92
92
  * @example
93
93
  * // Using Angular HttpClient
94
94
  * remult.apiClient.httpClient = httpClient;
95
+ * @see
96
+ * If you want to add headers using angular httpClient, see: https://medium.com/angular-shots/shot-3-how-to-add-http-headers-to-every-request-in-angular-fab3d10edc26
95
97
  *
96
98
  * @example
97
99
  * // Using fetch (default)
package/src/data-api.d.ts CHANGED
@@ -10,18 +10,22 @@ export declare class DataApi<T = any> {
10
10
  httpPost(res: DataApiResponse, req: DataApiRequest, body: any, serializeContext: () => Promise<any>): Promise<void>;
11
11
  static defaultGetLimit: number;
12
12
  get(response: DataApiResponse, id: any): Promise<void>;
13
- count(response: DataApiResponse, request: DataApiRequest, filterBody?: any): Promise<void>;
14
- deleteMany(response: DataApiResponse, request: DataApiRequest, filterBody?: any): Promise<void>;
15
- getArrayImpl(response: DataApiResponse, request: DataApiRequest, filterBody: any): Promise<{
13
+ count(response: DataApiResponse, request: DataApiRequest, body?: any): Promise<void>;
14
+ deleteMany(response: DataApiResponse, request: DataApiRequest, body?: any): Promise<void>;
15
+ getArrayImpl(response: DataApiResponse, request: DataApiRequest, body: any): Promise<{
16
16
  r: any[];
17
17
  findOptions: FindOptions<T>;
18
18
  }>;
19
19
  private includeNone;
20
- getArray(response: DataApiResponse, request: DataApiRequest, filterBody?: any): Promise<void>;
21
- liveQuery(response: DataApiResponse, request: DataApiRequest, filterBody: any, serializeContext: () => Promise<any>, queryChannel: string): Promise<void>;
20
+ getArray(response: DataApiResponse, request: DataApiRequest, body?: any): Promise<void>;
21
+ liveQuery(response: DataApiResponse, request: DataApiRequest, body: any, serializeContext: () => Promise<any>, queryChannel: string): Promise<void>;
22
22
  private buildWhere;
23
23
  private doOnId;
24
- updateMany(response: DataApiResponse, request: DataApiRequest, body?: any): Promise<void>;
24
+ updateMany(response: DataApiResponse, request: DataApiRequest, body: any): Promise<void>;
25
+ updateManyImplementation(response: DataApiResponse, request: DataApiRequest, body: {
26
+ where: any;
27
+ set: any;
28
+ }): Promise<void>;
25
29
  actualUpdate(row: any, body: any): Promise<rowHelperImplementation<T>>;
26
30
  put(response: DataApiResponse, id: any, body: any): Promise<void>;
27
31
  actualDelete(row: any): Promise<void>;
package/src/data-api.js CHANGED
@@ -44,7 +44,7 @@ var DataApi = /** @class */ (function () {
44
44
  case 1: return [2 /*return*/, this.getArray(res, req, body)];
45
45
  case 2: return [2 /*return*/, this.count(res, req, body)];
46
46
  case 3: return [2 /*return*/, this.deleteMany(res, req, body)];
47
- case 4: return [2 /*return*/, this.updateMany(res, req, body)];
47
+ case 4: return [2 /*return*/, this.updateManyImplementation(res, req, body)];
48
48
  case 5: return [4 /*yield*/, this.remult.liveQueryStorage.remove(body.id)];
49
49
  case 6:
50
50
  _b.sent();
@@ -75,7 +75,7 @@ var DataApi = /** @class */ (function () {
75
75
  });
76
76
  });
77
77
  };
78
- DataApi.prototype.count = function (response, request, filterBody) {
78
+ DataApi.prototype.count = function (response, request, body) {
79
79
  return tslib_1.__awaiter(this, void 0, void 0, function () {
80
80
  var _a, _b, _c, _d, err_1;
81
81
  var _e;
@@ -92,7 +92,7 @@ var DataApi = /** @class */ (function () {
92
92
  _b = (_a = response).success;
93
93
  _e = {};
94
94
  _d = (_c = this.repository).count;
95
- return [4 /*yield*/, this.buildWhere(request, filterBody)];
95
+ return [4 /*yield*/, this.buildWhere(request, body)];
96
96
  case 2: return [4 /*yield*/, _d.apply(_c, [_f.sent()])];
97
97
  case 3:
98
98
  _b.apply(_a, [(_e.count = +(_f.sent()),
@@ -107,82 +107,79 @@ var DataApi = /** @class */ (function () {
107
107
  });
108
108
  });
109
109
  };
110
- DataApi.prototype.deleteMany = function (response, request, filterBody) {
110
+ DataApi.prototype.deleteMany = function (response, request, body) {
111
111
  return tslib_1.__awaiter(this, void 0, void 0, function () {
112
- var err_2;
112
+ var deleted_1, where_1, err_2;
113
113
  var _this = this;
114
114
  return tslib_1.__generator(this, function (_a) {
115
115
  switch (_a.label) {
116
116
  case 0:
117
- _a.trys.push([0, 2, , 3]);
117
+ _a.trys.push([0, 3, , 4]);
118
+ deleted_1 = 0;
119
+ return [4 /*yield*/, this.buildWhere(request, body)];
120
+ case 1:
121
+ where_1 = _a.sent();
122
+ filter_interfaces_js_1.Filter.throwErrorIfFilterIsEmpty(where_1, 'deleteMany');
118
123
  return [4 /*yield*/, (0, context_js_1.doTransaction)(this.remult, function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
119
- var deleted, _a, _b, _c, _d, _e, x, e_1_1;
120
- var _f;
121
- var _g, e_1, _h, _j;
122
- return tslib_1.__generator(this, function (_k) {
123
- switch (_k.label) {
124
+ var _a, _b, _c, x, e_1_1;
125
+ var _d, e_1, _e, _f;
126
+ return tslib_1.__generator(this, function (_g) {
127
+ switch (_g.label) {
124
128
  case 0:
125
- deleted = 0;
126
- _k.label = 1;
127
- case 1:
128
- _k.trys.push([1, 8, 9, 14]);
129
- _a = true;
130
- _e = (_d = this.repository).query;
131
- _f = {};
132
- return [4 /*yield*/, this.buildWhere(request, filterBody)];
129
+ _g.trys.push([0, 6, 7, 12]);
130
+ _a = true, _b = tslib_1.__asyncValues(this.repository.query({
131
+ where: where_1,
132
+ include: this.includeNone(),
133
+ }));
134
+ _g.label = 1;
135
+ case 1: return [4 /*yield*/, _b.next()];
133
136
  case 2:
134
- _b = tslib_1.__asyncValues.apply(void 0, [_e.apply(_d, [(_f.where = _k.sent(),
135
- _f.include = this.includeNone(),
136
- _f)])]);
137
- _k.label = 3;
138
- case 3: return [4 /*yield*/, _b.next()];
139
- case 4:
140
- if (!(_c = _k.sent(), _g = _c.done, !_g)) return [3 /*break*/, 7];
141
- _j = _c.value;
137
+ if (!(_c = _g.sent(), _d = _c.done, !_d)) return [3 /*break*/, 5];
138
+ _f = _c.value;
142
139
  _a = false;
143
- x = _j;
140
+ x = _f;
144
141
  return [4 /*yield*/, this.actualDelete(x)];
145
- case 5:
146
- _k.sent();
147
- deleted++;
148
- _k.label = 6;
149
- case 6:
142
+ case 3:
143
+ _g.sent();
144
+ deleted_1++;
145
+ _g.label = 4;
146
+ case 4:
150
147
  _a = true;
151
- return [3 /*break*/, 3];
152
- case 7: return [3 /*break*/, 14];
153
- case 8:
154
- e_1_1 = _k.sent();
148
+ return [3 /*break*/, 1];
149
+ case 5: return [3 /*break*/, 12];
150
+ case 6:
151
+ e_1_1 = _g.sent();
155
152
  e_1 = { error: e_1_1 };
156
- return [3 /*break*/, 14];
157
- case 9:
158
- _k.trys.push([9, , 12, 13]);
159
- if (!(!_a && !_g && (_h = _b.return))) return [3 /*break*/, 11];
160
- return [4 /*yield*/, _h.call(_b)];
153
+ return [3 /*break*/, 12];
154
+ case 7:
155
+ _g.trys.push([7, , 10, 11]);
156
+ if (!(!_a && !_d && (_e = _b.return))) return [3 /*break*/, 9];
157
+ return [4 /*yield*/, _e.call(_b)];
158
+ case 8:
159
+ _g.sent();
160
+ _g.label = 9;
161
+ case 9: return [3 /*break*/, 11];
161
162
  case 10:
162
- _k.sent();
163
- _k.label = 11;
164
- case 11: return [3 /*break*/, 13];
165
- case 12:
166
163
  if (e_1) throw e_1.error;
167
164
  return [7 /*endfinally*/];
168
- case 13: return [7 /*endfinally*/];
169
- case 14:
170
- response.success({ deleted: deleted });
165
+ case 11: return [7 /*endfinally*/];
166
+ case 12:
167
+ response.success({ deleted: deleted_1 });
171
168
  return [2 /*return*/];
172
169
  }
173
170
  });
174
171
  }); })];
175
- case 1: return [2 /*return*/, _a.sent()];
176
- case 2:
172
+ case 2: return [2 /*return*/, _a.sent()];
173
+ case 3:
177
174
  err_2 = _a.sent();
178
175
  response.error(err_2, this.repository.metadata);
179
- return [3 /*break*/, 3];
180
- case 3: return [2 /*return*/];
176
+ return [3 /*break*/, 4];
177
+ case 4: return [2 /*return*/];
181
178
  }
182
179
  });
183
180
  });
184
181
  };
185
- DataApi.prototype.getArrayImpl = function (response, request, filterBody) {
182
+ DataApi.prototype.getArrayImpl = function (response, request, body) {
186
183
  return tslib_1.__awaiter(this, void 0, void 0, function () {
187
184
  var findOptions, _a, sort, dir, limit, hasId_1, w, r;
188
185
  var _this = this;
@@ -194,7 +191,7 @@ var DataApi = /** @class */ (function () {
194
191
  include: this.includeNone(),
195
192
  };
196
193
  _a = findOptions;
197
- return [4 /*yield*/, this.buildWhere(request, filterBody)];
194
+ return [4 /*yield*/, this.buildWhere(request, body)];
198
195
  case 1:
199
196
  _a.where = _b.sent();
200
197
  if (request) {
@@ -281,7 +278,7 @@ var DataApi = /** @class */ (function () {
281
278
  }
282
279
  return include;
283
280
  };
284
- DataApi.prototype.getArray = function (response, request, filterBody) {
281
+ DataApi.prototype.getArray = function (response, request, body) {
285
282
  return tslib_1.__awaiter(this, void 0, void 0, function () {
286
283
  var r, err_3;
287
284
  return tslib_1.__generator(this, function (_a) {
@@ -294,7 +291,7 @@ var DataApi = /** @class */ (function () {
294
291
  _a.label = 1;
295
292
  case 1:
296
293
  _a.trys.push([1, 3, , 4]);
297
- return [4 /*yield*/, this.getArrayImpl(response, request, filterBody)];
294
+ return [4 /*yield*/, this.getArrayImpl(response, request, body)];
298
295
  case 2:
299
296
  r = (_a.sent()).r;
300
297
  response.success(r);
@@ -311,7 +308,7 @@ var DataApi = /** @class */ (function () {
311
308
  });
312
309
  });
313
310
  };
314
- DataApi.prototype.liveQuery = function (response, request, filterBody, serializeContext, queryChannel) {
311
+ DataApi.prototype.liveQuery = function (response, request, body, serializeContext, queryChannel) {
315
312
  return tslib_1.__awaiter(this, void 0, void 0, function () {
316
313
  var r, data, err_4;
317
314
  var _a;
@@ -326,7 +323,7 @@ var DataApi = /** @class */ (function () {
326
323
  _b.label = 1;
327
324
  case 1:
328
325
  _b.trys.push([1, 5, , 6]);
329
- return [4 /*yield*/, this.getArrayImpl(response, request, filterBody)];
326
+ return [4 /*yield*/, this.getArrayImpl(response, request, body)];
330
327
  case 2:
331
328
  r = _b.sent();
332
329
  _a = {};
@@ -357,7 +354,7 @@ var DataApi = /** @class */ (function () {
357
354
  });
358
355
  });
359
356
  };
360
- DataApi.prototype.buildWhere = function (request, filterBody) {
357
+ DataApi.prototype.buildWhere = function (request, body) {
361
358
  return tslib_1.__awaiter(this, void 0, void 0, function () {
362
359
  var where, _a, _b;
363
360
  return tslib_1.__generator(this, function (_c) {
@@ -387,8 +384,8 @@ var DataApi = /** @class */ (function () {
387
384
  },
388
385
  }));
389
386
  }
390
- if (filterBody)
391
- where.push(filter_interfaces_js_1.Filter.entityFilterFromJson(this.repository.metadata, filterBody));
387
+ if (body === null || body === void 0 ? void 0 : body.where)
388
+ where.push(filter_interfaces_js_1.Filter.entityFilterFromJson(this.repository.metadata, body.where));
392
389
  return [2 /*return*/, { $and: where }];
393
390
  }
394
391
  });
@@ -455,6 +452,28 @@ var DataApi = /** @class */ (function () {
455
452
  });
456
453
  };
457
454
  DataApi.prototype.updateMany = function (response, request, body) {
455
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
456
+ var action, where;
457
+ return tslib_1.__generator(this, function (_a) {
458
+ switch (_a.label) {
459
+ case 0:
460
+ action = request === null || request === void 0 ? void 0 : request.get('__action');
461
+ if (action == 'emptyId') {
462
+ return [2 /*return*/, this.put(response, '', body)];
463
+ }
464
+ return [4 /*yield*/, this.buildWhere(request, body)];
465
+ case 1:
466
+ where = _a.sent();
467
+ filter_interfaces_js_1.Filter.throwErrorIfFilterIsEmpty(where, 'updateMany');
468
+ return [2 /*return*/, this.updateManyImplementation(response, request, {
469
+ where: undefined,
470
+ set: body,
471
+ })];
472
+ }
473
+ });
474
+ });
475
+ };
476
+ DataApi.prototype.updateManyImplementation = function (response, request, body) {
458
477
  return tslib_1.__awaiter(this, void 0, void 0, function () {
459
478
  var err_6;
460
479
  var _this = this;
@@ -476,7 +495,7 @@ var DataApi = /** @class */ (function () {
476
495
  _a = true;
477
496
  _e = (_d = this.repository).query;
478
497
  _f = {};
479
- return [4 /*yield*/, this.buildWhere(request, body.where)];
498
+ return [4 /*yield*/, this.buildWhere(request, body)];
480
499
  case 2:
481
500
  _b = tslib_1.__asyncValues.apply(void 0, [_e.apply(_d, [(_f.where = _k.sent(),
482
501
  _f.include = this.includeNone(),
@@ -165,7 +165,7 @@ var RestEntityDataProvider = /** @class */ (function () {
165
165
  return tslib_1.__awaiter(this, void 0, void 0, function () {
166
166
  var run;
167
167
  return tslib_1.__generator(this, function (_a) {
168
- run = this.buildFindRequest({ where: where }, true).run;
168
+ run = this.buildFindRequest({ where: where }, 'delete').run;
169
169
  return [2 /*return*/, run('deleteMany').then(function (r) { return +r.deleted; })];
170
170
  });
171
171
  });
@@ -174,8 +174,8 @@ var RestEntityDataProvider = /** @class */ (function () {
174
174
  return tslib_1.__awaiter(this, void 0, void 0, function () {
175
175
  var run;
176
176
  return tslib_1.__generator(this, function (_a) {
177
- run = this.buildFindRequest({ where: where }, true).run;
178
- return [2 /*return*/, run('updateMany', { set: this.toJsonOfIncludedKeys(data) }).then(function (r) { return +r.updated; })];
177
+ run = this.buildFindRequest({ where: where }, 'put').run;
178
+ return [2 /*return*/, run('updateMany', this.toJsonOfIncludedKeys(data)).then(function (r) { return +r.updated; })];
179
179
  });
180
180
  });
181
181
  };
@@ -185,16 +185,16 @@ var RestEntityDataProvider = /** @class */ (function () {
185
185
  return run().then(function (x) { return x.map(function (y) { return _this.translateFromJson(y); }); });
186
186
  };
187
187
  //@internal
188
- RestEntityDataProvider.prototype.buildFindRequest = function (options, forcePost) {
188
+ RestEntityDataProvider.prototype.buildFindRequest = function (options, method) {
189
189
  var _this = this;
190
- if (forcePost === void 0) { forcePost = false; }
190
+ if (!method)
191
+ method = 'get';
191
192
  var url = new urlBuilder_js_1.UrlBuilder(this.url());
192
193
  var filterObject;
193
194
  if (options) {
194
195
  if (options.where) {
195
196
  filterObject = options.where.toJson(); // options.where.__applyToConsumer(new FilterConsumnerBridgeToUrlBuilder(url));
196
- if (!forcePost &&
197
- addFilterToUrlAndReturnTrueIfSuccessful(filterObject, url))
197
+ if (addFilterToUrlAndReturnTrueIfSuccessful(filterObject, url))
198
198
  filterObject = undefined;
199
199
  }
200
200
  if (options.orderBy && options.orderBy.Segments) {
@@ -228,15 +228,12 @@ var RestEntityDataProvider = /** @class */ (function () {
228
228
  }
229
229
  if (action)
230
230
  u.add('__action', action);
231
- if (filterObject || forcePost) {
232
- if (!body)
233
- body = filterObject;
234
- else
235
- body = tslib_1.__assign(tslib_1.__assign({}, body), { where: filterObject });
231
+ if (filterObject) {
232
+ body = { set: body, where: filterObject };
236
233
  return _this.http().post(u.url, body);
237
234
  }
238
235
  else
239
- return _this.http().get(u.url);
236
+ return _this.http()[method](u.url, body);
240
237
  };
241
238
  return {
242
239
  createKey: function () { return JSON.stringify({ url: url, filterObject: filterObject }); },
@@ -270,7 +267,8 @@ var RestEntityDataProvider = /** @class */ (function () {
270
267
  RestEntityDataProvider.prototype.update = function (id, data) {
271
268
  var _this = this;
272
269
  return this.http()
273
- .put(this.url() + '/' + encodeURIComponent(id), this.toJsonOfIncludedKeys(data))
270
+ .put(this.url() +
271
+ (id != '' ? '/' + encodeURIComponent(id) : '?__action=emptyId'), this.toJsonOfIncludedKeys(data))
274
272
  .then(function (y) { return _this.translateFromJson(y); });
275
273
  };
276
274
  RestEntityDataProvider.prototype.toJsonOfIncludedKeys = function (data) {
@@ -294,7 +292,20 @@ var RestEntityDataProvider = /** @class */ (function () {
294
292
  return result;
295
293
  };
296
294
  RestEntityDataProvider.prototype.delete = function (id) {
297
- return this.http().delete(this.url() + '/' + encodeURIComponent(id));
295
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
296
+ return tslib_1.__generator(this, function (_a) {
297
+ switch (_a.label) {
298
+ case 0:
299
+ if (!(id == '')) return [3 /*break*/, 2];
300
+ return [4 /*yield*/, this.deleteMany(filter_interfaces_js_1.Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(id)))];
301
+ case 1:
302
+ _a.sent();
303
+ return [3 /*break*/, 3];
304
+ case 2: return [2 /*return*/, this.http().delete(this.url() + '/' + encodeURIComponent(id))];
305
+ case 3: return [2 /*return*/];
306
+ }
307
+ });
308
+ });
298
309
  };
299
310
  RestEntityDataProvider.prototype.insert = function (data) {
300
311
  var _this = this;
@@ -12,6 +12,58 @@ var Filter = /** @class */ (function () {
12
12
  function Filter(apply) {
13
13
  this.apply = apply;
14
14
  }
15
+ //@internal
16
+ Filter.throwErrorIfFilterIsEmpty = function (where, methodName) {
17
+ if (Filter.isFilterEmpty(where)) {
18
+ throw {
19
+ message: "".concat(methodName, ": requires a filter to protect against accidental delete/update of all rows"),
20
+ httpStatusCode: 400,
21
+ };
22
+ }
23
+ };
24
+ //@internal
25
+ Filter.isFilterEmpty = function (where) {
26
+ var e_1, _a, e_2, _b;
27
+ if (where.$and) {
28
+ try {
29
+ for (var _c = tslib_1.__values(where.$and), _d = _c.next(); !_d.done; _d = _c.next()) {
30
+ var a = _d.value;
31
+ if (!Filter.isFilterEmpty(a)) {
32
+ return false;
33
+ }
34
+ }
35
+ }
36
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
37
+ finally {
38
+ try {
39
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
40
+ }
41
+ finally { if (e_1) throw e_1.error; }
42
+ }
43
+ }
44
+ if (where.$or) {
45
+ try {
46
+ for (var _e = tslib_1.__values(where.$or), _f = _e.next(); !_f.done; _f = _e.next()) {
47
+ var a = _f.value;
48
+ if (Filter.isFilterEmpty(a)) {
49
+ return true;
50
+ }
51
+ }
52
+ }
53
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
54
+ finally {
55
+ try {
56
+ if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
57
+ }
58
+ finally { if (e_2) throw e_2.error; }
59
+ }
60
+ return false;
61
+ }
62
+ if (Object.keys(where).filter(function (x) { return !['$or', '$and'].includes(x); }).length == 0) {
63
+ return true;
64
+ }
65
+ return false;
66
+ };
15
67
  Filter.createCustom = function (rawFilterTranslator, key) {
16
68
  if (key === void 0) { key = ''; }
17
69
  var rawFilterInfo = { key: key, rawFilterTranslator: rawFilterTranslator };
@@ -317,19 +369,19 @@ var filterHelper = /** @class */ (function () {
317
369
  filterHelper.prototype.isNotIn = function (values) {
318
370
  var _this = this;
319
371
  return new Filter(function (add) {
320
- var e_1, _a;
372
+ var e_3, _a;
321
373
  try {
322
374
  for (var values_1 = tslib_1.__values(values), values_1_1 = values_1.next(); !values_1_1.done; values_1_1 = values_1.next()) {
323
375
  var v = values_1_1.value;
324
376
  add.isDifferentFrom(_this.metadata, _this.processVal(v));
325
377
  }
326
378
  }
327
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
379
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
328
380
  finally {
329
381
  try {
330
382
  if (values_1_1 && !values_1_1.done && (_a = values_1.return)) _a.call(values_1);
331
383
  }
332
- finally { if (e_1) throw e_1.error; }
384
+ finally { if (e_3) throw e_3.error; }
333
385
  }
334
386
  });
335
387
  };
@@ -462,7 +514,7 @@ var AndFilter = /** @class */ (function (_super) {
462
514
  filters[_i] = arguments[_i];
463
515
  }
464
516
  var _this = _super.call(this, function (add) {
465
- var e_2, _a;
517
+ var e_4, _a;
466
518
  try {
467
519
  for (var _b = tslib_1.__values(_this.filters), _c = _b.next(); !_c.done; _c = _b.next()) {
468
520
  var iterator = _c.value;
@@ -470,12 +522,12 @@ var AndFilter = /** @class */ (function (_super) {
470
522
  iterator.__applyToConsumer(add);
471
523
  }
472
524
  }
473
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
525
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
474
526
  finally {
475
527
  try {
476
528
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
477
529
  }
478
- finally { if (e_2) throw e_2.error; }
530
+ finally { if (e_4) throw e_4.error; }
479
531
  }
480
532
  }) || this;
481
533
  _this.filters = filters;
@@ -595,7 +647,7 @@ function buildFilterFromRequestParameters(entity, filterInfo) {
595
647
  tslib_1.__spreadArray([], tslib_1.__read(entity.fields), false).forEach(function (col) {
596
648
  var _a, _b;
597
649
  function addFilter(operation, theFilter, jsonArray, asString) {
598
- var e_3, _a;
650
+ var e_5, _a;
599
651
  if (jsonArray === void 0) { jsonArray = false; }
600
652
  if (asString === void 0) { asString = false; }
601
653
  var val = filterInfo.get(col.key + operation);
@@ -638,12 +690,12 @@ function buildFilterFromRequestParameters(entity, filterInfo) {
638
690
  addFilter_1(x);
639
691
  }
640
692
  }
641
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
693
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
642
694
  finally {
643
695
  try {
644
696
  if (array_1_1 && !array_1_1.done && (_a = array_1.return)) _a.call(array_1);
645
697
  }
646
- finally { if (e_3) throw e_3.error; }
698
+ finally { if (e_5) throw e_5.error; }
647
699
  }
648
700
  }
649
701
  }
@@ -717,7 +769,7 @@ function buildFilterFromRequestParameters(entity, filterInfo) {
717
769
  return where[0];
718
770
  return { $and: where };
719
771
  function separateArrayFromInnerArray(val) {
720
- var e_4, _a;
772
+ var e_6, _a;
721
773
  if (!Array.isArray(val))
722
774
  return [val];
723
775
  var nonArray = [], array = [];
@@ -731,12 +783,12 @@ function buildFilterFromRequestParameters(entity, filterInfo) {
731
783
  nonArray.push(v);
732
784
  }
733
785
  }
734
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
786
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
735
787
  finally {
736
788
  try {
737
789
  if (val_1_1 && !val_1_1.done && (_a = val_1.return)) _a.call(val_1);
738
790
  }
739
- finally { if (e_4) throw e_4.error; }
791
+ finally { if (e_6) throw e_6.error; }
740
792
  }
741
793
  array.push(nonArray);
742
794
  return array;
@@ -442,6 +442,7 @@ var RepositoryImplementation = /** @class */ (function () {
442
442
  return tslib_1.__generator(this, function (_j) {
443
443
  switch (_j.label) {
444
444
  case 0:
445
+ filter_interfaces_js_1.Filter.throwErrorIfFilterIsEmpty(where, 'updateMany');
445
446
  if (!this._dataProvider.isProxy) return [3 /*break*/, 2];
446
447
  _e = (_d = this._edp).updateMany;
447
448
  return [4 /*yield*/, this._translateWhereToFilter(where)];
@@ -1093,6 +1094,7 @@ var RepositoryImplementation = /** @class */ (function () {
1093
1094
  return tslib_1.__generator(this, function (_j) {
1094
1095
  switch (_j.label) {
1095
1096
  case 0:
1097
+ filter_interfaces_js_1.Filter.throwErrorIfFilterIsEmpty(where, 'deleteMany');
1096
1098
  if (!this._dataProvider.isProxy) return [3 /*break*/, 2];
1097
1099
  _e = (_d = this._edp).deleteMany;
1098
1100
  return [4 /*yield*/, this._translateWhereToFilter(where)];
@@ -1,17 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ //y1 - reconsider adding where to all in case of post - it is a breaking change and no longer required
4
+ //y1 - review that with deleteMany, and updateMany I've taken a similar approach to get, that when the filter is complex, we go to post - one reason is that delete doesn't accept a body.
5
+ //y1 - should the remult api be deleteMany({id:[1,2]}) or deleteMany({where:{id:[1,2]}})
3
6
  //p1 - in this video I'll use remult to turn a frontend app to a fullstack app
4
- /*p1 - discuss using delete & put - with url query language for deleteMany and updateMany -
5
- - put & delete, similar to get
6
- - add where to count, deleteMany,updateMany,
7
- - prevent delete all and update all - must have meaningful where.
8
- - try forcing this also in typescript
9
-
10
- - protect against deleting of all rows by mistake
11
- - https://github.com/remult/remult/issues/221#issuecomment-2016519746
12
-
13
- */
14
7
  //y1 - getFields didn't work for kobi in the home component
8
+ //y1 - consider replacing all errors with error classes that extend the base Error class
15
9
  //p1 - document offline support
16
10
  //p1 - add section to Fields doc, explaining field type in db
17
11
  //p1 - add section about union type
@@ -138,7 +138,7 @@ var ValueConverters = /** @class */ (function () {
138
138
  toJson: function (value) { return ValueConverters.Number.toDb(value); },
139
139
  fromInput: function (x, type) {
140
140
  var r = +x;
141
- if (!x)
141
+ if (x === null || x === undefined)
142
142
  return undefined;
143
143
  return r;
144
144
  },