feat(codegen,types): SetRelation on expanded types (#3477)
## What On expanded relations, mutate type using SetRelation, an alias for SetRequired with SetNonNullable. ## Why Simplifies implementation in client code. ## How * Export SetRelation type util * Update codegen template Extra scope: * Improve codegen error handling when processing x-expanded-relations * Add `eager` sub-categorization to x-expanded-relations to highlight relations that are loaded using TypeORM eager.
This commit is contained in:
6
.changeset/quiet-spiders-join.md
Normal file
6
.changeset/quiet-spiders-join.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@medusajs/openapi-typescript-codegen": minor
|
||||
"@medusajs/client-types": minor
|
||||
---
|
||||
|
||||
feat(codegen,types): SetRelation on expanded types
|
||||
@@ -1 +1,7 @@
|
||||
export * from "./lib"
|
||||
export {
|
||||
Merge,
|
||||
SetNonNullable,
|
||||
SetRelation,
|
||||
SetRequired,
|
||||
} from "./lib/core/ModelUtils"
|
||||
|
||||
@@ -4,5 +4,6 @@ export interface WithExtendedRelationsExtension {
|
||||
relations?: string[]
|
||||
totals?: string[]
|
||||
implicit?: string[]
|
||||
eager?: string[]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,13 +9,14 @@ export const handleExpandedRelations = (model: Model, allModels: Model[]) => {
|
||||
const relations = xExpandedRelation.relations ?? []
|
||||
const totals = xExpandedRelation.totals ?? []
|
||||
const implicit = xExpandedRelation.implicit ?? []
|
||||
const eager = xExpandedRelation.eager ?? []
|
||||
|
||||
const nestedRelation: NestedRelation = {
|
||||
field,
|
||||
nestedRelations: [],
|
||||
}
|
||||
|
||||
for (const relation of [...relations, ...totals, ...implicit]) {
|
||||
for (const relation of [...relations, ...totals, ...implicit, ...eager]) {
|
||||
const splitRelation = relation.split(".")
|
||||
walkSplitRelations(nestedRelation, splitRelation, 0)
|
||||
}
|
||||
@@ -24,9 +25,13 @@ export const handleExpandedRelations = (model: Model, allModels: Model[]) => {
|
||||
model.imports = [...new Set(model.imports)]
|
||||
|
||||
const prop = getPropertyByName(nestedRelation.field, model)
|
||||
if (prop) {
|
||||
prop.nestedRelations = [nestedRelation]
|
||||
if (!prop) {
|
||||
throw new Error(`x-expanded-relations error - field not found
|
||||
Schema: ${model.name}
|
||||
NestedRelation: ${JSON.stringify(nestedRelation, null, 2)}
|
||||
Model: ${JSON.stringify(model.spec, null, 2)}`)
|
||||
}
|
||||
prop.nestedRelations = [nestedRelation]
|
||||
}
|
||||
|
||||
const walkSplitRelations = (
|
||||
@@ -59,12 +64,20 @@ const walkNestedRelations = (
|
||||
nestedRelation: NestedRelation,
|
||||
parentNestedRelation?: NestedRelation
|
||||
) => {
|
||||
const prop =
|
||||
model.export === "all-of"
|
||||
? findPropInAllOf(nestedRelation.field, model, allModels)
|
||||
: getPropertyByName(nestedRelation.field, model)
|
||||
const prop = ["all-of", "any-of", "one-of"].includes(model.export)
|
||||
? findPropInCombination(nestedRelation.field, model, allModels)
|
||||
: getPropertyByName(nestedRelation.field, model)
|
||||
if (!prop) {
|
||||
return
|
||||
throw new Error(`x-expanded-relations - field not found
|
||||
Schema: ${rootModel.name}
|
||||
NestedRelation: ${JSON.stringify(nestedRelation, null, 2)}
|
||||
Model: ${JSON.stringify(model.spec, null, 2)}`)
|
||||
}
|
||||
if (["all-of", "any-of", "one-of"].includes(prop.export)) {
|
||||
throw new Error(`x-expanded-relations - unsupported - field referencing multiple models
|
||||
Schema: ${rootModel.name}
|
||||
NestedRelation: ${JSON.stringify(nestedRelation, null, 2)}
|
||||
Model: ${JSON.stringify(model.spec, null, 2)}`)
|
||||
}
|
||||
if (!["reference", "array"].includes(prop.export)) {
|
||||
return
|
||||
@@ -73,15 +86,21 @@ const walkNestedRelations = (
|
||||
nestedRelation.base = prop.type
|
||||
nestedRelation.isArray = prop.export === "array"
|
||||
|
||||
if (!nestedRelation.nestedRelations.length) {
|
||||
return
|
||||
}
|
||||
const childModel = getModelByName(prop.type, allModels)
|
||||
if (!childModel) {
|
||||
throw new Error(`x-expanded-relations - field referencing unknown model
|
||||
Schema: ${rootModel.name}
|
||||
NestedRelation: ${JSON.stringify(nestedRelation, null, 2)}
|
||||
Model: ${JSON.stringify(model.spec, null, 2)}`)
|
||||
}
|
||||
rootModel.imports.push(prop.type)
|
||||
if (parentNestedRelation) {
|
||||
parentNestedRelation.hasDepth = true
|
||||
}
|
||||
for (const childNestedRelation of nestedRelation.nestedRelations) {
|
||||
const childModel = getModelByName(prop.type, allModels)
|
||||
if (!childModel) {
|
||||
return
|
||||
}
|
||||
rootModel.imports.push(prop.type)
|
||||
if (parentNestedRelation) {
|
||||
parentNestedRelation.hasDepth = true
|
||||
}
|
||||
walkNestedRelations(
|
||||
allModels,
|
||||
rootModel,
|
||||
@@ -92,7 +111,7 @@ const walkNestedRelations = (
|
||||
}
|
||||
}
|
||||
|
||||
const findPropInAllOf = (
|
||||
const findPropInCombination = (
|
||||
fieldName: string,
|
||||
model: Model,
|
||||
allModels: Model[]
|
||||
|
||||
@@ -91,4 +91,11 @@ export type SetNonNullable<BaseType, Keys extends keyof BaseType = keyof BaseTyp
|
||||
export type Merge<Destination, Source> = EnforceOptional<
|
||||
SimpleMerge<PickIndexSignature<Destination>, PickIndexSignature<Source>>
|
||||
& SimpleMerge<OmitIndexSignature<Destination>, OmitIndexSignature<Source>>
|
||||
>;
|
||||
>;
|
||||
|
||||
/**
|
||||
* SetRelation
|
||||
* Alias combining SetRequire and SetNonNullable.
|
||||
*/
|
||||
export type SetRelation<BaseType, Keys extends keyof BaseType> =
|
||||
SetRequired<SetNonNullable<BaseType, Keys>, Keys>;
|
||||
@@ -1,6 +1,6 @@
|
||||
{{>header}}
|
||||
|
||||
import { SetRequired, Merge } from '../core/ModelUtils';
|
||||
import { SetRelation, Merge } from '../core/ModelUtils';
|
||||
{{#if imports}}
|
||||
|
||||
{{#each imports}}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{{~#if isArray}}Array<{{/if~}}
|
||||
{{~#if hasDepth}}Merge<{{/if~}}
|
||||
SetRequired<{{>base}}, {{#each nestedRelations}}'{{{field}}}'{{#unless @last}} | {{/unless}}{{/each}}>{{#if hasDepth}}, {
|
||||
SetRelation<{{>base}}, {{#each nestedRelations}}'{{{field}}}'{{#unless @last}} | {{/unless}}{{/each}}>{{#if hasDepth}}, {
|
||||
{{/if}}
|
||||
{{~#each nestedRelations~}}
|
||||
{{#if nestedRelations~}}
|
||||
|
||||
Reference in New Issue
Block a user