Skip to content

Commit

Permalink
fixup! apply feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
nabdelgadir committed Aug 13, 2019
1 parent f455a65 commit 602aa1b
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,11 @@ describe('relation helpers', () => {
const category = await categoryRepo.create({name: 'category 1'});
await productRepo.create({id: 1, name: 'product1', categoryId: 1});
await expect(
includeRelatedModels(categoryRepo, [category], {
include: [{relation: 'products'}],
}),
includeRelatedModels(
categoryRepo,
[category],
[{relation: 'products'}],
),
).to.be.rejectedWith(
/Invalid "filter.include" entries: {"relation":"products"}/,
);
Expand All @@ -169,9 +171,11 @@ describe('relation helpers', () => {

categoryRepo.inclusionResolvers.set('products', hasManyResolver);

const categories = await includeRelatedModels(categoryRepo, [category], {
include: [{relation: 'products'}],
});
const categories = await includeRelatedModels(
categoryRepo,
[category],
[{relation: 'products'}],
);

expect(categories[0].products).to.be.empty();
});
Expand All @@ -188,9 +192,7 @@ describe('relation helpers', () => {
const productWithCategories = await includeRelatedModels(
productRepo,
[product],
{
include: [{relation: 'category'}],
},
[{relation: 'category'}],
);

expect(productWithCategories[0].toJSON()).to.deepEqual({
Expand Down Expand Up @@ -222,9 +224,7 @@ describe('relation helpers', () => {
const productWithCategories = await includeRelatedModels(
productRepo,
[productOne, productTwo, productThree],
{
include: [{relation: 'category'}],
},
[{relation: 'category'}],
);

expect(toJSON(productWithCategories)).to.deepEqual([
Expand All @@ -251,7 +251,7 @@ describe('relation helpers', () => {
const categoryWithProducts = await includeRelatedModels(
categoryRepo,
[category],
{include: [{relation: 'products'}]},
[{relation: 'products'}],
);

expect(toJSON(categoryWithProducts)).to.deepEqual([
Expand Down Expand Up @@ -286,7 +286,7 @@ describe('relation helpers', () => {
const categoryWithProducts = await includeRelatedModels(
categoryRepo,
[categoryOne, categoryTwo, categoryThree],
{include: [{relation: 'products'}]},
[{relation: 'products'}],
);

expect(toJSON(categoryWithProducts)).to.deepEqual([
Expand All @@ -304,25 +304,29 @@ describe('relation helpers', () => {

// stubbed resolvers

const belongsToResolver: InclusionResolver = async entities => {
const categories: Category[] = [];
const belongsToResolver: InclusionResolver<
Product,
Category
> = async entities => {
const categories = [];

for (const entity of entities) {
const p = entity as Product;
const c = await categoryRepo.findById(p.categoryId);
categories.push(c);
for (const product of entities) {
const category = await categoryRepo.findById(product.categoryId);
categories.push(category);
}

return categories;
};

const hasManyResolver: InclusionResolver = async entities => {
const products: Product[][] = [];
const hasManyResolver: InclusionResolver<
Category,
Product
> = async entities => {
const products = [];

for (const entity of entities) {
const c = entity as Category;
const p = await categoryRepo.products(c.id).find();
products.push(p);
for (const category of entities) {
const product = await categoryRepo.products(category.id).find();
products.push(product);
}
return products;
};
Expand Down
30 changes: 11 additions & 19 deletions packages/repository/src/relations/relation.helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ type StringKeyOf<T> = Extract<keyof T, string>;
*
* @param targetRepository - The target repository where the model instances are found
* @param entities - An array of entity instances or data
* @param filter - Query filter
* @param include -Inclusion filter
* @param options - Options for the operations
*/

Expand All @@ -75,11 +75,10 @@ export async function includeRelatedModels<
>(
targetRepository: EntityCrudRepository<T, unknown, Relations>,
entities: T[],
filter?: Filter<T>,
include?: Inclusion<T>[],
options?: Options,
): Promise<(T & Relations)[]> {
const result = entities as (T & Relations)[];
const include = filter && filter.include;
if (!include) return result;

const invalidInclusions = include.filter(
Expand All @@ -103,10 +102,10 @@ export async function includeRelatedModels<
const resolver = targetRepository.inclusionResolvers.get(relationName)!;
const targets = await resolver(entities, inclusionFilter, options);

for (const ix in result) {
const src = result[ix];
(src as AnyObject)[relationName] = targets[ix];
}
result.forEach((entity, ix) => {
const src = entity as AnyObject;
src[relationName] = targets[ix];
});
});

await Promise.all(resolveTasks);
Expand All @@ -118,25 +117,18 @@ export async function includeRelatedModels<
* in the inclusionResolver of the target repository
*
* @param targetRepository - The target repository where the relations are registered
* @param inclusion - Inclusion filter
* @param include - Inclusion filter
*/
function isInclusionAllowed<T extends Entity, Relations extends object = {}>(
targetRepository: EntityCrudRepository<T, unknown, Relations>,
inclusionFilter: Inclusion,
include: Inclusion,
): boolean {
const relationName = inclusionFilter.relation;
const relationName = include.relation;
if (!relationName) {
debug(
'isInclusionAllowed for %j? No: missing relation name',
inclusionFilter,
);
debug('isInclusionAllowed for %j? No: missing relation name', include);
return false;
}
const allowed = targetRepository.inclusionResolvers.has(relationName);
debug(
'isInclusionAllowed for %j (relation %s)? %s',
inclusionFilter,
allowed,
);
debug('isInclusionAllowed for %j (relation %s)? %s', include, allowed);
return allowed;
}
6 changes: 3 additions & 3 deletions packages/repository/src/relations/relation.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,11 @@ export {Getter} from '@loopback/context';
* - `Entity` for relations targeting a single model
* - `Entity[]` for relations targeting multiple models
*/
export type InclusionResolver = (
export type InclusionResolver<S extends Entity, T extends Entity> = (
/**
* List of source models as returned by the first database query.
*/
sourceEntities: Entity[],
sourceEntities: S[],
/**
* Inclusion requested by the user (e.g. scope constraints to apply).
*/
Expand All @@ -131,4 +131,4 @@ export type InclusionResolver = (
* Generic options object, e.g. carrying the Transaction object.
*/
options?: Options,
) => Promise<(Entity | undefined)[] | (Entity[] | undefined)[]>;
) => Promise<(T | undefined)[] | (T[] | undefined)[]>;
4 changes: 2 additions & 2 deletions packages/repository/src/repositories/legacy-juggler-bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export class DefaultCrudRepository<
> implements EntityCrudRepository<T, ID, Relations> {
modelClass: juggler.PersistedModelClass;

public inclusionResolvers: Map<string, InclusionResolver>;
public inclusionResolvers: Map<string, InclusionResolver<T, Entity>>;

/**
* Constructor of DefaultCrudRepository
Expand All @@ -124,7 +124,7 @@ export class DefaultCrudRepository<
);

this.modelClass = this.definePersistedModel(entityClass);
this.inclusionResolvers = new Map<string, InclusionResolver>();
this.inclusionResolvers = new Map<string, InclusionResolver<T, Entity>>();
}

// Create an internal legacy Model attached to the datasource
Expand Down
6 changes: 3 additions & 3 deletions packages/repository/src/repositories/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export interface EntityCrudRepository<
> extends EntityRepository<T, ID>, CrudRepository<T, Relations> {
// entityClass should have type "typeof T", but that's not supported by TSC
entityClass: typeof Entity & {prototype: T};
inclusionResolvers: Map<string, InclusionResolver>;
inclusionResolvers: Map<string, InclusionResolver<T, Entity>>;

/**
* Save an entity. If no id is present, create a new entity
Expand Down Expand Up @@ -251,15 +251,15 @@ export interface EntityCrudRepository<
export class CrudRepositoryImpl<T extends Entity, ID>
implements EntityCrudRepository<T, ID> {
private connector: CrudConnector;
public inclusionResolvers: Map<string, InclusionResolver>;
public inclusionResolvers: Map<string, InclusionResolver<T, Entity>>;

constructor(
public dataSource: DataSource,
// model should have type "typeof T", but that's not supported by TSC
public entityClass: typeof Entity & {prototype: T},
) {
this.connector = dataSource.connector as CrudConnector;
this.inclusionResolvers = new Map<string, InclusionResolver>();
this.inclusionResolvers = new Map<string, InclusionResolver<T, Entity>>();
}

private toModels(data: Promise<DataObject<Entity>[]>): Promise<T[]> {
Expand Down

0 comments on commit 602aa1b

Please sign in to comment.