feat: define link util (#7931)
* feat: define link util * handle pluralized fieldAlias for isList * serviceName ar reference * finalize * todo * WIP * finalize * fix tests * update typings * fix Module * linkable * update errors
This commit is contained in:
@@ -25,6 +25,7 @@ import {
|
||||
ShippingOptionRule,
|
||||
ShippingProfile,
|
||||
} from "../__fixtures__/joiner-config/entities"
|
||||
import { upperCaseFirst } from "../../common"
|
||||
|
||||
describe("joiner-config-builder", () => {
|
||||
describe("defineJoiner | Mikro orm objects", () => {
|
||||
@@ -420,14 +421,15 @@ describe("joiner-config-builder", () => {
|
||||
})
|
||||
|
||||
const linkableKeys = buildLinkableKeysFromDmlObjects([user, car])
|
||||
|
||||
expectTypeOf(linkableKeys).toMatchTypeOf<{
|
||||
user_id: "User"
|
||||
car_number_plate: "Car"
|
||||
}>()
|
||||
|
||||
expect(linkableKeys).toEqual({
|
||||
user_id: user.name,
|
||||
car_number_plate: car.name,
|
||||
user_id: upperCaseFirst(user.name),
|
||||
car_number_plate: upperCaseFirst(car.name),
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -453,12 +455,18 @@ describe("joiner-config-builder", () => {
|
||||
name: model.text(),
|
||||
})
|
||||
|
||||
const car = model.define("car", {
|
||||
id: model.id(),
|
||||
number_plate: model.text().primaryKey(),
|
||||
})
|
||||
const car = model.define(
|
||||
{ name: "car", tableName: "car" },
|
||||
{
|
||||
id: model.id(),
|
||||
number_plate: model.text().primaryKey(),
|
||||
}
|
||||
)
|
||||
|
||||
const linkConfig = buildLinkConfigFromDmlObjects("myService", [user, car])
|
||||
const linkConfig = buildLinkConfigFromDmlObjects("myService", {
|
||||
user,
|
||||
car,
|
||||
})
|
||||
|
||||
expectTypeOf(linkConfig).toMatchTypeOf<{
|
||||
user: {
|
||||
|
||||
@@ -0,0 +1,316 @@
|
||||
import { LinkModulesExtraFields, ModuleJoinerConfig } from "@medusajs/types"
|
||||
import { isObject, pluralize, toPascalCase } from "../common"
|
||||
import { composeLinkName } from "../link"
|
||||
|
||||
type InputSource = {
|
||||
serviceName: string
|
||||
field: string
|
||||
linkable: string
|
||||
primaryKey: string
|
||||
}
|
||||
|
||||
type InputToJson = {
|
||||
toJSON: () => InputSource
|
||||
}
|
||||
|
||||
type CombinedSource = Record<any, any> & InputToJson
|
||||
|
||||
type InputOptions = {
|
||||
source: CombinedSource | InputSource
|
||||
isList?: boolean
|
||||
}
|
||||
|
||||
type ExtraOptions = {
|
||||
pk?: {
|
||||
[key: string]: string
|
||||
}
|
||||
database?: {
|
||||
table: string
|
||||
idPrefix?: string
|
||||
extraColumns?: LinkModulesExtraFields
|
||||
}
|
||||
}
|
||||
|
||||
type DefineLinkInputSource = InputSource | InputOptions | CombinedSource
|
||||
|
||||
type ModuleLinkableKeyConfig = {
|
||||
module: string
|
||||
key: string
|
||||
isList?: boolean
|
||||
primaryKey: string
|
||||
alias: string
|
||||
shortcuts?: {
|
||||
[key: string]: string | { path: string; isList?: boolean }
|
||||
}
|
||||
}
|
||||
|
||||
function isInputOptions(input: any): input is InputOptions {
|
||||
return isObject(input) && "source" in input
|
||||
}
|
||||
|
||||
function isInputSource(input: any): input is InputSource {
|
||||
return (isObject(input) && "serviceName" in input) || "toJSON" in input
|
||||
}
|
||||
|
||||
function isToJSON(input: any): input is InputToJson {
|
||||
return isObject(input) && "toJSON" in input
|
||||
}
|
||||
|
||||
export function defineLink(
|
||||
leftService: DefineLinkInputSource,
|
||||
rightService: DefineLinkInputSource,
|
||||
linkServiceOptions?: ExtraOptions
|
||||
) {
|
||||
let serviceAObj = {} as ModuleLinkableKeyConfig
|
||||
let serviceBObj = {} as ModuleLinkableKeyConfig
|
||||
|
||||
if (isInputSource(leftService)) {
|
||||
const source = isToJSON(leftService) ? leftService.toJSON() : leftService
|
||||
|
||||
serviceAObj = {
|
||||
key: source.linkable,
|
||||
alias: source.field,
|
||||
primaryKey: source.primaryKey,
|
||||
isList: false,
|
||||
module: source.serviceName,
|
||||
}
|
||||
} else if (isInputOptions(leftService)) {
|
||||
const source = isToJSON(leftService.source)
|
||||
? leftService.source.toJSON()
|
||||
: leftService.source
|
||||
|
||||
serviceAObj = {
|
||||
key: source.linkable,
|
||||
alias: source.field,
|
||||
primaryKey: source.primaryKey,
|
||||
isList: leftService.isList ?? false,
|
||||
module: source.serviceName,
|
||||
}
|
||||
} else {
|
||||
throw new Error("Invalid linkable passed for the first argument")
|
||||
}
|
||||
|
||||
if (isInputSource(rightService)) {
|
||||
const source = isToJSON(rightService) ? rightService.toJSON() : rightService
|
||||
|
||||
serviceBObj = {
|
||||
key: source.linkable,
|
||||
alias: source.field,
|
||||
primaryKey: source.primaryKey,
|
||||
isList: false,
|
||||
module: source.serviceName,
|
||||
}
|
||||
} else if (isInputOptions(rightService)) {
|
||||
const source = isToJSON(rightService.source)
|
||||
? rightService.source.toJSON()
|
||||
: rightService.source
|
||||
|
||||
serviceBObj = {
|
||||
key: source.linkable,
|
||||
alias: source.field,
|
||||
primaryKey: source.primaryKey,
|
||||
isList: rightService.isList ?? false,
|
||||
module: source.serviceName,
|
||||
}
|
||||
} else {
|
||||
throw new Error(`Invalid linkable passed for the second argument`)
|
||||
}
|
||||
|
||||
const output = { serviceName: "" }
|
||||
|
||||
const register = function (
|
||||
modules: ModuleJoinerConfig[]
|
||||
): ModuleJoinerConfig {
|
||||
const serviceAInfo = modules
|
||||
.map((mod) => mod[serviceAObj.module])
|
||||
.filter(Boolean)[0]
|
||||
const serviceBInfo = modules
|
||||
.map((mod) => mod[serviceBObj.module])
|
||||
.filter(Boolean)[0]
|
||||
if (!serviceAInfo) {
|
||||
throw new Error(`Service ${serviceAObj.module} was not found`)
|
||||
}
|
||||
if (!serviceBInfo) {
|
||||
throw new Error(`Service ${serviceBObj.module} was not found`)
|
||||
}
|
||||
|
||||
const serviceAKeyInfo =
|
||||
serviceAInfo.__joinerConfig.linkableKeys?.[serviceAObj.key]
|
||||
const serviceBKeyInfo =
|
||||
serviceBInfo.__joinerConfig.linkableKeys?.[serviceBObj.key]
|
||||
if (!serviceAKeyInfo) {
|
||||
throw new Error(
|
||||
`Key ${serviceAObj.key} is not linkable on service ${serviceAObj.module}`
|
||||
)
|
||||
}
|
||||
if (!serviceBKeyInfo) {
|
||||
throw new Error(
|
||||
`Key ${serviceBObj.key} is not linkable on service ${serviceBObj.module}`
|
||||
)
|
||||
}
|
||||
|
||||
let serviceAAliases = serviceAInfo.__joinerConfig.alias ?? []
|
||||
if (!Array.isArray(serviceAAliases)) {
|
||||
serviceAAliases = [serviceAAliases]
|
||||
}
|
||||
|
||||
let aliasAOptions =
|
||||
serviceAObj.alias ??
|
||||
serviceAAliases.find((a) => {
|
||||
return a.args?.entity == serviceAKeyInfo
|
||||
})?.name
|
||||
|
||||
let aliasA = aliasAOptions
|
||||
if (Array.isArray(aliasAOptions)) {
|
||||
aliasA = aliasAOptions[0]
|
||||
}
|
||||
if (!aliasA) {
|
||||
throw new Error(
|
||||
`You need to provide an alias for ${serviceAObj.module}.${serviceAObj.key}`
|
||||
)
|
||||
}
|
||||
|
||||
let serviceBAliases = serviceBInfo.__joinerConfig.alias ?? []
|
||||
if (!Array.isArray(serviceBAliases)) {
|
||||
serviceBAliases = [serviceBAliases]
|
||||
}
|
||||
|
||||
let aliasBOptions =
|
||||
serviceBObj.alias ??
|
||||
serviceBAliases.find((a) => {
|
||||
return a.args?.entity == serviceBKeyInfo
|
||||
})?.name
|
||||
|
||||
let aliasB = aliasBOptions
|
||||
if (Array.isArray(aliasBOptions)) {
|
||||
aliasB = aliasBOptions[0]
|
||||
}
|
||||
if (!aliasB) {
|
||||
throw new Error(
|
||||
`You need to provide an alias for ${serviceBObj.module}.${serviceBObj.key}`
|
||||
)
|
||||
}
|
||||
|
||||
const moduleAPrimaryKeys = serviceAInfo.__joinerConfig.primaryKeys
|
||||
let serviceAPrimaryKey =
|
||||
serviceAObj.primaryKey ??
|
||||
linkServiceOptions?.pk?.[serviceAObj.module] ??
|
||||
moduleAPrimaryKeys
|
||||
if (Array.isArray(serviceAPrimaryKey)) {
|
||||
serviceAPrimaryKey = serviceAPrimaryKey[0]
|
||||
}
|
||||
|
||||
const isModuleAPrimaryKeyValid =
|
||||
moduleAPrimaryKeys.includes(serviceAPrimaryKey)
|
||||
if (!isModuleAPrimaryKeyValid) {
|
||||
throw new Error(
|
||||
`Primary key ${serviceAPrimaryKey} is not defined on service ${serviceAObj.module}`
|
||||
)
|
||||
}
|
||||
|
||||
const moduleBPrimaryKeys = serviceBInfo.__joinerConfig.primaryKeys
|
||||
let serviceBPrimaryKey =
|
||||
serviceBObj.primaryKey ??
|
||||
linkServiceOptions?.pk?.[serviceBObj.module] ??
|
||||
moduleBPrimaryKeys
|
||||
if (Array.isArray(serviceBPrimaryKey)) {
|
||||
serviceBPrimaryKey = serviceBPrimaryKey[0]
|
||||
}
|
||||
|
||||
const isModuleBPrimaryKeyValid =
|
||||
moduleBPrimaryKeys.includes(serviceBPrimaryKey)
|
||||
if (!isModuleBPrimaryKeyValid) {
|
||||
throw new Error(
|
||||
`Primary key ${serviceBPrimaryKey} is not defined on service ${serviceBObj.module}`
|
||||
)
|
||||
}
|
||||
|
||||
output.serviceName = composeLinkName(
|
||||
serviceAObj.module,
|
||||
aliasA,
|
||||
serviceBObj.module,
|
||||
aliasB
|
||||
)
|
||||
|
||||
const linkDefinition: ModuleJoinerConfig = {
|
||||
serviceName: output.serviceName,
|
||||
isLink: true,
|
||||
alias: [
|
||||
{
|
||||
name: [aliasA + "_" + aliasB],
|
||||
args: {
|
||||
entity: toPascalCase(
|
||||
[
|
||||
"Link",
|
||||
serviceAObj.module,
|
||||
aliasA,
|
||||
serviceBObj.module,
|
||||
aliasB,
|
||||
].join("_")
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
primaryKeys: ["id", serviceAObj.key, serviceBObj.key],
|
||||
relationships: [
|
||||
{
|
||||
serviceName: serviceAObj.module,
|
||||
primaryKey: serviceAPrimaryKey,
|
||||
foreignKey: serviceAObj.key,
|
||||
alias: aliasA,
|
||||
},
|
||||
{
|
||||
serviceName: serviceBObj.module,
|
||||
primaryKey: serviceBPrimaryKey!,
|
||||
foreignKey: serviceBObj.key,
|
||||
alias: aliasB,
|
||||
},
|
||||
],
|
||||
extends: [
|
||||
{
|
||||
serviceName: serviceAObj.module,
|
||||
fieldAlias: {
|
||||
[serviceBObj.isList ? pluralize(aliasB) : aliasB]:
|
||||
aliasB + "_link." + aliasB, //plural aliasA
|
||||
},
|
||||
relationship: {
|
||||
serviceName: output.serviceName,
|
||||
primaryKey: serviceBObj.key,
|
||||
foreignKey: serviceBPrimaryKey,
|
||||
alias: aliasB + "_link", // plural alias
|
||||
isList: serviceBObj.isList,
|
||||
},
|
||||
},
|
||||
{
|
||||
serviceName: serviceBObj.module,
|
||||
fieldAlias: {
|
||||
[serviceAObj.isList ? pluralize(aliasA) : aliasA]:
|
||||
aliasA + "_link." + aliasA,
|
||||
},
|
||||
relationship: {
|
||||
serviceName: output.serviceName,
|
||||
primaryKey: serviceAObj.key,
|
||||
foreignKey: serviceAPrimaryKey,
|
||||
alias: aliasA + "_link", // plural alias
|
||||
isList: serviceAObj.isList,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
if (linkServiceOptions?.database) {
|
||||
const { table, idPrefix, extraColumns } = linkServiceOptions.database
|
||||
linkDefinition.databaseConfig = {
|
||||
tableName: table,
|
||||
idPrefix,
|
||||
extraFields: extraColumns,
|
||||
}
|
||||
}
|
||||
|
||||
return linkDefinition
|
||||
}
|
||||
|
||||
global.MedusaModule.setCustomLink(register)
|
||||
|
||||
return output
|
||||
}
|
||||
@@ -14,3 +14,4 @@ export * from "./medusa-service"
|
||||
export * from "./migration-scripts"
|
||||
export * from "./mikro-orm-cli-config-builder"
|
||||
export * from "./module"
|
||||
export * from "./define-link"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
IDmlEntity,
|
||||
JoinerServiceConfigAlias,
|
||||
ModuleJoinerConfig,
|
||||
PropertyType,
|
||||
@@ -108,13 +109,14 @@ export function defineJoinerConfig(
|
||||
}
|
||||
|
||||
if (!primaryKeys && modelDefinitions.size) {
|
||||
const linkConfig = buildLinkConfigFromDmlObjects(serviceName, [
|
||||
...modelDefinitions.values(),
|
||||
])
|
||||
const linkConfig = buildLinkConfigFromDmlObjects(
|
||||
serviceName,
|
||||
Object.fromEntries(modelDefinitions)
|
||||
)
|
||||
|
||||
primaryKeys = deduplicate(
|
||||
Object.values(linkConfig).flatMap((entityLinkConfig) => {
|
||||
return (Object.values(entityLinkConfig) as any[])
|
||||
return (Object.values(entityLinkConfig as any) as any[])
|
||||
.filter((linkableConfig) => isObject(linkableConfig))
|
||||
.map((linkableConfig) => {
|
||||
return linkableConfig.primaryKey
|
||||
@@ -152,7 +154,7 @@ export function defineJoinerConfig(
|
||||
`${pluralize(camelToSnakeCase(entity.name).toLowerCase())}`,
|
||||
],
|
||||
args: {
|
||||
entity: entity.name,
|
||||
entity: upperCaseFirst(entity.name),
|
||||
methodSuffix: pluralize(upperCaseFirst(entity.name)),
|
||||
},
|
||||
})),
|
||||
@@ -175,6 +177,8 @@ export function defineJoinerConfig(
|
||||
* test: model.text(),
|
||||
* })
|
||||
*
|
||||
* const linkableKeys = buildLinkableKeysFromDmlObjects([user, car])
|
||||
*
|
||||
* // output:
|
||||
* // {
|
||||
* // user_id: 'User',
|
||||
@@ -213,7 +217,7 @@ export function buildLinkableKeysFromDmlObjects<
|
||||
|
||||
if (primaryKeys.length) {
|
||||
primaryKeys.forEach((primaryKey) => {
|
||||
linkableKeys[primaryKey] = model.name
|
||||
linkableKeys[primaryKey] = upperCaseFirst(model.name)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -250,7 +254,7 @@ export function buildLinkableKeysFromMikroOrmObjects(
|
||||
* test: model.text(),
|
||||
* })
|
||||
*
|
||||
* const links = buildLinkConfigFromDmlObjects('userService', [user, car])
|
||||
* const links = buildLinkConfigFromDmlObjects('userService', { user, car })
|
||||
*
|
||||
* // output:
|
||||
* // {
|
||||
@@ -279,19 +283,17 @@ export function buildLinkableKeysFromMikroOrmObjects(
|
||||
*/
|
||||
export function buildLinkConfigFromDmlObjects<
|
||||
const ServiceName extends string,
|
||||
const T extends DmlEntity<any, any>[]
|
||||
>(
|
||||
serviceName: ServiceName,
|
||||
models: T = [] as unknown as T
|
||||
): InfersLinksConfig<ServiceName, T> {
|
||||
const T extends Record<string, IDmlEntity<any, any>>
|
||||
>(serviceName: ServiceName, models: T): InfersLinksConfig<ServiceName, T> {
|
||||
const linkConfig = {} as InfersLinksConfig<ServiceName, T>
|
||||
|
||||
for (const model of models) {
|
||||
for (const model of Object.values(models) ?? []) {
|
||||
if (!DmlEntity.isDmlEntity(model)) {
|
||||
continue
|
||||
}
|
||||
|
||||
const schema = model.schema
|
||||
// @ts-ignore
|
||||
const modelLinkConfig = (linkConfig[lowerCaseFirst(model.name)] ??= {
|
||||
toJSON: function () {
|
||||
const linkables = Object.entries(this)
|
||||
@@ -322,7 +324,7 @@ export function buildLinkConfigFromDmlObjects<
|
||||
}
|
||||
}
|
||||
|
||||
return linkConfig as InfersLinksConfig<ServiceName, T> & Record<any, any>
|
||||
return linkConfig as InfersLinksConfig<ServiceName, T>
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -353,13 +353,12 @@ export function MedusaService<
|
||||
class AbstractModuleService_ {
|
||||
[MedusaServiceSymbol] = true
|
||||
|
||||
static [MedusaServiceModelObjectsSymbol] = Object.values(
|
||||
entities
|
||||
) as unknown as MedusaServiceReturnType<
|
||||
EntitiesConfig extends { __empty: any }
|
||||
? ModelConfigurationsToConfigTemplate<TEntities>
|
||||
: EntitiesConfig
|
||||
>["$modelObjects"];
|
||||
static [MedusaServiceModelObjectsSymbol] =
|
||||
entities as unknown as MedusaServiceReturnType<
|
||||
EntitiesConfig extends { __empty: any }
|
||||
? ModelConfigurationsToConfigTemplate<TEntities>
|
||||
: EntitiesConfig
|
||||
>["$modelObjects"];
|
||||
|
||||
[MedusaServiceEntityNameToLinkableKeysMapSymbol]: MapToConfig
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { Constructor, ModuleExports } from "@medusajs/types"
|
||||
import { Constructor, IDmlEntity, ModuleExports } from "@medusajs/types"
|
||||
import { MedusaServiceModelObjectsSymbol } from "./medusa-service"
|
||||
import {
|
||||
buildLinkConfigFromDmlObjects,
|
||||
defineJoinerConfig,
|
||||
} from "./joiner-config-builder"
|
||||
import { InfersLinksConfig } from "./types/links-config"
|
||||
import { DmlEntity } from "../dml"
|
||||
|
||||
/**
|
||||
* Wrapper to build the module export and auto generate the joiner config if needed as well as
|
||||
@@ -19,28 +18,32 @@ import { DmlEntity } from "../dml"
|
||||
export function Module<
|
||||
const ServiceName extends string,
|
||||
const Service extends Constructor<any>,
|
||||
const ModelObjects extends DmlEntity<any, any>[] = Service extends {
|
||||
$modelObjects: infer $DmlObjects
|
||||
ModelObjects extends Record<string, IDmlEntity<any, any>> = Service extends {
|
||||
$modelObjects: any
|
||||
}
|
||||
? $DmlObjects
|
||||
: [],
|
||||
Links = keyof ModelObjects extends never
|
||||
? Service["$modelObjects"]
|
||||
: {},
|
||||
Linkable = keyof ModelObjects extends never
|
||||
? Record<string, any>
|
||||
: InfersLinksConfig<ServiceName, ModelObjects>
|
||||
>(
|
||||
serviceName: ServiceName,
|
||||
{ service, loaders }: ModuleExports<Service>
|
||||
): ModuleExports<Service> & {
|
||||
links: Links
|
||||
linkable: Linkable
|
||||
} {
|
||||
service.prototype.__joinerConfig ??= defineJoinerConfig(serviceName)
|
||||
|
||||
const dmlObjects = service[MedusaServiceModelObjectsSymbol]
|
||||
const dmlObjects = service[MedusaServiceModelObjectsSymbol] ?? {}
|
||||
|
||||
return {
|
||||
service,
|
||||
loaders,
|
||||
links: (dmlObjects?.length
|
||||
? buildLinkConfigFromDmlObjects<ServiceName, ModelObjects>(dmlObjects)
|
||||
: {}) as Links,
|
||||
linkable: (Object.keys(dmlObjects)?.length
|
||||
? buildLinkConfigFromDmlObjects<ServiceName, ModelObjects>(
|
||||
serviceName,
|
||||
dmlObjects
|
||||
)
|
||||
: {}) as Linkable,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import {
|
||||
DMLSchema,
|
||||
IDmlEntity,
|
||||
IDmlEntityConfig,
|
||||
InferDmlEntityNameFromConfig,
|
||||
Prettify,
|
||||
SnakeCase,
|
||||
} from "@medusajs/types"
|
||||
import { DmlEntity } from "../../dml"
|
||||
import { PrimaryKeyModifier } from "../../dml/properties/primary-key"
|
||||
|
||||
/**
|
||||
@@ -54,22 +55,22 @@ type InferLinkableKeyName<
|
||||
string}`
|
||||
: never
|
||||
|
||||
type InferSchemaLinkableKeys<T> = T extends DmlEntity<
|
||||
type InferSchemaLinkableKeys<T> = T extends IDmlEntity<
|
||||
infer Schema,
|
||||
infer Config
|
||||
>
|
||||
? {
|
||||
[K in keyof Schema as Schema[K] extends PrimaryKeyModifier<any, any>
|
||||
? InferLinkableKeyName<K, Schema[K], Config>
|
||||
: never]: InferDmlEntityNameFromConfig<Config>
|
||||
: never]: Capitalize<InferDmlEntityNameFromConfig<Config>>
|
||||
}
|
||||
: {}
|
||||
|
||||
type InferSchemasLinkableKeys<T extends DmlEntity<any, any>[]> = {
|
||||
type InferSchemasLinkableKeys<T extends IDmlEntity<any, any>[]> = {
|
||||
[K in keyof T]: InferSchemaLinkableKeys<T[K]>
|
||||
}
|
||||
|
||||
type AggregateSchemasLinkableKeys<T extends DmlEntity<any, any>[]> = {
|
||||
type AggregateSchemasLinkableKeys<T extends IDmlEntity<any, any>[]> = {
|
||||
[K in keyof InferSchemasLinkableKeys<T>]: InferSchemasLinkableKeys<T>[K]
|
||||
}
|
||||
|
||||
@@ -92,7 +93,7 @@ type AggregateSchemasLinkableKeys<T extends DmlEntity<any, any>[]> = {
|
||||
* const linkableKeys = buildLinkableKeysFromDmlObjects([user, car]) // { user_id: 'user', car_number_plate: 'car' }
|
||||
*
|
||||
*/
|
||||
export type InferLinkableKeys<T extends DmlEntity<any, any>[]> =
|
||||
export type InferLinkableKeys<T extends IDmlEntity<any, any>[]> =
|
||||
UnionToIntersection<FlattenUnion<AggregateSchemasLinkableKeys<T>>[0]>
|
||||
|
||||
/**
|
||||
@@ -141,14 +142,12 @@ type InferPrimaryKeyNameOrNever<
|
||||
type InferSchemaLinksConfig<
|
||||
ServiceName extends string,
|
||||
T
|
||||
> = T extends DmlEntity<infer Schema, infer Config>
|
||||
> = T extends IDmlEntity<infer Schema, infer Config>
|
||||
? {
|
||||
[K in keyof Schema as Schema[K] extends PrimaryKeyModifier<any, any>
|
||||
? InferPrimaryKeyNameOrNever<Schema, K>
|
||||
: never]: {
|
||||
[K in keyof Schema as InferPrimaryKeyNameOrNever<Schema, K>]: {
|
||||
serviceName: ServiceName
|
||||
field: T extends DmlEntity<any, infer Config>
|
||||
? Uncapitalize<InferDmlEntityNameFromConfig<Config>>
|
||||
field: T extends IDmlEntity<any, infer Config>
|
||||
? InferDmlEntityNameFromConfig<Config>
|
||||
: string
|
||||
linkable: InferLinkableKeyName<K, Schema[K], Config>
|
||||
primaryKey: K
|
||||
@@ -200,20 +199,22 @@ type InferSchemaLinksConfig<
|
||||
*/
|
||||
export type InfersLinksConfig<
|
||||
ServiceName extends string,
|
||||
T extends DmlEntity<any, any>[]
|
||||
> = UnionToIntersection<{
|
||||
[K in keyof T as T[K] extends DmlEntity<any, infer Config>
|
||||
? Uncapitalize<InferDmlEntityNameFromConfig<Config>>
|
||||
: never]: InferSchemaLinksConfig<ServiceName, T[K]> & {
|
||||
toJSON: () => {
|
||||
serviceName: ServiceName
|
||||
field: T[K] extends DmlEntity<any, infer Config>
|
||||
? Uncapitalize<InferDmlEntityNameFromConfig<Config>>
|
||||
: string
|
||||
linkable: InferLastLinkable<ServiceName, T[K]>
|
||||
primaryKey: InferLastPrimaryKey<ServiceName, T[K]>
|
||||
T extends Record<string, IDmlEntity<any, any>>
|
||||
> = Prettify<{
|
||||
[K in keyof T as T[K] extends IDmlEntity<any, infer Config>
|
||||
? InferDmlEntityNameFromConfig<Config>
|
||||
: never]: Prettify<
|
||||
InferSchemaLinksConfig<ServiceName, T[K]> & {
|
||||
toJSON: () => {
|
||||
serviceName: ServiceName
|
||||
field: T[K] extends IDmlEntity<any, infer Config>
|
||||
? InferDmlEntityNameFromConfig<Config>
|
||||
: string
|
||||
linkable: InferLastLinkable<ServiceName, T[K]>
|
||||
primaryKey: InferLastPrimaryKey<ServiceName, T[K]>
|
||||
}
|
||||
}
|
||||
}
|
||||
>
|
||||
}>
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
Constructor,
|
||||
Context,
|
||||
FindConfig,
|
||||
IDmlEntity,
|
||||
Pluralize,
|
||||
RestoreReturn,
|
||||
SoftDeleteReturn,
|
||||
@@ -42,7 +43,7 @@ export type ModelConfigurationsToConfigTemplate<T extends TEntityEntries> = {
|
||||
dto: T[Key] extends Constructor<any> ? InstanceType<T[Key]> : any
|
||||
model: T[Key] extends { model: infer MODEL }
|
||||
? MODEL
|
||||
: T[Key] extends DmlEntity<any, any>
|
||||
: T[Key] extends IDmlEntity<any, any>
|
||||
? T[Key]
|
||||
: never
|
||||
/**
|
||||
@@ -242,20 +243,20 @@ export type AbstractModuleService<
|
||||
type InferModelFromConfig<T> = {
|
||||
[K in keyof T as T[K] extends { model: any }
|
||||
? K
|
||||
: K extends DmlEntity<any, any>
|
||||
: K extends IDmlEntity<any, any>
|
||||
? K
|
||||
: never]: T[K] extends {
|
||||
model: infer MODEL
|
||||
}
|
||||
? MODEL extends DmlEntity<any, any>
|
||||
? MODEL extends IDmlEntity<any, any>
|
||||
? MODEL
|
||||
: never
|
||||
: T[K] extends DmlEntity<any, any>
|
||||
: T[K] extends IDmlEntity<any, any>
|
||||
? T[K]
|
||||
: never
|
||||
}
|
||||
|
||||
export type MedusaServiceReturnType<ModelsConfig extends Record<any, any>> = {
|
||||
new (...args: any[]): AbstractModuleService<ModelsConfig>
|
||||
$modelObjects: InferModelFromConfig<ModelsConfig>[keyof InferModelFromConfig<ModelsConfig>][]
|
||||
$modelObjects: InferModelFromConfig<ModelsConfig>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user