feat: refactor module joiner config and links generation (#7859)
* feat: refactor module joiner config and links generation * improve typings * WIP * WIP * WIP * rename type file * create link config * finish typings and add utils * improve links * WIP typings * finalize ExportModule utils * finalize ExportModule utils * fix: dml tests * improve and fixes * simplify typings with id changes * add toJSON * multiple fixes and entity builder fixes * fix currency searchable * fix tests * medusa service refactoring * cleanup * cleanup and fixes * make module name optional * renaming --------- Co-authored-by: Harminder Virk <virk.officials@gmail.com>
This commit is contained in:
co-authored by
Harminder Virk
parent
5aa62e59e4
commit
617a5972bf
+1
@@ -1,5 +1,6 @@
|
||||
import { model } from "@medusajs/utils"
|
||||
|
||||
export const dmlEntity = model.define("dmlEntity", {
|
||||
id: model.id().primaryKey(),
|
||||
name: model.text(),
|
||||
})
|
||||
|
||||
+1
@@ -1,5 +1,6 @@
|
||||
import { model } from "@medusajs/utils"
|
||||
|
||||
export const entityModel = model.define("entityModel", {
|
||||
id: model.id().primaryKey(),
|
||||
name: model.text(),
|
||||
})
|
||||
|
||||
+1
@@ -1,5 +1,6 @@
|
||||
import { model } from "@medusajs/utils"
|
||||
|
||||
export const dmlEntity = model.define("dmlEntity", {
|
||||
id: model.id().primaryKey(),
|
||||
name: model.text(),
|
||||
})
|
||||
|
||||
@@ -11,11 +11,11 @@ import {
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
createMedusaContainer,
|
||||
createMikrORMEntity,
|
||||
defineJoinerConfig,
|
||||
DmlEntity,
|
||||
MedusaModuleType,
|
||||
ModulesSdkUtils,
|
||||
toMikroOrmEntities,
|
||||
} from "@medusajs/utils"
|
||||
import { asFunction, asValue } from "awilix"
|
||||
import { statSync } from "fs"
|
||||
@@ -270,12 +270,11 @@ export async function loadResources(
|
||||
),
|
||||
])
|
||||
|
||||
const entityBuilder = createMikrORMEntity()
|
||||
const cleanupResources = (resources) => {
|
||||
return Object.values(resources)
|
||||
.map((resource) => {
|
||||
if (DmlEntity.isDmlEntity(resource)) {
|
||||
return entityBuilder(resource as DmlEntity<any>)
|
||||
return resource
|
||||
}
|
||||
|
||||
if (typeof resource === "function") {
|
||||
@@ -289,11 +288,12 @@ export async function loadResources(
|
||||
|
||||
const potentialServices = [...new Set(cleanupResources(services))]
|
||||
const potentialModels = [...new Set(cleanupResources(models))]
|
||||
const mikroOrmModels = toMikroOrmEntities(potentialModels)
|
||||
const potentialRepositories = [...new Set(cleanupResources(repositories))]
|
||||
|
||||
const finalLoaders = prepareLoaders({
|
||||
loadedModuleLoaders,
|
||||
models: potentialModels,
|
||||
models: mikroOrmModels,
|
||||
repositories: potentialRepositories,
|
||||
services: potentialServices,
|
||||
moduleResolution,
|
||||
@@ -308,7 +308,7 @@ export async function loadResources(
|
||||
|
||||
return {
|
||||
services: potentialServices,
|
||||
models: potentialModels,
|
||||
models: mikroOrmModels,
|
||||
repositories: potentialRepositories,
|
||||
loaders: finalLoaders,
|
||||
moduleService,
|
||||
@@ -433,15 +433,20 @@ function generateJoinerConfigIfNecessary({
|
||||
}: {
|
||||
moduleResolution: ModuleResolution
|
||||
service: Constructor<IModuleService>
|
||||
models: Function[]
|
||||
models: (Function | DmlEntity<any, any>)[]
|
||||
}) {
|
||||
if (service.prototype.__joinerConfig) {
|
||||
return
|
||||
}
|
||||
const originalJoinerConfigFn = service.prototype.__joinerConfig
|
||||
|
||||
service.prototype.__joinerConfig = function () {
|
||||
if (originalJoinerConfigFn) {
|
||||
return {
|
||||
serviceName: moduleResolution.definition.key,
|
||||
...originalJoinerConfigFn(),
|
||||
}
|
||||
}
|
||||
|
||||
return defineJoinerConfig(moduleResolution.definition.key, {
|
||||
entityQueryingConfig: models,
|
||||
models,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
type IsStringLiteral<Type> = Type extends string
|
||||
? string extends Type
|
||||
? false
|
||||
: true
|
||||
: false
|
||||
|
||||
type WordInCamelCase<
|
||||
Type,
|
||||
Word extends string = ""
|
||||
> = Type extends `${Word}${infer NextCharacter}${infer _}`
|
||||
? NextCharacter extends Capitalize<NextCharacter>
|
||||
? Word
|
||||
: WordInCamelCase<Type, `${Word}${NextCharacter}`>
|
||||
: Word
|
||||
|
||||
type Separator = "_" | "-"
|
||||
|
||||
type IncludesSeparator<Type> = Type extends `${string}${Separator}${string}`
|
||||
? true
|
||||
: false
|
||||
|
||||
type IsOneWord<Type> = Type extends Lowercase<Type & string>
|
||||
? true
|
||||
: Type extends Uppercase<Type & string>
|
||||
? true
|
||||
: false
|
||||
|
||||
type IsCamelCase<Type> = Type extends Uncapitalize<Type & string> ? true : false
|
||||
|
||||
type IsPascalCase<Type> = Type extends Capitalize<Type & string> ? true : false
|
||||
|
||||
/** snake_case, CONSTANT_CASE, kebab-case or COBOL-CASE */
|
||||
type SeparatorCaseParser<
|
||||
Type,
|
||||
Tuple extends readonly any[] = []
|
||||
> = Type extends `${infer Word}${Separator}${infer Tail}`
|
||||
? SeparatorCaseParser<Tail, [...Tuple, Lowercase<Word>]>
|
||||
: Type extends `${infer Word}`
|
||||
? [...Tuple, Lowercase<Word>]
|
||||
: Tuple
|
||||
|
||||
type CamelCaseParser<Type, Tuple extends readonly any[] = []> = Type extends ""
|
||||
? Tuple
|
||||
: Type extends `${WordInCamelCase<Type>}${infer Tail}`
|
||||
? Type extends `${infer Word}${Tail}`
|
||||
? CamelCaseParser<Uncapitalize<Tail>, [...Tuple, Lowercase<Word>]>
|
||||
: never
|
||||
: never
|
||||
|
||||
// Convert first character of string literal type to lowercase and reuse CamelCaseParser
|
||||
type PascalCaseParser<Type> = Type extends string
|
||||
? CamelCaseParser<Uncapitalize<Type>>
|
||||
: never
|
||||
|
||||
type SplitAnyCase<Type> = IncludesSeparator<Type> extends true
|
||||
? SeparatorCaseParser<Type>
|
||||
: IsOneWord<Type> extends true
|
||||
? [Lowercase<Type & string>]
|
||||
: IsCamelCase<Type> extends true
|
||||
? CamelCaseParser<Type>
|
||||
: IsPascalCase<Type> extends true
|
||||
? PascalCaseParser<Type>
|
||||
: []
|
||||
|
||||
type PascalCapitalizer<Type, Tuple extends readonly any[] = []> = Type extends [
|
||||
infer Head,
|
||||
...infer Tail
|
||||
]
|
||||
? Head extends string
|
||||
? PascalCapitalizer<Tail, [...Tuple, Capitalize<Head>]>
|
||||
: PascalCapitalizer<Tail, Tuple>
|
||||
: Tuple
|
||||
|
||||
type CamelCapitalizer<Type> = Type extends [infer First, ...infer Tail]
|
||||
? PascalCapitalizer<Tail, [First]>
|
||||
: []
|
||||
|
||||
type Join<Type, JoinedString extends string = ""> = Type extends [
|
||||
infer Head,
|
||||
...infer Tail
|
||||
]
|
||||
? Head extends string
|
||||
? Join<Tail, `${JoinedString}${Head}`>
|
||||
: Join<Tail>
|
||||
: JoinedString
|
||||
|
||||
export type CamelCase<Type> = IsStringLiteral<Type> extends true
|
||||
? Join<CamelCapitalizer<SplitAnyCase<Type>>>
|
||||
: Type
|
||||
@@ -5,3 +5,4 @@ export * from "./config-module"
|
||||
export * from "./medusa-cli"
|
||||
export * from "./medusa-container"
|
||||
export * from "./with-calculated"
|
||||
export * from "./camel-case"
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { CamelCase } from "../common"
|
||||
|
||||
/**
|
||||
* Symbol to identify a DML entity from an object
|
||||
*/
|
||||
@@ -13,11 +15,26 @@ export type DMLSchema = Record<
|
||||
PropertyType<any> | RelationshipType<any>
|
||||
>
|
||||
|
||||
export type IDmlEntityConfig = string | { name?: string; tableName: string }
|
||||
|
||||
export type InferDmlEntityNameFromConfig<TConfig extends IDmlEntityConfig> =
|
||||
TConfig extends string
|
||||
? Capitalize<CamelCase<TConfig>>
|
||||
: TConfig extends { name: string }
|
||||
? Capitalize<CamelCase<TConfig["name"] & string>>
|
||||
: TConfig extends { tableName: string }
|
||||
? Capitalize<CamelCase<TConfig["tableName"] & string>>
|
||||
: never
|
||||
|
||||
/**
|
||||
* Representation of a DML entity
|
||||
*/
|
||||
export interface IDmlEntity<Schema extends DMLSchema> {
|
||||
export interface IDmlEntity<
|
||||
Schema extends DMLSchema,
|
||||
Config extends IDmlEntityConfig
|
||||
> {
|
||||
[IsDmlEntity]: true
|
||||
name: InferDmlEntityNameFromConfig<Config>
|
||||
schema: Schema
|
||||
}
|
||||
|
||||
@@ -60,6 +77,7 @@ export type PropertyMetadata = {
|
||||
type: "index" | "unique"
|
||||
}[]
|
||||
relationships: RelationshipMetadata[]
|
||||
primaryKey?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,22 +143,23 @@ export type InferForeignKeys<Schema extends DMLSchema> = {
|
||||
[K in keyof Schema as Schema[K] extends { type: infer Type }
|
||||
? Type extends RelationshipTypes
|
||||
? `${K & string}_id`
|
||||
: K
|
||||
: K]: Schema[K] extends { type: infer Type }
|
||||
: never
|
||||
: never]: Schema[K] extends { type: infer Type }
|
||||
? Type extends RelationshipTypes
|
||||
? string
|
||||
: Schema[K]
|
||||
: Schema[K]
|
||||
: never
|
||||
: never
|
||||
}
|
||||
|
||||
/**
|
||||
* Infer fields for a belongsTo relationship
|
||||
*/
|
||||
export type InferBelongsToFields<Relation> = Relation extends () => IDmlEntity<
|
||||
infer R
|
||||
infer R,
|
||||
any
|
||||
>
|
||||
? InferSchemaFields<R>
|
||||
: Relation extends () => IDmlEntity<infer R> | null
|
||||
: Relation extends () => IDmlEntity<infer R, any> | null
|
||||
? InferSchemaFields<R> | null
|
||||
: never
|
||||
|
||||
@@ -153,7 +172,8 @@ export type InferHasOneFields<Relation> = InferBelongsToFields<Relation>
|
||||
* Infer fields for hasMany relationship
|
||||
*/
|
||||
export type InferHasManyFields<Relation> = Relation extends () => IDmlEntity<
|
||||
infer R
|
||||
infer R,
|
||||
any
|
||||
>
|
||||
? InferSchemaFields<R>[]
|
||||
: never
|
||||
@@ -184,7 +204,7 @@ export type InferSchemaFields<Schema extends DMLSchema> = {
|
||||
/**
|
||||
* Helper to infer the schema type of a DmlEntity
|
||||
*/
|
||||
export type Infer<T> = T extends IDmlEntity<infer Schema>
|
||||
export type Infer<T> = T extends IDmlEntity<infer Schema, any>
|
||||
? EntityConstructor<InferSchemaFields<Schema>>
|
||||
: never
|
||||
|
||||
@@ -217,12 +237,12 @@ export type EntityCascades<Relationships> = {
|
||||
/**
|
||||
* Helper to infer the instance type of a IDmlEntity once converted as an Entity
|
||||
*/
|
||||
export type InferTypeOf<T extends IDmlEntity<any>> = InstanceType<Infer<T>>
|
||||
export type InferTypeOf<T extends IDmlEntity<any, any>> = InstanceType<Infer<T>>
|
||||
|
||||
/**
|
||||
* Used in the module sdk internal service to infer propert entity typings from DML
|
||||
*/
|
||||
export type InferEntityType<T extends any> = T extends IDmlEntity<any>
|
||||
export type InferEntityType<T> = T extends IDmlEntity<any, any>
|
||||
? InferTypeOf<T>
|
||||
: T
|
||||
|
||||
@@ -230,7 +250,8 @@ export type InferEntityType<T extends any> = T extends IDmlEntity<any>
|
||||
* Infer all indexable properties from a DML entity including inferred foreign keys and excluding relationship
|
||||
*/
|
||||
export type InferIndexableProperties<T> = keyof (T extends IDmlEntity<
|
||||
infer Schema
|
||||
infer Schema,
|
||||
any
|
||||
>
|
||||
? {
|
||||
[K in keyof Schema as Schema[K] extends { type: infer Type }
|
||||
@@ -258,7 +279,7 @@ export type EntityIndex<
|
||||
/**
|
||||
* The list of properties to create the index on.
|
||||
*/
|
||||
on: InferIndexableProperties<IDmlEntity<TSchema>>[]
|
||||
on: InferIndexableProperties<IDmlEntity<TSchema, any>>[]
|
||||
/**
|
||||
* Conditions to restrict which records are indexed.
|
||||
*/
|
||||
@@ -270,7 +291,7 @@ export type NeQueryValue = { $ne: SimpleQueryValue }
|
||||
export type QueryValue = SimpleQueryValue | NeQueryValue
|
||||
|
||||
export type QueryCondition<T extends DMLSchema = DMLSchema> = {
|
||||
[K in keyof IDmlEntity<T>["schema"]]?: T[K] extends object
|
||||
[K in keyof IDmlEntity<T, any>["schema"]]?: T[K] extends object
|
||||
? QueryValue
|
||||
: QueryCondition<T>
|
||||
}
|
||||
|
||||
@@ -224,8 +224,8 @@ export declare type ModuleJoinerRelationship = JoinerRelationship & {
|
||||
deleteCascade?: boolean
|
||||
}
|
||||
|
||||
export type ModuleExports = {
|
||||
service: Constructor<any>
|
||||
export type ModuleExports<T = Constructor<any>> = {
|
||||
service: T
|
||||
loaders?: ModuleLoaderFunction[]
|
||||
runMigrations?(
|
||||
options: LoaderOptions<any>,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export function toCamelCase(str: string): string {
|
||||
return /^([a-z]+)(([A-Z]([a-z]+))+)$/.test(str)
|
||||
return /^([a-zA-Z]+)(([A-Z]([a-z]+))+)$/.test(str)
|
||||
? str
|
||||
: str
|
||||
.toLowerCase()
|
||||
|
||||
@@ -34,7 +34,6 @@ describe("Base property", () => {
|
||||
dataType: {
|
||||
name: "text",
|
||||
options: {
|
||||
primaryKey: false,
|
||||
searchable: true,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ArrayType, MetadataStorage } from "@mikro-orm/core"
|
||||
import { ArrayType, EntityMetadata, MetadataStorage } from "@mikro-orm/core"
|
||||
import { expectTypeOf } from "expect-type"
|
||||
import { DmlEntity } from "../entity"
|
||||
import { model } from "../entity-builder"
|
||||
@@ -72,7 +72,7 @@ describe("Entity builder", () => {
|
||||
phones: model.array(),
|
||||
})
|
||||
|
||||
expect(user.name).toEqual("user")
|
||||
expect(user.name).toEqual("User")
|
||||
expect(user.parse().tableName).toEqual("user")
|
||||
|
||||
const User = toMikroORMEntity(user)
|
||||
@@ -202,7 +202,7 @@ describe("Entity builder", () => {
|
||||
}
|
||||
)
|
||||
|
||||
expect(user.name).toEqual("user")
|
||||
expect(user.name).toEqual("User")
|
||||
expect(user.parse().tableName).toEqual("user_table")
|
||||
|
||||
const User = toMikroORMEntity(user)
|
||||
@@ -324,7 +324,7 @@ describe("Entity builder", () => {
|
||||
}
|
||||
)
|
||||
|
||||
expect(user.name).toEqual("userRole")
|
||||
expect(user.name).toEqual("UserRole")
|
||||
expect(user.parse().tableName).toEqual("user_role")
|
||||
|
||||
const User = toMikroORMEntity(user)
|
||||
@@ -1558,9 +1558,10 @@ describe("Entity builder", () => {
|
||||
account_id: model.number(),
|
||||
})
|
||||
|
||||
const entityBuilder = createMikrORMEntity()
|
||||
const User = entityBuilder(user)
|
||||
const metaData = MetadataStorage.getMetadataFromDecorator(User)
|
||||
const User = toMikroORMEntity(user)
|
||||
const metaData = MetadataStorage.getMetadataFromDecorator(
|
||||
User
|
||||
) as unknown as EntityMetadata<InstanceType<typeof User>>
|
||||
|
||||
expect(metaData.properties.id).toEqual({
|
||||
columnType: "text",
|
||||
@@ -3848,7 +3849,7 @@ describe("Entity builder", () => {
|
||||
})
|
||||
|
||||
expect(defineEmail).toThrow(
|
||||
'Cannot cascade delete "user" relationship(s) from "email" entity. Child to parent cascades are not allowed'
|
||||
'Cannot cascade delete "user" relationship(s) from "Email" entity. Child to parent cascades are not allowed'
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -10,9 +10,7 @@ describe("Id property", () => {
|
||||
fieldName: "id",
|
||||
dataType: {
|
||||
name: "id",
|
||||
options: {
|
||||
primaryKey: false,
|
||||
},
|
||||
options: {},
|
||||
},
|
||||
nullable: false,
|
||||
indexes: [],
|
||||
@@ -28,13 +26,12 @@ describe("Id property", () => {
|
||||
fieldName: "id",
|
||||
dataType: {
|
||||
name: "id",
|
||||
options: {
|
||||
primaryKey: true,
|
||||
},
|
||||
options: {},
|
||||
},
|
||||
nullable: false,
|
||||
indexes: [],
|
||||
relationships: [],
|
||||
primaryKey: true,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -10,9 +10,7 @@ describe("Number property", () => {
|
||||
fieldName: "age",
|
||||
dataType: {
|
||||
name: "number",
|
||||
options: {
|
||||
primaryKey: false,
|
||||
},
|
||||
options: {},
|
||||
},
|
||||
nullable: false,
|
||||
indexes: [],
|
||||
|
||||
@@ -10,7 +10,7 @@ describe("Text property", () => {
|
||||
fieldName: "username",
|
||||
dataType: {
|
||||
name: "text",
|
||||
options: { primaryKey: false, searchable: false },
|
||||
options: { searchable: false },
|
||||
},
|
||||
nullable: false,
|
||||
indexes: [],
|
||||
@@ -26,11 +26,12 @@ describe("Text property", () => {
|
||||
fieldName: "username",
|
||||
dataType: {
|
||||
name: "text",
|
||||
options: { primaryKey: true, searchable: false },
|
||||
options: { searchable: false },
|
||||
},
|
||||
nullable: false,
|
||||
indexes: [],
|
||||
relationships: [],
|
||||
primaryKey: true,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
import type { DMLSchema, RelationshipOptions } from "@medusajs/types"
|
||||
import {
|
||||
DMLSchema,
|
||||
IDmlEntityConfig,
|
||||
RelationshipOptions,
|
||||
} from "@medusajs/types"
|
||||
import { DmlEntity } from "./entity"
|
||||
import { createBigNumberProperties } from "./helpers/entity-builder/create-big-number-properties"
|
||||
import { createDefaultProperties } from "./helpers/entity-builder/create-default-properties"
|
||||
import {
|
||||
createBigNumberProperties,
|
||||
DMLSchemaWithBigNumber,
|
||||
} from "./helpers/entity-builder/create-big-number-properties"
|
||||
import {
|
||||
createDefaultProperties,
|
||||
DMLSchemaDefaults,
|
||||
} from "./helpers/entity-builder/create-default-properties"
|
||||
import { ArrayProperty } from "./properties/array"
|
||||
import { BigNumberProperty } from "./properties/big-number"
|
||||
import { BooleanProperty } from "./properties/boolean"
|
||||
@@ -57,7 +67,7 @@ export type ManyToManyOptions = RelationshipOptions &
|
||||
* representing the pivot table created in the
|
||||
* database for this relationship.
|
||||
*/
|
||||
pivotEntity?: () => DmlEntity<any>
|
||||
pivotEntity?: () => DmlEntity<any, any>
|
||||
}
|
||||
)
|
||||
|
||||
@@ -99,17 +109,23 @@ export class EntityBuilder {
|
||||
*
|
||||
* export default MyCustom
|
||||
*/
|
||||
define<Schema extends DMLSchema>(
|
||||
nameOrConfig: DefineOptions,
|
||||
define<Schema extends DMLSchema, TConfig extends IDmlEntityConfig>(
|
||||
nameOrConfig: TConfig,
|
||||
schema: Schema
|
||||
) {
|
||||
): DmlEntity<
|
||||
Schema & DMLSchemaWithBigNumber<Schema> & DMLSchemaDefaults,
|
||||
TConfig
|
||||
> {
|
||||
this.#disallowImplicitProperties(schema)
|
||||
|
||||
return new DmlEntity(nameOrConfig, {
|
||||
return new DmlEntity<Schema, TConfig>(nameOrConfig, {
|
||||
...schema,
|
||||
...createBigNumberProperties(schema),
|
||||
...createDefaultProperties(),
|
||||
})
|
||||
}) as unknown as DmlEntity<
|
||||
Schema & DMLSchemaWithBigNumber<Schema> & DMLSchemaDefaults,
|
||||
TConfig
|
||||
>
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,25 +4,32 @@ import {
|
||||
EntityIndex,
|
||||
ExtractEntityRelations,
|
||||
IDmlEntity,
|
||||
IDmlEntityConfig,
|
||||
InferDmlEntityNameFromConfig,
|
||||
IsDmlEntity,
|
||||
QueryCondition,
|
||||
} from "@medusajs/types"
|
||||
import { isObject, isString, toCamelCase } from "../common"
|
||||
import { isObject, isString, toCamelCase, upperCaseFirst } from "../common"
|
||||
import { transformIndexWhere } from "./helpers/entity-builder/build-indexes"
|
||||
import { BelongsTo } from "./relations/belongs-to"
|
||||
|
||||
type Config = string | { name?: string; tableName: string }
|
||||
|
||||
function extractNameAndTableName(nameOrConfig: Config) {
|
||||
function extractNameAndTableName<Config extends IDmlEntityConfig>(
|
||||
nameOrConfig: Config
|
||||
) {
|
||||
const result = {
|
||||
name: "",
|
||||
tableName: "",
|
||||
} as {
|
||||
name: InferDmlEntityNameFromConfig<Config>
|
||||
tableName: string
|
||||
}
|
||||
|
||||
if (isString(nameOrConfig)) {
|
||||
const [schema, ...rest] = nameOrConfig.split(".")
|
||||
const name = rest.length ? rest.join(".") : schema
|
||||
result.name = toCamelCase(name)
|
||||
result.name = upperCaseFirst(
|
||||
toCamelCase(name)
|
||||
) as InferDmlEntityNameFromConfig<Config>
|
||||
result.tableName = nameOrConfig
|
||||
}
|
||||
|
||||
@@ -37,7 +44,9 @@ function extractNameAndTableName(nameOrConfig: Config) {
|
||||
const [schema, ...rest] = potentialName.split(".")
|
||||
const name = rest.length ? rest.join(".") : schema
|
||||
|
||||
result.name = toCamelCase(name)
|
||||
result.name = upperCaseFirst(
|
||||
toCamelCase(name)
|
||||
) as InferDmlEntityNameFromConfig<Config>
|
||||
result.tableName = nameOrConfig.tableName
|
||||
}
|
||||
|
||||
@@ -48,17 +57,23 @@ function extractNameAndTableName(nameOrConfig: Config) {
|
||||
* Dml entity is a representation of a DML model with a unique
|
||||
* name, its schema and relationships.
|
||||
*/
|
||||
export class DmlEntity<Schema extends DMLSchema> implements IDmlEntity<Schema> {
|
||||
export class DmlEntity<
|
||||
Schema extends DMLSchema,
|
||||
TConfig extends IDmlEntityConfig
|
||||
> implements IDmlEntity<Schema, TConfig>
|
||||
{
|
||||
[IsDmlEntity]: true = true
|
||||
|
||||
name: string
|
||||
name: InferDmlEntityNameFromConfig<TConfig>
|
||||
schema: Schema
|
||||
|
||||
readonly #tableName: string
|
||||
#cascades: EntityCascades<string[]> = {}
|
||||
#indexes: EntityIndex<Schema>[] = []
|
||||
|
||||
constructor(nameOrConfig: Config, public schema: Schema) {
|
||||
constructor(nameOrConfig: TConfig, schema: Schema) {
|
||||
const { name, tableName } = extractNameAndTableName(nameOrConfig)
|
||||
this.schema = schema
|
||||
this.name = name
|
||||
this.#tableName = tableName
|
||||
}
|
||||
@@ -70,7 +85,7 @@ export class DmlEntity<Schema extends DMLSchema> implements IDmlEntity<Schema> {
|
||||
*
|
||||
* @param entity
|
||||
*/
|
||||
static isDmlEntity(entity: unknown): entity is DmlEntity<any> {
|
||||
static isDmlEntity(entity: unknown): entity is DmlEntity<any, any> {
|
||||
return !!entity?.[IsDmlEntity]
|
||||
}
|
||||
|
||||
@@ -78,7 +93,7 @@ export class DmlEntity<Schema extends DMLSchema> implements IDmlEntity<Schema> {
|
||||
* Parse entity to get its underlying information
|
||||
*/
|
||||
parse(): {
|
||||
name: string
|
||||
name: InferDmlEntityNameFromConfig<TConfig>
|
||||
tableName: string
|
||||
schema: DMLSchema
|
||||
cascades: EntityCascades<string[]>
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import type { EntityConstructor, Infer } from "@medusajs/types"
|
||||
import type {
|
||||
DMLSchema,
|
||||
EntityConstructor,
|
||||
IDmlEntity,
|
||||
Infer,
|
||||
PropertyType,
|
||||
} from "@medusajs/types"
|
||||
import { Entity, Filter } from "@mikro-orm/core"
|
||||
import { mikroOrmSoftDeletableFilterOptions } from "../../dal"
|
||||
import { DmlEntity } from "../entity"
|
||||
@@ -34,7 +40,9 @@ export function createMikrORMEntity() {
|
||||
* A helper function to define a Mikro ORM entity from a
|
||||
* DML entity.
|
||||
*/
|
||||
return function createEntity<T extends DmlEntity<any>>(entity: T): Infer<T> {
|
||||
return function createEntity<T extends DmlEntity<any, any>>(
|
||||
entity: T
|
||||
): Infer<T> {
|
||||
class MikroORMEntity {}
|
||||
|
||||
const { schema, cascades, indexes: entityIndexes = [] } = entity.parse()
|
||||
@@ -57,11 +65,11 @@ export function createMikrORMEntity() {
|
||||
/**
|
||||
* Processing schema fields
|
||||
*/
|
||||
Object.entries(schema).forEach(([name, property]) => {
|
||||
Object.entries(schema as DMLSchema).forEach(([name, property]) => {
|
||||
const field = property.parse(name)
|
||||
|
||||
if ("fieldName" in field) {
|
||||
defineProperty(MikroORMEntity, field)
|
||||
defineProperty(MikroORMEntity, name, property as PropertyType<any>)
|
||||
applyIndexes(MikroORMEntity, tableName, field)
|
||||
applySearchable(MikroORMEntity, field)
|
||||
} else {
|
||||
@@ -85,14 +93,16 @@ export function createMikrORMEntity() {
|
||||
* return the input idempotently
|
||||
* @param entity
|
||||
*/
|
||||
export const toMikroORMEntity = <T>(entity: T): Infer<T> => {
|
||||
export const toMikroORMEntity = <T>(
|
||||
entity: T
|
||||
): T extends IDmlEntity<any, any> ? Infer<T> : T => {
|
||||
let mikroOrmEntity: T | EntityConstructor<any> = entity
|
||||
|
||||
if (DmlEntity.isDmlEntity(entity)) {
|
||||
mikroOrmEntity = createMikrORMEntity()(entity)
|
||||
}
|
||||
|
||||
return mikroOrmEntity as Infer<T>
|
||||
return mikroOrmEntity as T extends IDmlEntity<any, any> ? Infer<T> : T
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,6 +120,6 @@ export const toMikroOrmEntities = function <T extends any[]>(entities: T) {
|
||||
|
||||
return entity
|
||||
}) as {
|
||||
[K in keyof T]: T[K] extends DmlEntity<any> ? Infer<T[K]> : T[K]
|
||||
[K in keyof T]: T[K] extends IDmlEntity<any, any> ? Infer<T[K]> : T[K]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import { NullableModifier } from "../../properties/nullable"
|
||||
* test.amount // valid | type = number
|
||||
* test.raw_amount // valid | type = Record<string, any>
|
||||
*/
|
||||
type DMLSchemaWithBigNumber<T extends DMLSchema> = {
|
||||
export type DMLSchemaWithBigNumber<T extends DMLSchema> = {
|
||||
[K in keyof T]: T[K]
|
||||
} & {
|
||||
[K in keyof T as T[K] extends
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
EntityConstructor,
|
||||
KnownDataTypes,
|
||||
PropertyMetadata,
|
||||
PropertyType,
|
||||
} from "@medusajs/types"
|
||||
import { MikroOrmBigNumberProperty } from "../../../dal"
|
||||
import { generateEntityId, isDefined } from "../../../common"
|
||||
@@ -14,6 +15,7 @@ import {
|
||||
Property,
|
||||
Utils,
|
||||
} from "@mikro-orm/core"
|
||||
import { PrimaryKeyModifier } from "../../properties/primary-key"
|
||||
|
||||
/**
|
||||
* DML entity data types to PostgreSQL data types via
|
||||
@@ -91,8 +93,10 @@ const SPECIAL_PROPERTIES: {
|
||||
*/
|
||||
export function defineProperty(
|
||||
MikroORMEntity: EntityConstructor<any>,
|
||||
field: PropertyMetadata
|
||||
propertyName: string,
|
||||
property: PropertyType<any>
|
||||
) {
|
||||
const field = property.parse(propertyName)
|
||||
/**
|
||||
* Here we initialize nullable properties with a null value
|
||||
*/
|
||||
@@ -169,7 +173,7 @@ export function defineProperty(
|
||||
* Defining an id property
|
||||
*/
|
||||
if (field.dataType.name === "id") {
|
||||
const IdDecorator = field.dataType.options?.primaryKey
|
||||
const IdDecorator = PrimaryKeyModifier.isPrimaryKeyModifier(property)
|
||||
? PrimaryKey({
|
||||
columnType: "text",
|
||||
type: "string",
|
||||
@@ -211,7 +215,7 @@ export function defineProperty(
|
||||
/**
|
||||
* Defining a primary key property
|
||||
*/
|
||||
if (field.dataType.options?.primaryKey) {
|
||||
if (PrimaryKeyModifier.isPrimaryKeyModifier(property)) {
|
||||
PrimaryKey({
|
||||
columnType,
|
||||
type: propertyType,
|
||||
|
||||
@@ -9,9 +9,9 @@ import {
|
||||
BeforeCreate,
|
||||
ManyToMany,
|
||||
ManyToOne,
|
||||
OnInit,
|
||||
OneToMany,
|
||||
OneToOne,
|
||||
OnInit,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import { camelToSnakeCase, pluralize } from "../../../common"
|
||||
@@ -81,7 +81,8 @@ export function defineBelongsToRelationship(
|
||||
MikroORMEntity: EntityConstructor<any>,
|
||||
relationship: RelationshipMetadata,
|
||||
relatedEntity: DmlEntity<
|
||||
Record<string, PropertyType<any> | RelationshipType<any>>
|
||||
Record<string, PropertyType<any> | RelationshipType<any>>,
|
||||
any
|
||||
>,
|
||||
{ relatedModelName }: { relatedModelName: string }
|
||||
) {
|
||||
@@ -213,7 +214,8 @@ export function defineManyToManyRelationship(
|
||||
MikroORMEntity: EntityConstructor<any>,
|
||||
relationship: RelationshipMetadata,
|
||||
relatedEntity: DmlEntity<
|
||||
Record<string, PropertyType<any> | RelationshipType<any>>
|
||||
Record<string, PropertyType<any> | RelationshipType<any>>,
|
||||
any
|
||||
>,
|
||||
{
|
||||
relatedModelName,
|
||||
|
||||
@@ -5,7 +5,7 @@ import { camelToSnakeCase, toCamelCase, upperCaseFirst } from "../../../common"
|
||||
* Parses entity name and returns model and table name from
|
||||
* it
|
||||
*/
|
||||
export function parseEntityName(entity: DmlEntity<any>) {
|
||||
export function parseEntityName(entity: DmlEntity<any, any>) {
|
||||
const parsedEntity = entity.parse()
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,19 +1,27 @@
|
||||
import { BaseProperty } from "./base"
|
||||
import { PrimaryKeyModifier } from "./primary-key"
|
||||
|
||||
const IsIdProperty = Symbol("IsIdProperty")
|
||||
|
||||
/**
|
||||
* The Id property defines a unique identifier for the schema.
|
||||
* Most of the times it will be the primary as well.
|
||||
*/
|
||||
export class IdProperty extends BaseProperty<string> {
|
||||
[IsIdProperty] = true
|
||||
|
||||
static isIdProperty(value: any): value is IdProperty {
|
||||
return !!value?.[IsIdProperty]
|
||||
}
|
||||
|
||||
protected dataType: {
|
||||
name: "id"
|
||||
options: {
|
||||
primaryKey: boolean
|
||||
prefix?: string
|
||||
}
|
||||
} = {
|
||||
name: "id",
|
||||
options: { primaryKey: false },
|
||||
options: {},
|
||||
}
|
||||
|
||||
constructor(options?: { prefix?: string }) {
|
||||
@@ -37,7 +45,6 @@ export class IdProperty extends BaseProperty<string> {
|
||||
* @customNamespace Property Configuration Methods
|
||||
*/
|
||||
primaryKey() {
|
||||
this.dataType.options.primaryKey = true
|
||||
return this
|
||||
return new PrimaryKeyModifier<string, IdProperty>(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { BaseProperty } from "./base"
|
||||
import { PrimaryKeyModifier } from "./primary-key"
|
||||
|
||||
/**
|
||||
* The NumberProperty is used to define a numeric/integer
|
||||
@@ -7,15 +8,11 @@ import { BaseProperty } from "./base"
|
||||
export class NumberProperty extends BaseProperty<number> {
|
||||
protected dataType: {
|
||||
name: "number"
|
||||
options: {
|
||||
primaryKey: boolean
|
||||
}
|
||||
options: {}
|
||||
}
|
||||
|
||||
primaryKey() {
|
||||
this.dataType.options.primaryKey = true
|
||||
|
||||
return this
|
||||
return new PrimaryKeyModifier<number, NumberProperty>(this)
|
||||
}
|
||||
|
||||
constructor(options?: { primaryKey?: boolean }) {
|
||||
@@ -23,7 +20,7 @@ export class NumberProperty extends BaseProperty<number> {
|
||||
|
||||
this.dataType = {
|
||||
name: "number",
|
||||
options: { primaryKey: false, ...options },
|
||||
options: { ...options },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import { PropertyType } from "@medusajs/types"
|
||||
|
||||
const IsPrimaryKeyModifier = Symbol.for("isPrimaryKeyModifier")
|
||||
/**
|
||||
* PrimaryKey modifier marks a schema node as primaryKey
|
||||
*/
|
||||
export class PrimaryKeyModifier<T, Schema extends PropertyType<T>>
|
||||
implements PropertyType<T>
|
||||
{
|
||||
[IsPrimaryKeyModifier]: true = true
|
||||
|
||||
static isPrimaryKeyModifier(obj: any): obj is PrimaryKeyModifier<any, any> {
|
||||
return !!obj?.[IsPrimaryKeyModifier]
|
||||
}
|
||||
/**
|
||||
* A type-only property to infer the JavScript data-type
|
||||
* of the schema property
|
||||
*/
|
||||
declare $dataType: T
|
||||
|
||||
/**
|
||||
* The parent schema on which the primaryKey modifier is
|
||||
* applied
|
||||
*/
|
||||
#schema: Schema
|
||||
|
||||
constructor(schema: Schema) {
|
||||
this.#schema = schema
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the serialized metadata
|
||||
*/
|
||||
parse(fieldName: string) {
|
||||
const schema = this.#schema.parse(fieldName)
|
||||
schema.primaryKey = true
|
||||
return schema
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { BaseProperty } from "./base"
|
||||
import { PrimaryKeyModifier } from "./primary-key"
|
||||
|
||||
/**
|
||||
* The TextProperty is used to define a textual property
|
||||
@@ -7,14 +8,12 @@ export class TextProperty extends BaseProperty<string> {
|
||||
protected dataType: {
|
||||
name: "text"
|
||||
options: {
|
||||
primaryKey: boolean
|
||||
prefix?: string
|
||||
searchable: boolean
|
||||
}
|
||||
} = {
|
||||
name: "text",
|
||||
options: {
|
||||
primaryKey: false,
|
||||
searchable: false,
|
||||
},
|
||||
}
|
||||
@@ -35,9 +34,7 @@ export class TextProperty extends BaseProperty<string> {
|
||||
* @customNamespace Property Configuration Methods
|
||||
*/
|
||||
primaryKey() {
|
||||
this.dataType.options.primaryKey = true
|
||||
|
||||
return this
|
||||
return new PrimaryKeyModifier<string, TextProperty>(this)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,11 +5,15 @@ import {
|
||||
RelationshipTypes,
|
||||
} from "@medusajs/types"
|
||||
|
||||
export const IsRelationship = Symbol.for("isRelationship")
|
||||
|
||||
/**
|
||||
* The BaseRelationship encapsulates the repetitive parts of defining
|
||||
* a relationship
|
||||
*/
|
||||
export abstract class BaseRelationship<T> implements RelationshipType<T> {
|
||||
[IsRelationship]: true = true
|
||||
|
||||
#referencedEntity: T
|
||||
|
||||
/**
|
||||
@@ -28,6 +32,12 @@ export abstract class BaseRelationship<T> implements RelationshipType<T> {
|
||||
*/
|
||||
declare $dataType: T
|
||||
|
||||
static isRelationship<T>(
|
||||
relationship: any
|
||||
): relationship is BaseRelationship<T> {
|
||||
return !!relationship?.[IsRelationship]
|
||||
}
|
||||
|
||||
constructor(referencedEntity: T, options: RelationshipOptions) {
|
||||
this.#referencedEntity = referencedEntity
|
||||
this.options = options
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { RelationshipType } from "@medusajs/types"
|
||||
import { IsRelationship } from "./base"
|
||||
|
||||
const IsNullableModifier = Symbol.for("isNullableModifier")
|
||||
|
||||
@@ -8,7 +9,8 @@ const IsNullableModifier = Symbol.for("isNullableModifier")
|
||||
export class NullableModifier<T, Relation extends RelationshipType<T>>
|
||||
implements RelationshipType<T | null>
|
||||
{
|
||||
[IsNullableModifier]: true = true
|
||||
[IsNullableModifier]: true = true;
|
||||
[IsRelationship]: true = true
|
||||
|
||||
static isNullableModifier<T>(
|
||||
modifier: any
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import { model } from "../../../dml"
|
||||
|
||||
export const FulfillmentSet = {
|
||||
name: "FulfillmentSet",
|
||||
}
|
||||
export const ShippingOption = {
|
||||
name: "ShippingOption",
|
||||
}
|
||||
export const ShippingProfile = {
|
||||
name: "ShippingProfile",
|
||||
}
|
||||
export const Fulfillment = {
|
||||
name: "Fulfillment",
|
||||
}
|
||||
export const FulfillmentProvider = {
|
||||
name: "FulfillmentProvider",
|
||||
}
|
||||
export const ServiceZone = {
|
||||
name: "ServiceZone",
|
||||
}
|
||||
export const GeoZone = {
|
||||
name: "GeoZone",
|
||||
}
|
||||
export const ShippingOptionRule = {
|
||||
name: "ShippingOptionRule",
|
||||
}
|
||||
|
||||
export const dmlFulfillmentSet = model.define(FulfillmentSet.name, {
|
||||
id: model.id().primaryKey(),
|
||||
})
|
||||
export const dmlShippingOption = model.define(ShippingOption.name, {
|
||||
id: model.id().primaryKey(),
|
||||
})
|
||||
export const dmlShippingProfile = model.define(ShippingProfile.name, {
|
||||
id: model.id().primaryKey(),
|
||||
})
|
||||
export const dmlFulfillment = model.define(Fulfillment.name, {
|
||||
id: model.id().primaryKey(),
|
||||
})
|
||||
export const dmlFulfillmentProvider = model.define(FulfillmentProvider.name, {
|
||||
id: model.id().primaryKey(),
|
||||
})
|
||||
export const dmlServiceZone = model.define(ServiceZone.name, {
|
||||
id: model.id().primaryKey(),
|
||||
})
|
||||
|
||||
export const dmlGeoZone = model.define(GeoZone.name, {
|
||||
id: model.id().primaryKey(),
|
||||
})
|
||||
|
||||
export const dmlShippingOptionRule = model.define(ShippingOptionRule.name, {
|
||||
id: model.id().primaryKey(),
|
||||
})
|
||||
@@ -1,315 +1,505 @@
|
||||
import { defineJoinerConfig } from "../joiner-config-builder"
|
||||
import {
|
||||
buildLinkableKeysFromDmlObjects,
|
||||
buildLinkableKeysFromMikroOrmObjects,
|
||||
buildLinkConfigFromDmlObjects,
|
||||
defineJoinerConfig,
|
||||
} from "../joiner-config-builder"
|
||||
import { Modules } from "../definition"
|
||||
import { model } from "../../dml"
|
||||
import { expectTypeOf } from "expect-type"
|
||||
import {
|
||||
dmlFulfillment,
|
||||
dmlFulfillmentProvider,
|
||||
dmlFulfillmentSet,
|
||||
dmlGeoZone,
|
||||
dmlServiceZone,
|
||||
dmlShippingOption,
|
||||
dmlShippingOptionRule,
|
||||
dmlShippingProfile,
|
||||
Fulfillment,
|
||||
FulfillmentProvider,
|
||||
FulfillmentSet,
|
||||
GeoZone,
|
||||
ServiceZone,
|
||||
ShippingOption,
|
||||
ShippingOptionRule,
|
||||
ShippingProfile,
|
||||
} from "../__fixtures__/joiner-config/entities"
|
||||
|
||||
const FulfillmentSet = {
|
||||
name: "FulfillmentSet",
|
||||
}
|
||||
const ShippingOption = {
|
||||
name: "ShippingOption",
|
||||
}
|
||||
const ShippingProfile = {
|
||||
name: "ShippingProfile",
|
||||
}
|
||||
const Fulfillment = {
|
||||
name: "Fulfillment",
|
||||
}
|
||||
const FulfillmentProvider = {
|
||||
name: "FulfillmentProvider",
|
||||
}
|
||||
const ServiceZone = {
|
||||
name: "ServiceZone",
|
||||
}
|
||||
const GeoZone = {
|
||||
name: "GeoZone",
|
||||
}
|
||||
const ShippingOptionRule = {
|
||||
name: "ShippingOptionRule",
|
||||
}
|
||||
describe("joiner-config-builder", () => {
|
||||
describe("defineJoiner | Mikro orm objects", () => {
|
||||
it("should return a full joiner configuration", () => {
|
||||
const joinerConfig = defineJoinerConfig(Modules.FULFILLMENT, {
|
||||
models: [
|
||||
FulfillmentSet,
|
||||
ShippingOption,
|
||||
ShippingProfile,
|
||||
Fulfillment,
|
||||
FulfillmentProvider,
|
||||
ServiceZone,
|
||||
GeoZone,
|
||||
ShippingOptionRule,
|
||||
],
|
||||
})
|
||||
|
||||
describe("defineJoiner", () => {
|
||||
it("should return a full joiner configuration", () => {
|
||||
const joinerConfig = defineJoinerConfig(Modules.FULFILLMENT, {
|
||||
entityQueryingConfig: [
|
||||
FulfillmentSet,
|
||||
ShippingOption,
|
||||
ShippingProfile,
|
||||
Fulfillment,
|
||||
FulfillmentProvider,
|
||||
ServiceZone,
|
||||
GeoZone,
|
||||
ShippingOptionRule,
|
||||
],
|
||||
expect(joinerConfig).toEqual({
|
||||
serviceName: Modules.FULFILLMENT,
|
||||
primaryKeys: ["id"],
|
||||
schema: undefined,
|
||||
linkableKeys: {
|
||||
fulfillment_set_id: FulfillmentSet.name,
|
||||
shipping_option_id: ShippingOption.name,
|
||||
shipping_profile_id: ShippingProfile.name,
|
||||
fulfillment_id: Fulfillment.name,
|
||||
fulfillment_provider_id: FulfillmentProvider.name,
|
||||
service_zone_id: ServiceZone.name,
|
||||
geo_zone_id: GeoZone.name,
|
||||
shipping_option_rule_id: ShippingOptionRule.name,
|
||||
},
|
||||
alias: [
|
||||
{
|
||||
name: ["fulfillment_set", "fulfillment_sets"],
|
||||
args: {
|
||||
entity: FulfillmentSet.name,
|
||||
methodSuffix: "FulfillmentSets",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["shipping_option", "shipping_options"],
|
||||
args: {
|
||||
entity: ShippingOption.name,
|
||||
methodSuffix: "ShippingOptions",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["shipping_profile", "shipping_profiles"],
|
||||
args: {
|
||||
entity: ShippingProfile.name,
|
||||
methodSuffix: "ShippingProfiles",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["fulfillment", "fulfillments"],
|
||||
args: {
|
||||
entity: Fulfillment.name,
|
||||
methodSuffix: "Fulfillments",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["fulfillment_provider", "fulfillment_providers"],
|
||||
args: {
|
||||
entity: FulfillmentProvider.name,
|
||||
methodSuffix: "FulfillmentProviders",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["service_zone", "service_zones"],
|
||||
args: {
|
||||
entity: ServiceZone.name,
|
||||
methodSuffix: "ServiceZones",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["geo_zone", "geo_zones"],
|
||||
args: {
|
||||
entity: GeoZone.name,
|
||||
methodSuffix: "GeoZones",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["shipping_option_rule", "shipping_option_rules"],
|
||||
args: {
|
||||
entity: ShippingOptionRule.name,
|
||||
methodSuffix: "ShippingOptionRules",
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
expect(joinerConfig).toEqual({
|
||||
serviceName: Modules.FULFILLMENT,
|
||||
primaryKeys: ["id"],
|
||||
schema: undefined,
|
||||
linkableKeys: {
|
||||
fulfillment_set_id: FulfillmentSet.name,
|
||||
shipping_option_id: ShippingOption.name,
|
||||
shipping_profile_id: ShippingProfile.name,
|
||||
fulfillment_id: Fulfillment.name,
|
||||
fulfillment_provider_id: FulfillmentProvider.name,
|
||||
service_zone_id: ServiceZone.name,
|
||||
geo_zone_id: GeoZone.name,
|
||||
shipping_option_rule_id: ShippingOptionRule.name,
|
||||
},
|
||||
alias: [
|
||||
{
|
||||
name: ["fulfillment_set", "fulfillment_sets"],
|
||||
args: {
|
||||
entity: FulfillmentSet.name,
|
||||
methodSuffix: "FulfillmentSets",
|
||||
it("should return a full joiner configuration with custom aliases", () => {
|
||||
const joinerConfig = defineJoinerConfig(Modules.FULFILLMENT, {
|
||||
alias: [
|
||||
{
|
||||
name: ["custom", "customs"],
|
||||
args: {
|
||||
entity: "Custom",
|
||||
methodSuffix: "Customs",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["shipping_option", "shipping_options"],
|
||||
args: {
|
||||
entity: ShippingOption.name,
|
||||
methodSuffix: "ShippingOptions",
|
||||
],
|
||||
})
|
||||
|
||||
expect(joinerConfig).toEqual({
|
||||
serviceName: Modules.FULFILLMENT,
|
||||
primaryKeys: ["id"],
|
||||
schema: undefined,
|
||||
linkableKeys: {},
|
||||
alias: [
|
||||
{
|
||||
name: ["custom", "customs"],
|
||||
args: {
|
||||
entity: "Custom",
|
||||
methodSuffix: "Customs",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["shipping_profile", "shipping_profiles"],
|
||||
args: {
|
||||
entity: ShippingProfile.name,
|
||||
methodSuffix: "ShippingProfiles",
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
it("should return a full joiner configuration with custom aliases and models", () => {
|
||||
const joinerConfig = defineJoinerConfig(Modules.FULFILLMENT, {
|
||||
models: [
|
||||
FulfillmentSet,
|
||||
ShippingOption,
|
||||
ShippingProfile,
|
||||
Fulfillment,
|
||||
FulfillmentProvider,
|
||||
ServiceZone,
|
||||
GeoZone,
|
||||
ShippingOptionRule,
|
||||
],
|
||||
alias: [
|
||||
{
|
||||
name: ["custom", "customs"],
|
||||
args: {
|
||||
entity: "Custom",
|
||||
methodSuffix: "Customs",
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
expect(joinerConfig).toEqual({
|
||||
serviceName: Modules.FULFILLMENT,
|
||||
primaryKeys: ["id"],
|
||||
schema: undefined,
|
||||
linkableKeys: {
|
||||
fulfillment_set_id: FulfillmentSet.name,
|
||||
shipping_option_id: ShippingOption.name,
|
||||
shipping_profile_id: ShippingProfile.name,
|
||||
fulfillment_id: Fulfillment.name,
|
||||
fulfillment_provider_id: FulfillmentProvider.name,
|
||||
service_zone_id: ServiceZone.name,
|
||||
geo_zone_id: GeoZone.name,
|
||||
shipping_option_rule_id: ShippingOptionRule.name,
|
||||
},
|
||||
{
|
||||
name: ["fulfillment", "fulfillments"],
|
||||
args: {
|
||||
entity: Fulfillment.name,
|
||||
methodSuffix: "Fulfillments",
|
||||
alias: [
|
||||
{
|
||||
name: ["custom", "customs"],
|
||||
args: {
|
||||
entity: "Custom",
|
||||
methodSuffix: "Customs",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["fulfillment_provider", "fulfillment_providers"],
|
||||
args: {
|
||||
entity: FulfillmentProvider.name,
|
||||
methodSuffix: "FulfillmentProviders",
|
||||
{
|
||||
name: ["fulfillment_set", "fulfillment_sets"],
|
||||
args: {
|
||||
entity: FulfillmentSet.name,
|
||||
methodSuffix: "FulfillmentSets",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["service_zone", "service_zones"],
|
||||
args: {
|
||||
entity: ServiceZone.name,
|
||||
methodSuffix: "ServiceZones",
|
||||
{
|
||||
name: ["shipping_option", "shipping_options"],
|
||||
args: {
|
||||
entity: ShippingOption.name,
|
||||
methodSuffix: "ShippingOptions",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["geo_zone", "geo_zones"],
|
||||
args: {
|
||||
entity: GeoZone.name,
|
||||
methodSuffix: "GeoZones",
|
||||
{
|
||||
name: ["shipping_profile", "shipping_profiles"],
|
||||
args: {
|
||||
entity: ShippingProfile.name,
|
||||
methodSuffix: "ShippingProfiles",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["shipping_option_rule", "shipping_option_rules"],
|
||||
args: {
|
||||
entity: ShippingOptionRule.name,
|
||||
methodSuffix: "ShippingOptionRules",
|
||||
{
|
||||
name: ["fulfillment", "fulfillments"],
|
||||
args: {
|
||||
entity: Fulfillment.name,
|
||||
methodSuffix: "Fulfillments",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["fulfillment_provider", "fulfillment_providers"],
|
||||
args: {
|
||||
entity: FulfillmentProvider.name,
|
||||
methodSuffix: "FulfillmentProviders",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["service_zone", "service_zones"],
|
||||
args: {
|
||||
entity: ServiceZone.name,
|
||||
methodSuffix: "ServiceZones",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["geo_zone", "geo_zones"],
|
||||
args: {
|
||||
entity: GeoZone.name,
|
||||
methodSuffix: "GeoZones",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["shipping_option_rule", "shipping_option_rules"],
|
||||
args: {
|
||||
entity: ShippingOptionRule.name,
|
||||
methodSuffix: "ShippingOptionRules",
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
it("should return a full joiner configuration with custom aliases without method suffix", () => {
|
||||
const joinerConfig = defineJoinerConfig(Modules.FULFILLMENT, {
|
||||
alias: [
|
||||
{
|
||||
name: ["custom", "customs"],
|
||||
args: {
|
||||
entity: "Custom",
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
expect(joinerConfig).toEqual({
|
||||
serviceName: Modules.FULFILLMENT,
|
||||
primaryKeys: ["id"],
|
||||
schema: undefined,
|
||||
linkableKeys: {},
|
||||
alias: [
|
||||
{
|
||||
name: ["custom", "customs"],
|
||||
args: {
|
||||
entity: "Custom",
|
||||
methodSuffix: "Customs",
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
it("should return a full joiner configuration with custom aliases overriding defaults", () => {
|
||||
const joinerConfig = defineJoinerConfig(Modules.FULFILLMENT, {
|
||||
models: [FulfillmentSet],
|
||||
alias: [
|
||||
{
|
||||
name: ["fulfillment_set", "fulfillment_sets"],
|
||||
args: {
|
||||
entity: "FulfillmentSet",
|
||||
methodSuffix: "fulfillmentSetCustom",
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
expect(joinerConfig).toEqual({
|
||||
serviceName: Modules.FULFILLMENT,
|
||||
primaryKeys: ["id"],
|
||||
schema: undefined,
|
||||
linkableKeys: {
|
||||
fulfillment_set_id: FulfillmentSet.name,
|
||||
},
|
||||
],
|
||||
alias: [
|
||||
{
|
||||
name: ["fulfillment_set", "fulfillment_sets"],
|
||||
args: {
|
||||
entity: "FulfillmentSet",
|
||||
methodSuffix: "fulfillmentSetCustom",
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it("should return a full joiner configuration with custom aliases", () => {
|
||||
const joinerConfig = defineJoinerConfig(Modules.FULFILLMENT, {
|
||||
alias: [
|
||||
{
|
||||
name: ["custom", "customs"],
|
||||
args: {
|
||||
entity: "Custom",
|
||||
methodSuffix: "Customs",
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
describe("defineJoiner | DML objects", () => {
|
||||
it("should return a full joiner configuration", () => {
|
||||
const joinerConfig = defineJoinerConfig(Modules.FULFILLMENT, {
|
||||
models: [
|
||||
dmlFulfillmentSet,
|
||||
dmlShippingOption,
|
||||
dmlShippingProfile,
|
||||
dmlFulfillment,
|
||||
dmlFulfillmentProvider,
|
||||
dmlServiceZone,
|
||||
dmlGeoZone,
|
||||
dmlShippingOptionRule,
|
||||
],
|
||||
})
|
||||
|
||||
expect(joinerConfig).toEqual({
|
||||
serviceName: Modules.FULFILLMENT,
|
||||
primaryKeys: ["id"],
|
||||
schema: undefined,
|
||||
linkableKeys: {},
|
||||
alias: [
|
||||
{
|
||||
name: ["custom", "customs"],
|
||||
args: {
|
||||
entity: "Custom",
|
||||
methodSuffix: "Customs",
|
||||
},
|
||||
expect(joinerConfig).toEqual({
|
||||
serviceName: Modules.FULFILLMENT,
|
||||
primaryKeys: ["id"],
|
||||
schema: undefined,
|
||||
linkableKeys: {
|
||||
fulfillment_set_id: FulfillmentSet.name,
|
||||
shipping_option_id: ShippingOption.name,
|
||||
shipping_profile_id: ShippingProfile.name,
|
||||
fulfillment_id: Fulfillment.name,
|
||||
fulfillment_provider_id: FulfillmentProvider.name,
|
||||
service_zone_id: ServiceZone.name,
|
||||
geo_zone_id: GeoZone.name,
|
||||
shipping_option_rule_id: ShippingOptionRule.name,
|
||||
},
|
||||
],
|
||||
alias: [
|
||||
{
|
||||
name: ["fulfillment_set", "fulfillment_sets"],
|
||||
args: {
|
||||
entity: FulfillmentSet.name,
|
||||
methodSuffix: "FulfillmentSets",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["shipping_option", "shipping_options"],
|
||||
args: {
|
||||
entity: ShippingOption.name,
|
||||
methodSuffix: "ShippingOptions",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["shipping_profile", "shipping_profiles"],
|
||||
args: {
|
||||
entity: ShippingProfile.name,
|
||||
methodSuffix: "ShippingProfiles",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["fulfillment", "fulfillments"],
|
||||
args: {
|
||||
entity: Fulfillment.name,
|
||||
methodSuffix: "Fulfillments",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["fulfillment_provider", "fulfillment_providers"],
|
||||
args: {
|
||||
entity: FulfillmentProvider.name,
|
||||
methodSuffix: "FulfillmentProviders",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["service_zone", "service_zones"],
|
||||
args: {
|
||||
entity: ServiceZone.name,
|
||||
methodSuffix: "ServiceZones",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["geo_zone", "geo_zones"],
|
||||
args: {
|
||||
entity: GeoZone.name,
|
||||
methodSuffix: "GeoZones",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["shipping_option_rule", "shipping_option_rules"],
|
||||
args: {
|
||||
entity: ShippingOptionRule.name,
|
||||
methodSuffix: "ShippingOptionRules",
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it("should return a full joiner configuration with custom aliases and models", () => {
|
||||
const joinerConfig = defineJoinerConfig(Modules.FULFILLMENT, {
|
||||
entityQueryingConfig: [
|
||||
FulfillmentSet,
|
||||
ShippingOption,
|
||||
ShippingProfile,
|
||||
Fulfillment,
|
||||
FulfillmentProvider,
|
||||
ServiceZone,
|
||||
GeoZone,
|
||||
ShippingOptionRule,
|
||||
],
|
||||
alias: [
|
||||
{
|
||||
name: ["custom", "customs"],
|
||||
args: {
|
||||
entity: "Custom",
|
||||
methodSuffix: "Customs",
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
describe("buildLinkableKeysFromDmlObjects", () => {
|
||||
it("should return a linkableKeys object based on the DML's primary keys", () => {
|
||||
const user = model.define("user", {
|
||||
id: model.id().primaryKey(),
|
||||
name: model.text(),
|
||||
})
|
||||
|
||||
expect(joinerConfig).toEqual({
|
||||
serviceName: Modules.FULFILLMENT,
|
||||
primaryKeys: ["id"],
|
||||
schema: undefined,
|
||||
linkableKeys: {
|
||||
fulfillment_set_id: FulfillmentSet.name,
|
||||
shipping_option_id: ShippingOption.name,
|
||||
shipping_profile_id: ShippingProfile.name,
|
||||
fulfillment_id: Fulfillment.name,
|
||||
fulfillment_provider_id: FulfillmentProvider.name,
|
||||
service_zone_id: ServiceZone.name,
|
||||
geo_zone_id: GeoZone.name,
|
||||
shipping_option_rule_id: ShippingOptionRule.name,
|
||||
},
|
||||
alias: [
|
||||
{
|
||||
name: ["custom", "customs"],
|
||||
args: {
|
||||
entity: "Custom",
|
||||
methodSuffix: "Customs",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["fulfillment_set", "fulfillment_sets"],
|
||||
args: {
|
||||
entity: FulfillmentSet.name,
|
||||
methodSuffix: "FulfillmentSets",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["shipping_option", "shipping_options"],
|
||||
args: {
|
||||
entity: ShippingOption.name,
|
||||
methodSuffix: "ShippingOptions",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["shipping_profile", "shipping_profiles"],
|
||||
args: {
|
||||
entity: ShippingProfile.name,
|
||||
methodSuffix: "ShippingProfiles",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["fulfillment", "fulfillments"],
|
||||
args: {
|
||||
entity: Fulfillment.name,
|
||||
methodSuffix: "Fulfillments",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["fulfillment_provider", "fulfillment_providers"],
|
||||
args: {
|
||||
entity: FulfillmentProvider.name,
|
||||
methodSuffix: "FulfillmentProviders",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["service_zone", "service_zones"],
|
||||
args: {
|
||||
entity: ServiceZone.name,
|
||||
methodSuffix: "ServiceZones",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["geo_zone", "geo_zones"],
|
||||
args: {
|
||||
entity: GeoZone.name,
|
||||
methodSuffix: "GeoZones",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["shipping_option_rule", "shipping_option_rules"],
|
||||
args: {
|
||||
entity: ShippingOptionRule.name,
|
||||
methodSuffix: "ShippingOptionRules",
|
||||
},
|
||||
},
|
||||
],
|
||||
const car = model.define("car", {
|
||||
id: model.id(),
|
||||
number_plate: model.text().primaryKey(),
|
||||
test: model.text(),
|
||||
})
|
||||
|
||||
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,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it("should return a full joiner configuration with custom aliases without method suffix", () => {
|
||||
const joinerConfig = defineJoinerConfig(Modules.FULFILLMENT, {
|
||||
alias: [
|
||||
{
|
||||
name: ["custom", "customs"],
|
||||
args: {
|
||||
entity: "Custom",
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
describe("buildLinkableKeysFromMikroOrmObjects", () => {
|
||||
it("should return a linkableKeys object based on the mikro orm models name", () => {
|
||||
class User {}
|
||||
class Car {}
|
||||
|
||||
expect(joinerConfig).toEqual({
|
||||
serviceName: Modules.FULFILLMENT,
|
||||
primaryKeys: ["id"],
|
||||
schema: undefined,
|
||||
linkableKeys: {},
|
||||
alias: [
|
||||
{
|
||||
name: ["custom", "customs"],
|
||||
args: {
|
||||
entity: "Custom",
|
||||
methodSuffix: "Customs",
|
||||
},
|
||||
},
|
||||
],
|
||||
const linkableKeys = buildLinkableKeysFromMikroOrmObjects([Car, User])
|
||||
|
||||
expect(linkableKeys).toEqual({
|
||||
user_id: User.name,
|
||||
car_id: Car.name,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it("should return a full joiner configuration with custom aliases overriding defaults", () => {
|
||||
const joinerConfig = defineJoinerConfig(Modules.FULFILLMENT, {
|
||||
entityQueryingConfig: [FulfillmentSet],
|
||||
alias: [
|
||||
{
|
||||
name: ["fulfillment_set", "fulfillment_sets"],
|
||||
args: {
|
||||
entity: "FulfillmentSet",
|
||||
methodSuffix: "fulfillmentSetCustom",
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
describe("buildLinkConfigFromDmlObjects", () => {
|
||||
it("should return a link config object based on the DML's primary keys", () => {
|
||||
const user = model.define("user", {
|
||||
id: model.id().primaryKey(),
|
||||
name: model.text(),
|
||||
})
|
||||
|
||||
expect(joinerConfig).toEqual({
|
||||
serviceName: Modules.FULFILLMENT,
|
||||
primaryKeys: ["id"],
|
||||
schema: undefined,
|
||||
linkableKeys: {
|
||||
fulfillment_set_id: FulfillmentSet.name,
|
||||
},
|
||||
alias: [
|
||||
{
|
||||
name: ["fulfillment_set", "fulfillment_sets"],
|
||||
args: {
|
||||
entity: "FulfillmentSet",
|
||||
methodSuffix: "fulfillmentSetCustom",
|
||||
},
|
||||
},
|
||||
],
|
||||
const car = model.define("car", {
|
||||
id: model.id(),
|
||||
number_plate: model.text().primaryKey(),
|
||||
})
|
||||
|
||||
const linkConfig = buildLinkConfigFromDmlObjects([user, car])
|
||||
|
||||
expectTypeOf(linkConfig).toMatchTypeOf<{
|
||||
user: {
|
||||
id: {
|
||||
linkable: "user_id"
|
||||
primaryKey: "id"
|
||||
}
|
||||
toJSON: () => {
|
||||
linkable: string
|
||||
primaryKey: string
|
||||
}
|
||||
}
|
||||
car: {
|
||||
number_plate: {
|
||||
linkable: "car_number_plate"
|
||||
primaryKey: "number_plate"
|
||||
}
|
||||
toJSON: () => {
|
||||
linkable: string
|
||||
primaryKey: string
|
||||
}
|
||||
}
|
||||
}>()
|
||||
|
||||
expect(linkConfig.user.id).toEqual({
|
||||
linkable: "user_id",
|
||||
primaryKey: "id",
|
||||
})
|
||||
expect(linkConfig.car.number_plate).toEqual({
|
||||
linkable: "car_number_plate",
|
||||
primaryKey: "number_plate",
|
||||
})
|
||||
|
||||
expect(linkConfig.car.toJSON()).toEqual({
|
||||
linkable: "car_number_plate",
|
||||
primaryKey: "number_plate",
|
||||
})
|
||||
expect(linkConfig.user.toJSON()).toEqual({
|
||||
linkable: "user_id",
|
||||
primaryKey: "id",
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { Context, EventBusTypes } from "@medusajs/types"
|
||||
|
||||
// TODO should that move closer to the event bus? and maybe be rename to moduleEventBuilderFactory
|
||||
|
||||
/**
|
||||
*
|
||||
* Factory function to create event builders for different entities
|
||||
*
|
||||
* @example
|
||||
@@ -48,7 +51,8 @@ export function eventBuilderFactory({
|
||||
|
||||
// The event enums contains event formatted like so [object]_[action] e.g. PRODUCT_CREATED
|
||||
// We expect the keys of events to be fully uppercased
|
||||
const eventName = eventsEnum[`${object.toUpperCase()}_${action.toUpperCase()}`]
|
||||
const eventName =
|
||||
eventsEnum[`${object.toUpperCase()}_${action.toUpperCase()}`]
|
||||
|
||||
data.forEach((dataItem) => {
|
||||
messages.push({
|
||||
|
||||
@@ -13,4 +13,4 @@ export * from "./medusa-internal-service"
|
||||
export * from "./medusa-service"
|
||||
export * from "./migration-scripts"
|
||||
export * from "./mikro-orm-cli-config-builder"
|
||||
|
||||
export * from "./module"
|
||||
|
||||
@@ -1,14 +1,24 @@
|
||||
import { JoinerServiceConfigAlias, ModuleJoinerConfig } from "@medusajs/types"
|
||||
import {
|
||||
JoinerServiceConfigAlias,
|
||||
ModuleJoinerConfig,
|
||||
PropertyType,
|
||||
} from "@medusajs/types"
|
||||
import { dirname, join } from "path"
|
||||
import {
|
||||
MapToConfig,
|
||||
camelToSnakeCase,
|
||||
deduplicate,
|
||||
getCallerFilePath,
|
||||
isObject,
|
||||
lowerCaseFirst,
|
||||
MapToConfig,
|
||||
pluralize,
|
||||
upperCaseFirst,
|
||||
} from "../common"
|
||||
import { loadModels } from "./loaders/load-models"
|
||||
import { DmlEntity } from "../dml"
|
||||
import { BaseRelationship } from "../dml/relations/base"
|
||||
import { PrimaryKeyModifier } from "../dml/properties/primary-key"
|
||||
import { InferLinkableKeys, InfersLinksConfig } from "./types/links-config"
|
||||
|
||||
/**
|
||||
* Define joiner config for a module based on the models (object representation or entities) present in the models directory. This action will be sync until
|
||||
@@ -20,7 +30,7 @@ import { loadModels } from "./loaders/load-models"
|
||||
* @param moduleName
|
||||
* @param alias
|
||||
* @param schema
|
||||
* @param entityQueryingConfig
|
||||
* @param models
|
||||
* @param linkableKeys
|
||||
* @param primaryKeys
|
||||
*/
|
||||
@@ -29,13 +39,13 @@ export function defineJoinerConfig(
|
||||
{
|
||||
alias,
|
||||
schema,
|
||||
entityQueryingConfig,
|
||||
models,
|
||||
linkableKeys,
|
||||
primaryKeys,
|
||||
}: {
|
||||
alias?: JoinerServiceConfigAlias[]
|
||||
schema?: string
|
||||
entityQueryingConfig?: { name: string }[]
|
||||
models?: DmlEntity<any, any>[] | { name: string }[]
|
||||
linkableKeys?: Record<string, string>
|
||||
primaryKeys?: string[]
|
||||
} = {}
|
||||
@@ -62,20 +72,64 @@ export function defineJoinerConfig(
|
||||
|
||||
basePath = join(basePath, "models")
|
||||
|
||||
const models = deduplicate(
|
||||
[...(entityQueryingConfig ?? loadModels(basePath))].flatMap((v) => v!.name)
|
||||
).map((name) => ({ name }))
|
||||
let loadedModels = models ?? loadModels(basePath)
|
||||
const modelDefinitions = new Map(
|
||||
loadedModels
|
||||
.filter((model) => !!DmlEntity.isDmlEntity(model))
|
||||
.map((model) => [model.name, model])
|
||||
)
|
||||
const mikroOrmObjects = new Map(
|
||||
loadedModels
|
||||
.filter((model) => !DmlEntity.isDmlEntity(model))
|
||||
.map((model) => [model.name, model])
|
||||
)
|
||||
|
||||
// We prioritize DML if there is any equivalent Mikro orm entities found
|
||||
loadedModels = [...modelDefinitions.values()]
|
||||
mikroOrmObjects.forEach((model) => {
|
||||
if (modelDefinitions.has(model.name)) {
|
||||
return
|
||||
}
|
||||
|
||||
loadedModels.push(model)
|
||||
})
|
||||
|
||||
if (!linkableKeys) {
|
||||
const linkableKeysFromDml = buildLinkableKeysFromDmlObjects([
|
||||
...modelDefinitions.values(),
|
||||
])
|
||||
const linkableKeysFromMikroOrm = buildLinkableKeysFromMikroOrmObjects([
|
||||
...mikroOrmObjects.values(),
|
||||
])
|
||||
linkableKeys = {
|
||||
...linkableKeysFromDml,
|
||||
...linkableKeysFromMikroOrm,
|
||||
}
|
||||
}
|
||||
|
||||
if (!primaryKeys && modelDefinitions.size) {
|
||||
const linkConfig = buildLinkConfigFromDmlObjects([
|
||||
...modelDefinitions.values(),
|
||||
])
|
||||
|
||||
primaryKeys = deduplicate(
|
||||
Object.values(linkConfig).flatMap((entityLinkConfig) => {
|
||||
return (Object.values(entityLinkConfig) as any[])
|
||||
.filter((linkableConfig) => isObject(linkableConfig))
|
||||
.map((linkableConfig) => {
|
||||
return linkableConfig.primaryKey
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: In the context of DML add a validation on primary keys and linkable keys if the consumer provide them manually. follow up pr
|
||||
|
||||
return {
|
||||
serviceName: moduleName,
|
||||
primaryKeys: primaryKeys ?? ["id"],
|
||||
schema,
|
||||
linkableKeys:
|
||||
linkableKeys ??
|
||||
models.reduce((acc, entity) => {
|
||||
acc[`${camelToSnakeCase(entity.name).toLowerCase()}_id`] = entity.name
|
||||
return acc
|
||||
}, {} as Record<string, string>),
|
||||
linkableKeys: linkableKeys,
|
||||
alias: [
|
||||
...[...(alias ?? ([] as any))].map((alias) => ({
|
||||
name: alias.name,
|
||||
@@ -86,7 +140,7 @@ export function defineJoinerConfig(
|
||||
pluralize(upperCaseFirst(alias.args.entity)),
|
||||
},
|
||||
})),
|
||||
...models
|
||||
...loadedModels
|
||||
.filter((model) => {
|
||||
return (
|
||||
!alias || !alias.some((alias) => alias.args?.entity === model.name)
|
||||
@@ -106,8 +160,153 @@ export function defineJoinerConfig(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* From a set of DML objects, build the linkable keys
|
||||
*
|
||||
* @example
|
||||
* const user = model.define("user", {
|
||||
* id: model.id(),
|
||||
* name: model.text(),
|
||||
* })
|
||||
*
|
||||
* const car = model.define("car", {
|
||||
* id: model.id(),
|
||||
* number_plate: model.text().primaryKey(),
|
||||
* test: model.text(),
|
||||
* })
|
||||
*
|
||||
* // output:
|
||||
* // {
|
||||
* // user_id: 'User',
|
||||
* // car_number_plate: 'Car',
|
||||
* // }
|
||||
*
|
||||
* @param models
|
||||
*/
|
||||
export function buildLinkableKeysFromDmlObjects<
|
||||
const T extends DmlEntity<any, any>[],
|
||||
LinkableKeys = InferLinkableKeys<T>
|
||||
>(models: T): LinkableKeys {
|
||||
const linkableKeys = {} as LinkableKeys
|
||||
|
||||
for (const model of models) {
|
||||
if (!DmlEntity.isDmlEntity(model)) {
|
||||
continue
|
||||
}
|
||||
|
||||
const schema = model.schema
|
||||
const primaryKeys: string[] = []
|
||||
|
||||
for (const [property, value] of Object.entries(schema)) {
|
||||
if (BaseRelationship.isRelationship(value)) {
|
||||
continue
|
||||
}
|
||||
|
||||
const parsedProperty = (value as PropertyType<any>).parse(property)
|
||||
if (PrimaryKeyModifier.isPrimaryKeyModifier(value)) {
|
||||
const linkableKeyName =
|
||||
parsedProperty.dataType.options?.linkable ??
|
||||
`${camelToSnakeCase(model.name).toLowerCase()}_${property}`
|
||||
primaryKeys.push(linkableKeyName)
|
||||
}
|
||||
}
|
||||
|
||||
if (primaryKeys.length) {
|
||||
primaryKeys.forEach((primaryKey) => {
|
||||
linkableKeys[primaryKey] = model.name
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return linkableKeys
|
||||
}
|
||||
|
||||
/**
|
||||
* Build linkable keys from MikroORM objects
|
||||
* @deprecated
|
||||
* @param models
|
||||
*/
|
||||
export function buildLinkableKeysFromMikroOrmObjects(
|
||||
models: Function[]
|
||||
): Record<string, string> {
|
||||
return models.reduce((acc, entity) => {
|
||||
acc[`${camelToSnakeCase(entity.name).toLowerCase()}_id`] = entity.name
|
||||
return acc
|
||||
}, {}) as Record<string, string>
|
||||
}
|
||||
|
||||
/**
|
||||
* Build entities name to linkable keys map
|
||||
*
|
||||
* @example
|
||||
* const user = model.define("user", {
|
||||
* id: model.id(),
|
||||
* name: model.text(),
|
||||
* })
|
||||
*
|
||||
* const car = model.define("car", {
|
||||
* id: model.id(),
|
||||
* number_plate: model.text().primaryKey(),
|
||||
* test: model.text(),
|
||||
* })
|
||||
*
|
||||
* // output:
|
||||
* // {
|
||||
* // toJSON: function () { },
|
||||
* // user: {
|
||||
* // id: "user_id",
|
||||
* // },
|
||||
* // car: {
|
||||
* // number_plate: "car_number_plate",
|
||||
* // },
|
||||
* // }
|
||||
*
|
||||
* @param models
|
||||
*/
|
||||
export function buildLinkConfigFromDmlObjects<
|
||||
const T extends DmlEntity<any, any>[]
|
||||
>(models: T = [] as unknown as T): InfersLinksConfig<T> {
|
||||
const linkConfig = {} as InfersLinksConfig<T>
|
||||
|
||||
for (const model of models) {
|
||||
if (!DmlEntity.isDmlEntity(model)) {
|
||||
continue
|
||||
}
|
||||
|
||||
const schema = model.schema
|
||||
const modelLinkConfig = (linkConfig[lowerCaseFirst(model.name)] ??= {
|
||||
toJSON: function () {
|
||||
const linkables = Object.entries(this)
|
||||
.filter(([name]) => name !== "toJSON")
|
||||
.map(([, object]) => object)
|
||||
const lastIndex = linkables.length - 1
|
||||
return linkables[lastIndex]
|
||||
},
|
||||
})
|
||||
|
||||
for (const [property, value] of Object.entries(schema)) {
|
||||
if (BaseRelationship.isRelationship(value)) {
|
||||
continue
|
||||
}
|
||||
|
||||
const parsedProperty = (value as PropertyType<any>).parse(property)
|
||||
if (PrimaryKeyModifier.isPrimaryKeyModifier(value)) {
|
||||
const linkableKeyName =
|
||||
parsedProperty.dataType.options?.linkable ??
|
||||
`${camelToSnakeCase(model.name).toLowerCase()}_${property}`
|
||||
modelLinkConfig[property] = {
|
||||
linkable: linkableKeyName,
|
||||
primaryKey: property,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return linkConfig as InfersLinksConfig<T> & Record<any, any>
|
||||
}
|
||||
|
||||
/**
|
||||
* Reversed map from linkableKeys to entity name to linkable keys
|
||||
* @param linkableKeys
|
||||
*/
|
||||
export function buildEntitiesNameToLinkableKeysMap(
|
||||
|
||||
@@ -27,15 +27,15 @@ export function loadModels(basePath: string) {
|
||||
|
||||
if (stats.isFile()) {
|
||||
try {
|
||||
const required = require(filePath) as {
|
||||
[key: string]: { name?: string }
|
||||
}
|
||||
const required = require(filePath)
|
||||
|
||||
return Object.values(required).filter((resource) => !!resource.name)
|
||||
return Object.values(required).filter(
|
||||
(resource: any) => !!resource.name
|
||||
)
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
return
|
||||
})
|
||||
.filter(Boolean) as { name: string }[]
|
||||
.filter(Boolean) as any[]
|
||||
}
|
||||
|
||||
@@ -35,12 +35,16 @@ type SelectorAndData = {
|
||||
data: any
|
||||
}
|
||||
|
||||
export function MedusaInternalService<TContainer extends object = object>(
|
||||
export function MedusaInternalService<
|
||||
TContainer extends object = object,
|
||||
TEntity extends object = any
|
||||
>(
|
||||
rawModel: any
|
||||
): {
|
||||
new <TEntity extends object = any>(
|
||||
container: TContainer
|
||||
): ModulesSdkTypes.IMedusaInternalService<TEntity, TContainer>
|
||||
new (container: TContainer): ModulesSdkTypes.IMedusaInternalService<
|
||||
TEntity,
|
||||
TContainer
|
||||
>
|
||||
} {
|
||||
const model = DmlEntity.isDmlEntity(rawModel)
|
||||
? toMikroORMEntity(rawModel)
|
||||
@@ -49,7 +53,7 @@ export function MedusaInternalService<TContainer extends object = object>(
|
||||
const injectedRepositoryName = `${lowerCaseFirst(model.name)}Repository`
|
||||
const propertyRepositoryName = `__${injectedRepositoryName}__`
|
||||
|
||||
class AbstractService_<TEntity extends object>
|
||||
class AbstractService_
|
||||
implements ModulesSdkTypes.IMedusaInternalService<TEntity, TContainer>
|
||||
{
|
||||
readonly __container__: TContainer;
|
||||
@@ -556,7 +560,5 @@ export function MedusaInternalService<TContainer extends object = object>(
|
||||
}
|
||||
}
|
||||
|
||||
return AbstractService_ as unknown as new <TEntity extends {}>(
|
||||
container: TContainer
|
||||
) => ModulesSdkTypes.IMedusaInternalService<TEntity, TContainer>
|
||||
return AbstractService_ as any
|
||||
}
|
||||
|
||||
@@ -2,11 +2,10 @@
|
||||
* Utility factory and interfaces for module service public facing API
|
||||
*/
|
||||
import {
|
||||
Constructor,
|
||||
Context,
|
||||
FindConfig,
|
||||
IEventBusModuleService,
|
||||
Pluralize,
|
||||
ModuleJoinerConfig,
|
||||
RepositoryService,
|
||||
RestoreReturn,
|
||||
SoftDeleteReturn,
|
||||
@@ -22,17 +21,15 @@ import {
|
||||
} from "../common"
|
||||
import { InjectManager, MedusaContext } from "./decorators"
|
||||
import { ModuleRegistrationName } from "./definition"
|
||||
import { DmlEntity } from "../dml"
|
||||
|
||||
type BaseMethods =
|
||||
| "retrieve"
|
||||
| "list"
|
||||
| "listAndCount"
|
||||
| "delete"
|
||||
| "softDelete"
|
||||
| "restore"
|
||||
| "create"
|
||||
| "update"
|
||||
import {
|
||||
BaseMethods,
|
||||
EntitiesConfigTemplate,
|
||||
ExtractKeysFromConfig,
|
||||
MedusaServiceReturnType,
|
||||
ModelConfigurationsToConfigTemplate,
|
||||
TEntityEntries,
|
||||
} from "./types/medusa-service"
|
||||
import { buildEntitiesNameToLinkableKeysMap } from "./joiner-config-builder"
|
||||
|
||||
const readMethods = ["retrieve", "list", "listAndCount"] as BaseMethods[]
|
||||
const writeMethods = [
|
||||
@@ -45,200 +42,6 @@ const writeMethods = [
|
||||
|
||||
const methods: BaseMethods[] = [...readMethods, ...writeMethods]
|
||||
|
||||
type ModelDTOConfig = {
|
||||
dto: object
|
||||
create?: any
|
||||
update?: any
|
||||
/**
|
||||
* @internal
|
||||
* @deprecated
|
||||
*/
|
||||
singular?: string
|
||||
/**
|
||||
* @internal
|
||||
* @deprecated
|
||||
*/
|
||||
plural?: string
|
||||
}
|
||||
|
||||
type EntitiesConfigTemplate = { [key: string]: ModelDTOConfig }
|
||||
|
||||
type ModelConfigurationsToConfigTemplate<T extends TEntityEntries> = {
|
||||
[Key in keyof T as `${Capitalize<Key & string>}`]: {
|
||||
dto: T[Key] extends Constructor<any> ? InstanceType<T[Key]> : any
|
||||
create: any
|
||||
update: any
|
||||
singular: T[Key] extends { singular: string } ? T[Key]["singular"] : Key
|
||||
plural: T[Key] extends { plural: string }
|
||||
? T[Key]["plural"]
|
||||
: Pluralize<Key & string>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated should all notion of singular and plural be removed once all modules are aligned with the convention
|
||||
*/
|
||||
type ExtractSingularName<T extends Record<any, any>, K = keyof T> = Capitalize<
|
||||
T[K] extends { singular?: string } ? T[K]["singular"] & string : K & string
|
||||
>
|
||||
|
||||
/**
|
||||
* @deprecated should all notion of singular and plural be removed once all modules are aligned with the convention
|
||||
* The pluralize will move to where it should be used instead
|
||||
*/
|
||||
type ExtractPluralName<T extends Record<any, any>, K = keyof T> = Capitalize<
|
||||
T[K] extends {
|
||||
plural?: string
|
||||
}
|
||||
? T[K]["plural"] & string
|
||||
: Pluralize<K & string>
|
||||
>
|
||||
|
||||
// TODO: The future expected entry will be a DML object but in the meantime we have to maintain backward compatibility for ouw own modules and therefore we need to support Constructor<any> as well as this temporary object
|
||||
type TEntityEntries<Keys = string> = Record<
|
||||
Keys & string,
|
||||
| Constructor<any>
|
||||
| DmlEntity<any>
|
||||
| { name?: string; singular?: string; plural?: string }
|
||||
>
|
||||
|
||||
type ExtractKeysFromConfig<EntitiesConfig> = EntitiesConfig extends {
|
||||
__empty: any
|
||||
}
|
||||
? string
|
||||
: keyof EntitiesConfig
|
||||
|
||||
export type AbstractModuleService<
|
||||
TEntitiesDtoConfig extends Record<string, any>
|
||||
> = {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `retrieve${ExtractSingularName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: (
|
||||
id: string,
|
||||
config?: FindConfig<any>,
|
||||
sharedContext?: Context
|
||||
) => Promise<TEntitiesDtoConfig[TEntityName]["dto"]>
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `list${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: (
|
||||
filters?: any,
|
||||
config?: FindConfig<any>,
|
||||
sharedContext?: Context
|
||||
) => Promise<TEntitiesDtoConfig[TEntityName]["dto"][]>
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `listAndCount${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
(filters?: any, config?: FindConfig<any>, sharedContext?: Context): Promise<
|
||||
[TEntitiesDtoConfig[TEntityName]["dto"][], number]
|
||||
>
|
||||
}
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `delete${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
(
|
||||
primaryKeyValues: string | object | string[] | object[],
|
||||
sharedContext?: Context
|
||||
): Promise<void>
|
||||
}
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `softDelete${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
<TReturnableLinkableKeys extends string>(
|
||||
primaryKeyValues: string | object | string[] | object[],
|
||||
config?: SoftDeleteReturn<TReturnableLinkableKeys>,
|
||||
sharedContext?: Context
|
||||
): Promise<Record<string, string[]> | void>
|
||||
}
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `restore${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
<TReturnableLinkableKeys extends string>(
|
||||
primaryKeyValues: string | object | string[] | object[],
|
||||
config?: RestoreReturn<TReturnableLinkableKeys>,
|
||||
sharedContext?: Context
|
||||
): Promise<Record<string, string[]> | void>
|
||||
}
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `create${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
(...args: any[]): Promise<any>
|
||||
}
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `update${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
(...args: any[]): Promise<any>
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Because of a bug, those methods were not made visible which now cause issues with the fix as our interface are not consistent with the expectations
|
||||
|
||||
// are not consistent accross modules
|
||||
/* & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `create${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
(data: any[], sharedContext?: Context): Promise<
|
||||
TEntitiesDtoConfig[TEntityName]["dto"][]
|
||||
>
|
||||
}
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `create${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
(data: any, sharedContext?: Context): Promise<
|
||||
TEntitiesDtoConfig[TEntityName]["dto"][]
|
||||
>
|
||||
}
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `update${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
(
|
||||
data: TEntitiesDtoConfig[TEntityName]["update"][],
|
||||
sharedContext?: Context
|
||||
): Promise<TEntitiesDtoConfig[TEntityName]["dto"][]>
|
||||
}
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `update${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
(
|
||||
data: TEntitiesDtoConfig[TEntityName]["update"],
|
||||
sharedContext?: Context
|
||||
): Promise<TEntitiesDtoConfig[TEntityName]["dto"]>
|
||||
}
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `update${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
(
|
||||
idOrdSelector: any,
|
||||
data: TEntitiesDtoConfig[TEntityName]["update"],
|
||||
sharedContext?: Context
|
||||
): Promise<TEntitiesDtoConfig[TEntityName]["dto"][]>
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@@ -263,6 +66,36 @@ function buildMethodNamesFromModel(
|
||||
}, {})
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessible from the MedusaService, holds the model objects when provided
|
||||
*/
|
||||
export const MedusaServiceModelObjectsSymbol = Symbol.for(
|
||||
"MedusaServiceModelObjectsSymbol"
|
||||
)
|
||||
|
||||
/**
|
||||
* Symbol to mark a class as a Medusa service
|
||||
*/
|
||||
export const MedusaServiceSymbol = Symbol.for("MedusaServiceSymbol")
|
||||
|
||||
/**
|
||||
* Accessible from the MedusaService, holds the entity name to linkable keys map
|
||||
* to be used for softDelete and restore methods
|
||||
*/
|
||||
export const MedusaServiceEntityNameToLinkableKeysMapSymbol = Symbol.for(
|
||||
"MedusaServiceEntityNameToLinkableKeysMapSymbol"
|
||||
)
|
||||
|
||||
/**
|
||||
* Check if a value is a Medusa service
|
||||
* @param value
|
||||
*/
|
||||
export function isMedusaService(
|
||||
value: any
|
||||
): value is MedusaServiceReturnType<any> {
|
||||
return value && value?.prototype[MedusaServiceSymbol]
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory function for creating an abstract module service
|
||||
*
|
||||
@@ -281,26 +114,22 @@ function buildMethodNamesFromModel(
|
||||
* RuleType,
|
||||
* }
|
||||
*
|
||||
* class MyService extends ModulesSdkUtils.MedusaService(entities, entityNameToLinkableKeysMap) {}
|
||||
* class MyService extends ModulesSdkUtils.MedusaService(entities) {}
|
||||
*
|
||||
* @param entities
|
||||
* @param entityNameToLinkableKeysMap
|
||||
*/
|
||||
export function MedusaService<
|
||||
EntitiesConfig extends EntitiesConfigTemplate = { __empty: any },
|
||||
TEntities extends TEntityEntries<
|
||||
const EntitiesConfig extends EntitiesConfigTemplate = { __empty: any },
|
||||
const TEntities extends TEntityEntries<
|
||||
ExtractKeysFromConfig<EntitiesConfig>
|
||||
> = TEntityEntries<ExtractKeysFromConfig<EntitiesConfig>>
|
||||
>(
|
||||
entities: TEntities,
|
||||
entityNameToLinkableKeysMap: MapToConfig = {}
|
||||
): {
|
||||
new (...args: any[]): AbstractModuleService<
|
||||
EntitiesConfig extends { __empty: any }
|
||||
? ModelConfigurationsToConfigTemplate<TEntities>
|
||||
: EntitiesConfig
|
||||
>
|
||||
} {
|
||||
entities: TEntities
|
||||
): MedusaServiceReturnType<
|
||||
EntitiesConfig extends { __empty: any }
|
||||
? ModelConfigurationsToConfigTemplate<TEntities>
|
||||
: EntitiesConfig
|
||||
> {
|
||||
const buildAndAssignMethodImpl = function (
|
||||
klassPrototype: any,
|
||||
method: string,
|
||||
@@ -474,7 +303,7 @@ export function MedusaService<
|
||||
// eg: product.id = product_id, variant.id = variant_id
|
||||
const mappedCascadedEntitiesMap = mapObjectTo(
|
||||
cascadedEntitiesMap,
|
||||
entityNameToLinkableKeysMap,
|
||||
this[MedusaServiceEntityNameToLinkableKeysMapSymbol],
|
||||
{
|
||||
pick: config.returnLinkableKeys,
|
||||
}
|
||||
@@ -506,7 +335,7 @@ export function MedusaService<
|
||||
// eg: product.id = product_id, variant.id = variant_id
|
||||
mappedCascadedEntitiesMap = mapObjectTo(
|
||||
cascadedEntitiesMap,
|
||||
entityNameToLinkableKeysMap,
|
||||
this[MedusaServiceEntityNameToLinkableKeysMapSymbol],
|
||||
{
|
||||
pick: config.returnLinkableKeys,
|
||||
}
|
||||
@@ -522,11 +351,23 @@ export function MedusaService<
|
||||
}
|
||||
|
||||
class AbstractModuleService_ {
|
||||
[MedusaServiceSymbol] = true
|
||||
|
||||
static [MedusaServiceModelObjectsSymbol] = Object.values(
|
||||
entities
|
||||
) as unknown as MedusaServiceReturnType<
|
||||
EntitiesConfig extends { __empty: any }
|
||||
? ModelConfigurationsToConfigTemplate<TEntities>
|
||||
: EntitiesConfig
|
||||
>["$modelObjects"];
|
||||
|
||||
[MedusaServiceEntityNameToLinkableKeysMapSymbol]: MapToConfig
|
||||
|
||||
readonly __container__: Record<any, any>
|
||||
readonly baseRepository_: RepositoryService
|
||||
readonly eventBusModuleService_: IEventBusModuleService;
|
||||
readonly eventBusModuleService_: IEventBusModuleService
|
||||
|
||||
[key: string]: any
|
||||
__joinerConfig?(): ModuleJoinerConfig
|
||||
|
||||
constructor(container: Record<any, any>) {
|
||||
this.__container__ = container
|
||||
@@ -539,6 +380,11 @@ export function MedusaService<
|
||||
this.eventBusModuleService_ = hasEventBusModuleService
|
||||
? this.__container__.eventBusModuleService
|
||||
: undefined
|
||||
|
||||
this[MedusaServiceEntityNameToLinkableKeysMapSymbol] =
|
||||
buildEntitiesNameToLinkableKeysMap(
|
||||
this.__joinerConfig?.()?.linkableKeys ?? {}
|
||||
)
|
||||
}
|
||||
|
||||
protected async emitEvents_(groupedEvents) {
|
||||
@@ -563,7 +409,7 @@ export function MedusaService<
|
||||
string,
|
||||
TEntities[keyof TEntities],
|
||||
Record<string, string>
|
||||
][] = Object.entries(entities).map(([name, config]) => [
|
||||
][] = Object.entries(entities as {}).map(([name, config]) => [
|
||||
name,
|
||||
config as TEntities[keyof TEntities],
|
||||
buildMethodNamesFromModel(name, config as TEntities[keyof TEntities]),
|
||||
|
||||
@@ -14,7 +14,7 @@ type Options = Partial<MikroORMOptions> & {
|
||||
| EntityClass<AnyEntity>
|
||||
| EntityClassGroup<AnyEntity>
|
||||
| EntitySchema
|
||||
| DmlEntity<any>
|
||||
| DmlEntity<any, any>
|
||||
)[]
|
||||
databaseName: string
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import { Constructor, 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
|
||||
* return a links object based on the DML objects
|
||||
* @param moduleName
|
||||
* @param service
|
||||
* @param loaders
|
||||
* @constructor
|
||||
*/
|
||||
export function Module<
|
||||
const Service extends Constructor<any>,
|
||||
const ModelObjects extends DmlEntity<any, any>[] = Service extends {
|
||||
$modelObjects: infer $DmlObjects
|
||||
}
|
||||
? $DmlObjects
|
||||
: [],
|
||||
Links = keyof ModelObjects extends never
|
||||
? Record<string, any>
|
||||
: InfersLinksConfig<ModelObjects>
|
||||
>({
|
||||
name = "",
|
||||
service,
|
||||
loaders,
|
||||
}: ModuleExports<Service> & { name?: string }): ModuleExports<Service> & {
|
||||
links: Links
|
||||
} {
|
||||
service.prototype.__joinerConfig ??= defineJoinerConfig(name)
|
||||
|
||||
const dmlObjects = service[MedusaServiceModelObjectsSymbol]
|
||||
return {
|
||||
service,
|
||||
loaders,
|
||||
links: (dmlObjects?.length
|
||||
? buildLinkConfigFromDmlObjects(dmlObjects)
|
||||
: {}) as Links,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
import {
|
||||
DMLSchema,
|
||||
IDmlEntityConfig,
|
||||
InferDmlEntityNameFromConfig,
|
||||
SnakeCase,
|
||||
} from "@medusajs/types"
|
||||
import { DmlEntity } from "../../dml"
|
||||
import { PrimaryKeyModifier } from "../../dml/properties/primary-key"
|
||||
|
||||
type FlattenUnion<T> = T extends { [K in keyof T]: infer U }
|
||||
? { [K in keyof T]: U }
|
||||
: never
|
||||
|
||||
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
|
||||
k: infer I
|
||||
) => void
|
||||
? I
|
||||
: never
|
||||
|
||||
type InferLinkableKeyName<
|
||||
Key,
|
||||
Property,
|
||||
DmlConfig extends IDmlEntityConfig
|
||||
> = Property extends PrimaryKeyModifier<any, any>
|
||||
? `${Lowercase<SnakeCase<InferDmlEntityNameFromConfig<DmlConfig>>>}_${Key &
|
||||
string}`
|
||||
: never
|
||||
|
||||
type InferSchemaLinkableKeys<T> = T extends DmlEntity<
|
||||
infer Schema,
|
||||
infer Config
|
||||
>
|
||||
? {
|
||||
[K in keyof Schema as Schema[K] extends PrimaryKeyModifier<any, any>
|
||||
? InferLinkableKeyName<K, Schema[K], Config>
|
||||
: never]: InferDmlEntityNameFromConfig<Config>
|
||||
}
|
||||
: {}
|
||||
|
||||
type InferSchemasLinkableKeys<T extends DmlEntity<any, any>[]> = {
|
||||
[K in keyof T]: InferSchemaLinkableKeys<T[K]>
|
||||
}
|
||||
|
||||
type AggregateSchemasLinkableKeys<T extends DmlEntity<any, any>[]> = {
|
||||
[K in keyof InferSchemasLinkableKeys<T>]: InferSchemasLinkableKeys<T>[K]
|
||||
}
|
||||
|
||||
/**
|
||||
* From an array of DmlEntity, returns a formatted object with the linkable keys
|
||||
*
|
||||
* @example:
|
||||
*
|
||||
* const user = model.define("user", {
|
||||
* id: model.id(),
|
||||
* name: model.text(),
|
||||
* })
|
||||
*
|
||||
* const car = model.define("car", {
|
||||
* id: model.id(),
|
||||
* number_plate: model.text().primaryKey(),
|
||||
* test: model.text(),
|
||||
* })
|
||||
*
|
||||
* const linkableKeys = buildLinkableKeysFromDmlObjects([user, car]) // { user_id: 'user', car_number_plate: 'car' }
|
||||
*
|
||||
*/
|
||||
export type InferLinkableKeys<T extends DmlEntity<any, any>[]> =
|
||||
UnionToIntersection<FlattenUnion<AggregateSchemasLinkableKeys<T>>[0]>
|
||||
|
||||
type InferPrimaryKeyNameOrNever<
|
||||
Schema extends DMLSchema,
|
||||
Key extends keyof Schema
|
||||
> = Schema[Key] extends PrimaryKeyModifier<any, any> ? Key : never
|
||||
|
||||
type InferSchemaLinksConfig<T> = T extends DmlEntity<infer Schema, infer Config>
|
||||
? {
|
||||
[K in keyof Schema as Schema[K] extends PrimaryKeyModifier<any, any>
|
||||
? InferPrimaryKeyNameOrNever<Schema, K>
|
||||
: never]: {
|
||||
linkable: InferLinkableKeyName<K, Schema[K], Config>
|
||||
primaryKey: K
|
||||
}
|
||||
}
|
||||
: {}
|
||||
|
||||
/**
|
||||
* From an array of DmlEntity, returns a formatted object with the linkable keys
|
||||
*
|
||||
* @example:
|
||||
*
|
||||
* const user = model.define("user", {
|
||||
* id: model.id(),
|
||||
* name: model.text(),
|
||||
* })
|
||||
*
|
||||
* const car = model.define("car", {
|
||||
* id: model.id(),
|
||||
* number_plate: model.text().primaryKey(),
|
||||
* test: model.text(),
|
||||
* })
|
||||
*
|
||||
* const linkConfig = buildLinkConfigFromDmlObjects([user, car])
|
||||
* // {
|
||||
* // user: {
|
||||
* // id: {
|
||||
* // linkable: 'user_id',
|
||||
* // primaryKey: 'id'
|
||||
* // },
|
||||
* // toJSON() { ... }
|
||||
* // },
|
||||
* // car: {
|
||||
* // number_plate: {
|
||||
* // linkable: 'car_number_plate',
|
||||
* // primaryKey: 'number_plate'
|
||||
* // },
|
||||
* // toJSON() { ... }
|
||||
* // }
|
||||
* // }
|
||||
*
|
||||
*/
|
||||
export type InfersLinksConfig<T extends DmlEntity<any, any>[]> =
|
||||
UnionToIntersection<{
|
||||
[K in keyof T as T[K] extends DmlEntity<any, infer Config>
|
||||
? Uncapitalize<InferDmlEntityNameFromConfig<Config>>
|
||||
: never]: InferSchemaLinksConfig<T[K]> & {
|
||||
toJSON: () => {
|
||||
linkable: string
|
||||
primaryKey: string
|
||||
}
|
||||
}
|
||||
}>
|
||||
@@ -0,0 +1,261 @@
|
||||
import {
|
||||
Constructor,
|
||||
Context,
|
||||
FindConfig,
|
||||
Pluralize,
|
||||
RestoreReturn,
|
||||
SoftDeleteReturn,
|
||||
} from "@medusajs/types"
|
||||
import { DmlEntity } from "../../dml"
|
||||
|
||||
export type BaseMethods =
|
||||
| "retrieve"
|
||||
| "list"
|
||||
| "listAndCount"
|
||||
| "delete"
|
||||
| "softDelete"
|
||||
| "restore"
|
||||
| "create"
|
||||
| "update"
|
||||
|
||||
export type ModelDTOConfig = {
|
||||
dto: object
|
||||
model?: DmlEntity<any, any>
|
||||
create?: any
|
||||
update?: any
|
||||
/**
|
||||
* @internal
|
||||
* @deprecated
|
||||
*/
|
||||
singular?: string
|
||||
/**
|
||||
* @internal
|
||||
* @deprecated
|
||||
*/
|
||||
plural?: string
|
||||
}
|
||||
|
||||
export type EntitiesConfigTemplate = { [key: string]: ModelDTOConfig }
|
||||
|
||||
export type ModelConfigurationsToConfigTemplate<T extends TEntityEntries> = {
|
||||
[Key in keyof T]: {
|
||||
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]
|
||||
: never
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
create: any
|
||||
update: any
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
singular: T[Key] extends { singular: string } ? T[Key]["singular"] : Key
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
plural: T[Key] extends { plural: string }
|
||||
? T[Key]["plural"]
|
||||
: Pluralize<Key & string>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated should all notion of singular and plural be removed once all modules are aligned with the convention
|
||||
*/
|
||||
export type ExtractSingularName<
|
||||
T extends Record<any, any>,
|
||||
K = keyof T
|
||||
> = Capitalize<
|
||||
T[K] extends { singular?: string } ? T[K]["singular"] & string : K & string
|
||||
>
|
||||
|
||||
/**
|
||||
* @deprecated should all notion of singular and plural be removed once all modules are aligned with the convention
|
||||
* The pluralize will move to where it should be used instead
|
||||
*/
|
||||
export type ExtractPluralName<
|
||||
T extends Record<any, any>,
|
||||
K = keyof T
|
||||
> = Capitalize<
|
||||
T[K] extends {
|
||||
plural?: string
|
||||
}
|
||||
? T[K]["plural"] & string
|
||||
: Pluralize<K & string>
|
||||
>
|
||||
|
||||
// TODO: The future expected entry will be a MODEL object but in the meantime we have to maintain backward compatibility for ouw own modules and therefore we need to support Constructor<any> as well as this temporary object
|
||||
export type TEntityEntries<Keys = string> = Record<
|
||||
Keys & string,
|
||||
| DmlEntity<any, any>
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
| Constructor<any>
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
| { name?: string; singular?: string; plural?: string }
|
||||
>
|
||||
|
||||
export type ExtractKeysFromConfig<EntitiesConfig> = EntitiesConfig extends {
|
||||
__empty: any
|
||||
}
|
||||
? string
|
||||
: keyof EntitiesConfig
|
||||
|
||||
export type AbstractModuleService<
|
||||
TEntitiesDtoConfig extends Record<string, any>
|
||||
> = {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `retrieve${ExtractSingularName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: (
|
||||
id: string,
|
||||
config?: FindConfig<any>,
|
||||
sharedContext?: Context
|
||||
) => Promise<TEntitiesDtoConfig[TEntityName]["dto"]>
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `list${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: (
|
||||
filters?: any,
|
||||
config?: FindConfig<any>,
|
||||
sharedContext?: Context
|
||||
) => Promise<TEntitiesDtoConfig[TEntityName]["dto"][]>
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `listAndCount${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
(filters?: any, config?: FindConfig<any>, sharedContext?: Context): Promise<
|
||||
[TEntitiesDtoConfig[TEntityName]["dto"][], number]
|
||||
>
|
||||
}
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `delete${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
(
|
||||
primaryKeyValues: string | object | string[] | object[],
|
||||
sharedContext?: Context
|
||||
): Promise<void>
|
||||
}
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `softDelete${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
<TReturnableLinkableKeys extends string>(
|
||||
primaryKeyValues: string | object | string[] | object[],
|
||||
config?: SoftDeleteReturn<TReturnableLinkableKeys>,
|
||||
sharedContext?: Context
|
||||
): Promise<Record<string, string[]> | void>
|
||||
}
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `restore${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
<TReturnableLinkableKeys extends string>(
|
||||
primaryKeyValues: string | object | string[] | object[],
|
||||
config?: RestoreReturn<TReturnableLinkableKeys>,
|
||||
sharedContext?: Context
|
||||
): Promise<Record<string, string[]> | void>
|
||||
}
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `create${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
(...args: any[]): Promise<any>
|
||||
}
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `update${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
(...args: any[]): Promise<any>
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Because of a bug, those methods were not made visible which now cause issues with the fix as our interface are not consistent with the expectations
|
||||
|
||||
// are not consistent accross modules
|
||||
/* & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `create${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
(data: any[], sharedContext?: Context): Promise<
|
||||
TEntitiesDtoConfig[TEntityName]["dto"][]
|
||||
>
|
||||
}
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `create${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
(data: any, sharedContext?: Context): Promise<
|
||||
TEntitiesDtoConfig[TEntityName]["dto"][]
|
||||
>
|
||||
}
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `update${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
(
|
||||
data: TEntitiesDtoConfig[TEntityName]["update"][],
|
||||
sharedContext?: Context
|
||||
): Promise<TEntitiesDtoConfig[TEntityName]["dto"][]>
|
||||
}
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `update${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
(
|
||||
data: TEntitiesDtoConfig[TEntityName]["update"],
|
||||
sharedContext?: Context
|
||||
): Promise<TEntitiesDtoConfig[TEntityName]["dto"]>
|
||||
}
|
||||
} & {
|
||||
[TEntityName in keyof TEntitiesDtoConfig as `update${ExtractPluralName<
|
||||
TEntitiesDtoConfig,
|
||||
TEntityName
|
||||
>}`]: {
|
||||
(
|
||||
idOrdSelector: any,
|
||||
data: TEntitiesDtoConfig[TEntityName]["update"],
|
||||
sharedContext?: Context
|
||||
): Promise<TEntitiesDtoConfig[TEntityName]["dto"][]>
|
||||
}
|
||||
}*/
|
||||
|
||||
type InferModelFromConfig<T> = {
|
||||
[K in keyof T as T[K] extends { model: any }
|
||||
? K
|
||||
: K extends DmlEntity<any, any>
|
||||
? K
|
||||
: never]: T[K] extends {
|
||||
model: infer MODEL
|
||||
}
|
||||
? MODEL extends DmlEntity<any, any>
|
||||
? MODEL
|
||||
: never
|
||||
: T[K] extends DmlEntity<any, any>
|
||||
? T[K]
|
||||
: never
|
||||
}
|
||||
|
||||
export type MedusaServiceReturnType<ModelsConfig extends Record<any, any>> = {
|
||||
new (...args: any[]): AbstractModuleService<ModelsConfig>
|
||||
$modelObjects: InferModelFromConfig<ModelsConfig>[keyof InferModelFromConfig<ModelsConfig>][]
|
||||
}
|
||||
@@ -1,11 +1,3 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.API_KEY)
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
ModuleJoinerConfig,
|
||||
ModulesSdkTypes,
|
||||
} from "@medusajs/types"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
import { ApiKey } from "@models"
|
||||
import {
|
||||
CreateApiKeyDTO,
|
||||
@@ -41,7 +41,7 @@ type InjectedDependencies = {
|
||||
export default class ApiKeyModuleService
|
||||
extends MedusaService<{
|
||||
ApiKey: { dto: ApiKeyTypes.ApiKeyDTO }
|
||||
}>({ ApiKey }, entityNameToLinkableKeysMap)
|
||||
}>({ ApiKey })
|
||||
implements IApiKeyModuleService
|
||||
{
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
import { AuthIdentity } from "@models"
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.AUTH, {
|
||||
entityQueryingConfig: [AuthIdentity],
|
||||
models: [AuthIdentity],
|
||||
})
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
|
||||
import { AuthIdentity, ProviderIdentity } from "@models"
|
||||
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
|
||||
import {
|
||||
InjectManager,
|
||||
@@ -32,7 +32,7 @@ export default class AuthModuleService
|
||||
extends MedusaService<{
|
||||
AuthIdentity: { dto: AuthTypes.AuthIdentityDTO }
|
||||
ProviderIdentity: { dto: AuthTypes.ProviderIdentityDTO }
|
||||
}>({ AuthIdentity, ProviderIdentity }, entityNameToLinkableKeysMap)
|
||||
}>({ AuthIdentity, ProviderIdentity })
|
||||
implements AuthTypes.IAuthModuleService
|
||||
{
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.CART)
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -39,7 +39,7 @@ import {
|
||||
UpdateLineItemDTO,
|
||||
UpdateShippingMethodTaxLineDTO,
|
||||
} from "@types"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
|
||||
type InjectedDependencies = {
|
||||
baseRepository: DAL.RepositoryService
|
||||
@@ -74,7 +74,7 @@ export default class CartModuleService
|
||||
ShippingMethod: { dto: CartTypes.CartShippingMethodDTO }
|
||||
ShippingMethodAdjustment: { dto: CartTypes.ShippingMethodAdjustmentDTO }
|
||||
ShippingMethodTaxLine: { dto: CartTypes.ShippingMethodTaxLineDTO }
|
||||
}>(generateMethodForModels, entityNameToLinkableKeysMap)
|
||||
}>(generateMethodForModels)
|
||||
implements ICartModuleService
|
||||
{
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { CurrencyModuleService } from "@services"
|
||||
import initialDataLoader from "./loaders/initial-data"
|
||||
import { ModuleExports } from "@medusajs/types"
|
||||
import { Module, Modules } from "@medusajs/utils"
|
||||
|
||||
const service = CurrencyModuleService
|
||||
const loaders = [initialDataLoader]
|
||||
|
||||
export const moduleDefinition: ModuleExports = {
|
||||
export default Module({
|
||||
name: Modules.CURRENCY,
|
||||
service,
|
||||
loaders,
|
||||
}
|
||||
|
||||
export default moduleDefinition
|
||||
})
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.CURRENCY, {
|
||||
primaryKeys: ["code"],
|
||||
@@ -11,6 +6,3 @@ export const joinerConfig = defineJoinerConfig(Modules.CURRENCY, {
|
||||
currency_code: "currency",
|
||||
},
|
||||
})
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { model } from "@medusajs/utils"
|
||||
|
||||
export default model.define("currency", {
|
||||
code: model.text().primaryKey().searchable(),
|
||||
code: model.text().searchable().primaryKey(),
|
||||
symbol: model.text(),
|
||||
symbol_native: model.text(),
|
||||
name: model.text().searchable(),
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
|
||||
import { MedusaService } from "@medusajs/utils"
|
||||
import { Currency } from "@models"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
|
||||
type InjectedDependencies = {
|
||||
baseRepository: DAL.RepositoryService
|
||||
@@ -22,8 +22,8 @@ type InjectedDependencies = {
|
||||
|
||||
export default class CurrencyModuleService
|
||||
extends MedusaService<{
|
||||
Currency: { dto: CurrencyTypes.CurrencyDTO }
|
||||
}>({ Currency }, entityNameToLinkableKeysMap)
|
||||
Currency: { dto: CurrencyTypes.CurrencyDTO; model: typeof Currency }
|
||||
}>({ Currency })
|
||||
implements ICurrencyModuleService
|
||||
{
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.CUSTOMER, {
|
||||
alias: [
|
||||
@@ -16,6 +11,3 @@ export const joinerConfig = defineJoinerConfig(Modules.CUSTOMER, {
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
CustomerGroup,
|
||||
CustomerGroupCustomer,
|
||||
} from "@models"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
|
||||
type InjectedDependencies = {
|
||||
baseRepository: DAL.RepositoryService
|
||||
@@ -42,10 +42,7 @@ export default class CustomerModuleService
|
||||
Customer: { dto: CustomerDTO }
|
||||
CustomerGroup: { dto: CustomerGroupDTO }
|
||||
CustomerGroupCustomer: { dto: CustomerGroupCustomerDTO }
|
||||
}>(
|
||||
{ Address, Customer, CustomerGroup, CustomerGroupCustomer },
|
||||
entityNameToLinkableKeysMap
|
||||
)
|
||||
}>({ Address, Customer, CustomerGroup, CustomerGroupCustomer })
|
||||
implements ICustomerModuleService
|
||||
{
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.FILE, {
|
||||
entityQueryingConfig: [{ name: "File" }],
|
||||
models: [{ name: "File" }],
|
||||
})
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap({})
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
import {
|
||||
Fulfillment,
|
||||
FulfillmentSet,
|
||||
@@ -19,6 +14,3 @@ export const joinerConfig = defineJoinerConfig(Modules.FULFILLMENT, {
|
||||
shipping_option_rule_id: ShippingOptionRule.name,
|
||||
},
|
||||
})
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -47,7 +47,7 @@ import {
|
||||
isContextValid,
|
||||
validateAndNormalizeRules,
|
||||
} from "@utils"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
import { UpdateShippingOptionsInput } from "../types/service"
|
||||
import { buildCreatedShippingOptionEvents } from "../utils/events"
|
||||
import FulfillmentProviderService from "./fulfillment-provider"
|
||||
@@ -87,7 +87,7 @@ export default class FulfillmentModuleService
|
||||
ShippingOptionRule: { dto: FulfillmentTypes.ShippingOptionRuleDTO }
|
||||
ShippingOptionType: { dto: FulfillmentTypes.ShippingOptionTypeDTO }
|
||||
FulfillmentProvider: { dto: FulfillmentTypes.FulfillmentProviderDTO }
|
||||
}>(generateMethodForModels, entityNameToLinkableKeysMap)
|
||||
}>(generateMethodForModels)
|
||||
implements IFulfillmentModuleService
|
||||
{
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.INVENTORY, {
|
||||
alias: [
|
||||
@@ -35,6 +30,3 @@ export const joinerConfig = defineJoinerConfig(Modules.INVENTORY, {
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -8,9 +8,10 @@ type InjectedDependencies = {
|
||||
inventoryLevelRepository: InventoryLevelRepository
|
||||
}
|
||||
|
||||
export default class InventoryLevelService extends ModulesSdkUtils.MedusaInternalService<InjectedDependencies>(
|
||||
export default class InventoryLevelService extends ModulesSdkUtils.MedusaInternalService<
|
||||
InjectedDependencies,
|
||||
InventoryLevel
|
||||
)<InventoryLevel> {
|
||||
>(InventoryLevel) {
|
||||
protected readonly inventoryLevelRepository: InventoryLevelRepository
|
||||
|
||||
constructor(container: InjectedDependencies) {
|
||||
|
||||
@@ -11,22 +11,22 @@ import {
|
||||
} from "@medusajs/types"
|
||||
import { IInventoryService } from "@medusajs/types/dist/inventory"
|
||||
import {
|
||||
arrayDifference,
|
||||
CommonEvents,
|
||||
EmitEvents,
|
||||
InjectManager,
|
||||
InjectTransactionManager,
|
||||
InventoryEvents,
|
||||
isDefined,
|
||||
isString,
|
||||
MedusaContext,
|
||||
MedusaError,
|
||||
MedusaService,
|
||||
arrayDifference,
|
||||
isDefined,
|
||||
isString,
|
||||
partitionArray,
|
||||
promiseAll,
|
||||
} from "@medusajs/utils"
|
||||
import { InventoryItem, InventoryLevel, ReservationItem } from "@models"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
import InventoryLevelService from "./inventory-level"
|
||||
|
||||
type InjectedDependencies = {
|
||||
@@ -47,14 +47,11 @@ export default class InventoryModuleService
|
||||
ReservationItem: {
|
||||
dto: InventoryTypes.ReservationItemDTO
|
||||
}
|
||||
}>(
|
||||
{
|
||||
InventoryItem,
|
||||
InventoryLevel,
|
||||
ReservationItem,
|
||||
},
|
||||
entityNameToLinkableKeysMap
|
||||
)
|
||||
}>({
|
||||
InventoryItem,
|
||||
InventoryLevel,
|
||||
ReservationItem,
|
||||
})
|
||||
implements IInventoryService
|
||||
{
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.NOTIFICATION, {
|
||||
entityQueryingConfig: [{ name: "Notification" }],
|
||||
models: [{ name: "Notification" }],
|
||||
})
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import {
|
||||
Context,
|
||||
DAL,
|
||||
InferEntityType,
|
||||
INotificationModuleService,
|
||||
InternalModuleDeclaration,
|
||||
ModuleJoinerConfig,
|
||||
ModulesSdkTypes,
|
||||
NotificationTypes,
|
||||
InferEntityType,
|
||||
} from "@medusajs/types"
|
||||
import {
|
||||
InjectManager,
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
promiseAll,
|
||||
} from "@medusajs/utils"
|
||||
import { Notification } from "@models"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
import NotificationProviderService from "./notification-provider"
|
||||
|
||||
type InjectedDependencies = {
|
||||
@@ -31,7 +31,7 @@ type InjectedDependencies = {
|
||||
export default class NotificationModuleService
|
||||
extends MedusaService<{
|
||||
Notification: { dto: NotificationTypes.NotificationDTO }
|
||||
}>({ Notification }, entityNameToLinkableKeysMap)
|
||||
}>({ Notification })
|
||||
implements INotificationModuleService
|
||||
{
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
|
||||
@@ -12,9 +12,10 @@ type InjectedDependencies = {
|
||||
]: NotificationTypes.INotificationProvider
|
||||
}
|
||||
|
||||
export default class NotificationProviderService extends ModulesSdkUtils.MedusaInternalService<InjectedDependencies>(
|
||||
NotificationProvider
|
||||
) {
|
||||
export default class NotificationProviderService extends ModulesSdkUtils.MedusaInternalService<
|
||||
InjectedDependencies,
|
||||
typeof NotificationProvider
|
||||
>(NotificationProvider) {
|
||||
protected readonly notificationProviderRepository_: DAL.RepositoryService<
|
||||
InferEntityType<typeof NotificationProvider>
|
||||
>
|
||||
@@ -50,6 +51,8 @@ export default class NotificationProviderService extends ModulesSdkUtils.MedusaI
|
||||
): Promise<InferEntityType<typeof NotificationProvider> | undefined> {
|
||||
if (!this.providersCache) {
|
||||
const providers = await this.notificationProviderRepository_.find()
|
||||
|
||||
type name = (typeof NotificationProvider)["name"]
|
||||
this.providersCache = new Map(
|
||||
providers.flatMap((provider) =>
|
||||
provider.channels.map((c) => [c, provider])
|
||||
|
||||
@@ -1,12 +1,4 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
|
||||
// TODO: review configuration
|
||||
export const joinerConfig = defineJoinerConfig(Modules.ORDER)
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -20,9 +20,10 @@ type InjectedDependencies = {
|
||||
orderChangeRepository: DAL.RepositoryService
|
||||
}
|
||||
|
||||
export default class OrderChangeService extends ModulesSdkUtils.MedusaInternalService<InjectedDependencies>(
|
||||
export default class OrderChangeService extends ModulesSdkUtils.MedusaInternalService<
|
||||
InjectedDependencies,
|
||||
OrderChange
|
||||
)<OrderChange> {
|
||||
>(OrderChange) {
|
||||
protected readonly orderChangeRepository_: RepositoryService<OrderChange>
|
||||
|
||||
constructor(container: InjectedDependencies) {
|
||||
|
||||
@@ -65,7 +65,7 @@ import {
|
||||
UpdateOrderLineItemTaxLineDTO,
|
||||
UpdateOrderShippingMethodTaxLineDTO,
|
||||
} from "@types"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
import {
|
||||
applyChangesToOrder,
|
||||
ApplyOrderChangeDTO,
|
||||
@@ -165,7 +165,7 @@ export default class OrderModuleService<
|
||||
ReturnItem: { dto: any } // TODO: Add return item dto
|
||||
OrderClaim: { dto: any } // TODO: Add claim dto
|
||||
OrderExchange: { dto: any } // TODO: Add exchange dto
|
||||
}>(generateMethodForModels, entityNameToLinkableKeysMap)
|
||||
}>(generateMethodForModels)
|
||||
implements IOrderModuleService
|
||||
{
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
|
||||
@@ -17,9 +17,10 @@ type InjectedDependencies = {
|
||||
orderRepository: DAL.RepositoryService
|
||||
}
|
||||
|
||||
export default class OrderService extends ModulesSdkUtils.MedusaInternalService<InjectedDependencies>(
|
||||
export default class OrderService extends ModulesSdkUtils.MedusaInternalService<
|
||||
InjectedDependencies,
|
||||
Order
|
||||
)<Order> {
|
||||
>(Order) {
|
||||
protected readonly orderRepository_: RepositoryService<Order>
|
||||
|
||||
constructor(container: InjectedDependencies) {
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
import {
|
||||
Payment,
|
||||
PaymentCollection,
|
||||
@@ -12,18 +7,10 @@ import {
|
||||
} from "@models"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.PAYMENT, {
|
||||
entityQueryingConfig: [
|
||||
Payment,
|
||||
PaymentCollection,
|
||||
PaymentProvider,
|
||||
PaymentSession,
|
||||
],
|
||||
models: [Payment, PaymentCollection, PaymentProvider, PaymentSession],
|
||||
linkableKeys: {
|
||||
payment_id: Payment.name,
|
||||
payment_collection_id: PaymentCollection.name,
|
||||
payment_provider_id: PaymentProvider.name,
|
||||
},
|
||||
})
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -48,7 +48,7 @@ import {
|
||||
PaymentSession,
|
||||
Refund,
|
||||
} from "@models"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
import PaymentProviderService from "./payment-provider"
|
||||
|
||||
type InjectedDependencies = {
|
||||
@@ -76,7 +76,7 @@ export default class PaymentModuleService
|
||||
Payment: { dto: PaymentDTO }
|
||||
Capture: { dto: CaptureDTO }
|
||||
Refund: { dto: RefundDTO }
|
||||
}>(generateMethodForModels, entityNameToLinkableKeysMap)
|
||||
}>(generateMethodForModels)
|
||||
implements IPaymentModuleService
|
||||
{
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
|
||||
@@ -1,19 +1,11 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
import { Price, PriceList, PriceSet } from "@models"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.PRICING, {
|
||||
entityQueryingConfig: [PriceSet, PriceList, Price],
|
||||
models: [PriceSet, PriceList, Price],
|
||||
linkableKeys: {
|
||||
price_set_id: PriceSet.name,
|
||||
price_list_id: PriceList.name,
|
||||
price_id: Price.name,
|
||||
},
|
||||
})
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -38,7 +38,7 @@ import { Price, PriceList, PriceListRule, PriceRule, PriceSet } from "@models"
|
||||
|
||||
import { ServiceTypes } from "@types"
|
||||
import { eventBuilders, validatePriceListDates } from "@utils"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
import { CreatePriceListDTO, UpsertPriceDTO } from "src/types/services"
|
||||
|
||||
type InjectedDependencies = {
|
||||
@@ -70,7 +70,7 @@ export default class PricingModuleService
|
||||
}
|
||||
PriceList: { dto: PricingTypes.PriceListDTO }
|
||||
PriceListRule: { dto: PricingTypes.PriceListRuleDTO }
|
||||
}>(generateMethodForModels, entityNameToLinkableKeysMap)
|
||||
}>(generateMethodForModels)
|
||||
implements PricingTypes.IPricingModuleService
|
||||
{
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.PRODUCT, {
|
||||
primaryKeys: ["id", "handle"],
|
||||
// This module provides more alias than the default config builder
|
||||
alias: [
|
||||
{
|
||||
@@ -58,6 +54,3 @@ export const joinerConfig = defineJoinerConfig(Modules.PRODUCT, {
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -51,7 +51,7 @@ import {
|
||||
UpdateTypeInput,
|
||||
} from "../types"
|
||||
import { eventBuilders } from "../utils"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "./../joiner-config"
|
||||
import { joinerConfig } from "./../joiner-config"
|
||||
|
||||
type InjectedDependencies = {
|
||||
baseRepository: DAL.RepositoryService
|
||||
@@ -90,18 +90,15 @@ export default class ProductModuleService
|
||||
ProductVariant: {
|
||||
dto: ProductTypes.ProductVariantDTO
|
||||
}
|
||||
}>(
|
||||
{
|
||||
Product,
|
||||
ProductCategory,
|
||||
ProductCollection,
|
||||
ProductOption,
|
||||
ProductTag,
|
||||
ProductType,
|
||||
ProductVariant,
|
||||
},
|
||||
entityNameToLinkableKeysMap
|
||||
)
|
||||
}>({
|
||||
Product,
|
||||
ProductCategory,
|
||||
ProductCollection,
|
||||
ProductOption,
|
||||
ProductTag,
|
||||
ProductType,
|
||||
ProductVariant,
|
||||
})
|
||||
implements ProductTypes.IProductModuleService
|
||||
{
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
|
||||
@@ -18,9 +18,10 @@ type NormalizedFilterableProductProps = ProductTypes.FilterableProductProps & {
|
||||
}
|
||||
}
|
||||
|
||||
export default class ProductService extends ModulesSdkUtils.MedusaInternalService<InjectedDependencies>(
|
||||
export default class ProductService extends ModulesSdkUtils.MedusaInternalService<
|
||||
InjectedDependencies,
|
||||
Product
|
||||
)<Product> {
|
||||
>(Product) {
|
||||
protected readonly productRepository_: DAL.RepositoryService<Product>
|
||||
|
||||
constructor({ productRepository }: InjectedDependencies) {
|
||||
|
||||
@@ -1,19 +1,11 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
import { Campaign, Promotion, PromotionRule } from "@models"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.PROMOTION, {
|
||||
entityQueryingConfig: [Promotion, Campaign, PromotionRule],
|
||||
models: [Promotion, Campaign, PromotionRule],
|
||||
linkableKeys: {
|
||||
promotion_id: Promotion.name,
|
||||
campaign_id: Campaign.name,
|
||||
promotion_rule_id: PromotionRule.name,
|
||||
},
|
||||
})
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -23,7 +23,6 @@ import {
|
||||
MedusaContext,
|
||||
MedusaError,
|
||||
MedusaService,
|
||||
ModulesSdkUtils,
|
||||
PromotionType,
|
||||
transformPropertiesToBigNumber,
|
||||
} from "@medusajs/utils"
|
||||
@@ -54,7 +53,7 @@ import {
|
||||
validateApplicationMethodAttributes,
|
||||
validatePromotionRuleAttributes,
|
||||
} from "@utils"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
import { CreatePromotionRuleValueDTO } from "../types/promotion-rule-value"
|
||||
|
||||
type InjectedDependencies = {
|
||||
@@ -75,17 +74,14 @@ export default class PromotionModuleService
|
||||
CampaignBudget: { dto: PromotionTypes.CampaignBudgetDTO }
|
||||
PromotionRule: { dto: PromotionTypes.PromotionRuleDTO }
|
||||
PromotionRuleValue: { dto: PromotionTypes.PromotionRuleValueDTO }
|
||||
}>(
|
||||
{
|
||||
Promotion,
|
||||
ApplicationMethod,
|
||||
Campaign,
|
||||
CampaignBudget,
|
||||
PromotionRule,
|
||||
PromotionRuleValue,
|
||||
},
|
||||
entityNameToLinkableKeysMap
|
||||
)
|
||||
}>({
|
||||
Promotion,
|
||||
ApplicationMethod,
|
||||
Campaign,
|
||||
CampaignBudget,
|
||||
PromotionRule,
|
||||
PromotionRuleValue,
|
||||
})
|
||||
implements PromotionTypes.IPromotionModuleService
|
||||
{
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.REGION)
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -3,9 +3,9 @@ import {
|
||||
CreateRegionDTO,
|
||||
DAL,
|
||||
FilterableRegionProps,
|
||||
IRegionModuleService,
|
||||
InferEntityType,
|
||||
InternalModuleDeclaration,
|
||||
IRegionModuleService,
|
||||
ModuleJoinerConfig,
|
||||
ModulesSdkTypes,
|
||||
RegionCountryDTO,
|
||||
@@ -15,20 +15,20 @@ import {
|
||||
UpsertRegionDTO,
|
||||
} from "@medusajs/types"
|
||||
import {
|
||||
arrayDifference,
|
||||
getDuplicates,
|
||||
InjectManager,
|
||||
InjectTransactionManager,
|
||||
isString,
|
||||
MedusaContext,
|
||||
MedusaError,
|
||||
MedusaService,
|
||||
arrayDifference,
|
||||
getDuplicates,
|
||||
isString,
|
||||
promiseAll,
|
||||
removeUndefined,
|
||||
} from "@medusajs/utils"
|
||||
import { RegionCountry as Country, Region } from "@models"
|
||||
import { Region, RegionCountry as Country } from "@models"
|
||||
import { UpdateRegionInput } from "@types"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
|
||||
type InjectedDependencies = {
|
||||
baseRepository: DAL.RepositoryService
|
||||
@@ -44,7 +44,7 @@ export default class RegionModuleService
|
||||
Country: {
|
||||
dto: RegionCountryDTO
|
||||
}
|
||||
}>({ Region, Country }, entityNameToLinkableKeysMap)
|
||||
}>({ Region, Country })
|
||||
implements IRegionModuleService
|
||||
{
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.SALES_CHANNEL)
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
ModulesSdkTypes,
|
||||
SalesChannelDTO,
|
||||
UpdateSalesChannelDTO,
|
||||
UpsertSalesChannelDTO,
|
||||
} from "@medusajs/types"
|
||||
import {
|
||||
InjectManager,
|
||||
@@ -20,10 +21,8 @@ import {
|
||||
} from "@medusajs/utils"
|
||||
|
||||
import { SalesChannel } from "@models"
|
||||
|
||||
import { UpsertSalesChannelDTO } from "@medusajs/types"
|
||||
import { UpdateSalesChanneInput } from "@types"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
|
||||
type InjectedDependencies = {
|
||||
baseRepository: DAL.RepositoryService
|
||||
@@ -31,10 +30,9 @@ type InjectedDependencies = {
|
||||
}
|
||||
|
||||
export default class SalesChannelModuleService
|
||||
extends MedusaService<{ SalesChannel: { dto: SalesChannelDTO } }>(
|
||||
{ SalesChannel },
|
||||
entityNameToLinkableKeysMap
|
||||
)
|
||||
extends MedusaService<{ SalesChannel: { dto: SalesChannelDTO } }>({
|
||||
SalesChannel,
|
||||
})
|
||||
implements ISalesChannelModuleService
|
||||
{
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
import { StockLocation } from "./models"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.STOCK_LOCATION, {
|
||||
@@ -12,6 +7,3 @@ export const joinerConfig = defineJoinerConfig(Modules.STOCK_LOCATION, {
|
||||
location_id: StockLocation.name,
|
||||
},
|
||||
})
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
MedusaService,
|
||||
promiseAll,
|
||||
} from "@medusajs/utils"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
import { StockLocation, StockLocationAddress } from "../models"
|
||||
|
||||
type InjectedDependencies = {
|
||||
@@ -38,7 +38,7 @@ export default class StockLocationModuleService
|
||||
extends MedusaService<{
|
||||
StockLocation: { dto: StockLocationTypes.StockLocationDTO }
|
||||
StockLocationAddress: { dto: StockLocationTypes.StockLocationAddressDTO }
|
||||
}>({ StockLocation, StockLocationAddress }, entityNameToLinkableKeysMap)
|
||||
}>({ StockLocation, StockLocationAddress })
|
||||
implements IStockLocationService
|
||||
{
|
||||
protected readonly eventBusModuleService_: IEventBusService
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.STORE)
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
} from "@medusajs/utils"
|
||||
|
||||
import { Store, StoreCurrency } from "@models"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
import { UpdateStoreInput } from "@types"
|
||||
|
||||
type InjectedDependencies = {
|
||||
@@ -32,7 +32,7 @@ export default class StoreModuleService
|
||||
extends MedusaService<{
|
||||
Store: { dto: StoreTypes.StoreDTO }
|
||||
StoreCurrency: { dto: StoreTypes.StoreCurrencyDTO }
|
||||
}>({ Store, StoreCurrency }, entityNameToLinkableKeysMap)
|
||||
}>({ Store, StoreCurrency })
|
||||
implements IStoreModuleService
|
||||
{
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.TAX)
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
promiseAll,
|
||||
} from "@medusajs/utils"
|
||||
import { TaxProvider, TaxRate, TaxRateRule, TaxRegion } from "@models"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
|
||||
type InjectedDependencies = {
|
||||
baseRepository: DAL.RepositoryService
|
||||
@@ -44,7 +44,7 @@ export default class TaxModuleService
|
||||
TaxRegion: { dto: TaxTypes.TaxRegionDTO }
|
||||
TaxRateRule: { dto: TaxTypes.TaxRateRuleDTO }
|
||||
TaxProvider: { dto: TaxTypes.TaxProviderDTO }
|
||||
}>(generateForModels, entityNameToLinkableKeysMap)
|
||||
}>(generateForModels)
|
||||
implements ITaxModuleService
|
||||
{
|
||||
protected readonly container_: InjectedDependencies
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.USER)
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
UserEvents,
|
||||
} from "@medusajs/utils"
|
||||
import jwt, { JwtPayload } from "jsonwebtoken"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
import crypto from "node:crypto"
|
||||
|
||||
import { Invite, User } from "@models"
|
||||
@@ -41,7 +41,7 @@ export default class UserModuleService
|
||||
Invite: {
|
||||
dto: UserTypes.InviteDTO
|
||||
}
|
||||
}>({ User, Invite }, entityNameToLinkableKeysMap)
|
||||
}>({ User, Invite })
|
||||
implements UserTypes.IUserModuleService
|
||||
{
|
||||
__joinerConfig(): ModuleJoinerConfig {
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.WORKFLOW_ENGINE)
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -17,7 +17,7 @@ import type {
|
||||
} from "@medusajs/workflows-sdk"
|
||||
import { WorkflowExecution } from "@models"
|
||||
import { WorkflowOrchestratorService } from "@services"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
|
||||
type InjectedDependencies = {
|
||||
baseRepository: DAL.RepositoryService
|
||||
@@ -29,7 +29,7 @@ export class WorkflowsModuleService<
|
||||
TWorkflowExecution extends WorkflowExecution = WorkflowExecution
|
||||
> extends ModulesSdkUtils.MedusaService<{
|
||||
WorkflowExecution: { dto: WorkflowExecution }
|
||||
}>({ WorkflowExecution }, entityNameToLinkableKeysMap) {
|
||||
}>({ WorkflowExecution }) {
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
protected workflowExecutionService_: ModulesSdkTypes.IMedusaInternalService<TWorkflowExecution>
|
||||
protected workflowOrchestratorService_: WorkflowOrchestratorService
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
Modules,
|
||||
} from "@medusajs/utils"
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.WORKFLOW_ENGINE)
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -17,7 +17,7 @@ import type {
|
||||
} from "@medusajs/workflows-sdk"
|
||||
import { WorkflowExecution } from "@models"
|
||||
import { WorkflowOrchestratorService } from "@services"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
|
||||
type InjectedDependencies = {
|
||||
baseRepository: DAL.RepositoryService
|
||||
@@ -30,7 +30,7 @@ export class WorkflowsModuleService<
|
||||
TWorkflowExecution extends WorkflowExecution = WorkflowExecution
|
||||
> extends ModulesSdkUtils.MedusaService<{
|
||||
WorkflowExecution: { dto: WorkflowExecution }
|
||||
}>({ WorkflowExecution }, entityNameToLinkableKeysMap) {
|
||||
}>({ WorkflowExecution }) {
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
protected workflowExecutionService_: ModulesSdkTypes.IMedusaInternalService<TWorkflowExecution>
|
||||
protected workflowOrchestratorService_: WorkflowOrchestratorService
|
||||
|
||||
Reference in New Issue
Block a user