Skip to content

Commit

Permalink
feat(cli): add inclusion resolver to lb4 relation
Browse files Browse the repository at this point in the history
  • Loading branch information
Agnes Lin committed Oct 8, 2019
1 parent 3d61841 commit 14a6131
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 48 deletions.
11 changes: 11 additions & 0 deletions docs/site/Relation-generator.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ lb4 relation --sourceModel=<sourceModel>

- `<relationName>` - Name of the relation that will be created.

After setting up the definition for the relation, you need to confirm if you
want to register the inclusion resolver for this relation:

```ts
? Allow <sourceModel> queries to include data from related <destinationModel> instances? (Y/n)
```
Check the site [Relations](HasMany-relation.md) and the
[Querying Related Models](HasMany-relation.md#querying-related-models) section
in each relation for more use cases.
### Interactive Prompts
The tool will prompt you for:
Expand Down
6 changes: 6 additions & 0 deletions packages/cli/generators/relation/base-relation.generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ module.exports = class BaseRelationGenerator extends ArtifactGenerator {
);
this._addParametersToRepositoryConstructor(classConstructor);
this._addCreatorToRepositoryConstructor(classConstructor);
this._registerInclusionResolverForRelation(classConstructor, options);
await this.artifactInfo.srcRepositoryFileObj.save();
}

Expand Down Expand Up @@ -134,6 +135,11 @@ module.exports = class BaseRelationGenerator extends ArtifactGenerator {
throw new Error('Not implemented');
}

_registerInclusionResolverForRelation(classConstructor, options) {
/* istanbul ignore next */
throw new Error('Not implemented');
}

_initializeProperties(options) {
// src configuration.
this.artifactInfo.srcModelPrimaryKey = options.sourceModelPrimaryKey;
Expand Down
37 changes: 21 additions & 16 deletions packages/cli/generators/relation/belongs-to-relation.generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ module.exports = class BelongsToRelationGenerator extends BaseRelationGenerator

getBelongsTo(className, relationName, fktype) {
return {
decorators: [{name: 'belongsTo', arguments: ['() => ' + className]}],
decorators: [{name: 'belongsTo', arguments: [`() => ${className}`]}],
name: relationName,
type: fktype,
};
Expand Down Expand Up @@ -132,26 +132,31 @@ module.exports = class BelongsToRelationGenerator extends BaseRelationGenerator

_getRepositoryRelationPropertyType() {
return (
'BelongsToAccessor<' +
utils.toClassName(this.artifactInfo.dstModelClass) +
', typeof ' +
utils.toClassName(this.artifactInfo.srcModelClass) +
'.prototype.' +
this.artifactInfo.srcModelPrimaryKey +
'>'
`BelongsToAccessor<` +
`${utils.toClassName(this.artifactInfo.dstModelClass)}` +
`, typeof ${utils.toClassName(this.artifactInfo.srcModelClass)}` +
`.prototype.${this.artifactInfo.srcModelPrimaryKey}>`
);
}

_addCreatorToRepositoryConstructor(classConstructor) {
const relationPropertyName = this._getRepositoryRelationPropertyName();
const statement =
'this.' +
this._getRepositoryRelationPropertyName() +
' = ' +
"this.createBelongsToAccessorFor('" +
this.artifactInfo.relationName.replace(/Id$/, '') +
"', " +
utils.camelCase(this.artifactInfo.dstRepositoryClassName) +
'Getter,);';
`this.${relationPropertyName} = ` +
`this.createBelongsToAccessorFor('` +
`${this.artifactInfo.relationName.replace(/Id$/, '')}',` +
` ${utils.camelCase(this.artifactInfo.dstRepositoryClassName)}` +
`Getter,);`;
classConstructor.insertStatements(1, statement);
}

_registerInclusionResolverForRelation(classConstructor, options) {
const relationPropertyName = this._getRepositoryRelationPropertyName();
if (options.registerInclusionResolver) {
const statement =
`this.registerInclusionResolver(` +
`'${relationPropertyName}', this.${relationPropertyName}.inclusionResolver);`;
classConstructor.insertStatements(2, statement);
}
}
};
41 changes: 20 additions & 21 deletions packages/cli/generators/relation/has-many-relation.generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,12 @@ module.exports = class HasManyRelationGenerator extends BaseRelationGenerator {
let relationDecorator = [
{
name: 'hasMany',
arguments: [
'() => ' + className + " ,{keyTo: '" + foreignKeyName + "'}",
],
arguments: [`() => ${className}, {keyTo: '${foreignKeyName}'}`],
},
];
if (isDefaultForeignKey) {
relationDecorator = [
{name: 'hasMany', arguments: ['() => ' + className]},
{name: 'hasMany', arguments: [`() => ${className}`]},
];
}

Expand Down Expand Up @@ -172,28 +170,29 @@ module.exports = class HasManyRelationGenerator extends BaseRelationGenerator {
}

_getRepositoryRelationPropertyType() {
return (
'HasManyRepositoryFactory<' +
utils.toClassName(this.artifactInfo.dstModelClass) +
', typeof ' +
utils.toClassName(this.artifactInfo.srcModelClass) +
'.prototype.' +
this.artifactInfo.srcModelPrimaryKey +
'>'
);
return `HasManyRepositoryFactory<${utils.toClassName(
this.artifactInfo.dstModelClass,
)}, typeof ${utils.toClassName(
this.artifactInfo.srcModelClass,
)}.prototype.${this.artifactInfo.srcModelPrimaryKey}>`;
}

_addCreatorToRepositoryConstructor(classConstructor) {
const relationPropertyName = this._getRepositoryRelationPropertyName();
const statement =
'this.' +
relationPropertyName +
' = ' +
"this.createHasManyRepositoryFactoryFor('" +
relationPropertyName +
"', " +
utils.camelCase(this.artifactInfo.dstRepositoryClassName) +
'Getter,);';
`this.${relationPropertyName} = ` +
`this.createHasManyRepositoryFactoryFor('${relationPropertyName}', ` +
`${utils.camelCase(this.artifactInfo.dstRepositoryClassName)}Getter,);`;
classConstructor.insertStatements(1, statement);
}

_registerInclusionResolverForRelation(classConstructor, options) {
const relationPropertyName = this._getRepositoryRelationPropertyName();
if (options.registerInclusionResolver) {
const statement =
`this.registerInclusionResolver(` +
`'${relationPropertyName}', this.${relationPropertyName}.inclusionResolver);`;
classConstructor.insertStatements(2, statement);
}
}
};
25 changes: 25 additions & 0 deletions packages/cli/generators/relation/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ module.exports = class RelationGenerator extends ArtifactGenerator {
required: false,
description: 'Relation name',
});

this.option('registerInclusionResolver', {
type: Boolean,
required: false,
description:
'Allow <sourceModel> queries to include data from related <destinationModel>',
});
this.artifactInfo = {
type: 'relation',
rootDir: utils.sourceRootDir,
Expand Down Expand Up @@ -374,6 +381,24 @@ module.exports = class RelationGenerator extends ArtifactGenerator {
});
}

async promptRegisterInclusionResolver() {
const props = await this.prompt([
{
type: 'confirm',
name: 'registerInclusionResolver',
message: `Allow ${chalk.yellow(
this.artifactInfo.sourceModel,
)} queries to include data from related ${chalk.yellow(
this.artifactInfo.destinationModel,
)} instances?`,
default: true,
},
]);
debug(`props after inclusion resolver promps: ${inspect(props)}`);
Object.assign(this.artifactInfo, props);
return props;
}

async scaffold() {
if (this.shouldExit()) return false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ export class OrderRepository extends DefaultCrudRepository<
constructor(@inject('datasources.db') dataSource: DbDataSource, @repository.getter('CustomerRepository') protected customerRepositoryGetter: Getter<CustomerRepository>,) {
super(Order, dataSource);
this.customer = this.createBelongsToAccessorFor('customer', customerRepositoryGetter,);
this.registerInclusionResolver('customer', this.customer.inclusionResolver);
}
}
`;

exports[
`lb4 relation checks generated source class repository answers {"relationType":"belongsTo","sourceModel":"OrderClass","destinationModel":"CustomerClass"} generates OrderClass repository file with different inputs 1`
`lb4 relation checks generated source class repository answers {"relationType":"belongsTo","sourceModel":"OrderClass","destinationModel":"CustomerClass","registerInclusionResolver":true} generates OrderClass repository file with different inputs 1`
] = `
import {DefaultCrudRepository, repository, BelongsToAccessor} from '@loopback/repository';
import {OrderClass, CustomerClass} from '../models';
Expand All @@ -50,13 +51,14 @@ export class OrderClassRepository extends DefaultCrudRepository<
constructor(@inject('datasources.myDB') dataSource: MyDBDataSource, @repository.getter('CustomerClassRepository') protected customerClassRepositoryGetter: Getter<CustomerClassRepository>,) {
super(OrderClass, dataSource);
this.customerClass = this.createBelongsToAccessorFor('customerClassCustNumber', customerClassRepositoryGetter,);
this.registerInclusionResolver('customerClass', this.customerClass.inclusionResolver);
}
}
`;

exports[
`lb4 relation checks generated source class repository answers {"relationType":"belongsTo","sourceModel":"OrderClassType","destinationModel":"CustomerClassType"} generates OrderClassType repository file with different inputs 1`
`lb4 relation checks generated source class repository answers {"relationType":"belongsTo","sourceModel":"OrderClassType","destinationModel":"CustomerClassType","registerInclusionResolver":false} generates OrderClassType repository file with different inputs 1`
] = `
import {DefaultCrudRepository, repository, BelongsToAccessor} from '@loopback/repository';
import {OrderClassType, CustomerClassType} from '../models';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ export class CustomerRepository extends DefaultCrudRepository<
constructor(@inject('datasources.db') dataSource: DbDataSource, @repository.getter('OrderRepository') protected orderRepositoryGetter: Getter<OrderRepository>,) {
super(Customer, dataSource);
this.orders = this.createHasManyRepositoryFactoryFor('orders', orderRepositoryGetter,);
this.registerInclusionResolver('orders', this.orders.inclusionResolver);
}
}
`;

exports[
`lb4 relation HasMany checks generated source class repository answers {"relationType":"hasMany","sourceModel":"CustomerClass","destinationModel":"OrderClass"} generates CustomerClass repository file with different inputs 1`
`lb4 relation HasMany checks generated source class repository answers {"relationType":"hasMany","sourceModel":"CustomerClass","destinationModel":"OrderClass","registerInclusionResolver":true} generates CustomerClass repository file with different inputs 1`
] = `
import {DefaultCrudRepository, repository, HasManyRepositoryFactory} from '@loopback/repository';
import {CustomerClass, OrderClass} from '../models';
Expand All @@ -50,13 +51,14 @@ export class CustomerClassRepository extends DefaultCrudRepository<
constructor(@inject('datasources.myDB') dataSource: MyDBDataSource, @repository.getter('OrderClassRepository') protected orderClassRepositoryGetter: Getter<OrderClassRepository>,) {
super(CustomerClass, dataSource);
this.orderClasses = this.createHasManyRepositoryFactoryFor('orderClasses', orderClassRepositoryGetter,);
this.registerInclusionResolver('orderClasses', this.orderClasses.inclusionResolver);
}
}
`;

exports[
`lb4 relation HasMany checks generated source class repository answers {"relationType":"hasMany","sourceModel":"CustomerClassType","destinationModel":"OrderClassType"} generates CustomerClassType repository file with different inputs 1`
`lb4 relation HasMany checks generated source class repository answers {"relationType":"hasMany","sourceModel":"CustomerClassType","destinationModel":"OrderClassType","registerInclusionResolver":false} generates CustomerClassType repository file with different inputs 1`
] = `
import {DefaultCrudRepository, repository, HasManyRepositoryFactory} from '@loopback/repository';
import {CustomerClassType, OrderClassType} from '../models';
Expand Down Expand Up @@ -447,7 +449,7 @@ export class Customer extends Entity {
})
name?: string;
@hasMany(() => Order ,{keyTo: 'mykey'})
@hasMany(() => Order, {keyTo: 'mykey'})
orders: Order[];
constructor(data?: Partial<Customer>) {
Expand Down Expand Up @@ -507,7 +509,7 @@ export class CustomerClass extends Entity {
})
name?: string;
@hasMany(() => OrderClass ,{keyTo: 'mykey'})
@hasMany(() => OrderClass, {keyTo: 'mykey'})
orderClasses: OrderClass[];
constructor(data?: Partial<CustomerClass>) {
Expand Down Expand Up @@ -566,7 +568,7 @@ export class CustomerClassType extends Entity {
})
name?: string;
@hasMany(() => OrderClassType ,{keyTo: 'mykey'})
@hasMany(() => OrderClassType, {keyTo: 'mykey'})
orderClassTypes: OrderClassType[];
constructor(data?: Partial<CustomerClassType>) {
Expand Down Expand Up @@ -686,7 +688,7 @@ export class CustomerClass extends Entity {
})
name?: string;
@hasMany(() => OrderClass ,{keyTo: 'customerClassCustNumber'})
@hasMany(() => OrderClass, {keyTo: 'customerClassCustNumber'})
myOrders: OrderClass[];
constructor(data?: Partial<CustomerClass>) {
Expand Down Expand Up @@ -745,7 +747,7 @@ export class CustomerClassType extends Entity {
})
name?: string;
@hasMany(() => OrderClassType ,{keyTo: 'customerClassTypeCustNumber'})
@hasMany(() => OrderClassType, {keyTo: 'customerClassTypeCustNumber'})
myOrders: OrderClassType[];
constructor(data?: Partial<CustomerClassType>) {
Expand Down Expand Up @@ -834,7 +836,7 @@ export class CustomerClass extends Entity {
})
name?: string;
@hasMany(() => OrderClass ,{keyTo: 'customerClassCustNumber'})
@hasMany(() => OrderClass, {keyTo: 'customerClassCustNumber'})
orderClasses: OrderClass[];
constructor(data?: Partial<CustomerClass>) {
Expand Down Expand Up @@ -863,7 +865,7 @@ export class CustomerClassType extends Entity {
})
name?: string;
@hasMany(() => OrderClassType ,{keyTo: 'customerClassTypeCustNumber'})
@hasMany(() => OrderClassType, {keyTo: 'customerClassTypeCustNumber'})
orderClassTypes: OrderClassType[];
constructor(data?: Partial<CustomerClassType>) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,11 +343,13 @@ describe('lb4 relation', function() {
relationType: 'belongsTo',
sourceModel: 'OrderClass',
destinationModel: 'CustomerClass',
registerInclusionResolver: true,
},
{
relationType: 'belongsTo',
sourceModel: 'OrderClassType',
destinationModel: 'CustomerClassType',
registerInclusionResolver: false,
},
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -338,11 +338,13 @@ describe('lb4 relation HasMany', function() {
relationType: 'hasMany',
sourceModel: 'CustomerClass',
destinationModel: 'OrderClass',
registerInclusionResolver: true,
},
{
relationType: 'hasMany',
sourceModel: 'CustomerClassType',
destinationModel: 'OrderClassType',
registerInclusionResolver: false,
},
];

Expand Down

0 comments on commit 14a6131

Please sign in to comment.