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 2, 2019
1 parent 517c201 commit d096fbd
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export function createRetrieveSuite(
it('retrieves an instance of a model from its foreign key value', async () => {
const pens = await repo.create({name: 'Pens', categoryId: 1});
const pencils = await repo.create({name: 'Pencils', categoryId: 2});
const products = await findByForeignKeys(repo, 'categoryId', [1]);
const products = await findByForeignKeys(repo, 'categoryId', 1);
expect(products).deepEqual([pens]);
expect(products).to.not.containDeep(pencils);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,39 @@ describe('findByForeignKeys', () => {

it('returns an empty array when no instances have the foreign key value', async () => {
await productRepo.create({id: 1, name: 'product', categoryId: 1});
const products = await findByForeignKeys(productRepo, 'categoryId', [2]);
const products = await findByForeignKeys(productRepo, 'categoryId', 2);
expect(products).to.be.empty();
});

it('returns an empty array when no instances have the foreign key values', async () => {
await productRepo.create({id: 1, name: 'product', categoryId: 1});
const products = await findByForeignKeys(productRepo, 'categoryId', [2, 3]);
expect(products).to.be.empty();
});

it('returns all instances that have the foreign key value', async () => {
const pens = await productRepo.create({name: 'pens', categoryId: 1});
const pencils = await productRepo.create({name: 'pencils', categoryId: 1});
const products = await findByForeignKeys(productRepo, 'categoryId', [1]);
const products = await findByForeignKeys(productRepo, 'categoryId', 1);
expect(products).to.deepEqual([pens, pencils]);
});

it('does not include instances with different foreign key values', async () => {
const pens = await productRepo.create({name: 'pens', categoryId: 1});
const pencils = await productRepo.create({name: 'pencils', categoryId: 2});
const products = await findByForeignKeys(productRepo, 'categoryId', [1]);
const products = await findByForeignKeys(productRepo, 'categoryId', 1);
expect(products).to.deepEqual([pens]);
expect(products).to.not.containDeep(pencils);
});

it('includes instances when there is one value in the array of foreign key values', async () => {
const pens = await productRepo.create({name: 'pens', categoryId: 1});
const pencils = await productRepo.create({name: 'pencils', categoryId: 2});
const products = await findByForeignKeys(productRepo, 'categoryId', [2]);
expect(products).to.deepEqual([pencils]);
expect(products).to.not.containDeep(pens);
});

it('returns all instances that have any of multiple foreign key values', async () => {
const pens = await productRepo.create({name: 'pens', categoryId: 1});
const pencils = await productRepo.create({name: 'pencils', categoryId: 2});
Expand All @@ -61,6 +75,20 @@ describe('findByForeignKeys', () => {
expect(errorMessage).to.eql('scope is not supported');
});

it('does not throw an error if scope is passed in and is undefined or empty', async () => {
let products = await findByForeignKeys(
productRepo,
'categoryId',
[1],
undefined,
{},
);
expect(products).to.be.empty();

products = await findByForeignKeys(productRepo, 'categoryId', 1, {}, {});
expect(products).to.be.empty();
});

/******************* HELPERS *******************/

@model()
Expand Down
23 changes: 13 additions & 10 deletions packages/repository/src/relations/relation.helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,18 @@ import {Entity, EntityCrudRepository, Filter, Options, Where} from '..';
*
* @param targetRepository - The target repository where the model instances are found
* @param fkName - Name of the foreign key
* @param fkValues - Array of the values of the foreign keys to be included
* @param fkValues - One value or array of values of the foreign key to be included
* @param scope - Additional scope constraints (not currently supported)
* @param options - Options for the operations
*/
export async function findByForeignKeys<
Target extends Entity,
TargetID,
TargetRelations extends object,
ForeignKey
ForeignKey extends StringKeyOf<Target>
>(
targetRepository: EntityCrudRepository<Target, TargetID, TargetRelations>,
fkName: StringKeyOf<Target>,
fkValues: ForeignKey[],
targetRepository: EntityCrudRepository<Target, unknown, TargetRelations>,
fkName: ForeignKey,
fkValues: Target[ForeignKey][] | Target[ForeignKey],
scope?: Filter<Target>,
options?: Options,
): Promise<(Target & TargetRelations)[]> {
Expand All @@ -33,12 +32,16 @@ export async function findByForeignKeys<
throw new Error('scope is not supported');
}

const where = ({
[fkName]: fkValues.length === 1 ? fkValues[0] : {inq: fkValues},
} as unknown) as Where<Target>;
const value = Array.isArray(fkValues)
? fkValues.length === 1
? fkValues[0]
: {inq: fkValues}
: fkValues;

const where = ({[fkName]: value} as unknown) as Where<Target>;
const targetFilter = {where};

return targetRepository.find(targetFilter, options);
}

export type StringKeyOf<T> = Extract<keyof T, string>;
type StringKeyOf<T> = Extract<keyof T, string>;

0 comments on commit d096fbd

Please sign in to comment.