-
Notifications
You must be signed in to change notification settings - Fork 5
Controller
You can choose to define controller with Repository or Service depends on your demand!
- Note Application included User, UserProfile and Note entities
- User HAS_ONE UserProfile
- User HAS_MANY Note
- UserProfile BELONGS_TO User
- Note BELONGS_TO User
@model({})
export class User extends BaseTzEntity {
@property({ type: 'number' })
id: number
@hasOne(() => UserProfile, { keyTo: 'userId' })
profile?: UserProfile;
@hasMany(() => Note, { keyTo: 'userId' })
notes: Array<Note>;
// Many more properties
}
export interface IUserRelations {
profile?: UserProfile,
notes?: Array<Note>
}@model({})
class UserProfile extends BaseTzEntity {
@property({ type: 'number' })
id: number
@belongsTo(() => User, { keyFrom: 'userId' }, { name: 'user_id' })
userId: number;
// Many more properties
}
export interface IUserProfileRelations {
user?: User
}@model({})
class Note extends BaseTzEntity {
@property({ type: 'number' })
id: number
@belongsTo(() => User, { keyFrom: 'userId' }, { name: 'user_id' })
userId: number;
// Many more properties
}
export interface INoteRelations {
user?: User
}export class UserRepository extends TzCrudRepository<User, IUserRelations> {
public readonly profile: HasOneRepositoryFactory<UserProfile, IdType>;
public readonly notes: HasManyRepositoryFactory<Note, IdType>;
constructor(
@inject(`YOUR_DATABASE_KEY_HERE`)
dataSource: DataSource,
@repository.getter('UserProfileRepository')
protected userProfileRepositoryGetter: Getter<UserProfileRepository>,
@repository.getter('NoteRepository')
protected noteRepositoryGetter: Getter<NoteRepository>,
) {
super(User, dataSource);
this.profile = this.createHasOneRepositoryFactoryFor('profile', userProfileRepositoryGetter);
this.registerInclusionResolver('profile', this.profile.inclusionResolver);
this.note = this.createHasManyRepositoryFactoryFor('note', noteRepositoryGetter);
this.registerInclusionResolver('note', this.note.inclusionResolver);
}export class UserProfileRepository extends TzCrudRepository<UserProfile, IUserProfileRelations> {
public readonly user: BelongsToAccessor<User, IdType>;
constructor(
@inject(`YOUR_DATABASE_KEY_HERE`)
dataSource: DataSource,
@repository.getter('UserRepository')
protected userRepositoryGetter: Getter<UserRepository>,
) {
super(UserProfile, dataSource);
this.user = this.createBelongsToAccessorFor('user', userRepositoryGetter);
this.registerInclusionResolver('user', this.user.inclusionResolver);
}
}export class NoteRepository extends TzCrudRepository<Note, INoteRelations> {
public readonly user: BelongsToAccessor<User, IdType>;
constructor(
@inject(`YOUR_DATABASE_KEY_HERE`)
dataSource: DataSource,
@repository.getter('UserRepository')
protected userRepositoryGetter: Getter<UserRepository>,
) {
super(Note, dataSource);
this.user = this.createBelongsToAccessorFor('user', userRepositoryGetter);
this.registerInclusionResolver('user', this.user.inclusionResolver);
}
}Require steps: . Define CRUD Controller
const basePath = '/users';
const Controller = defineCrudController({
entity: User,
repository: { name: UserRepository.name }, // NOTICE THIS
controller: { basePath },
});
@api({ basePath })
export class UserController extends Controller {
constructor(
@inject('repositories.UserRepository')
private userRepository: UserRepository,
) {
super(userRepository);
}
}const basePath = '/user-profiles'
const Controller = defineCrudController({
entity: UserProfile,
repository: { name: UserProfileRepository.name },
controller: { basePath },
});
@api({ basePath })
export class UserController extends Controller {
constructor(
@inject('repositories.UserProfileRepository')
private userProfileRepository: UserProfileRepository,
) {
super(userProfileRepository);
}
}const basePath = '/notes'
const Controller = defineCrudController({
entity: Note,
repository: { name: NoteRepository.name },
controller: { basePath },
});
@api({ basePath })
export class NoteController extends Controller {
constructor(
@inject('repositories.NoteRepository')
private noteRepository: NoteRepository,
) {
super(noteRepository);
}
}Define CRUD Controller With Repository Options: REF
After defining all controllers, your application will have all necessary controller endpoints.
Example: NoteController (These endpoints gonna be similar for another entites)
GET /notes/count
GET /notes/find-one
GET /notes
POST /notes
PATCH /notes
PUT /notes/{id}
PATCH /notes/{id}
GET /notes/{id}
DELETE /notes/{id}
Note: By this way, in case you want to customize logic of 1 endpoint, you have to re-define whole endpoint and implement endpoint business logic!
Required steps: . Define CRUD Service for Entity . Define Service CRUD Controller
Define CRUD Service for Entity
export class NoteService extends BaseCrudService<Note> {
constructor(
// repositories
@inject('repositories.NoteRepository')
private noteRepository: NoteRepository,
) {
super({
scope: NoteService.name,
repository: noteRepository,
});
}
// Overridable methods
// GET /<entity_endpoint> find(filter, options);
// GET /<entity_endpoint>/{id} findById(id, filter, options);
// GET /<entity_endpoint>/fine-one findOne(filter, options);
// GET /<entity_endpoint>/count count(where, options);
// POST /<entity_endpoint> create(data, options);
// PATCH /<entity_endpoint> updateAll(data, where, options);
// PATCH /<entity_endpoint>/{id} updateWithReturn(id, data, options);
// PUT /<entity_endpoint>/{id} replaceById(id, data, options);
// DELETE /<entity_endpoint>/{id} deleteById(id, options);
// Example
async updateWithReturn(
id: number,
payload: Partial<Note>,
options: ICrudMethodOptions,
): Promise<ProductionOrderProcess> {
// YOUR BUSINESS LOGIC HERE
}
}Define Service CRUD Controller
const basePath = '/notes'
const CRUDController = defineServiceCrudController({
entity: Note,
service: { name: NoteService.name }, // NOTICE THIS
controller: { basePath },
});
@api({ basePath })
export class NoteController extends CRUDController {}Define CRUD Controller With Service Options: REF
Similar to defineCrudController, all necessary endpoints will available in your application after using defineServiceCrudController.
Note:
By this way, in case you want to customize logic of 1 endpoint, you have to override implementation of 1 method in CrudService
NO NEED TO DECLARE AGAIN ENDPOINT!
Required steps: . Define Relation CRUD Controller
const basePath = '/users';
const relationPath = '/notes'
const Controller = defineRelationCrudController({
association: {
source: User.name,
target: Note.name,
relationType: 'hasMany',
relationName: 'Note',
},
schema: { target: getModelSchemaRef(Note, { exclude: ['id', 'createdAt', 'modifiedAt'] }) },
options: {
useControlTarget: true,
endPoint: relationPath,
},
});
@api({ basePath })
export class UserNoteController extends Controller {
constructor(
@inject('repositories.UserRepository')
private userRepository: UserRepository,
@inject('repositories.NoteRepository')
private noteRepository: NoteRepository,
) {
super(userRepository, noteRepository);
}
}Define Relation CRUD Controller Options: REF
After defining all controllers, your application will have all necessary controller endpoints for relation.
Example: UserNoteController (These endpoints gonna be similar for another entites)
GET /users/{id}/notes/count
GET /users/{id}/notes
POST /users/{id}/notes
PATCH /users/{id}/notes
DELETE /users/{id}/notes
Minimal Technology Vietnam
Minimal Technology Vietnam