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:
@@ -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 * from "./lib"
|
||||||
|
export {
|
||||||
|
Merge,
|
||||||
|
SetNonNullable,
|
||||||
|
SetRelation,
|
||||||
|
SetRequired,
|
||||||
|
} from "./lib/core/ModelUtils"
|
||||||
|
|||||||
+1
@@ -4,5 +4,6 @@ export interface WithExtendedRelationsExtension {
|
|||||||
relations?: string[]
|
relations?: string[]
|
||||||
totals?: string[]
|
totals?: string[]
|
||||||
implicit?: string[]
|
implicit?: string[]
|
||||||
|
eager?: string[]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+36
-17
@@ -9,13 +9,14 @@ export const handleExpandedRelations = (model: Model, allModels: Model[]) => {
|
|||||||
const relations = xExpandedRelation.relations ?? []
|
const relations = xExpandedRelation.relations ?? []
|
||||||
const totals = xExpandedRelation.totals ?? []
|
const totals = xExpandedRelation.totals ?? []
|
||||||
const implicit = xExpandedRelation.implicit ?? []
|
const implicit = xExpandedRelation.implicit ?? []
|
||||||
|
const eager = xExpandedRelation.eager ?? []
|
||||||
|
|
||||||
const nestedRelation: NestedRelation = {
|
const nestedRelation: NestedRelation = {
|
||||||
field,
|
field,
|
||||||
nestedRelations: [],
|
nestedRelations: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const relation of [...relations, ...totals, ...implicit]) {
|
for (const relation of [...relations, ...totals, ...implicit, ...eager]) {
|
||||||
const splitRelation = relation.split(".")
|
const splitRelation = relation.split(".")
|
||||||
walkSplitRelations(nestedRelation, splitRelation, 0)
|
walkSplitRelations(nestedRelation, splitRelation, 0)
|
||||||
}
|
}
|
||||||
@@ -24,9 +25,13 @@ export const handleExpandedRelations = (model: Model, allModels: Model[]) => {
|
|||||||
model.imports = [...new Set(model.imports)]
|
model.imports = [...new Set(model.imports)]
|
||||||
|
|
||||||
const prop = getPropertyByName(nestedRelation.field, model)
|
const prop = getPropertyByName(nestedRelation.field, model)
|
||||||
if (prop) {
|
if (!prop) {
|
||||||
prop.nestedRelations = [nestedRelation]
|
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 = (
|
const walkSplitRelations = (
|
||||||
@@ -59,12 +64,20 @@ const walkNestedRelations = (
|
|||||||
nestedRelation: NestedRelation,
|
nestedRelation: NestedRelation,
|
||||||
parentNestedRelation?: NestedRelation
|
parentNestedRelation?: NestedRelation
|
||||||
) => {
|
) => {
|
||||||
const prop =
|
const prop = ["all-of", "any-of", "one-of"].includes(model.export)
|
||||||
model.export === "all-of"
|
? findPropInCombination(nestedRelation.field, model, allModels)
|
||||||
? findPropInAllOf(nestedRelation.field, model, allModels)
|
: getPropertyByName(nestedRelation.field, model)
|
||||||
: getPropertyByName(nestedRelation.field, model)
|
|
||||||
if (!prop) {
|
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)) {
|
if (!["reference", "array"].includes(prop.export)) {
|
||||||
return
|
return
|
||||||
@@ -73,15 +86,21 @@ const walkNestedRelations = (
|
|||||||
nestedRelation.base = prop.type
|
nestedRelation.base = prop.type
|
||||||
nestedRelation.isArray = prop.export === "array"
|
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) {
|
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(
|
walkNestedRelations(
|
||||||
allModels,
|
allModels,
|
||||||
rootModel,
|
rootModel,
|
||||||
@@ -92,7 +111,7 @@ const walkNestedRelations = (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const findPropInAllOf = (
|
const findPropInCombination = (
|
||||||
fieldName: string,
|
fieldName: string,
|
||||||
model: Model,
|
model: Model,
|
||||||
allModels: Model[]
|
allModels: Model[]
|
||||||
|
|||||||
@@ -91,4 +91,11 @@ export type SetNonNullable<BaseType, Keys extends keyof BaseType = keyof BaseTyp
|
|||||||
export type Merge<Destination, Source> = EnforceOptional<
|
export type Merge<Destination, Source> = EnforceOptional<
|
||||||
SimpleMerge<PickIndexSignature<Destination>, PickIndexSignature<Source>>
|
SimpleMerge<PickIndexSignature<Destination>, PickIndexSignature<Source>>
|
||||||
& SimpleMerge<OmitIndexSignature<Destination>, OmitIndexSignature<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}}
|
{{>header}}
|
||||||
|
|
||||||
import { SetRequired, Merge } from '../core/ModelUtils';
|
import { SetRelation, Merge } from '../core/ModelUtils';
|
||||||
{{#if imports}}
|
{{#if imports}}
|
||||||
|
|
||||||
{{#each imports}}
|
{{#each imports}}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{{~#if isArray}}Array<{{/if~}}
|
{{~#if isArray}}Array<{{/if~}}
|
||||||
{{~#if hasDepth}}Merge<{{/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}}
|
{{/if}}
|
||||||
{{~#each nestedRelations~}}
|
{{~#each nestedRelations~}}
|
||||||
{{#if nestedRelations~}}
|
{{#if nestedRelations~}}
|
||||||
|
|||||||
Reference in New Issue
Block a user