Skip to content

Commit ccb7d3f

Browse files
committed
fix(sequelize): support "defaultScope" via Model settings
Signed-off-by: KalleV <[email protected]>
1 parent caf07ef commit ccb7d3f

File tree

8 files changed

+113
-0
lines changed

8 files changed

+113
-0
lines changed

extensions/sequelize/src/__tests__/fixtures/controllers/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export * from './doctor.controller';
77
export * from './patient.controller';
88
export * from './product.controller';
99
export * from './programming-languange.controller';
10+
export * from './scoped-task.controller';
1011
export * from './task.controller';
1112
export * from './test.controller.base';
1213
export * from './todo-list-todo.controller';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import {repository} from '@loopback/repository';
2+
import {get, response} from '@loopback/rest';
3+
import {ScopedTaskRepository} from '../repositories';
4+
import {TestControllerBase} from './test.controller.base';
5+
6+
export class ScopedTaskController extends TestControllerBase {
7+
constructor(
8+
@repository(ScopedTaskRepository)
9+
public scopedTaskRepository: ScopedTaskRepository,
10+
) {
11+
super(scopedTaskRepository);
12+
}
13+
14+
@get('/scoped-tasks/sync-sequelize-model')
15+
@response(200)
16+
async syncSequelizeModel(): Promise<void> {
17+
await this.beforeEach();
18+
}
19+
}

extensions/sequelize/src/__tests__/fixtures/models/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export * from './doctor.model';
66
export * from './patient.model';
77
export * from './product.model';
88
export * from './programming-language.model';
9+
export * from './scoped-task.model';
910
export * from './task.model';
1011
export * from './todo-list.model';
1112
export * from './todo.model';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import {Entity, model, property} from '@loopback/repository';
2+
3+
/**
4+
* Simplified Entity used for testing settings "scope" functionality
5+
*/
6+
@model({
7+
settings: {
8+
scope: {
9+
limit: 1,
10+
},
11+
},
12+
})
13+
export class ScopedTask extends Entity {
14+
@property({
15+
type: 'number',
16+
id: true,
17+
generated: true,
18+
})
19+
id?: number;
20+
21+
@property({
22+
type: 'string',
23+
required: true,
24+
})
25+
title: string;
26+
27+
constructor(data?: Partial<ScopedTask>) {
28+
super(data);
29+
}
30+
}
31+
32+
export interface ScopedTaskRelations {
33+
// describe navigational properties here
34+
}
35+
36+
export type ScopedTaskWithRelations = ScopedTask & ScopedTaskRelations;

extensions/sequelize/src/__tests__/fixtures/repositories/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export * from './doctor.repository';
66
export * from './patient.repository';
77
export * from './product.repository';
88
export * from './programming-language.repository';
9+
export * from './scoped-task.repository';
910
export * from './task.repository';
1011
export * from './todo-list.repository';
1112
export * from './todo.repository';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import {inject} from '@loopback/core';
2+
import {SequelizeCrudRepository} from '../../../sequelize';
3+
import {PrimaryDataSource} from '../datasources/primary.datasource';
4+
import {ScopedTask, ScopedTaskRelations} from '../models/index';
5+
6+
/**
7+
* Simplified repository used for testing Model settings "scope" functionality
8+
*/
9+
export class ScopedTaskRepository extends SequelizeCrudRepository<
10+
ScopedTask,
11+
typeof ScopedTask.prototype.id,
12+
ScopedTaskRelations
13+
> {
14+
constructor(@inject('datasources.primary') dataSource: PrimaryDataSource) {
15+
super(ScopedTask, dataSource);
16+
}
17+
18+
protected getDefaultFnRegistry() {
19+
return {
20+
...super.getDefaultFnRegistry(),
21+
customAlias: () => Math.random(),
22+
};
23+
}
24+
}

extensions/sequelize/src/__tests__/integration/repository.integration.ts

+29
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
TaskRepository,
2727
UserRepository,
2828
} from '../fixtures/repositories';
29+
import {ScopedTaskRepository} from '../fixtures/repositories/scoped-task.repository';
2930

3031
type Entities =
3132
| 'users'
@@ -42,6 +43,7 @@ describe('Sequelize CRUD Repository (integration)', () => {
4243
let app: SequelizeSandboxApplication;
4344
let userRepo: UserRepository;
4445
let taskRepo: TaskRepository;
46+
let scopedTaskRepo: ScopedTaskRepository;
4547
let developerRepo: DeveloperRepository;
4648
let languagesRepo: ProgrammingLanguageRepository;
4749
let client: Client;
@@ -74,6 +76,29 @@ describe('Sequelize CRUD Repository (integration)', () => {
7476
}
7577
});
7678

79+
describe('Model settings Support', () => {
80+
beforeEach(async () => {
81+
await client.get('/scoped-tasks/sync-sequelize-model').send();
82+
});
83+
it('supports setting a default "scope" in the Model settings', async () => {
84+
await Promise.all([
85+
scopedTaskRepo.create({title: 'Task 1'}),
86+
scopedTaskRepo.create({title: 'Task 2'}),
87+
scopedTaskRepo.create({title: 'Task 3'}),
88+
]);
89+
90+
const tasksDefaultLimit = await scopedTaskRepo.find();
91+
92+
expect(tasksDefaultLimit.length).to.be.eql(1);
93+
94+
const tasksCustomLimit = await scopedTaskRepo.find({
95+
limit: 3,
96+
});
97+
98+
expect(tasksCustomLimit.length).to.be.eql(3);
99+
});
100+
});
101+
77102
describe('defaultFn Support', () => {
78103
beforeEach(async () => {
79104
await client.get('/tasks/sync-sequelize-model').send();
@@ -919,6 +944,7 @@ describe('Sequelize CRUD Repository (integration)', () => {
919944
'book.model',
920945
'category.model',
921946
'product.model',
947+
'scoped-task.model',
922948
'task.model',
923949
],
924950
repositories: [
@@ -934,6 +960,7 @@ describe('Sequelize CRUD Repository (integration)', () => {
934960
'book.repository',
935961
'category.repository',
936962
'product.repository',
963+
'scoped-task.repository',
937964
'task.repository',
938965
],
939966
controllers: [
@@ -956,6 +983,7 @@ describe('Sequelize CRUD Repository (integration)', () => {
956983
'product.controller',
957984
'test.controller.base',
958985
'task.controller',
986+
'scoped-task.controller',
959987
],
960988
};
961989

@@ -993,6 +1021,7 @@ describe('Sequelize CRUD Repository (integration)', () => {
9931021
developerRepo = await app.getRepository(DeveloperRepository);
9941022
languagesRepo = await app.getRepository(ProgrammingLanguageRepository);
9951023
taskRepo = await app.getRepository(TaskRepository);
1024+
scopedTaskRepo = await app.getRepository(ScopedTaskRepository);
9961025
client = createRestAppClient(app as RestApplication);
9971026
}
9981027

extensions/sequelize/src/sequelize/sequelize.repository.base.ts

+2
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,8 @@ export class SequelizeCrudRepository<
682682
timestamps: false,
683683
tableName: this.getTableName(entityClass),
684684
freezeTableName: true,
685+
// Set up optional default scope: https://sequelize.org/docs/v6/other-topics/scopes/#definition
686+
defaultScope: entityClass.definition.settings.scope,
685687
},
686688
);
687689

0 commit comments

Comments
 (0)