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