remult 0.27.20-next.4 → 0.27.20
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 +2 -2
- package/esm/remult-mongo.js +1 -3
- package/esm/server/remult-api-server.js +1 -1
- package/esm/src/data-api.js +57 -110
- package/esm/src/data-providers/rest-data-provider.js +9 -30
- package/esm/src/remult-proxy.js +2 -6
- package/esm/src/remult3/RepositoryImplementation.js +134 -73
- package/esm/src/remult3/remult3.js +22 -14
- package/esm/src/validators.js +4 -1
- package/graphql.js +2 -2
- package/package.json +1 -1
- package/remult-mongo.js +2 -5
- package/server/remult-api-server.js +3 -6
- package/src/data-api.d.ts +4 -9
- package/src/data-api.js +99 -217
- package/src/data-interfaces.d.ts +0 -8
- package/src/data-providers/rest-data-provider.d.ts +0 -9
- package/src/data-providers/rest-data-provider.js +13 -44
- package/src/remult-proxy.js +9 -10
- package/src/remult3/RepositoryImplementation.d.ts +6 -12
- package/src/remult3/RepositoryImplementation.js +402 -289
- package/src/remult3/remult3.d.ts +23 -101
- package/src/remult3/remult3.js +22 -14
- package/src/validators.js +8 -3
- package/esm/src/remult3/QueryResultImpl.js +0 -147
- package/src/remult3/QueryResultImpl.d.ts +0 -16
- package/src/remult3/QueryResultImpl.js +0 -268
package/esm/graphql.js
CHANGED
|
@@ -315,7 +315,7 @@ export function remultGraphql(options) {
|
|
|
315
315
|
value: getMetaType(meta),
|
|
316
316
|
}, argErrorDetail, argClientMutationId);
|
|
317
317
|
root[createResolverKey] = handleMutationWithErrors(async (dApi, response, setResult, arg1, req) => {
|
|
318
|
-
await dApi.
|
|
318
|
+
await dApi.post({
|
|
319
319
|
...response,
|
|
320
320
|
created: (y) => {
|
|
321
321
|
const orig = { ...y };
|
|
@@ -324,7 +324,7 @@ export function remultGraphql(options) {
|
|
|
324
324
|
[toCamelCase(getMetaType(meta))]: y,
|
|
325
325
|
});
|
|
326
326
|
},
|
|
327
|
-
},
|
|
327
|
+
}, arg1.input);
|
|
328
328
|
});
|
|
329
329
|
resolversMutation[createResolverKey] = (origItem, args, req, gqlInfo) => root[createResolverKey](args, req, gqlInfo);
|
|
330
330
|
}
|
package/esm/remult-mongo.js
CHANGED
|
@@ -266,9 +266,7 @@ class MongoEntityDataProvider {
|
|
|
266
266
|
const { e, collection } = await this.collection();
|
|
267
267
|
let f = new FilterConsumerBridgeToMongo(e);
|
|
268
268
|
Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(id)).__applyToConsumer(f);
|
|
269
|
-
|
|
270
|
-
session: this.session,
|
|
271
|
-
});
|
|
269
|
+
collection.deleteOne(await f.resolveWhere(), { session: this.session });
|
|
272
270
|
}
|
|
273
271
|
async insert(data) {
|
|
274
272
|
let { collection, e } = await this.collection();
|
|
@@ -258,7 +258,7 @@ export class RemultServerImplementation {
|
|
|
258
258
|
if (this.options.logApiEndPoints)
|
|
259
259
|
console.info('[remult] ' + myRoute);
|
|
260
260
|
r.route(myRoute)
|
|
261
|
-
.get(this.process(
|
|
261
|
+
.get(this.process((c, req, res, orig) => dataApiFactory(c).httpGet(res, req, () => this.serializeContext(c))))
|
|
262
262
|
.put(this.process(async (c, req, res, _, __, orig) => dataApiFactory(c).updateManyThroughPutRequest(res, req, await this.coreOptions.getRequestBody(orig))))
|
|
263
263
|
.delete(this.process(async (c, req, res, _, __, orig) => dataApiFactory(c).deleteMany(res, req, undefined)))
|
|
264
264
|
.post(this.process(async (c, req, res, _, __, orig) => dataApiFactory(c).httpPost(res, req, await this.coreOptions.getRequestBody(orig), () => this.serializeContext(c))));
|
package/esm/src/data-api.js
CHANGED
|
@@ -20,7 +20,7 @@ export class DataApi {
|
|
|
20
20
|
case 'count':
|
|
21
21
|
return this.count(res, req, undefined);
|
|
22
22
|
case 'groupBy':
|
|
23
|
-
return
|
|
23
|
+
return this.groupBy(res, req, undefined);
|
|
24
24
|
}
|
|
25
25
|
return this.getArray(res, req, undefined);
|
|
26
26
|
}
|
|
@@ -34,90 +34,31 @@ export class DataApi {
|
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return this.liveQuery(res, req, body, serializeContext, action.substring(liveQueryAction.length));
|
|
41
|
-
}
|
|
42
|
-
switch (action) {
|
|
43
|
-
case 'get':
|
|
44
|
-
validateWhereInBody();
|
|
45
|
-
return this.getArray(res, req, body);
|
|
46
|
-
case 'count':
|
|
47
|
-
validateWhereInBody();
|
|
48
|
-
return this.count(res, req, body);
|
|
49
|
-
case 'groupBy':
|
|
50
|
-
return res.success(await this.groupBy(req, body));
|
|
51
|
-
case 'deleteMany':
|
|
52
|
-
validateWhereInBody();
|
|
53
|
-
return this.deleteMany(res, req, body);
|
|
54
|
-
case 'updateMany':
|
|
55
|
-
validateWhereInBody();
|
|
56
|
-
return this.updateManyImplementation(res, req, body);
|
|
57
|
-
case 'upsertMany':
|
|
58
|
-
return this.upsertMany(res, req, body);
|
|
59
|
-
case 'endLiveQuery':
|
|
60
|
-
await this.remult.liveQueryStorage.remove(body.id);
|
|
61
|
-
res.success('ok');
|
|
62
|
-
return;
|
|
63
|
-
case 'query':
|
|
64
|
-
return res.success(await this.query(res, req, body));
|
|
65
|
-
default:
|
|
66
|
-
return res.created(await this.post(body));
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
catch (err) {
|
|
70
|
-
if (err.isForbiddenError)
|
|
71
|
-
res.forbidden(err.message);
|
|
72
|
-
else
|
|
73
|
-
res.error(err, this.repository.metadata);
|
|
37
|
+
if (action?.startsWith(liveQueryAction)) {
|
|
38
|
+
validateWhereInBody();
|
|
39
|
+
return this.liveQuery(res, req, body, serializeContext, action.substring(liveQueryAction.length));
|
|
74
40
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
response.success(result);
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
async query(response, request, body) {
|
|
101
|
-
if (!this.repository.metadata.apiReadAllowed) {
|
|
102
|
-
response.forbidden();
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
try {
|
|
106
|
-
let { aggregate, ...rest } = body;
|
|
107
|
-
let [{ r }, [aggregates]] = await Promise.all([
|
|
108
|
-
this.getArrayImpl(request, rest),
|
|
109
|
-
this.groupBy(request, aggregate),
|
|
110
|
-
]);
|
|
111
|
-
return {
|
|
112
|
-
items: r,
|
|
113
|
-
aggregates,
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
catch (err) {
|
|
117
|
-
if (err.isForbiddenError)
|
|
118
|
-
response.forbidden();
|
|
119
|
-
else
|
|
120
|
-
response.error(err, this.repository.metadata);
|
|
41
|
+
switch (action) {
|
|
42
|
+
case 'get':
|
|
43
|
+
validateWhereInBody();
|
|
44
|
+
return this.getArray(res, req, body);
|
|
45
|
+
case 'count':
|
|
46
|
+
validateWhereInBody();
|
|
47
|
+
return this.count(res, req, body);
|
|
48
|
+
case 'groupBy':
|
|
49
|
+
return this.groupBy(res, req, body);
|
|
50
|
+
case 'deleteMany':
|
|
51
|
+
validateWhereInBody();
|
|
52
|
+
return this.deleteMany(res, req, body);
|
|
53
|
+
case 'updateMany':
|
|
54
|
+
validateWhereInBody();
|
|
55
|
+
return this.updateManyImplementation(res, req, body);
|
|
56
|
+
case 'endLiveQuery':
|
|
57
|
+
await this.remult.liveQueryStorage.remove(body.id);
|
|
58
|
+
res.success('ok');
|
|
59
|
+
return;
|
|
60
|
+
default:
|
|
61
|
+
return this.post(res, body);
|
|
121
62
|
}
|
|
122
63
|
}
|
|
123
64
|
static defaultGetLimit = 0;
|
|
@@ -151,7 +92,6 @@ export class DataApi {
|
|
|
151
92
|
for await (const x of this.repository.query({
|
|
152
93
|
where,
|
|
153
94
|
include: this.includeNone(),
|
|
154
|
-
aggregate: undefined,
|
|
155
95
|
})) {
|
|
156
96
|
await this.actualDelete(x);
|
|
157
97
|
deleted++;
|
|
@@ -163,7 +103,7 @@ export class DataApi {
|
|
|
163
103
|
response.error(err, this.repository.metadata);
|
|
164
104
|
}
|
|
165
105
|
}
|
|
166
|
-
async groupBy(request, body) {
|
|
106
|
+
async groupBy(response, request, body) {
|
|
167
107
|
let findOptions = await this.findOptionsFromRequest(request, body);
|
|
168
108
|
let orderBy = {};
|
|
169
109
|
if (body?.orderBy) {
|
|
@@ -206,9 +146,9 @@ export class DataApi {
|
|
|
206
146
|
x[f] = this.repository.fields.find(f).valueConverter.toJson(x[f]);
|
|
207
147
|
}
|
|
208
148
|
});
|
|
209
|
-
|
|
149
|
+
response.success(result);
|
|
210
150
|
}
|
|
211
|
-
async getArrayImpl(request, body) {
|
|
151
|
+
async getArrayImpl(response, request, body) {
|
|
212
152
|
let findOptions = await this.findOptionsFromRequest(request, body);
|
|
213
153
|
const r = await this.repository.find(findOptions).then(async (r) => {
|
|
214
154
|
return await Promise.all(r.map(async (y) => this.repository.getEntityRef(y).toApiJson()));
|
|
@@ -284,7 +224,7 @@ export class DataApi {
|
|
|
284
224
|
return;
|
|
285
225
|
}
|
|
286
226
|
try {
|
|
287
|
-
const { r } = await this.getArrayImpl(request, body);
|
|
227
|
+
const { r } = await this.getArrayImpl(response, request, body);
|
|
288
228
|
response.success(r);
|
|
289
229
|
}
|
|
290
230
|
catch (err) {
|
|
@@ -300,7 +240,7 @@ export class DataApi {
|
|
|
300
240
|
return;
|
|
301
241
|
}
|
|
302
242
|
try {
|
|
303
|
-
const r = await this.getArrayImpl(request, body);
|
|
243
|
+
const r = await this.getArrayImpl(response, request, body);
|
|
304
244
|
const data = {
|
|
305
245
|
requestJson: await serializeContext(),
|
|
306
246
|
findOptionsJson: findOptionsToJson(r.findOptions, this.repository.metadata),
|
|
@@ -405,7 +345,6 @@ export class DataApi {
|
|
|
405
345
|
for await (const x of this.repository.query({
|
|
406
346
|
where,
|
|
407
347
|
include: this.includeNone(),
|
|
408
|
-
aggregate: undefined,
|
|
409
348
|
})) {
|
|
410
349
|
await this.actualUpdate(x, body.set);
|
|
411
350
|
updated++;
|
|
@@ -444,27 +383,35 @@ export class DataApi {
|
|
|
444
383
|
response.deleted();
|
|
445
384
|
});
|
|
446
385
|
}
|
|
447
|
-
async post(body) {
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
await this.repository.getEntityRef(newr).save();
|
|
455
|
-
return this.repository.getEntityRef(newr).toApiJson();
|
|
456
|
-
};
|
|
457
|
-
if (Array.isArray(body)) {
|
|
458
|
-
const result = [];
|
|
459
|
-
await doTransaction(this.remult, async () => {
|
|
460
|
-
for (const item of body) {
|
|
461
|
-
result.push(await insert(item));
|
|
386
|
+
async post(response, body) {
|
|
387
|
+
try {
|
|
388
|
+
const insert = async (what) => {
|
|
389
|
+
let newr = this.repository.create();
|
|
390
|
+
await this.repository.getEntityRef(newr)._updateEntityBasedOnApi(what);
|
|
391
|
+
if (!this.repository.getEntityRef(newr).apiInsertAllowed) {
|
|
392
|
+
throw new ForbiddenError();
|
|
462
393
|
}
|
|
463
|
-
|
|
464
|
-
|
|
394
|
+
await this.repository.getEntityRef(newr).save();
|
|
395
|
+
return this.repository.getEntityRef(newr).toApiJson();
|
|
396
|
+
};
|
|
397
|
+
if (Array.isArray(body)) {
|
|
398
|
+
const result = [];
|
|
399
|
+
await doTransaction(this.remult, async () => {
|
|
400
|
+
for (const item of body) {
|
|
401
|
+
result.push(await insert(item));
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
response.created(result);
|
|
405
|
+
}
|
|
406
|
+
else
|
|
407
|
+
response.created(await insert(body));
|
|
408
|
+
}
|
|
409
|
+
catch (err) {
|
|
410
|
+
if (err.isForbiddenError)
|
|
411
|
+
response.forbidden(err.message);
|
|
412
|
+
else
|
|
413
|
+
response.error(err, this.repository.metadata);
|
|
465
414
|
}
|
|
466
|
-
else
|
|
467
|
-
return await insert(body);
|
|
468
415
|
}
|
|
469
416
|
}
|
|
470
417
|
export function determineSort(sortUrlParm, dirUrlParam) {
|
|
@@ -103,35 +103,13 @@ export class RestEntityDataProvider {
|
|
|
103
103
|
this.http = http;
|
|
104
104
|
this.entity = entity;
|
|
105
105
|
}
|
|
106
|
-
query(options, aggregateOptions) {
|
|
107
|
-
const r = this.buildFindRequest(options);
|
|
108
|
-
return r
|
|
109
|
-
.run('query', {
|
|
110
|
-
aggregate: this.buildAggregateOptions(aggregateOptions),
|
|
111
|
-
})
|
|
112
|
-
.then(({ items, aggregates }) => ({
|
|
113
|
-
items: items.map((x) => this.translateFromJson(x)),
|
|
114
|
-
aggregates,
|
|
115
|
-
}));
|
|
116
|
-
}
|
|
117
106
|
async groupBy(options) {
|
|
118
107
|
const { run } = this.buildFindRequest({
|
|
119
108
|
where: options?.where,
|
|
120
109
|
limit: options?.limit,
|
|
121
110
|
page: options?.page,
|
|
122
111
|
});
|
|
123
|
-
const body =
|
|
124
|
-
const result = await run('groupBy', Object.keys(body).length > 0 ? body : undefined);
|
|
125
|
-
if (options?.group)
|
|
126
|
-
result.forEach((row) => {
|
|
127
|
-
for (const g of options.group) {
|
|
128
|
-
row[g.key] = g.valueConverter.fromJson(row[g.key]);
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
return result;
|
|
132
|
-
}
|
|
133
|
-
buildAggregateOptions(options) {
|
|
134
|
-
return {
|
|
112
|
+
const body = {
|
|
135
113
|
groupBy: options?.group?.map((x) => x.key),
|
|
136
114
|
sum: options?.sum?.map((x) => x.key),
|
|
137
115
|
avg: options?.avg?.map((x) => x.key),
|
|
@@ -140,6 +118,14 @@ export class RestEntityDataProvider {
|
|
|
140
118
|
distinctCount: options?.distinctCount?.map((x) => x.key),
|
|
141
119
|
orderBy: options?.orderBy?.map((x) => ({ ...x, field: x.field?.key })),
|
|
142
120
|
};
|
|
121
|
+
const result = await run('groupBy', Object.keys(body).length > 0 ? body : undefined);
|
|
122
|
+
if (options?.group)
|
|
123
|
+
result.forEach((row) => {
|
|
124
|
+
for (const g of options.group) {
|
|
125
|
+
row[g.key] = g.valueConverter.fromJson(row[g.key]);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
return result;
|
|
143
129
|
}
|
|
144
130
|
translateFromJson(row) {
|
|
145
131
|
let result = {};
|
|
@@ -167,13 +153,6 @@ export class RestEntityDataProvider {
|
|
|
167
153
|
const { run } = this.buildFindRequest({ where }, 'put');
|
|
168
154
|
return run('updateMany', this.toJsonOfIncludedKeys(data)).then((r) => +r.updated);
|
|
169
155
|
}
|
|
170
|
-
async upsertMany(options) {
|
|
171
|
-
const { run } = this.buildFindRequest(undefined);
|
|
172
|
-
return run('upsertMany', options.map((x) => ({
|
|
173
|
-
where: this.toJsonOfIncludedKeys(x.where),
|
|
174
|
-
set: x.set !== undefined ? this.toJsonOfIncludedKeys(x.set) : undefined,
|
|
175
|
-
}))).then((r) => r.map((x) => this.translateFromJson(x)));
|
|
176
|
-
}
|
|
177
156
|
find(options) {
|
|
178
157
|
let { run } = this.buildFindRequest(options);
|
|
179
158
|
return run().then((x) => x.map((y) => this.translateFromJson(y)));
|
package/esm/src/remult-proxy.js
CHANGED
|
@@ -161,18 +161,14 @@ export class RemultProxy {
|
|
|
161
161
|
get metadata() {
|
|
162
162
|
return remultStatic.remultFactory().repo(...args).metadata;
|
|
163
163
|
},
|
|
164
|
-
query: (
|
|
164
|
+
query: (...args2) => self
|
|
165
165
|
.remultFactory()
|
|
166
166
|
.repo(...args)
|
|
167
|
-
.query(
|
|
167
|
+
.query(...args2),
|
|
168
168
|
save: (args2) => self
|
|
169
169
|
.remultFactory()
|
|
170
170
|
.repo(...args)
|
|
171
171
|
.save(args2),
|
|
172
|
-
upsert: (args2) => self
|
|
173
|
-
.remultFactory()
|
|
174
|
-
.repo(...args)
|
|
175
|
-
.upsert(args2),
|
|
176
172
|
update: (a, b) => self
|
|
177
173
|
.remultFactory()
|
|
178
174
|
.repo(...args)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LookupColumn, makeTitle } from '../column.js';
|
|
2
2
|
import { CompoundIdField } from '../CompoundIdField.js';
|
|
3
|
-
import { Remult, isBackend } from '../context.js';
|
|
3
|
+
import { Remult, isBackend, queryConfig } from '../context.js';
|
|
4
4
|
import { Filter } from '../filter/filter-interfaces.js';
|
|
5
5
|
import { Sort } from '../sort.js';
|
|
6
6
|
import { GroupByForApiKey, } from './remult3.js';
|
|
@@ -18,7 +18,6 @@ import { remultStatic } from '../remult-static.js';
|
|
|
18
18
|
import { Validators } from '../validators.js';
|
|
19
19
|
import { addValidator } from './addValidator.js';
|
|
20
20
|
import { isOfType } from '../isOfType.js';
|
|
21
|
-
import { QueryResultImpl } from './QueryResultImpl.js';
|
|
22
21
|
//import { remult } from "../remult-proxy";
|
|
23
22
|
let classValidatorValidate = undefined;
|
|
24
23
|
// import ("class-validator".toString())
|
|
@@ -133,23 +132,6 @@ export class RepositoryImplementation {
|
|
|
133
132
|
return (await this.groupBy(options))[0];
|
|
134
133
|
}
|
|
135
134
|
async groupBy(options) {
|
|
136
|
-
var dpOptions = await this.__buildGroupByOptions(options);
|
|
137
|
-
const result = await this._edp.groupBy(dpOptions);
|
|
138
|
-
//@ts-ignore
|
|
139
|
-
if (!options?.[GroupByForApiKey] && options.group) {
|
|
140
|
-
const loaderOptions = {
|
|
141
|
-
include: {},
|
|
142
|
-
};
|
|
143
|
-
for (const key of options.group) {
|
|
144
|
-
loaderOptions.include[key] = true;
|
|
145
|
-
}
|
|
146
|
-
const loader = new RelationLoader();
|
|
147
|
-
await this._populateRelationsForFields(dpOptions.group, loaderOptions, result, loader);
|
|
148
|
-
await loader.resolveAll();
|
|
149
|
-
}
|
|
150
|
-
return result;
|
|
151
|
-
}
|
|
152
|
-
async __buildGroupByOptions(options) {
|
|
153
135
|
let findOptions = await this._buildEntityDataProviderFindOptions({
|
|
154
136
|
...options,
|
|
155
137
|
});
|
|
@@ -203,7 +185,20 @@ export class RepositoryImplementation {
|
|
|
203
185
|
}
|
|
204
186
|
}
|
|
205
187
|
}
|
|
206
|
-
|
|
188
|
+
const result = await this._edp.groupBy(dpOptions);
|
|
189
|
+
//@ts-ignore
|
|
190
|
+
if (!options?.[GroupByForApiKey] && options.group) {
|
|
191
|
+
const loaderOptions = {
|
|
192
|
+
include: {},
|
|
193
|
+
};
|
|
194
|
+
for (const key of options.group) {
|
|
195
|
+
loaderOptions.include[key] = true;
|
|
196
|
+
}
|
|
197
|
+
const loader = new RelationLoader();
|
|
198
|
+
await this._populateRelationsForFields(dpOptions.group, loaderOptions, result, loader);
|
|
199
|
+
await loader.resolveAll();
|
|
200
|
+
}
|
|
201
|
+
return result;
|
|
207
202
|
}
|
|
208
203
|
_idCache = new Map();
|
|
209
204
|
_getCachedById(id, doNotLoadIfNotFound) {
|
|
@@ -350,26 +345,14 @@ export class RepositoryImplementation {
|
|
|
350
345
|
}
|
|
351
346
|
}
|
|
352
347
|
}
|
|
353
|
-
__createDto(basedOn) {
|
|
354
|
-
const ref = this.getEntityRef({
|
|
355
|
-
...basedOn,
|
|
356
|
-
});
|
|
357
|
-
const r = ref.copyDataToObject(false);
|
|
358
|
-
const keys = Object.keys(basedOn);
|
|
359
|
-
for (const element of this.fields) {
|
|
360
|
-
if (element.dbReadOnly || !keys.includes(element.key))
|
|
361
|
-
delete r[element.key];
|
|
362
|
-
}
|
|
363
|
-
return r;
|
|
364
|
-
}
|
|
365
348
|
async updateMany({ where, set, }) {
|
|
366
349
|
Filter.throwErrorIfFilterIsEmpty(where, 'updateMany');
|
|
367
350
|
if (this._dataProvider.isProxy) {
|
|
368
|
-
return this._edp.updateMany(await this._translateWhereToFilter(where),
|
|
351
|
+
return this._edp.updateMany(await this._translateWhereToFilter(where), set);
|
|
369
352
|
}
|
|
370
353
|
else {
|
|
371
354
|
let updated = 0;
|
|
372
|
-
for await (const item of this.query({ where
|
|
355
|
+
for await (const item of this.query({ where })) {
|
|
373
356
|
assign(item, set);
|
|
374
357
|
await getEntityRef(item).save();
|
|
375
358
|
updated++;
|
|
@@ -418,40 +401,6 @@ export class RepositoryImplementation {
|
|
|
418
401
|
return await ref.save();
|
|
419
402
|
}
|
|
420
403
|
}
|
|
421
|
-
async upsert(options) {
|
|
422
|
-
if (this._dataProvider.isProxy) {
|
|
423
|
-
let rawRows = await this._edp.upsertMany((Array.isArray(options) ? options : [options]).map((x) => ({
|
|
424
|
-
where: this.__createDto(x.where),
|
|
425
|
-
set: x.set ? this.__createDto(x.set) : undefined,
|
|
426
|
-
})));
|
|
427
|
-
const loader = new RelationLoader();
|
|
428
|
-
const result = await this._loadManyToOneForManyRows(rawRows, {}, loader);
|
|
429
|
-
await loader.resolveAll();
|
|
430
|
-
if (Array.isArray(options))
|
|
431
|
-
return result;
|
|
432
|
-
else
|
|
433
|
-
return result[0];
|
|
434
|
-
}
|
|
435
|
-
if (Array.isArray(options)) {
|
|
436
|
-
return promiseAll(options, (x) => this.upsert(x));
|
|
437
|
-
}
|
|
438
|
-
let op = options;
|
|
439
|
-
var row = await this.findFirst(op.where, { createIfNotFound: true });
|
|
440
|
-
var ref = getEntityRef(row, false);
|
|
441
|
-
if (ref.isNew()) {
|
|
442
|
-
if (op.set) {
|
|
443
|
-
assign(row, op.set);
|
|
444
|
-
}
|
|
445
|
-
return await ref.save();
|
|
446
|
-
}
|
|
447
|
-
else {
|
|
448
|
-
if (op.set) {
|
|
449
|
-
assign(row, op.set);
|
|
450
|
-
return await ref.save();
|
|
451
|
-
}
|
|
452
|
-
return row;
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
404
|
_getRefForExistingRow(entity, id) {
|
|
456
405
|
let ref = getEntityRef(entity, false);
|
|
457
406
|
if (!ref) {
|
|
@@ -516,7 +465,7 @@ export class RepositoryImplementation {
|
|
|
516
465
|
},
|
|
517
466
|
};
|
|
518
467
|
}
|
|
519
|
-
async _rawFind(options, skipOrderByAndLimit = false, loader
|
|
468
|
+
async _rawFind(options, skipOrderByAndLimit = false, loader) {
|
|
520
469
|
if (!options)
|
|
521
470
|
options = {};
|
|
522
471
|
if (this._defaultFindOptions) {
|
|
@@ -528,13 +477,13 @@ export class RepositoryImplementation {
|
|
|
528
477
|
delete opt.limit;
|
|
529
478
|
}
|
|
530
479
|
Remult.onFind(this._info, options);
|
|
531
|
-
const rawRows = await
|
|
480
|
+
const rawRows = await this._edp.find(opt);
|
|
532
481
|
let result = await this._loadManyToOneForManyRows(rawRows, options, loader);
|
|
533
482
|
return result;
|
|
534
483
|
}
|
|
535
484
|
async find(options, skipOrderByAndLimit = false) {
|
|
536
485
|
const loader = new RelationLoader();
|
|
537
|
-
const result = await this._rawFind(options, skipOrderByAndLimit, loader
|
|
486
|
+
const result = await this._rawFind(options, skipOrderByAndLimit, loader);
|
|
538
487
|
await loader.resolveAll();
|
|
539
488
|
return result;
|
|
540
489
|
}
|
|
@@ -629,7 +578,7 @@ export class RepositoryImplementation {
|
|
|
629
578
|
loader
|
|
630
579
|
.load({
|
|
631
580
|
entityType,
|
|
632
|
-
find: (options) => toRepo._rawFind(options, false, loader
|
|
581
|
+
find: (options) => toRepo._rawFind(options, false, loader),
|
|
633
582
|
metadata: toRepo.metadata,
|
|
634
583
|
}, findOptions)
|
|
635
584
|
.then((result) => {
|
|
@@ -780,7 +729,7 @@ export class RepositoryImplementation {
|
|
|
780
729
|
}
|
|
781
730
|
else {
|
|
782
731
|
let deleted = 0;
|
|
783
|
-
for await (const item of this.query({ where
|
|
732
|
+
for await (const item of this.query({ where })) {
|
|
784
733
|
await getEntityRef(item).delete();
|
|
785
734
|
deleted++;
|
|
786
735
|
}
|
|
@@ -1506,9 +1455,11 @@ export class rowHelperImplementation extends rowHelperBase {
|
|
|
1506
1455
|
await this.__validateEntity();
|
|
1507
1456
|
this.__assertValidity();
|
|
1508
1457
|
let d = this.copyDataToObject(this.isNew());
|
|
1458
|
+
let ignoreKeys = [];
|
|
1509
1459
|
for (const field of this.metadata.fields) {
|
|
1510
1460
|
if (field.dbReadOnly) {
|
|
1511
1461
|
d[field.key] = undefined;
|
|
1462
|
+
ignoreKeys.push(field.key);
|
|
1512
1463
|
let f = this.fields.find(field);
|
|
1513
1464
|
f.value = f.originalValue;
|
|
1514
1465
|
}
|
|
@@ -2429,6 +2380,116 @@ export class ControllerBase {
|
|
|
2429
2380
|
return getControllerRef(this, this.remult);
|
|
2430
2381
|
}
|
|
2431
2382
|
}
|
|
2383
|
+
class QueryResultImpl {
|
|
2384
|
+
options;
|
|
2385
|
+
repo;
|
|
2386
|
+
constructor(options, repo) {
|
|
2387
|
+
this.options = options;
|
|
2388
|
+
this.repo = repo;
|
|
2389
|
+
if (!this.options)
|
|
2390
|
+
this.options = {};
|
|
2391
|
+
if (!this.options.pageSize) {
|
|
2392
|
+
this.options.pageSize = queryConfig.defaultPageSize;
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
_count = undefined;
|
|
2396
|
+
async getPage(page) {
|
|
2397
|
+
if ((page ?? 0) < 1)
|
|
2398
|
+
page = 1;
|
|
2399
|
+
return this.repo.find({
|
|
2400
|
+
where: this.options.where,
|
|
2401
|
+
orderBy: this.options.orderBy,
|
|
2402
|
+
limit: this.options.pageSize,
|
|
2403
|
+
page: page,
|
|
2404
|
+
load: this.options.load,
|
|
2405
|
+
include: this.options.include,
|
|
2406
|
+
});
|
|
2407
|
+
}
|
|
2408
|
+
async count() {
|
|
2409
|
+
if (this._count === undefined)
|
|
2410
|
+
this._count = await this.repo.count(this.options.where);
|
|
2411
|
+
return this._count;
|
|
2412
|
+
}
|
|
2413
|
+
async forEach(what) {
|
|
2414
|
+
let i = 0;
|
|
2415
|
+
for await (const x of this) {
|
|
2416
|
+
await what(x);
|
|
2417
|
+
i++;
|
|
2418
|
+
}
|
|
2419
|
+
return i;
|
|
2420
|
+
}
|
|
2421
|
+
async paginator(pNextPageFilter) {
|
|
2422
|
+
this.options.orderBy = Sort.createUniqueEntityOrderBy(this.repo.metadata, this.options.orderBy);
|
|
2423
|
+
let items = await this.repo.find({
|
|
2424
|
+
where: {
|
|
2425
|
+
$and: [this.options.where, pNextPageFilter],
|
|
2426
|
+
},
|
|
2427
|
+
orderBy: this.options.orderBy,
|
|
2428
|
+
limit: this.options.pageSize,
|
|
2429
|
+
load: this.options.load,
|
|
2430
|
+
include: this.options.include,
|
|
2431
|
+
});
|
|
2432
|
+
let nextPage = () => {
|
|
2433
|
+
throw new Error('no more pages');
|
|
2434
|
+
};
|
|
2435
|
+
let hasNextPage = items.length == this.options.pageSize;
|
|
2436
|
+
if (hasNextPage) {
|
|
2437
|
+
let nextPageFilter = await this.repo._createAfterFilter(this.options.orderBy, items[items.length - 1]);
|
|
2438
|
+
nextPage = () => this.paginator(nextPageFilter);
|
|
2439
|
+
}
|
|
2440
|
+
return {
|
|
2441
|
+
count: () => this.count(),
|
|
2442
|
+
hasNextPage,
|
|
2443
|
+
items,
|
|
2444
|
+
nextPage,
|
|
2445
|
+
};
|
|
2446
|
+
}
|
|
2447
|
+
[Symbol.asyncIterator]() {
|
|
2448
|
+
if (!this.options.where) {
|
|
2449
|
+
this.options.where = {};
|
|
2450
|
+
}
|
|
2451
|
+
let ob = this.options.orderBy;
|
|
2452
|
+
this.options.orderBy = Sort.createUniqueEntityOrderBy(this.repo.metadata, ob);
|
|
2453
|
+
let itemIndex = -1;
|
|
2454
|
+
let currentPage = undefined;
|
|
2455
|
+
let itStrategy;
|
|
2456
|
+
let j = 0;
|
|
2457
|
+
itStrategy = async () => {
|
|
2458
|
+
if (this.options.progress) {
|
|
2459
|
+
this.options.progress.progress(j++ / (await this.count()));
|
|
2460
|
+
}
|
|
2461
|
+
if (currentPage === undefined || itemIndex == currentPage.items.length) {
|
|
2462
|
+
if (currentPage && !currentPage.hasNextPage)
|
|
2463
|
+
return { value: undefined, done: true };
|
|
2464
|
+
let prev = currentPage;
|
|
2465
|
+
if (currentPage)
|
|
2466
|
+
currentPage = await currentPage.nextPage();
|
|
2467
|
+
else
|
|
2468
|
+
currentPage = await this.paginator();
|
|
2469
|
+
itemIndex = 0;
|
|
2470
|
+
if (currentPage.items.length == 0) {
|
|
2471
|
+
return { value: undefined, done: true };
|
|
2472
|
+
}
|
|
2473
|
+
else {
|
|
2474
|
+
if (prev?.items.length ?? 0 > 0) {
|
|
2475
|
+
if (this.repo.getEntityRef(prev.items[0]).getId() ==
|
|
2476
|
+
this.repo.getEntityRef(currentPage.items[0]).getId())
|
|
2477
|
+
throw new Error('pagination failure, returned same first row');
|
|
2478
|
+
}
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2481
|
+
if (itemIndex < currentPage.items.length)
|
|
2482
|
+
return { value: currentPage.items[itemIndex++], done: false };
|
|
2483
|
+
return { done: true, value: undefined };
|
|
2484
|
+
};
|
|
2485
|
+
return {
|
|
2486
|
+
next: async () => {
|
|
2487
|
+
let r = itStrategy();
|
|
2488
|
+
return r;
|
|
2489
|
+
},
|
|
2490
|
+
};
|
|
2491
|
+
}
|
|
2492
|
+
}
|
|
2432
2493
|
class cacheEntityInfo {
|
|
2433
2494
|
value = {};
|
|
2434
2495
|
promise;
|