Description
Suggestion
At the moment, we allow sharing of repository code via Repository Base Classes only. The command lb4 repository
looks for src/repositories/*.repository.base.ts
and treat them as repository base classes to offer in the prompt:
$ lb4 repository
? Please select the datasource DbDatasource
? Select the model(s) you want to generate a repository for Product
? Please select the repository base class (Use arrow keys)
DefaultCrudRepository (Legacy juggler bridge)
----- Custom Repositories -----
❯ AuditingRepository
While easy to use, Repository Base Classes have few shortcomings too.
-
JavaScript does not support multiple inheritance, thus it's not possible to combine behavior from multiple repository base classes in the same model-specific repository class.
-
Inheritance-based reuse is considered as an anti-pattern in Object Oriented Design, it's recommended to use composition instead ("prefer composition over inheritance").
Let's enhance lb4 repository
and lb4 rest-crud
commands to all allow the user to choose which Repository Mixins to apply.
Examples
Model-specific repository class:
$ lb4 repository
? Please select the datasource DbDatasource
? Select the model(s) you want to generate a repository for Product
? Please select the repository base class DefaultCrudRepository (Legacy juggler bridge)
? Select the mixin(s) you want to apply (Press <space> to select, <a> to toggle all, <i> to invert
selection)
❯◉ AuditingMixin (src/mixins/auditing.repository-mixin.ts)
◯ TimeStampMixin (src/mixins/timestamp.repository-mixin.ts)
Emitted code:
// src/repositories/product.repository.ts
import {Constructor, inject} from '@loopback/core';
import {DefaultCrudRepository} from '@loopback/repository';
import {DbDataSource} from '../datasources';
import {AuditingRepositoryMixin} from '../mixins/auditing.repository-mixin';
import {Product, ProductRelations} from '../models';
export class ProductRepository extends AuditingRepositoryMixin<
Product,
Constructor<
DefaultCrudRepository<
Product,
typeof Product.prototype.id,
ProductRelations
>
>
>(DefaultCrudRepository) {
constructor(@inject('datasources.db') dataSource: DbDataSource) {
super(Product, dataSource);
}
}
Model API booter (rest-crud)
$ lb4 rest-crud
? Please select the datasource DbDatasource
? Select the model(s) you want to generate a CRUD REST endpoint Category
? Select the mixin(s) you want to apply (Press <space> to select, <a> to toggle all, <i> to invert
selection)
❯◉ AuditingMixin (src/mixins/auditing.repository-mixin.ts)
◯ TimeStampMixin (src/mixins/timestamp.repository-mixin.ts)
Emitted code:
// src/model-endpoints/category.rest-config.ts
import {ModelCrudRestApiConfig} from '@loopback/rest-crud';
import {AuditingRepositoryMixin} from '../mixins/auditing.repository-mixin';
import {Category} from '../models';
const config: ModelCrudRestApiConfig = {
model: Category,
pattern: 'CrudRest',
dataSource: 'db',
basePath: '/categories',
repositoryMixins: [
AuditingRepositoryMixin
],
};
module.exports = config;
(This will require us to enhance Model API booters to support the new config option repositoryMixins
.)
Acceptance criteria
-
Documentation to show how to create repository mixins. At the moment, Key concepts >> Mixins does not provide any information specific to repositories. There are detailed instructions in our migration guide, see Defining A Repository Mixin Class Factory Function. It's time to reorganize and clean up this area of our docs.
-
The API contract for repository mixins to allow them to be picked applied by our CLI. For repository base classes, the convention is that the class must accept the same generic parameters and constructor arguments as
DefaultCrudRepository
. We need to come up with a similar convention for repository mixins.The tricky part is how to support mixins that rely on
Model
andCrudRepository
features vs. mixins that require Entity-specific things. For the initial version, I think it's fine to support Entity-based mixins only. -
A new generator
lb4 repository-mixin
to scaffold a new repository mixin -
A new helper function in
packages/cli/lib
to find all repository mixins. I am proposing to use the following file naming convention:src/mixins/{name}.repository-mixin.ts
-
Enhance
lb4 repository
to ask the user which mixins to apply and apply them in the scaffolded repository class. -
A new prompt in
lb4 rest-crud
to ask the user which mixins to apply and apply them in the scaffolded model-api config. -
Update the relevant documentation
- Repository generator
- REST CRUD model endpoints generator
- Key concepts >> Mixins should document the requirements on repository mixins and show how to use them with CLI.