@loopback/repository 1.15.4 → 1.18.0
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/CHANGELOG.md +60 -0
- package/dist/common-types.d.ts +10 -1
- package/dist/common-types.js +1 -0
- package/dist/common-types.js.map +1 -1
- package/dist/decorators/model.decorator.js +7 -6
- package/dist/decorators/model.decorator.js.map +1 -1
- package/dist/decorators/repository.decorator.js +5 -2
- package/dist/decorators/repository.decorator.js.map +1 -1
- package/dist/define-model-class.d.ts +55 -0
- package/dist/define-model-class.js +60 -0
- package/dist/define-model-class.js.map +1 -0
- package/dist/errors/invalid-relation.error.js +2 -1
- package/dist/errors/invalid-relation.error.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/mixins/repository.mixin.js +11 -4
- package/dist/mixins/repository.mixin.js.map +1 -1
- package/dist/model.js +2 -2
- package/dist/model.js.map +1 -1
- package/dist/query.js +8 -5
- package/dist/query.js.map +1 -1
- package/dist/relations/belongs-to/belongs-to-accessor.js +12 -3
- package/dist/relations/belongs-to/belongs-to-accessor.js.map +1 -1
- package/dist/relations/belongs-to/belongs-to.helpers.js +5 -2
- package/dist/relations/belongs-to/belongs-to.helpers.js.map +1 -1
- package/dist/relations/has-many/has-many-repository.factory.js +5 -2
- package/dist/relations/has-many/has-many-repository.factory.js.map +1 -1
- package/dist/relations/has-many/has-many-through.repository.d.ts +66 -0
- package/dist/relations/has-many/has-many-through.repository.js +7 -0
- package/dist/relations/has-many/has-many-through.repository.js.map +1 -0
- package/dist/relations/has-many/has-many.helpers.js +18 -4
- package/dist/relations/has-many/has-many.helpers.js.map +1 -1
- package/dist/relations/has-many/has-many.inclusion-resolver.js +5 -2
- package/dist/relations/has-many/has-many.inclusion-resolver.js.map +1 -1
- package/dist/relations/has-one/has-one-repository.factory.js +5 -2
- package/dist/relations/has-one/has-one-repository.factory.js.map +1 -1
- package/dist/relations/has-one/has-one.helpers.js +14 -3
- package/dist/relations/has-one/has-one.helpers.js.map +1 -1
- package/dist/relations/relation.decorator.js +2 -1
- package/dist/relations/relation.decorator.js.map +1 -1
- package/dist/relations/relation.helpers.d.ts +1 -1
- package/dist/relations/relation.helpers.js +18 -13
- package/dist/relations/relation.helpers.js.map +1 -1
- package/dist/relations/relation.types.d.ts +50 -3
- package/dist/relations/relation.types.js.map +1 -1
- package/dist/repositories/kv.repository.bridge.d.ts +3 -3
- package/dist/repositories/kv.repository.bridge.js +1 -1
- package/dist/repositories/kv.repository.bridge.js.map +1 -1
- package/dist/repositories/legacy-juggler-bridge.d.ts +20 -1
- package/dist/repositories/legacy-juggler-bridge.js +82 -20
- package/dist/repositories/legacy-juggler-bridge.js.map +1 -1
- package/dist/types/array.js +5 -2
- package/dist/types/array.js.map +1 -1
- package/dist/types/buffer.d.ts +1 -1
- package/dist/types/buffer.js +8 -4
- package/dist/types/buffer.js.map +1 -1
- package/dist/types/date.js +5 -2
- package/dist/types/date.js.map +1 -1
- package/dist/types/number.js +5 -2
- package/dist/types/number.js.map +1 -1
- package/dist/types/object.d.ts +1 -1
- package/dist/types/object.js +5 -2
- package/dist/types/object.js.map +1 -1
- package/dist/types/union.js +5 -2
- package/dist/types/union.js.map +1 -1
- package/package.json +12 -12
- package/src/common-types.ts +15 -1
- package/src/decorators/model.decorator.ts +5 -5
- package/src/decorators/repository.decorator.ts +1 -1
- package/src/define-model-class.ts +88 -0
- package/src/errors/invalid-relation.error.ts +1 -1
- package/src/index.ts +1 -0
- package/src/mixins/repository.mixin.ts +7 -3
- package/src/model.ts +2 -2
- package/src/query.ts +3 -3
- package/src/relations/belongs-to/belongs-to-accessor.ts +8 -2
- package/src/relations/belongs-to/belongs-to.helpers.ts +1 -1
- package/src/relations/has-many/has-many-repository.factory.ts +1 -1
- package/src/relations/has-many/has-many-through.repository.ts +100 -0
- package/src/relations/has-many/has-many.helpers.ts +15 -4
- package/src/relations/has-many/has-many.inclusion-resolver.ts +1 -1
- package/src/relations/has-one/has-one-repository.factory.ts +1 -1
- package/src/relations/has-one/has-one.helpers.ts +11 -2
- package/src/relations/relation.decorator.ts +1 -1
- package/src/relations/relation.helpers.ts +13 -12
- package/src/relations/relation.types.ts +56 -2
- package/src/repositories/kv.repository.bridge.ts +5 -8
- package/src/repositories/legacy-juggler-bridge.ts +81 -13
- package/src/types/array.ts +1 -1
- package/src/types/buffer.ts +4 -4
- package/src/types/date.ts +1 -1
- package/src/types/number.ts +1 -1
- package/src/types/object.ts +2 -2
- package/src/types/union.ts +1 -1
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
// License text available at https://opensource.org/licenses/MIT
|
|
5
5
|
|
|
6
6
|
import {Getter} from '@loopback/context';
|
|
7
|
-
import
|
|
8
|
-
import
|
|
7
|
+
import assert from 'assert';
|
|
8
|
+
import legacy from 'loopback-datasource-juggler';
|
|
9
9
|
import {
|
|
10
10
|
AnyObject,
|
|
11
11
|
Command,
|
|
@@ -339,14 +339,18 @@ export class DefaultCrudRepository<
|
|
|
339
339
|
}
|
|
340
340
|
|
|
341
341
|
async create(entity: DataObject<T>, options?: Options): Promise<T> {
|
|
342
|
-
|
|
342
|
+
// perform persist hook
|
|
343
|
+
const data = await this.entityToData(entity, options);
|
|
344
|
+
const model = await ensurePromise(this.modelClass.create(data, options));
|
|
343
345
|
return this.toEntity(model);
|
|
344
346
|
}
|
|
345
347
|
|
|
346
348
|
async createAll(entities: DataObject<T>[], options?: Options): Promise<T[]> {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
+
// perform persist hook
|
|
350
|
+
const data = await Promise.all(
|
|
351
|
+
entities.map(e => this.entityToData(e, options)),
|
|
349
352
|
);
|
|
353
|
+
const models = await ensurePromise(this.modelClass.create(data, options));
|
|
350
354
|
return this.toEntities(models);
|
|
351
355
|
}
|
|
352
356
|
|
|
@@ -364,7 +368,7 @@ export class DefaultCrudRepository<
|
|
|
364
368
|
filter?: Filter<T>,
|
|
365
369
|
options?: Options,
|
|
366
370
|
): Promise<(T & Relations)[]> {
|
|
367
|
-
const include = filter
|
|
371
|
+
const include = filter?.include;
|
|
368
372
|
const models = await ensurePromise(
|
|
369
373
|
this.modelClass.find(this.normalizeFilter(filter), options),
|
|
370
374
|
);
|
|
@@ -381,7 +385,7 @@ export class DefaultCrudRepository<
|
|
|
381
385
|
);
|
|
382
386
|
if (!model) return null;
|
|
383
387
|
const entity = this.toEntity(model);
|
|
384
|
-
const include = filter
|
|
388
|
+
const include = filter?.include;
|
|
385
389
|
const resolved = await this.includeRelatedModels(
|
|
386
390
|
[entity],
|
|
387
391
|
include,
|
|
@@ -395,7 +399,7 @@ export class DefaultCrudRepository<
|
|
|
395
399
|
filter?: Filter<T>,
|
|
396
400
|
options?: Options,
|
|
397
401
|
): Promise<T & Relations> {
|
|
398
|
-
const include = filter
|
|
402
|
+
const include = filter?.include;
|
|
399
403
|
const model = await ensurePromise(
|
|
400
404
|
this.modelClass.findById(id, this.normalizeFilter(filter), options),
|
|
401
405
|
);
|
|
@@ -415,7 +419,9 @@ export class DefaultCrudRepository<
|
|
|
415
419
|
return this.updateById(entity.getId(), entity, options);
|
|
416
420
|
}
|
|
417
421
|
|
|
418
|
-
delete(entity: T, options?: Options): Promise<void> {
|
|
422
|
+
async delete(entity: T, options?: Options): Promise<void> {
|
|
423
|
+
// perform persist hook
|
|
424
|
+
await this.entityToData(entity, options);
|
|
419
425
|
return this.deleteById(entity.getId(), options);
|
|
420
426
|
}
|
|
421
427
|
|
|
@@ -424,9 +430,10 @@ export class DefaultCrudRepository<
|
|
|
424
430
|
where?: Where<T>,
|
|
425
431
|
options?: Options,
|
|
426
432
|
): Promise<Count> {
|
|
427
|
-
where = where
|
|
433
|
+
where = where ?? {};
|
|
434
|
+
const persistedData = await this.entityToData(data, options);
|
|
428
435
|
const result = await ensurePromise(
|
|
429
|
-
this.modelClass.updateAll(where,
|
|
436
|
+
this.modelClass.updateAll(where, persistedData, options),
|
|
430
437
|
);
|
|
431
438
|
return {count: result.count};
|
|
432
439
|
}
|
|
@@ -451,7 +458,8 @@ export class DefaultCrudRepository<
|
|
|
451
458
|
options?: Options,
|
|
452
459
|
): Promise<void> {
|
|
453
460
|
try {
|
|
454
|
-
await
|
|
461
|
+
const payload = await this.entityToData(data, options);
|
|
462
|
+
await ensurePromise(this.modelClass.replaceById(id, payload, options));
|
|
455
463
|
} catch (err) {
|
|
456
464
|
if (err.statusCode === 404) {
|
|
457
465
|
throw new EntityNotFoundError(this.entityClass, id);
|
|
@@ -528,6 +536,66 @@ export class DefaultCrudRepository<
|
|
|
528
536
|
return includeRelatedModels<T, Relations>(this, entities, include, options);
|
|
529
537
|
}
|
|
530
538
|
|
|
539
|
+
/**
|
|
540
|
+
* This function works as a persist hook.
|
|
541
|
+
* It converts an entity from the CRUD operations' caller
|
|
542
|
+
* to a persistable data that can will be stored in the
|
|
543
|
+
* back-end database.
|
|
544
|
+
*
|
|
545
|
+
* User can extend `DefaultCrudRepository` then override this
|
|
546
|
+
* function to execute custom persist hook.
|
|
547
|
+
* @param entity The entity passed from CRUD operations' caller.
|
|
548
|
+
* @param options
|
|
549
|
+
*/
|
|
550
|
+
protected async entityToData<R extends T>(
|
|
551
|
+
entity: R | DataObject<R>,
|
|
552
|
+
options = {},
|
|
553
|
+
): Promise<legacy.ModelData<legacy.PersistedModel>> {
|
|
554
|
+
return this.ensurePersistable(entity, options);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/** Converts an entity object to a JSON object to check if it contains navigational property.
|
|
558
|
+
* Throws an error if `entity` contains navigational property.
|
|
559
|
+
*
|
|
560
|
+
* @param entity The entity passed from CRUD operations' caller.
|
|
561
|
+
* @param options
|
|
562
|
+
*/
|
|
563
|
+
protected ensurePersistable<R extends T>(
|
|
564
|
+
entity: R | DataObject<R>,
|
|
565
|
+
options = {},
|
|
566
|
+
): legacy.ModelData<legacy.PersistedModel> {
|
|
567
|
+
// FIXME(bajtos) Ideally, we should call toJSON() to convert R to data object
|
|
568
|
+
// Unfortunately that breaks replaceById for MongoDB connector, where we
|
|
569
|
+
// would call replaceId with id *argument* set to ObjectID value but
|
|
570
|
+
// id *property* set to string value.
|
|
571
|
+
/*
|
|
572
|
+
const data: AnyObject =
|
|
573
|
+
typeof entity.toJSON === 'function' ? entity.toJSON() : {...entity};
|
|
574
|
+
*/
|
|
575
|
+
|
|
576
|
+
const data: AnyObject = new this.entityClass(entity);
|
|
577
|
+
|
|
578
|
+
const def = this.entityClass.definition;
|
|
579
|
+
const props = def.properties;
|
|
580
|
+
for (const r in def.relations) {
|
|
581
|
+
const relName = def.relations[r].name;
|
|
582
|
+
if (relName in data) {
|
|
583
|
+
let invalidNameMsg = '';
|
|
584
|
+
if (relName in props) {
|
|
585
|
+
invalidNameMsg =
|
|
586
|
+
` The error might be invoked by belongsTo relations, please make sure the relation name is not the same as` +
|
|
587
|
+
` the property name.`;
|
|
588
|
+
}
|
|
589
|
+
throw new Error(
|
|
590
|
+
`Navigational properties are not allowed in model data (model "${this.entityClass.modelName}"` +
|
|
591
|
+
` property "${relName}"), please remove it.` +
|
|
592
|
+
invalidNameMsg,
|
|
593
|
+
);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
return data;
|
|
597
|
+
}
|
|
598
|
+
|
|
531
599
|
/**
|
|
532
600
|
* Removes juggler's "include" filter as it does not apply to LoopBack 4
|
|
533
601
|
* relations.
|
|
@@ -555,7 +623,7 @@ export class DefaultTransactionalRepository<
|
|
|
555
623
|
async beginTransaction(
|
|
556
624
|
options?: IsolationLevel | Options,
|
|
557
625
|
): Promise<Transaction> {
|
|
558
|
-
const dsOptions: juggler.IsolationLevel | Options = options
|
|
626
|
+
const dsOptions: juggler.IsolationLevel | Options = options ?? {};
|
|
559
627
|
// juggler.Transaction still has the Promise/Callback variants of the
|
|
560
628
|
// Transaction methods
|
|
561
629
|
// so we need it cast it back
|
package/src/types/array.ts
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
// This file is licensed under the MIT License.
|
|
4
4
|
// License text available at https://opensource.org/licenses/MIT
|
|
5
5
|
|
|
6
|
+
import util from 'util';
|
|
6
7
|
import {Type} from './type';
|
|
7
|
-
import * as util from 'util';
|
|
8
8
|
|
|
9
9
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
10
10
|
|
package/src/types/buffer.ts
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
// This file is licensed under the MIT License.
|
|
4
4
|
// License text available at https://opensource.org/licenses/MIT
|
|
5
5
|
|
|
6
|
-
import
|
|
7
|
-
import {Type} from './type';
|
|
6
|
+
import util from 'util';
|
|
8
7
|
import {Options} from '../common-types';
|
|
8
|
+
import {Type} from './type';
|
|
9
9
|
|
|
10
10
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
11
11
|
|
|
@@ -35,7 +35,7 @@ export class BufferType implements Type<Buffer> {
|
|
|
35
35
|
if (value == null) return value;
|
|
36
36
|
if (Buffer.isBuffer(value)) return value as Buffer;
|
|
37
37
|
if (typeof value === 'string') {
|
|
38
|
-
options = options
|
|
38
|
+
options = options ?? {};
|
|
39
39
|
const encoding = options.encoding || 'utf-8';
|
|
40
40
|
return Buffer.from(value, encoding);
|
|
41
41
|
} else if (Array.isArray(value)) {
|
|
@@ -47,7 +47,7 @@ export class BufferType implements Type<Buffer> {
|
|
|
47
47
|
|
|
48
48
|
serialize(value: Buffer | null | undefined, options?: Options) {
|
|
49
49
|
if (value == null) return value;
|
|
50
|
-
const encoding =
|
|
50
|
+
const encoding = options?.encoding || 'base64';
|
|
51
51
|
return value.toString(encoding);
|
|
52
52
|
}
|
|
53
53
|
}
|
package/src/types/date.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// This file is licensed under the MIT License.
|
|
4
4
|
// License text available at https://opensource.org/licenses/MIT
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
import util from 'util';
|
|
7
7
|
import {Type} from './type';
|
|
8
8
|
|
|
9
9
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
package/src/types/number.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// This file is licensed under the MIT License.
|
|
4
4
|
// License text available at https://opensource.org/licenses/MIT
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
import util from 'util';
|
|
7
7
|
import {Type} from './type';
|
|
8
8
|
|
|
9
9
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
package/src/types/object.ts
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
// This file is licensed under the MIT License.
|
|
4
4
|
// License text available at https://opensource.org/licenses/MIT
|
|
5
5
|
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
6
|
+
import util from 'util';
|
|
7
|
+
import {AnyObject, Class} from '../common-types';
|
|
8
8
|
import {Type} from './type';
|
|
9
9
|
|
|
10
10
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
package/src/types/union.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// This file is licensed under the MIT License.
|
|
4
4
|
// License text available at https://opensource.org/licenses/MIT
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
import util from 'util';
|
|
7
7
|
import {Type} from './type';
|
|
8
8
|
|
|
9
9
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|