remult 3.3.18-next.0 → 3.3.19-next.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/index.js +7 -6
- package/esm/internals.js +0 -1
- package/esm/remult-d1.js +1 -0
- package/esm/remult-knex/index.js +112 -2
- package/esm/remult-mongo.js +17 -8
- package/esm/remult-sqlite-core.js +1 -0
- package/esm/server/initAsyncHooks.js +3 -7
- package/esm/server/test-api-data-provider.js +0 -1
- package/esm/src/context.js +7 -66
- package/esm/src/data-interfaces.js +4 -4
- package/esm/src/data-providers/array-entity-data-provider.js +22 -4
- package/esm/src/data-providers/indexed-db-data-provider.js +644 -0
- package/esm/src/data-providers/json-data-provider.js +2 -2
- package/esm/src/data-providers/rest-data-provider.js +11 -12
- package/esm/src/data-providers/sql-database.js +110 -43
- package/esm/src/remult-proxy.js +0 -4
- package/esm/src/remult3/RepositoryImplementation.js +90 -60
- package/index.d.ts +31 -17
- package/index.js +5 -2
- package/internals.d.ts +0 -1
- package/internals.js +1 -3
- package/package.json +1 -1
- package/remult-d1.d.ts +1 -0
- package/remult-d1.js +1 -0
- package/remult-knex/index.d.ts +2 -2
- package/remult-knex/index.js +329 -44
- package/remult-mongo.js +80 -36
- package/remult-sqlite-core.d.ts +1 -0
- package/remult-sqlite-core.js +1 -0
- package/server/initAsyncHooks.d.ts +11 -15
- package/server/initAsyncHooks.js +15 -13
- package/server/test-api-data-provider.js +0 -1
- package/src/column-interfaces.d.ts +4 -0
- package/src/context.d.ts +12 -37
- package/src/context.js +21 -114
- package/src/data-interfaces.d.ts +2 -3
- package/src/data-interfaces.js +4 -4
- package/src/data-providers/array-entity-data-provider.d.ts +2 -2
- package/src/data-providers/array-entity-data-provider.js +100 -16
- package/src/data-providers/indexed-db-data-provider.d.ts +37 -0
- package/src/data-providers/indexed-db-data-provider.js +1048 -0
- package/src/data-providers/json-data-provider.js +2 -2
- package/src/data-providers/rest-data-provider.d.ts +2 -3
- package/src/data-providers/rest-data-provider.js +18 -17
- package/src/data-providers/sql-database.js +254 -105
- package/src/remult-proxy.js +0 -8
- package/src/remult3/RepositoryImplementation.d.ts +1 -1
- package/src/remult3/RepositoryImplementation.js +384 -270
- package/src/remult3/remult3.d.ts +2 -2
- package/src/sql-command.d.ts +2 -0
- package/src/standard-schema/index.d.ts +1 -1
package/esm/index.js
CHANGED
|
@@ -9,31 +9,32 @@ export { LabelTransformer } from './src/remult3/RepositoryImplementation.js';
|
|
|
9
9
|
export const CaptionTransformer = LabelTransformer;
|
|
10
10
|
export { Entity } from './src/remult3/entity.js';
|
|
11
11
|
export { getEntityRef } from './src/remult3/getEntityRef.js';
|
|
12
|
-
export { Field, Fields, Relations
|
|
12
|
+
export { Field, Fields, Relations } from './src/remult3/Fields.js';
|
|
13
13
|
export { IdEntity } from './src/remult3/IdEntity.js';
|
|
14
14
|
export { describeClass, describeBackendMethods, describeEntity, } from './src/remult3/classDescribers.js';
|
|
15
|
-
export { EntityError
|
|
15
|
+
export { EntityError } from './src/data-interfaces.js'; //V
|
|
16
16
|
export { RestDataProvider } from './src/data-providers/rest-data-provider.js'; //V
|
|
17
17
|
export { InMemoryDataProvider } from './src/data-providers/in-memory-database.js'; //V
|
|
18
18
|
export { SqlDatabase } from './src/data-providers/sql-database.js'; //V
|
|
19
19
|
export { CustomSqlFilterBuilder, dbNamesOf, } from './src/filter/filter-consumer-bridge-to-sql-request.js';
|
|
20
|
-
export { JsonDataProvider
|
|
20
|
+
export { JsonDataProvider } from './src/data-providers/json-data-provider.js'; //V
|
|
21
21
|
export { JsonEntityOpfsStorage } from './src/data-providers/json-entity-opfs-storage.js';
|
|
22
22
|
export { JsonEntityIndexedDbStorage } from './src/data-providers/json-entity-indexed-db-data-provider.js';
|
|
23
|
+
export { IndexedDbDataProvider, IndexedDbIndexBuilder, } from './src/data-providers/indexed-db-data-provider.js';
|
|
23
24
|
//export * from './src/data-api'; //reconsider if to make internal
|
|
24
25
|
export { Controller, BackendMethod, ProgressListener, ForbiddenError, } from './src/server-action.js';
|
|
25
26
|
export { Allow, Remult, withRemult, isBackend, EventSource, } from './src/context.js';
|
|
26
27
|
export { Sort } from './src/sort.js';
|
|
27
28
|
export { CompoundIdField } from './src/CompoundIdField.js';
|
|
28
|
-
export { Filter
|
|
29
|
+
export { Filter } from './src/filter/filter-interfaces.js';
|
|
29
30
|
export { UrlBuilder } from './urlBuilder.js';
|
|
30
31
|
export { Validators, valueValidator, createValidator, createValidatorWithArgs, createValueValidatorWithArgs, createValueValidator, } from './src/validators.js';
|
|
31
32
|
export { ValueConverters } from './src/valueConverters.js';
|
|
32
33
|
export { remult } from './src/remult-proxy.js';
|
|
33
34
|
import { remult } from './src/remult-proxy.js';
|
|
34
35
|
//export { getId } from './src/remult3/getId';
|
|
35
|
-
export { InMemoryLiveQueryStorage
|
|
36
|
-
export { SubscriptionChannel
|
|
36
|
+
export { InMemoryLiveQueryStorage } from './src/live-query/SubscriptionServer.js';
|
|
37
|
+
export { SubscriptionChannel } from './src/live-query/SubscriptionChannel.js';
|
|
37
38
|
/**
|
|
38
39
|
* A convenient shortcut function to quickly obtain a repository for a specific entity type in Remult.
|
|
39
40
|
*
|
package/esm/internals.js
CHANGED
|
@@ -9,4 +9,3 @@ export { isOfType } from './src/isOfType.js';
|
|
|
9
9
|
export { flags } from './src/remult3/remult3.js';
|
|
10
10
|
export { DataProviderPromiseWrapper } from './src/data-interfaces.js';
|
|
11
11
|
export { pagedQueryResult } from './src/remult3/pagedQueryResult.js';
|
|
12
|
-
export { withFetch } from './src/context.js';
|
package/esm/remult-d1.js
CHANGED
package/esm/remult-knex/index.js
CHANGED
|
@@ -234,16 +234,87 @@ class KnexEntityDataProvider {
|
|
|
234
234
|
return undefined;
|
|
235
235
|
return getRowAfterUpdate(this.entity, this, data, id, 'update');
|
|
236
236
|
}
|
|
237
|
-
async delete(
|
|
237
|
+
async delete(ids) {
|
|
238
|
+
if (ids.length === 0)
|
|
239
|
+
return;
|
|
238
240
|
const e = await this.init();
|
|
239
241
|
let f = new FilterConsumerBridgeToKnexRequest(e, this.rawSqlWrapIdentifier);
|
|
240
|
-
Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(
|
|
242
|
+
Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(...ids)).__applyToConsumer(f);
|
|
241
243
|
let where = await f.resolveWhere();
|
|
242
244
|
await this.getEntityFrom(e)
|
|
243
245
|
.delete()
|
|
244
246
|
.where((b) => where.forEach((w) => w(b)));
|
|
245
247
|
}
|
|
246
248
|
async insert(data, options) {
|
|
249
|
+
if (data.length === 0)
|
|
250
|
+
return [];
|
|
251
|
+
if (isMysqlKnex(this.knex) &&
|
|
252
|
+
isAutoIncrement(this.entity.idMetadata.field) &&
|
|
253
|
+
options?.select !== 'none') {
|
|
254
|
+
const result = [];
|
|
255
|
+
for (const row of data)
|
|
256
|
+
result.push(await this.insertOne(row, options));
|
|
257
|
+
return result;
|
|
258
|
+
}
|
|
259
|
+
const e = await this.init();
|
|
260
|
+
const batches = splitByMaxParameters(data, (row) => countKnexInsertBindParameters(this.entity, e, row), knexMaxParametersInOneSqlStatement(this.knex));
|
|
261
|
+
const result = [];
|
|
262
|
+
for (const batch of batches)
|
|
263
|
+
result.push(...(await this.insertBatch(batch, e, options)));
|
|
264
|
+
return result;
|
|
265
|
+
}
|
|
266
|
+
async insertBatch(batch, e, options) {
|
|
267
|
+
const cols = [];
|
|
268
|
+
for (const x of this.entity.fields) {
|
|
269
|
+
if (isDbReadonly(x, e))
|
|
270
|
+
continue;
|
|
271
|
+
if (batch.some((row) => translateValueAndHandleArrayAndHandleArray(x, row[x.key]) !=
|
|
272
|
+
undefined))
|
|
273
|
+
cols.push(x);
|
|
274
|
+
}
|
|
275
|
+
const insertObjects = [];
|
|
276
|
+
for (const row of batch) {
|
|
277
|
+
const insertObject = {};
|
|
278
|
+
for (const x of cols) {
|
|
279
|
+
const v = translateValueAndHandleArrayAndHandleArray(x, row[x.key]);
|
|
280
|
+
const key = await e.$dbNameOf(x);
|
|
281
|
+
if (v != undefined)
|
|
282
|
+
insertObject[key] = v;
|
|
283
|
+
else if (x.allowNull)
|
|
284
|
+
insertObject[key] = null;
|
|
285
|
+
else
|
|
286
|
+
insertObject[key] = this.knex.raw('DEFAULT');
|
|
287
|
+
}
|
|
288
|
+
insertObjects.push(insertObject);
|
|
289
|
+
}
|
|
290
|
+
let insert = this.getEntityFrom(e).insert(insertObjects);
|
|
291
|
+
const wantRows = options?.select !== 'none';
|
|
292
|
+
if (isAutoIncrement(this.entity.idMetadata.field) && wantRows) {
|
|
293
|
+
const result = await insert.returning(this.entity.idMetadata.field.dbName);
|
|
294
|
+
const ids = result.map((r) => r && typeof r === 'object'
|
|
295
|
+
? r[this.entity.idMetadata.field.dbName]
|
|
296
|
+
: r);
|
|
297
|
+
return this.loadRowsByIds(ids);
|
|
298
|
+
}
|
|
299
|
+
await insert;
|
|
300
|
+
if (!wantRows)
|
|
301
|
+
return batch.map(() => undefined);
|
|
302
|
+
return this.loadRowsByIds(batch.map((row) => this.entity.idMetadata.getId(row)));
|
|
303
|
+
}
|
|
304
|
+
async loadRowsByIds(ids) {
|
|
305
|
+
const found = await this.find({
|
|
306
|
+
where: Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(...ids)),
|
|
307
|
+
});
|
|
308
|
+
const byId = new Map(found.map((row) => [this.entity.idMetadata.getId(row) + '', row]));
|
|
309
|
+
return ids.map((id) => {
|
|
310
|
+
const row = byId.get(id + '');
|
|
311
|
+
if (!row)
|
|
312
|
+
throw new Error(`Failed to insert row - result contained ${found.length} rows`);
|
|
313
|
+
return row;
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
//@internal
|
|
317
|
+
async insertOne(data, options) {
|
|
247
318
|
const e = await this.init();
|
|
248
319
|
let insertObject = {};
|
|
249
320
|
for (const x of this.entity.fields) {
|
|
@@ -591,6 +662,45 @@ export async function createKnexDataProvider(config) {
|
|
|
591
662
|
let result = new KnexDataProvider(k);
|
|
592
663
|
return result;
|
|
593
664
|
}
|
|
665
|
+
const defaultMaxParametersInOneSqlStatement = 2000;
|
|
666
|
+
function isMysqlKnex(knex) {
|
|
667
|
+
const client = knex.client.config.client;
|
|
668
|
+
return client === 'mysql2' || client === 'mysql';
|
|
669
|
+
}
|
|
670
|
+
function knexMaxParametersInOneSqlStatement(knex) {
|
|
671
|
+
const client = String(knex.client.config.client ?? '');
|
|
672
|
+
if (client.includes('sqlite'))
|
|
673
|
+
return 999;
|
|
674
|
+
return defaultMaxParametersInOneSqlStatement;
|
|
675
|
+
}
|
|
676
|
+
function splitByMaxParameters(items, parametersInItem, maxParameters) {
|
|
677
|
+
const batches = [];
|
|
678
|
+
let batch = [];
|
|
679
|
+
let params = 0;
|
|
680
|
+
for (const item of items) {
|
|
681
|
+
const n = parametersInItem(item);
|
|
682
|
+
if (batch.length > 0 && params + n > maxParameters) {
|
|
683
|
+
batches.push(batch);
|
|
684
|
+
batch = [];
|
|
685
|
+
params = 0;
|
|
686
|
+
}
|
|
687
|
+
batch.push(item);
|
|
688
|
+
params += n;
|
|
689
|
+
}
|
|
690
|
+
if (batch.length)
|
|
691
|
+
batches.push(batch);
|
|
692
|
+
return batches;
|
|
693
|
+
}
|
|
694
|
+
function countKnexInsertBindParameters(entity, e, row) {
|
|
695
|
+
let n = 0;
|
|
696
|
+
for (const x of entity.fields) {
|
|
697
|
+
if (isDbReadonly(x, e))
|
|
698
|
+
continue;
|
|
699
|
+
if (translateValueAndHandleArrayAndHandleArray(x, row[x.key]) != undefined)
|
|
700
|
+
n++;
|
|
701
|
+
}
|
|
702
|
+
return n;
|
|
703
|
+
}
|
|
594
704
|
function translateValueAndHandleArrayAndHandleArray(field, val) {
|
|
595
705
|
let result = field.valueConverter.toDb(val);
|
|
596
706
|
if (Array.isArray(result))
|
package/esm/remult-mongo.js
CHANGED
|
@@ -266,22 +266,31 @@ class MongoEntityDataProvider {
|
|
|
266
266
|
return undefined;
|
|
267
267
|
return getRowAfterUpdate(this.entity, this, data, id, 'update');
|
|
268
268
|
}
|
|
269
|
-
async delete(
|
|
269
|
+
async delete(ids) {
|
|
270
|
+
if (ids.length === 0)
|
|
271
|
+
return;
|
|
270
272
|
const { e, collection } = await this.collection();
|
|
271
273
|
let f = new FilterConsumerBridgeToMongo(e);
|
|
272
|
-
Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(
|
|
273
|
-
await collection.
|
|
274
|
+
Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(...ids)).__applyToConsumer(f);
|
|
275
|
+
await collection.deleteMany(await f.resolveWhere(), {
|
|
274
276
|
session: this.session,
|
|
275
277
|
});
|
|
276
278
|
}
|
|
277
279
|
async insert(data, options) {
|
|
280
|
+
if (data.length === 0)
|
|
281
|
+
return [];
|
|
278
282
|
let { collection, e } = await this.collection();
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
283
|
+
const docs = [];
|
|
284
|
+
for (const row of data)
|
|
285
|
+
docs.push(await this.translateToDb(row, e));
|
|
286
|
+
const r = await collection.insertMany(docs, { session: this.session });
|
|
282
287
|
if (options?.select === 'none')
|
|
283
|
-
return undefined;
|
|
284
|
-
|
|
288
|
+
return data.map(() => undefined);
|
|
289
|
+
const result = [];
|
|
290
|
+
for (let i = 0; i < data.length; i++) {
|
|
291
|
+
result.push(await this.translateFromDb(await collection.findOne({ _id: r.insertedIds[i] }, { session: this.session }), e));
|
|
292
|
+
}
|
|
293
|
+
return result;
|
|
285
294
|
}
|
|
286
295
|
async collection() {
|
|
287
296
|
const e = await dbNamesOf(this.entity);
|
|
@@ -13,6 +13,7 @@ export class SqliteCoreDataProvider {
|
|
|
13
13
|
this.doesNotSupportReturningSyntaxOnlyForUpdate = doesNotSupportReturningSyntaxOnlyForUpdate;
|
|
14
14
|
}
|
|
15
15
|
orderByNullsFirst;
|
|
16
|
+
maxParametersInOneSqlStatement = 999;
|
|
16
17
|
getLimitSqlSyntax(limit, offset) {
|
|
17
18
|
return ' limit ' + limit + ' offset ' + offset;
|
|
18
19
|
}
|
|
@@ -16,7 +16,7 @@ export function initAsyncHooks() {
|
|
|
16
16
|
}
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
|
-
export class
|
|
19
|
+
export class AsyncLocalStorageBridgeToRemultAsyncLocalStorageCoreImpl {
|
|
20
20
|
asyncLocalStorage = new AsyncLocalStorage();
|
|
21
21
|
wasImplemented = 'yes';
|
|
22
22
|
run(store, callback) {
|
|
@@ -36,14 +36,8 @@ export class AsyncLocalStorageBridgeToRemultAsyncLocalStorageCore {
|
|
|
36
36
|
getStore() {
|
|
37
37
|
return this.asyncLocalStorage.getStore();
|
|
38
38
|
}
|
|
39
|
-
createDataProviderAsyncLocalStorage() {
|
|
40
|
-
return new AsyncLocalStorage();
|
|
41
|
-
}
|
|
42
39
|
}
|
|
43
40
|
export class StubRemultAsyncLocalStorageCore {
|
|
44
|
-
createDataProviderAsyncLocalStorage() {
|
|
45
|
-
return undefined;
|
|
46
|
-
}
|
|
47
41
|
isStub = true;
|
|
48
42
|
wasImplemented = 'yes';
|
|
49
43
|
async run(store, callback) {
|
|
@@ -56,3 +50,5 @@ export class StubRemultAsyncLocalStorageCore {
|
|
|
56
50
|
lastPromise = Promise.resolve(undefined);
|
|
57
51
|
currentValue;
|
|
58
52
|
}
|
|
53
|
+
export class AsyncLocalStorageBridgeToRemultAsyncLocalStorageCore extends AsyncLocalStorageBridgeToRemultAsyncLocalStorageCoreImpl {
|
|
54
|
+
}
|
package/esm/src/context.js
CHANGED
|
@@ -45,9 +45,6 @@ export class RemultAsyncLocalStorage {
|
|
|
45
45
|
if (val || this.remultObjectStorage?.isStub)
|
|
46
46
|
store.inInitRequest = val;
|
|
47
47
|
}
|
|
48
|
-
createDataProviderAsyncLocalStorage() {
|
|
49
|
-
return this.remultObjectStorage?.createDataProviderAsyncLocalStorage();
|
|
50
|
-
}
|
|
51
48
|
getStore() {
|
|
52
49
|
if (!this.remultObjectStorage) {
|
|
53
50
|
throw new Error("can't use static remult in this environment, `async_hooks` were not initialized");
|
|
@@ -186,15 +183,8 @@ export class Remult {
|
|
|
186
183
|
httpClient: fetch,
|
|
187
184
|
}));
|
|
188
185
|
}
|
|
189
|
-
/* @internal */
|
|
190
|
-
_myDataProviderStore = new RemultInstanceDataProviderStore(new RestDataProvider(() => this.apiClient));
|
|
191
186
|
/** The current data provider */
|
|
192
|
-
|
|
193
|
-
this._myDataProviderStore.getStore().dataProvider = dataProvider;
|
|
194
|
-
}
|
|
195
|
-
get dataProvider() {
|
|
196
|
-
return this._myDataProviderStore.getStore().dataProvider;
|
|
197
|
-
}
|
|
187
|
+
dataProvider = new RestDataProvider(() => this.apiClient);
|
|
198
188
|
/* @internal */
|
|
199
189
|
repCache = new Map();
|
|
200
190
|
constructor(provider) {
|
|
@@ -321,11 +311,10 @@ export async function doTransaction(remult, what) {
|
|
|
321
311
|
const prev = remult.dataProvider;
|
|
322
312
|
try {
|
|
323
313
|
await remult.dataProvider.transaction(async (ds) => {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
});
|
|
314
|
+
remult.dataProvider = ds;
|
|
315
|
+
remult.liveQueryPublisher = trans;
|
|
316
|
+
await what(ds);
|
|
317
|
+
ok = true;
|
|
329
318
|
});
|
|
330
319
|
if (ok)
|
|
331
320
|
await trans.flush();
|
|
@@ -369,54 +358,6 @@ class transactionLiveQueryPublisher {
|
|
|
369
358
|
}
|
|
370
359
|
export async function withRemult(callback, options) {
|
|
371
360
|
const remult = new Remult();
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
return await callback(r);
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
export class RemultInstanceDataProviderStore {
|
|
378
|
-
constructor(dataProvider) {
|
|
379
|
-
this._myDataProviderStore = { dataProvider };
|
|
380
|
-
}
|
|
381
|
-
_myDataProviderStore;
|
|
382
|
-
getStore = () => this._myDataProviderStore;
|
|
383
|
-
asyncStore;
|
|
384
|
-
async withDataProvider(dataProvider, callback) {
|
|
385
|
-
if (!this.asyncStore) {
|
|
386
|
-
this.asyncStore =
|
|
387
|
-
remultStatic.asyncContext.createDataProviderAsyncLocalStorage();
|
|
388
|
-
if (this.asyncStore) {
|
|
389
|
-
this.getStore = () => this.asyncStore.getStore() ?? this._myDataProviderStore;
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
if (this.asyncStore) {
|
|
393
|
-
return this.asyncStore.run({ dataProvider }, async () => {
|
|
394
|
-
return await callback();
|
|
395
|
-
});
|
|
396
|
-
}
|
|
397
|
-
else {
|
|
398
|
-
const prev = this._myDataProviderStore;
|
|
399
|
-
try {
|
|
400
|
-
this._myDataProviderStore = { dataProvider };
|
|
401
|
-
return await callback();
|
|
402
|
-
}
|
|
403
|
-
finally {
|
|
404
|
-
this._myDataProviderStore = prev;
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
export function withRemultDataProvider({ dataProvider, remult }, callback) {
|
|
410
|
-
remult = remult ?? remultStatic.remultFactory();
|
|
411
|
-
return remult._myDataProviderStore.withDataProvider(dataProvider, callback);
|
|
412
|
-
}
|
|
413
|
-
export function withFetch(fetch, callback) {
|
|
414
|
-
const remult = remultStatic.remultFactory();
|
|
415
|
-
return withRemultDataProvider({
|
|
416
|
-
remult,
|
|
417
|
-
dataProvider: new RestDataProvider(() => ({
|
|
418
|
-
...remult.apiClient,
|
|
419
|
-
httpClient: fetch,
|
|
420
|
-
})),
|
|
421
|
-
}, callback);
|
|
361
|
+
remult.dataProvider = await initDataProvider(options?.dataProvider, true, async () => remult.dataProvider);
|
|
362
|
+
return remultStatic.asyncContext.run(remult, (r) => callback(r));
|
|
422
363
|
}
|
|
@@ -40,11 +40,11 @@ class EntityDataProviderPromiseWrapper {
|
|
|
40
40
|
constructor(dataProvider) {
|
|
41
41
|
this.dataProvider = dataProvider;
|
|
42
42
|
}
|
|
43
|
-
delete(
|
|
44
|
-
return this.dataProvider.then((dp) => dp.delete(
|
|
43
|
+
delete(ids) {
|
|
44
|
+
return this.dataProvider.then((dp) => dp.delete(ids));
|
|
45
45
|
}
|
|
46
|
-
insert(data) {
|
|
47
|
-
return this.dataProvider.then((dp) => dp.insert(data));
|
|
46
|
+
insert(data, options) {
|
|
47
|
+
return this.dataProvider.then((dp) => dp.insert(data, options));
|
|
48
48
|
}
|
|
49
49
|
count(where) {
|
|
50
50
|
return this.dataProvider.then((dp) => dp.count(where));
|
|
@@ -267,8 +267,14 @@ export class ArrayEntityDataProvider {
|
|
|
267
267
|
translateToJson(row, dbNames) {
|
|
268
268
|
let result = {};
|
|
269
269
|
for (const col of this.entity.fields) {
|
|
270
|
-
if (!isDbReadonly(col, dbNames))
|
|
271
|
-
|
|
270
|
+
if (!isDbReadonly(col, dbNames)) {
|
|
271
|
+
let val = row[col.key];
|
|
272
|
+
if (val === undefined) {
|
|
273
|
+
if (col.allowNull)
|
|
274
|
+
val = null;
|
|
275
|
+
}
|
|
276
|
+
result[dbNames.$dbNameOf(col)] = col.valueConverter.toJson(val);
|
|
277
|
+
}
|
|
272
278
|
}
|
|
273
279
|
return result;
|
|
274
280
|
}
|
|
@@ -312,18 +318,30 @@ export class ArrayEntityDataProvider {
|
|
|
312
318
|
}
|
|
313
319
|
throw new Error(`ArrayEntityDataProvider: Couldn't find row with id "${id}" in entity "${this.entity.key}" to update`);
|
|
314
320
|
}
|
|
315
|
-
async delete(
|
|
321
|
+
async delete(ids) {
|
|
322
|
+
for (const id of ids)
|
|
323
|
+
await this.deleteOne(id);
|
|
324
|
+
}
|
|
325
|
+
//@internal
|
|
326
|
+
async deleteOne(id) {
|
|
316
327
|
const names = await this.init();
|
|
317
328
|
let idMatches = this.idMatches(id, names);
|
|
318
329
|
for (let i = 0; i < this.rows().length; i++) {
|
|
319
330
|
if (idMatches(this.rows()[i])) {
|
|
320
331
|
this.rows().splice(i, 1);
|
|
321
|
-
return
|
|
332
|
+
return;
|
|
322
333
|
}
|
|
323
334
|
}
|
|
324
335
|
throw new Error(`ArrayEntityDataProvider: Couldn't find row with id "${id}" in entity "${this.entity.key}" to delete`);
|
|
325
336
|
}
|
|
326
337
|
async insert(data) {
|
|
338
|
+
const result = [];
|
|
339
|
+
for (const row of data)
|
|
340
|
+
result.push(await this.insertOne(row));
|
|
341
|
+
return result;
|
|
342
|
+
}
|
|
343
|
+
//@internal
|
|
344
|
+
async insertOne(data) {
|
|
327
345
|
const names = await this.init();
|
|
328
346
|
let j = this.translateToJson(data, names);
|
|
329
347
|
let idf = this.entity.idMetadata.field;
|