remult 3.3.0-next.1 → 3.3.1
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 +1 -1
- package/esm/remult-knex/index.js +10 -3
- package/esm/remult-mongo.js +7 -3
- package/esm/server/get-remult-admin-html.js +125 -111
- package/esm/server/remult-admin.js +2 -0
- package/esm/server/remult-api-server.js +1 -1
- package/esm/src/data-api.js +30 -19
- package/esm/src/data-providers/rest-data-provider.js +48 -37
- package/esm/src/data-providers/sql-database.js +14 -3
- package/esm/src/live-query/SubscriptionChannel.js +52 -4
- package/esm/src/remult-proxy.js +4 -4
- package/esm/src/remult3/RepositoryImplementation.js +53 -25
- package/esm/src/server-action.js +2 -2
- package/esm/src/valueConverters.js +9 -5
- package/graphql.js +1 -1
- package/index.d.ts +1 -1
- package/package.json +1 -1
- package/remult-knex/index.js +18 -9
- package/remult-mongo.js +6 -2
- package/server/get-remult-admin-html.js +1 -1
- package/server/remult-admin.d.ts +2 -0
- package/server/remult-admin.js +2 -1
- package/server/remult-api-server.js +1 -0
- package/src/data-api.d.ts +4 -4
- package/src/data-api.js +50 -30
- package/src/data-interfaces.d.ts +6 -6
- package/src/data-providers/rest-data-provider.d.ts +4 -4
- package/src/data-providers/rest-data-provider.js +48 -37
- package/src/data-providers/sql-database.js +14 -3
- package/src/live-query/SubscriptionChannel.d.ts +52 -4
- package/src/live-query/SubscriptionChannel.js +52 -4
- package/src/remult-proxy.js +4 -4
- package/src/remult3/RepositoryImplementation.d.ts +11 -10
- package/src/remult3/RepositoryImplementation.js +237 -177
- package/src/remult3/remult3.d.ts +25 -23
- package/src/server-action.js +2 -2
- package/src/valueConverters.d.ts +3 -1
- package/src/valueConverters.js +9 -6
|
@@ -51,6 +51,7 @@ export function buildEntityInfo(options) {
|
|
|
51
51
|
if (relRepo.metadata.apiReadAllowed) {
|
|
52
52
|
relation = {
|
|
53
53
|
...relInfo,
|
|
54
|
+
allowNull: x.allowNull,
|
|
54
55
|
where,
|
|
55
56
|
entityKey: relRepo.metadata.key,
|
|
56
57
|
idField,
|
|
@@ -81,6 +82,7 @@ export function buildEntityInfo(options) {
|
|
|
81
82
|
caption: x.label,
|
|
82
83
|
relationToOne: relation,
|
|
83
84
|
inputType: x.inputType,
|
|
85
|
+
allowNull: x.allowNull,
|
|
84
86
|
type: x.inputType === InputTypes.json
|
|
85
87
|
? 'json'
|
|
86
88
|
: x.valueType === Number
|
|
@@ -316,7 +316,7 @@ export class RemultServerImplementation {
|
|
|
316
316
|
//@ts-ignore
|
|
317
317
|
.get(this.process(async (c, req, res, orig) => dataApiFactory(c).get(res, orig.params.id)))
|
|
318
318
|
//@ts-ignore
|
|
319
|
-
.put(this.process(async (c, req, res, reqInfo, _, orig) => dataApiFactory(c).put(res, reqInfo.params.id, await this.coreOptions.getRequestBody(orig))))
|
|
319
|
+
.put(this.process(async (c, req, res, reqInfo, _, orig) => dataApiFactory(c).put(res, req, reqInfo.params.id, await this.coreOptions.getRequestBody(orig))))
|
|
320
320
|
//@ts-ignore
|
|
321
321
|
.delete(this.process(async (c, req, res, orig) => dataApiFactory(c).delete(res, orig.params.id)));
|
|
322
322
|
}
|
package/esm/src/data-api.js
CHANGED
|
@@ -72,7 +72,7 @@ export class DataApi {
|
|
|
72
72
|
case 'query':
|
|
73
73
|
return res.success(await this.query(res, req, body));
|
|
74
74
|
default:
|
|
75
|
-
return res.created(await this.post(body));
|
|
75
|
+
return res.created(await this.post(body, req));
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
catch (err) {
|
|
@@ -93,11 +93,11 @@ export class DataApi {
|
|
|
93
93
|
include: this.includeNone(),
|
|
94
94
|
});
|
|
95
95
|
if (r.length == 0) {
|
|
96
|
-
result.push(await this.post({ ...item.where, ...item.set }));
|
|
96
|
+
result.push(await this.post({ ...item.where, ...item.set }, request));
|
|
97
97
|
}
|
|
98
98
|
else {
|
|
99
99
|
if (item.set !== undefined) {
|
|
100
|
-
result.push(
|
|
100
|
+
result.push(await this.actualUpdate(r[0], item.set, request));
|
|
101
101
|
}
|
|
102
102
|
else
|
|
103
103
|
result.push(this.repository.getEntityRef(r[0]).toApiJson());
|
|
@@ -154,8 +154,7 @@ export class DataApi {
|
|
|
154
154
|
async deleteMany(response, request, body) {
|
|
155
155
|
try {
|
|
156
156
|
let deleted = 0;
|
|
157
|
-
let where = await this.
|
|
158
|
-
Filter.throwErrorIfFilterIsEmpty(where, 'deleteMany');
|
|
157
|
+
let where = await this.prepareWhereForManyOperation(body, request);
|
|
159
158
|
return await doTransaction(this.remult, async () => {
|
|
160
159
|
for await (const x of this.repository.query({
|
|
161
160
|
where,
|
|
@@ -172,6 +171,14 @@ export class DataApi {
|
|
|
172
171
|
response.error(err, this.repository.metadata);
|
|
173
172
|
}
|
|
174
173
|
}
|
|
174
|
+
async prepareWhereForManyOperation(body, request) {
|
|
175
|
+
let where = undefined;
|
|
176
|
+
if (body?.where !== 'all') {
|
|
177
|
+
where = await this.buildWhere(request, body);
|
|
178
|
+
Filter.throwErrorIfFilterIsEmpty(where, 'deleteMany');
|
|
179
|
+
}
|
|
180
|
+
return where;
|
|
181
|
+
}
|
|
175
182
|
async groupBy(request, body) {
|
|
176
183
|
if (!this.repository.metadata.apiReadAllowed) {
|
|
177
184
|
throw new ForbiddenError();
|
|
@@ -412,7 +419,7 @@ export class DataApi {
|
|
|
412
419
|
async updateManyThroughPutRequest(response, request, body) {
|
|
413
420
|
const action = request?.get('__action');
|
|
414
421
|
if (action == 'emptyId') {
|
|
415
|
-
return this.put(response, '', body);
|
|
422
|
+
return this.put(response, request, '', body);
|
|
416
423
|
}
|
|
417
424
|
return this.updateManyImplementation(response, request, {
|
|
418
425
|
where: undefined,
|
|
@@ -421,8 +428,7 @@ export class DataApi {
|
|
|
421
428
|
}
|
|
422
429
|
async updateManyImplementation(response, request, body) {
|
|
423
430
|
try {
|
|
424
|
-
let where = await this.
|
|
425
|
-
Filter.throwErrorIfFilterIsEmpty(where, 'updateMany');
|
|
431
|
+
let where = await this.prepareWhereForManyOperation(body, request);
|
|
426
432
|
return await doTransaction(this.remult, async () => {
|
|
427
433
|
let updated = 0;
|
|
428
434
|
for await (const x of this.repository.query({
|
|
@@ -430,7 +436,7 @@ export class DataApi {
|
|
|
430
436
|
include: this.includeNone(),
|
|
431
437
|
aggregate: undefined,
|
|
432
438
|
})) {
|
|
433
|
-
await this.actualUpdate(x, body.set);
|
|
439
|
+
await this.actualUpdate(x, body.set, request);
|
|
434
440
|
updated++;
|
|
435
441
|
}
|
|
436
442
|
response.success({ updated });
|
|
@@ -440,20 +446,22 @@ export class DataApi {
|
|
|
440
446
|
response.error(err, this.repository.metadata);
|
|
441
447
|
}
|
|
442
448
|
}
|
|
443
|
-
async actualUpdate(row, body) {
|
|
449
|
+
async actualUpdate(row, body, req, doNotSelect) {
|
|
444
450
|
let ref = this.repository.getEntityRef(row);
|
|
445
451
|
await ref._updateEntityBasedOnApi(body);
|
|
446
452
|
if (!ref.apiUpdateAllowed) {
|
|
447
453
|
throw new ForbiddenError();
|
|
448
454
|
}
|
|
449
|
-
|
|
450
|
-
|
|
455
|
+
let options = req.get('_select') === 'none' || doNotSelect
|
|
456
|
+
? { select: 'none' }
|
|
457
|
+
: undefined;
|
|
458
|
+
await ref.save(options);
|
|
459
|
+
if (options?.select === 'none')
|
|
460
|
+
return undefined;
|
|
461
|
+
return ref.toApiJson();
|
|
451
462
|
}
|
|
452
|
-
async put(response, id, body) {
|
|
453
|
-
await this.doOnId(response, id, async (row) =>
|
|
454
|
-
const ref = await this.actualUpdate(row, body);
|
|
455
|
-
response.success(ref.toApiJson());
|
|
456
|
-
});
|
|
463
|
+
async put(response, req, id, body) {
|
|
464
|
+
await this.doOnId(response, id, async (row) => response.success(await this.actualUpdate(row, body, req)));
|
|
457
465
|
}
|
|
458
466
|
async actualDelete(row) {
|
|
459
467
|
if (!this.repository.getEntityRef(row).apiDeleteAllowed) {
|
|
@@ -467,14 +475,17 @@ export class DataApi {
|
|
|
467
475
|
response.deleted();
|
|
468
476
|
});
|
|
469
477
|
}
|
|
470
|
-
async post(body) {
|
|
478
|
+
async post(body, req) {
|
|
479
|
+
let options = req.get('_select') === 'none' ? { select: 'none' } : undefined;
|
|
471
480
|
const insert = async (what) => {
|
|
472
481
|
let newr = this.repository.create();
|
|
473
482
|
await this.repository.getEntityRef(newr)._updateEntityBasedOnApi(what);
|
|
474
483
|
if (!this.repository.getEntityRef(newr).apiInsertAllowed) {
|
|
475
484
|
throw new ForbiddenError();
|
|
476
485
|
}
|
|
477
|
-
await this.repository.getEntityRef(newr).save();
|
|
486
|
+
await this.repository.getEntityRef(newr).save(options);
|
|
487
|
+
if (options?.select === 'none')
|
|
488
|
+
return undefined;
|
|
478
489
|
return this.repository.getEntityRef(newr).toApiJson();
|
|
479
490
|
};
|
|
480
491
|
if (Array.isArray(body)) {
|
|
@@ -199,37 +199,42 @@ export class RestEntityDataProvider {
|
|
|
199
199
|
let url = new UrlBuilder(this.url());
|
|
200
200
|
let filterObject;
|
|
201
201
|
if (options) {
|
|
202
|
-
if (options.where) {
|
|
203
|
-
filterObject =
|
|
204
|
-
if (options.args === undefined)
|
|
205
|
-
if (addFilterToUrlAndReturnTrueIfSuccessful(filterObject, url))
|
|
206
|
-
filterObject = undefined;
|
|
202
|
+
if (options.where === 'all') {
|
|
203
|
+
filterObject = 'all';
|
|
207
204
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
205
|
+
else {
|
|
206
|
+
if (options.where) {
|
|
207
|
+
filterObject = options.where.toJson();
|
|
208
|
+
if (options.args === undefined)
|
|
209
|
+
if (addFilterToUrlAndReturnTrueIfSuccessful(filterObject, url))
|
|
210
|
+
filterObject = undefined;
|
|
211
|
+
}
|
|
212
|
+
if (options.orderBy && options.orderBy.Segments) {
|
|
213
|
+
let sort = '';
|
|
214
|
+
let order = '';
|
|
215
|
+
let hasDescending = false;
|
|
216
|
+
options.orderBy.Segments.forEach((c) => {
|
|
217
|
+
if (sort.length > 0) {
|
|
218
|
+
sort += ',';
|
|
219
|
+
order += ',';
|
|
220
|
+
}
|
|
221
|
+
sort += c.field.key;
|
|
222
|
+
order += c.isDescending ? 'desc' : 'asc';
|
|
223
|
+
if (c.isDescending)
|
|
224
|
+
hasDescending = true;
|
|
225
|
+
});
|
|
226
|
+
if (sort)
|
|
227
|
+
url.add('_sort', sort);
|
|
228
|
+
if (hasDescending)
|
|
229
|
+
url.add('_order', order);
|
|
230
|
+
}
|
|
231
|
+
if (options.limit)
|
|
232
|
+
url.add('_limit', options.limit);
|
|
233
|
+
if (options.page)
|
|
234
|
+
url.add('_page', options.page);
|
|
235
|
+
if (options.select) {
|
|
236
|
+
url.add('_select', options.select.join(','));
|
|
237
|
+
}
|
|
233
238
|
}
|
|
234
239
|
}
|
|
235
240
|
const run = (action, body) => {
|
|
@@ -246,7 +251,7 @@ export class RestEntityDataProvider {
|
|
|
246
251
|
else
|
|
247
252
|
body = { ...body, where: filterObject };
|
|
248
253
|
}
|
|
249
|
-
if (options
|
|
254
|
+
if (options && 'args' in options)
|
|
250
255
|
body.args = options.args;
|
|
251
256
|
if (body && method != 'put')
|
|
252
257
|
return this.http().post(u.url, body);
|
|
@@ -269,10 +274,16 @@ export class RestEntityDataProvider {
|
|
|
269
274
|
},
|
|
270
275
|
};
|
|
271
276
|
}
|
|
272
|
-
update(id, data) {
|
|
277
|
+
update(id, data, options) {
|
|
278
|
+
const urlArgs = [];
|
|
279
|
+
if (id == '')
|
|
280
|
+
urlArgs.push('__action=emptyId');
|
|
281
|
+
if (options?.select === 'none')
|
|
282
|
+
urlArgs.push('_select=$none');
|
|
273
283
|
return this.http()
|
|
274
284
|
.put(this.url() +
|
|
275
|
-
(id != '' ? '/' + encodeURIComponent(id) : '
|
|
285
|
+
(id != '' ? '/' + encodeURIComponent(id) : '') +
|
|
286
|
+
(urlArgs.length > 0 ? '?' + urlArgs.join('&') : ''), this.toJsonOfIncludedKeys(data))
|
|
276
287
|
.then((y) => this.translateFromJson(y));
|
|
277
288
|
}
|
|
278
289
|
toJsonOfIncludedKeys(data) {
|
|
@@ -290,14 +301,14 @@ export class RestEntityDataProvider {
|
|
|
290
301
|
else
|
|
291
302
|
return this.http().delete(this.url() + '/' + encodeURIComponent(id));
|
|
292
303
|
}
|
|
293
|
-
insert(data) {
|
|
304
|
+
insert(data, options) {
|
|
294
305
|
return this.http()
|
|
295
|
-
.post(this.url(), this.translateToJson(data))
|
|
306
|
+
.post(this.url() + (options?.select === 'none' ? '?_select=$none' : ''), this.translateToJson(data))
|
|
296
307
|
.then((y) => this.translateFromJson(y));
|
|
297
308
|
}
|
|
298
|
-
insertMany(data) {
|
|
309
|
+
insertMany(data, options) {
|
|
299
310
|
return this.http()
|
|
300
|
-
.post(this.url(), data.map((data) => this.translateToJson(data)))
|
|
311
|
+
.post(this.url() + (options?.select === 'none' ? '?_select=$none' : ''), data.map((data) => this.translateToJson(data)))
|
|
301
312
|
.then((y) => y.map((y) => this.translateFromJson(y)));
|
|
302
313
|
}
|
|
303
314
|
}
|
|
@@ -392,7 +392,7 @@ class ActualSQLEntityDataProvider {
|
|
|
392
392
|
}
|
|
393
393
|
return { colKeys, select };
|
|
394
394
|
}
|
|
395
|
-
async update(id, data) {
|
|
395
|
+
async update(id, data, options) {
|
|
396
396
|
let e = await this.init();
|
|
397
397
|
let r = this.sql.createCommand();
|
|
398
398
|
let statement = 'update ' + e.$entityName + ' set ';
|
|
@@ -419,6 +419,8 @@ class ActualSQLEntityDataProvider {
|
|
|
419
419
|
let returning = true;
|
|
420
420
|
if (this.sql._getSourceSql().doesNotSupportReturningSyntax)
|
|
421
421
|
returning = false;
|
|
422
|
+
if (options?.select === 'none')
|
|
423
|
+
returning = false;
|
|
422
424
|
if (returning &&
|
|
423
425
|
this.sql._getSourceSql().doesNotSupportReturningSyntaxOnlyForUpdate)
|
|
424
426
|
returning = false;
|
|
@@ -427,6 +429,8 @@ class ActualSQLEntityDataProvider {
|
|
|
427
429
|
return r.execute(statement).then((sqlResult) => {
|
|
428
430
|
this.sql._getSourceSql().afterMutation?.();
|
|
429
431
|
if (!returning) {
|
|
432
|
+
if (options?.select === 'none')
|
|
433
|
+
return undefined;
|
|
430
434
|
return getRowAfterUpdate(this.entity, this, data, id, 'update');
|
|
431
435
|
}
|
|
432
436
|
if (sqlResult.rows.length != 1)
|
|
@@ -448,7 +452,7 @@ class ActualSQLEntityDataProvider {
|
|
|
448
452
|
this.sql._getSourceSql().afterMutation?.();
|
|
449
453
|
});
|
|
450
454
|
}
|
|
451
|
-
async insert(data) {
|
|
455
|
+
async insert(data, options) {
|
|
452
456
|
let e = await this.init();
|
|
453
457
|
let r = this.sql.createCommand();
|
|
454
458
|
let cols = '';
|
|
@@ -473,7 +477,8 @@ class ActualSQLEntityDataProvider {
|
|
|
473
477
|
}
|
|
474
478
|
let statement = `insert into ${e.$entityName} (${cols}) values (${vals})`;
|
|
475
479
|
let { colKeys, select } = await this.buildSelect(e, r, undefined, undefined);
|
|
476
|
-
if (!this.sql._getSourceSql().doesNotSupportReturningSyntax
|
|
480
|
+
if (!this.sql._getSourceSql().doesNotSupportReturningSyntax &&
|
|
481
|
+
!(options?.select === 'none'))
|
|
477
482
|
statement += ' returning ' + select;
|
|
478
483
|
return await r.execute(statement).then((sql) => {
|
|
479
484
|
this.sql._getSourceSql().afterMutation?.();
|
|
@@ -483,14 +488,20 @@ class ActualSQLEntityDataProvider {
|
|
|
483
488
|
if (typeof id !== 'number')
|
|
484
489
|
throw new Error('Auto increment, for a database that is does not support returning syntax, should return an array with the single last added id. Instead it returned: ' +
|
|
485
490
|
JSON.stringify(id));
|
|
491
|
+
if (options?.select === 'none')
|
|
492
|
+
return undefined;
|
|
486
493
|
return this.find({
|
|
487
494
|
where: new Filter((x) => x.isEqualTo(this.entity.idMetadata.field, id)),
|
|
488
495
|
}).then((r) => r[0]);
|
|
489
496
|
}
|
|
490
497
|
else {
|
|
498
|
+
if (options?.select === 'none')
|
|
499
|
+
return undefined;
|
|
491
500
|
return getRowAfterUpdate(this.entity, this, data, undefined, 'insert');
|
|
492
501
|
}
|
|
493
502
|
}
|
|
503
|
+
if (options?.select === 'none')
|
|
504
|
+
return undefined;
|
|
494
505
|
return this.buildResultRow(colKeys, sql.rows[0], sql);
|
|
495
506
|
});
|
|
496
507
|
}
|
|
@@ -106,18 +106,66 @@ export const liveQueryKeepAliveRoute = '_liveQueryKeepAlive';
|
|
|
106
106
|
*
|
|
107
107
|
* @template messageType The type of the message that the channel will handle.
|
|
108
108
|
* @example
|
|
109
|
+
* ```ts
|
|
109
110
|
* // Defined in code that is shared between the frontend and the backend
|
|
110
|
-
* const
|
|
111
|
+
* export const notif = new SubscriptionChannel<{ coolInfo: string }>("notif");
|
|
111
112
|
*
|
|
112
113
|
* // Backend: Publishing a message
|
|
113
|
-
*
|
|
114
|
+
* notif.publish({ coolInfo: "Message coming from the backend" });
|
|
114
115
|
*
|
|
115
116
|
* // Frontend: Subscribing to messages
|
|
116
|
-
*
|
|
117
|
-
* console.log(`
|
|
117
|
+
* notif.subscribe((message) => {
|
|
118
|
+
* console.log(`Something exciting happened: ${message.coolInfo}`);
|
|
118
119
|
* });
|
|
119
120
|
*
|
|
120
121
|
* // Note: If you want to publish from the frontend, use a BackendMethod for that.
|
|
122
|
+
* ```
|
|
123
|
+
* ---
|
|
124
|
+
*
|
|
125
|
+
* ### Use cases:
|
|
126
|
+
*
|
|
127
|
+
* #### A user _(Paul)_ wants to notify everyone _(Eric & Simona)_
|
|
128
|
+
* ```ts
|
|
129
|
+
* // shared code between the frontend and the backend
|
|
130
|
+
* export const notif = new SubscriptionChannel<{ from: UserInfo, msg: string }>("notif");
|
|
131
|
+
*
|
|
132
|
+
* // Frontend, Paul can call a BackendMethod to send his message
|
|
133
|
+
* NotificationContoller.send("Hello everyone!")
|
|
134
|
+
*
|
|
135
|
+
* // Backend
|
|
136
|
+
* export class NotificationContoller {
|
|
137
|
+
* @BackendMethod({ allowed: true })
|
|
138
|
+
* static async send(message: string) {
|
|
139
|
+
* notif.publish({ from: remult.user, msg: message });
|
|
140
|
+
* }
|
|
141
|
+
* }
|
|
142
|
+
*
|
|
143
|
+
* // Frontend: Eric & Simona can subscribe to messages
|
|
144
|
+
* notif.subscribe((message) => {
|
|
145
|
+
* if (message.from === remult.user) return;
|
|
146
|
+
* console.log(`Message from ${message.from.name}: ${message.msg}`);
|
|
147
|
+
* });
|
|
148
|
+
* ```
|
|
149
|
+
*
|
|
150
|
+
* #### A complexe chart that needs to be updated on multiple changes
|
|
151
|
+
* ```ts
|
|
152
|
+
* // shared code between the frontend and the backend
|
|
153
|
+
* export const chart = new SubscriptionChannel<{ kind: "pie" | "bar" | "line", data: number[] }>("chart");
|
|
154
|
+
*
|
|
155
|
+
* // Entity
|
|
156
|
+
* @Entity<Task>("tasks", {
|
|
157
|
+
* saved: async (e) => {
|
|
158
|
+
* if (e.completed) chart.publish({ kind: "pie", data: [1, 2, 3] });
|
|
159
|
+
* }
|
|
160
|
+
* })
|
|
161
|
+
* export class Task { ... }
|
|
162
|
+
*
|
|
163
|
+
* // Frontend: in the chart component, we can subscribe to messages
|
|
164
|
+
* chart.subscribe((message) => {
|
|
165
|
+
* chartData = message.data;
|
|
166
|
+
* });
|
|
167
|
+
* ```
|
|
168
|
+
*
|
|
121
169
|
*/
|
|
122
170
|
export class SubscriptionChannel {
|
|
123
171
|
channelKey;
|
package/esm/src/remult-proxy.js
CHANGED
|
@@ -156,10 +156,10 @@ export class RemultProxy {
|
|
|
156
156
|
.remultFactory()
|
|
157
157
|
.repo(...args)
|
|
158
158
|
.getEntityRef(...args2),
|
|
159
|
-
insert: (args2) => self
|
|
159
|
+
insert: (args2, args3) => self
|
|
160
160
|
.remultFactory()
|
|
161
161
|
.repo(...args)
|
|
162
|
-
.insert(args2),
|
|
162
|
+
.insert(args2, args3),
|
|
163
163
|
liveQuery: (...args2) => self
|
|
164
164
|
.remultFactory()
|
|
165
165
|
.repo(...args)
|
|
@@ -179,10 +179,10 @@ export class RemultProxy {
|
|
|
179
179
|
.remultFactory()
|
|
180
180
|
.repo(...args)
|
|
181
181
|
.upsert(args2),
|
|
182
|
-
update: (a, b) => self
|
|
182
|
+
update: (a, b, c) => self
|
|
183
183
|
.remultFactory()
|
|
184
184
|
.repo(...args)
|
|
185
|
-
.update(a, b),
|
|
185
|
+
.update(a, b, c),
|
|
186
186
|
};
|
|
187
187
|
entityCache.set(args[1], result);
|
|
188
188
|
return result;
|
|
@@ -317,7 +317,7 @@ export class RepositoryImplementation {
|
|
|
317
317
|
for (const field of this.fields) {
|
|
318
318
|
}
|
|
319
319
|
}
|
|
320
|
-
async insert(entity) {
|
|
320
|
+
async insert(entity, options) {
|
|
321
321
|
if (Array.isArray(entity)) {
|
|
322
322
|
if (this._dataProvider.isProxy) {
|
|
323
323
|
let refs = [];
|
|
@@ -335,27 +335,36 @@ export class RepositoryImplementation {
|
|
|
335
335
|
refs.push(ref);
|
|
336
336
|
raw.push(await ref.buildDtoForInsert());
|
|
337
337
|
}
|
|
338
|
-
|
|
338
|
+
const inserted = await this._edp.insertMany(raw, options);
|
|
339
|
+
if (options?.select === 'none')
|
|
340
|
+
return undefined;
|
|
341
|
+
return promiseAll(inserted, (item, i) => refs[i].processInsertResponseDto(item));
|
|
339
342
|
}
|
|
340
343
|
else {
|
|
341
344
|
let r = [];
|
|
342
345
|
for (const item of entity) {
|
|
343
|
-
r.push(await this.insert(item));
|
|
346
|
+
r.push(await this.insert(item, options));
|
|
344
347
|
}
|
|
348
|
+
if (options?.select === 'none')
|
|
349
|
+
return undefined;
|
|
345
350
|
return r;
|
|
346
351
|
}
|
|
347
352
|
}
|
|
348
353
|
else {
|
|
349
354
|
let ref = getEntityRef(entity, false);
|
|
355
|
+
let result = undefined;
|
|
350
356
|
if (ref) {
|
|
351
357
|
if (!ref.isNew())
|
|
352
358
|
throw 'Item is not new';
|
|
353
|
-
|
|
359
|
+
result = await ref.save(options);
|
|
354
360
|
}
|
|
355
361
|
else {
|
|
356
362
|
this.__cleanupPartialObject(entity);
|
|
357
|
-
|
|
363
|
+
result = await this.getEntityRef(this.create(entity)).save(options);
|
|
358
364
|
}
|
|
365
|
+
if (options?.select === 'none')
|
|
366
|
+
return undefined;
|
|
367
|
+
return result;
|
|
359
368
|
}
|
|
360
369
|
}
|
|
361
370
|
get fields() {
|
|
@@ -399,29 +408,36 @@ export class RepositoryImplementation {
|
|
|
399
408
|
this.__cleanupPartialObject(set);
|
|
400
409
|
Filter.throwErrorIfFilterIsEmpty(where, 'updateMany');
|
|
401
410
|
if (this._dataProvider.isProxy) {
|
|
402
|
-
return this._edp.updateMany(await this._translateWhereToFilter(where), this.__createDto({ ...set }));
|
|
411
|
+
return this._edp.updateMany(where === 'all' ? 'all' : await this._translateWhereToFilter(where), this.__createDto({ ...set }));
|
|
403
412
|
}
|
|
404
413
|
else {
|
|
405
414
|
let updated = 0;
|
|
415
|
+
if (where === 'all')
|
|
416
|
+
where = undefined;
|
|
406
417
|
for await (const item of this.query({ where, aggregate: undefined })) {
|
|
407
418
|
assign(item, set);
|
|
408
|
-
await getEntityRef(item).save();
|
|
419
|
+
await getEntityRef(item).save({ select: 'none' });
|
|
409
420
|
updated++;
|
|
410
421
|
}
|
|
411
422
|
return updated;
|
|
412
423
|
}
|
|
413
424
|
}
|
|
414
|
-
async update(id, entity) {
|
|
425
|
+
async update(id, entity, options) {
|
|
426
|
+
function returnResult(result) {
|
|
427
|
+
if (options?.select === 'none')
|
|
428
|
+
return undefined;
|
|
429
|
+
return result;
|
|
430
|
+
}
|
|
415
431
|
{
|
|
416
432
|
let ref = getEntityRef(entity, false);
|
|
417
433
|
if (ref)
|
|
418
|
-
return (await ref.save());
|
|
434
|
+
return returnResult((await ref.save(options)));
|
|
419
435
|
}
|
|
420
436
|
{
|
|
421
437
|
let ref = getEntityRef(id, false);
|
|
422
438
|
if (ref) {
|
|
423
439
|
assign(id, entity);
|
|
424
|
-
return ref.save();
|
|
440
|
+
return returnResult(await ref.save(options));
|
|
425
441
|
}
|
|
426
442
|
}
|
|
427
443
|
this.__cleanupPartialObject(entity);
|
|
@@ -433,7 +449,7 @@ export class RepositoryImplementation {
|
|
|
433
449
|
else
|
|
434
450
|
ref = this._getRefForExistingRow(entity, id);
|
|
435
451
|
if (this._dataProvider.isProxy) {
|
|
436
|
-
return await ref.save(Object.keys(entity));
|
|
452
|
+
return returnResult(await ref.save(options, Object.keys(entity)));
|
|
437
453
|
}
|
|
438
454
|
else {
|
|
439
455
|
const r = await ref.reload();
|
|
@@ -450,7 +466,7 @@ export class RepositoryImplementation {
|
|
|
450
466
|
}
|
|
451
467
|
}
|
|
452
468
|
await this._fixTypes(r);
|
|
453
|
-
return await ref.save();
|
|
469
|
+
return returnResult(await ref.save(options));
|
|
454
470
|
}
|
|
455
471
|
}
|
|
456
472
|
async upsert(options) {
|
|
@@ -518,22 +534,22 @@ export class RepositoryImplementation {
|
|
|
518
534
|
}
|
|
519
535
|
return ref;
|
|
520
536
|
}
|
|
521
|
-
async save(entity) {
|
|
537
|
+
async save(entity, options) {
|
|
522
538
|
if (Array.isArray(entity)) {
|
|
523
539
|
return promiseAll(entity, (x) => this.save(x));
|
|
524
540
|
}
|
|
525
541
|
else {
|
|
526
542
|
let ref = getEntityRef(entity, false);
|
|
527
543
|
if (ref)
|
|
528
|
-
return await ref.save();
|
|
544
|
+
return await ref.save(options);
|
|
529
545
|
else if (entity instanceof EntityBase) {
|
|
530
|
-
return await this.getEntityRef(entity).save();
|
|
546
|
+
return await this.getEntityRef(entity).save(options);
|
|
531
547
|
}
|
|
532
548
|
else {
|
|
533
549
|
let id = this.metadata.idMetadata.getId(entity);
|
|
534
550
|
if (id === undefined)
|
|
535
|
-
return this.insert(entity);
|
|
536
|
-
return this.update(id, entity);
|
|
551
|
+
return this.insert(entity, options);
|
|
552
|
+
return this.update(id, entity, options);
|
|
537
553
|
}
|
|
538
554
|
}
|
|
539
555
|
}
|
|
@@ -855,10 +871,12 @@ export class RepositoryImplementation {
|
|
|
855
871
|
async deleteMany({ where, }) {
|
|
856
872
|
Filter.throwErrorIfFilterIsEmpty(where, 'deleteMany');
|
|
857
873
|
if (this._dataProvider.isProxy) {
|
|
858
|
-
return this._edp.deleteMany(await this._translateWhereToFilter(where));
|
|
874
|
+
return this._edp.deleteMany(where === 'all' ? 'all' : await this._translateWhereToFilter(where));
|
|
859
875
|
}
|
|
860
876
|
else {
|
|
861
877
|
let deleted = 0;
|
|
878
|
+
if (where === 'all')
|
|
879
|
+
where = undefined;
|
|
862
880
|
for await (const item of this.query({ where, aggregate: undefined })) {
|
|
863
881
|
await getEntityRef(item).delete();
|
|
864
882
|
deleted++;
|
|
@@ -1374,6 +1392,15 @@ export class rowHelperImplementation extends rowHelperBase {
|
|
|
1374
1392
|
repo;
|
|
1375
1393
|
edp;
|
|
1376
1394
|
_isNew;
|
|
1395
|
+
async _updateResultsFromServerAction(rowInfo) {
|
|
1396
|
+
await this._updateEntityBasedOnApi(rowInfo.data, true);
|
|
1397
|
+
if (this._isNew != rowInfo.isNewRow) {
|
|
1398
|
+
this._isNew = rowInfo.isNewRow;
|
|
1399
|
+
this.originalId = rowInfo.id;
|
|
1400
|
+
}
|
|
1401
|
+
if (!rowInfo.wasChanged)
|
|
1402
|
+
this.originalValues = this.copyDataToObject();
|
|
1403
|
+
}
|
|
1377
1404
|
constructor(info, instance, repo, edp, remult, _isNew, excludeRelationMembers) {
|
|
1378
1405
|
super(info.fieldsMetadata, instance, remult, _isNew, excludeRelationMembers);
|
|
1379
1406
|
this.info = info;
|
|
@@ -1474,7 +1501,7 @@ export class rowHelperImplementation extends rowHelperBase {
|
|
|
1474
1501
|
return this._columns;
|
|
1475
1502
|
}
|
|
1476
1503
|
_saving = false;
|
|
1477
|
-
async save(onlyTheseFieldsSentOnlyInTheCaseOfProxySaveWithPartialObject) {
|
|
1504
|
+
async save(options, onlyTheseFieldsSentOnlyInTheCaseOfProxySaveWithPartialObject) {
|
|
1478
1505
|
try {
|
|
1479
1506
|
if (this._saving)
|
|
1480
1507
|
throw new Error('cannot save while entity is already saving');
|
|
@@ -1517,13 +1544,13 @@ export class rowHelperImplementation extends rowHelperBase {
|
|
|
1517
1544
|
try {
|
|
1518
1545
|
this._subscribers?.reportChanged();
|
|
1519
1546
|
if (this.isNew()) {
|
|
1520
|
-
if (doNotSave) {
|
|
1547
|
+
if (doNotSave && options?.select !== 'none') {
|
|
1521
1548
|
updatedRow = (updatedRow = await this.edp.find({
|
|
1522
1549
|
where: await this.getIdFilter(),
|
|
1523
1550
|
}))[0];
|
|
1524
1551
|
}
|
|
1525
1552
|
else
|
|
1526
|
-
updatedRow = await this.edp.insert(d);
|
|
1553
|
+
updatedRow = await this.edp.insert(d, options);
|
|
1527
1554
|
}
|
|
1528
1555
|
else {
|
|
1529
1556
|
let changesOnly = {};
|
|
@@ -1542,12 +1569,13 @@ export class rowHelperImplementation extends rowHelperBase {
|
|
|
1542
1569
|
if (!wasChanged)
|
|
1543
1570
|
return this.instance;
|
|
1544
1571
|
if (doNotSave) {
|
|
1545
|
-
|
|
1572
|
+
if (options?.select !== 'none')
|
|
1573
|
+
updatedRow = (await this.edp.find({ where: await this.getIdFilter() }))[0];
|
|
1546
1574
|
}
|
|
1547
1575
|
else {
|
|
1548
1576
|
if (this.id === undefined)
|
|
1549
1577
|
throw new Error('Invalid operation, id is undefined');
|
|
1550
|
-
updatedRow = await this.edp.update(this.id, changesOnly);
|
|
1578
|
+
updatedRow = await this.edp.update(this.id, changesOnly, options);
|
|
1551
1579
|
}
|
|
1552
1580
|
}
|
|
1553
1581
|
if (updatedRow)
|
|
@@ -2500,8 +2528,8 @@ export class EntityBase {
|
|
|
2500
2528
|
get _() {
|
|
2501
2529
|
return getEntityRef(this);
|
|
2502
2530
|
}
|
|
2503
|
-
save() {
|
|
2504
|
-
return getEntityRef(this).save();
|
|
2531
|
+
save(options) {
|
|
2532
|
+
return getEntityRef(this).save(options);
|
|
2505
2533
|
}
|
|
2506
2534
|
assign(values) {
|
|
2507
2535
|
assign(this, values);
|