-
Notifications
You must be signed in to change notification settings - Fork 1.1k
feat(repository): add more helpers for HasManyThrough #5605
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,10 +7,12 @@ import debugFactory from 'debug'; | |
| import {camelCase} from 'lodash'; | ||
| import { | ||
| DataObject, | ||
| deduplicate, | ||
| Entity, | ||
| HasManyDefinition, | ||
| InvalidRelationError, | ||
| isTypeResolver, | ||
| StringKeyOf, | ||
| } from '../..'; | ||
| import {resolveHasManyMetaHelper} from './has-many.helpers'; | ||
|
|
||
|
|
@@ -27,7 +29,7 @@ export type HasManyThroughResolvedDefinition = HasManyDefinition & { | |
|
|
||
| /** | ||
| * Creates constraint used to query target | ||
| * @param relationMeta - hasManyThrough metadata to resolve | ||
| * @param relationMeta - resolved hasManyThrough metadata | ||
| * @param throughInstances - Instances of through entities used to constrain the target | ||
| * @internal | ||
| * | ||
|
|
@@ -50,26 +52,32 @@ export type HasManyThroughResolvedDefinition = HasManyDefinition & { | |
| categoryId: 2, | ||
| productId: 8, | ||
| }, { | ||
| id: 2, | ||
| id: 1, | ||
| categoryId: 2, | ||
| productId: 9, | ||
| } | ||
| ]); | ||
|
|
||
| >>> {id: {inq: [9, 8]}} | ||
| * ``` | ||
| */ | ||
| export function createTargetConstraint< | ||
| Target extends Entity, | ||
| Through extends Entity | ||
| >( | ||
| relationMeta: HasManyThroughResolvedDefinition, | ||
| throughInstances: Through[], | ||
| throughInstances: Through | Through[], | ||
| ): DataObject<Target> { | ||
| const targetPrimaryKey = relationMeta.keyTo; | ||
| const targetFkName = relationMeta.through.keyTo; | ||
| const fkValues = throughInstances.map( | ||
| if (!Array.isArray(throughInstances)) { | ||
| throughInstances = [throughInstances]; | ||
| } | ||
| let fkValues = throughInstances.map( | ||
| (throughInstance: Through) => | ||
| throughInstance[targetFkName as keyof Through], | ||
| ); | ||
| fkValues = deduplicate(fkValues); | ||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
| const constraint: any = { | ||
| [targetPrimaryKey]: fkValues.length === 1 ? fkValues[0] : {inq: fkValues}, | ||
|
|
@@ -80,7 +88,7 @@ export function createTargetConstraint< | |
| /** | ||
| * Creates constraint used to query through model | ||
| * | ||
| * @param relationMeta - hasManyThrough metadata to resolve | ||
| * @param relationMeta - resolved hasManyThrough metadata | ||
| * @param fkValue - Value of the foreign key of the source model used to constrain through | ||
| * @param targetInstance - Instance of target entity used to constrain through | ||
| * @internal | ||
|
|
@@ -98,6 +106,8 @@ export function createTargetConstraint< | |
| * }, | ||
| * }; | ||
| * createThroughConstraint(resolvedMetadata, 1); | ||
| * | ||
| * >>> {categoryId: 1} | ||
| * ``` | ||
| */ | ||
| export function createThroughConstraint<Through extends Entity, ForeignKeyType>( | ||
|
|
@@ -109,6 +119,45 @@ export function createThroughConstraint<Through extends Entity, ForeignKeyType>( | |
| const constraint: any = {[sourceFkName]: fkValue}; | ||
| return constraint; | ||
| } | ||
| /** | ||
| * Creates constraint used to create the through model | ||
| * | ||
| * @param relationMeta - resolved hasManyThrough metadata | ||
| * @param targetInstance instance of target entity used to constrain through | ||
| * @internal | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const resolvedMetadata = { | ||
| * // .. other props | ||
| * keyFrom: 'id', | ||
| * keyTo: 'id', | ||
| * through: { | ||
| * model: () => CategoryProductLink, | ||
| * keyFrom: 'categoryId', | ||
| * keyTo: 'productId', | ||
| * }, | ||
| * }; | ||
| * createThroughConstraint(resolvedMetadata, {id: 3, name: 'a product'}); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The additional query field reminds me sth(sorry don't remember where is the original chat :p) : We want to distinguish the query on through model(CategoryProductLink) and target model(Product), how do we achieve that? For example,
(I started from the helper function, might missing the code/docs if they are created other places.)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jannyHou I think these helpers are just for handling the relation metadata. And filters are handled in the hasManyThrough repository. Here is an example in the original design: find method. They won't be included in this PR. But I'd love to discuss it: So far from those two community PRs(#2359 , #4438 ), I only see the target model is capable of applying filters. Not sure if we need it for through models ( I don't see the reason to allow filtering through models tho). Do we need it? |
||
| * | ||
| * >>> {productId: 1} | ||
| * | ||
| * createThroughConstraint(resolvedMetadata, {id: {inq:[3,4]}}); | ||
| * | ||
| * >>> {productId: {inq:[3,4]}} | ||
| */ | ||
| export function createThroughFkConstraint<Target, Through extends Entity>( | ||
| relationMeta: HasManyThroughResolvedDefinition, | ||
| targetInstance: Target, | ||
| ): DataObject<Through> { | ||
| const targetKey = relationMeta.keyTo as StringKeyOf<Target>; | ||
| const targetFkName = relationMeta.through.keyTo; | ||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
| const constraint: any = { | ||
| [targetFkName]: targetInstance[targetKey], | ||
| }; | ||
| return constraint; | ||
| } | ||
|
|
||
| /** | ||
| * Resolves given hasMany metadata if target is specified to be a resolver. | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.