Skip to content

Commit

Permalink
feat(repository): define constants for repository binding namespaces …
Browse files Browse the repository at this point in the history
…and tags
  • Loading branch information
raymondfeng committed May 15, 2020
1 parent 275f479 commit a01d4d2
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ describe('RepositoryMixin', () => {
expect(boundRepositories).to.containEql('repositories.NoteRepo');
const binding = myApp.getBinding('repositories.NoteRepo');
expect(binding.scope).to.equal(BindingScope.TRANSIENT);
expect(binding.tagMap).to.have.property('repository');
const repoInstance = myApp.getSync('repositories.NoteRepo');
expect(repoInstance).to.be.instanceOf(NoteRepo);
}
Expand Down Expand Up @@ -248,7 +249,8 @@ describe('RepositoryMixin dataSource', () => {
it('binds dataSource class using the dataSourceName property', () => {
const myApp = new AppWithRepoMixin();

myApp.dataSource(FooDataSource);
const binding = myApp.dataSource(FooDataSource);
expect(binding.tagMap).to.have.property('datasource');
expectDataSourceToBeBound(myApp, FooDataSource, 'foo');
});

Expand Down Expand Up @@ -293,6 +295,9 @@ describe('RepositoryMixin dataSource', () => {
expect(app.find('datasources.*').map(d => d.key)).to.containEql(
`datasources.${name}`,
);
expect(app.findByTag('datasource').map(d => d.key)).to.containEql(
`datasources.${name}`,
);
expect(app.getSync(`datasources.${name}`)).to.be.instanceOf(ds);
};

Expand Down
3 changes: 2 additions & 1 deletion packages/repository/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@ export * from './connectors';
export * from './datasource';
export * from './decorators';
export * from './define-model-class';
export * from './define-repository-class';
export * from './errors';
export * from './keys';
export * from './mixins';
export * from './model';
export * from './query';
export * from './relations';
export * from './repositories';
export * from './define-repository-class';
export * from './transaction';
export * from './type-resolver';
export * from './types';
40 changes: 40 additions & 0 deletions packages/repository/src/keys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright IBM Corp. 2020. All Rights Reserved.
// Node module: @loopback/repository
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

/**
* Binding tags for repository related bindings
*/
export namespace RepositoryTags {
/**
* Tag for model class bindings
*/
export const MODEL = 'model';
/**
* Tag for repository bindings
*/
export const REPOSITORY = 'repository';
/**
* Tag for datasource bindings
*/
export const DATASOURCE = 'datasource';
}

/**
* Binding keys and namespaces for repository related bindings
*/
export namespace RepositoryBindings {
/**
* Namespace for model class bindings
*/
export const MODELS = 'models';
/**
* Namespace for repository bindings
*/
export const REPOSITORIES = 'repositories';
/**
* Namespace for datasource bindings
*/
export const DATASOURCES = 'datasources';
}
47 changes: 33 additions & 14 deletions packages/repository/src/mixins/repository.mixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@ import {
BindingScope,
createBindingFromClass,
} from '@loopback/context';
import {Application, Component, Constructor, MixinTarget} from '@loopback/core';
import {
Application,
Component,
Constructor,
CoreBindings,
MixinTarget,
} from '@loopback/core';
import debugFactory from 'debug';
import {Class} from '../common-types';
import {SchemaMigrationOptions} from '../datasource';
import {RepositoryBindings, RepositoryTags} from '../keys';
import {Model} from '../model';
import {juggler, Repository} from '../repositories';

Expand Down Expand Up @@ -71,11 +78,11 @@ export function RepositoryMixin<T extends MixinTarget<Application>>(
nameOrOptions?: string | BindingFromClassOptions,
): Binding<R> {
const binding = createBindingFromClass(repoClass, {
namespace: 'repositories',
type: 'repository',
namespace: RepositoryBindings.REPOSITORIES,
type: RepositoryTags.REPOSITORY,
defaultScope: BindingScope.TRANSIENT,
...toOptions(nameOrOptions),
});
}).tag(RepositoryTags.REPOSITORY);
this.add(binding);
return binding;
}
Expand Down Expand Up @@ -122,15 +129,15 @@ export function RepositoryMixin<T extends MixinTarget<Application>>(
if (dataSource instanceof juggler.DataSource) {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
const name = options.name || dataSource.name;
const namespace = options.namespace ?? 'datasources';
const namespace = options.namespace ?? RepositoryBindings.DATASOURCES;
const key = `${namespace}.${name}`;
return this.bind(key).to(dataSource).tag('datasource');
return this.bind(key).to(dataSource).tag(RepositoryTags.DATASOURCE);
} else if (typeof dataSource === 'function') {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
options.name = options.name || dataSource.dataSourceName;
const binding = createBindingFromClass(dataSource, {
namespace: 'datasources',
type: 'datasource',
namespace: RepositoryBindings.DATASOURCES,
type: RepositoryTags.DATASOURCE,
defaultScope: BindingScope.SINGLETON,
...options,
});
Expand All @@ -142,13 +149,13 @@ export function RepositoryMixin<T extends MixinTarget<Application>>(
}

/**
* Register a model class
* Register a model class as a binding in the target context
* @param modelClass - Model class
*/
model<M extends Class<unknown>>(modelClass: M) {
return this.bind<M>(`models.${modelClass.name}`)
.to(modelClass)
.tag('model');
const binding = createModelClassBinding(modelClass);
this.add(binding);
return binding;
}

/**
Expand Down Expand Up @@ -194,7 +201,7 @@ export function RepositoryMixin<T extends MixinTarget<Application>>(
* @param component - The component to mount repositories of
*/
mountComponentRepositories(component: Class<unknown>) {
const componentKey = `components.${component.name}`;
const componentKey = `${CoreBindings.COMPONENTS}.${component.name}`;
const compInstance = this.getSync<{
repositories?: Class<Repository<Model>>[];
}>(componentKey);
Expand Down Expand Up @@ -232,7 +239,7 @@ export function RepositoryMixin<T extends MixinTarget<Application>>(

// Look up all datasources and update/migrate schemas one by one
const dsBindings: Readonly<Binding<object>>[] = this.findByTag(
'datasource',
RepositoryTags.DATASOURCE,
);
for (const b of dsBindings) {
const ds = await this.get<juggler.DataSource>(b.key);
Expand Down Expand Up @@ -416,3 +423,15 @@ export class RepositoryMixinDoc {
*/
async migrateSchema(options?: SchemaMigrationOptions): Promise<void> {}
}

/**
* Create a binding for the given model class
* @param modelClass - Model class
*/
export function createModelClassBinding<M extends Class<unknown>>(
modelClass: M,
) {
return Binding.bind<M>(`${RepositoryBindings.MODELS}.${modelClass.name}`)
.to(modelClass)
.tag(RepositoryTags.MODEL);
}

0 comments on commit a01d4d2

Please sign in to comment.