fix(medusa): model loader with customizations (#4443)
* fix(medusa): model loader with customizations * fix plugin models loader * Create late-insects-punch.md * Address pr feedback * remove unnecessary bits * remove unnecessary bits * fix * remove unnecessary changes * rm duplicate param jsdoc
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix(medusa): model loader with customizations
|
||||||
@@ -12,7 +12,7 @@ describe("models loader", () => {
|
|||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
try {
|
try {
|
||||||
models = await modelsLoader({
|
models = modelsLoader({
|
||||||
container,
|
container,
|
||||||
isTest: true,
|
isTest: true,
|
||||||
coreTestPathGlob: "../models/{product,product-variant}.ts",
|
coreTestPathGlob: "../models/{product,product-variant}.ts",
|
||||||
@@ -30,9 +30,9 @@ describe("models loader", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("ensure that the product model is an extended model", () => {
|
it("ensure that the product model is an extended model", () => {
|
||||||
const productModel = models.find((model) => model.name === "Product")
|
const productModel = container.resolve("productModel")
|
||||||
|
|
||||||
expect(new productModel().custom_attribute).toEqual("test")
|
expect(productModel.custom_attribute).toEqual("test")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("ensure that the extended product model is registered in db_entities", () => {
|
it("ensure that the extended product model is registered in db_entities", () => {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import path from "path"
|
|||||||
import { ClassConstructor, MedusaContainer } from "../types/global"
|
import { ClassConstructor, MedusaContainer } from "../types/global"
|
||||||
import { EntitySchema } from "typeorm"
|
import { EntitySchema } from "typeorm"
|
||||||
import { asClass, asValue } from "awilix"
|
import { asClass, asValue } from "awilix"
|
||||||
|
import { upperCaseFirst } from "@medusajs/utils"
|
||||||
|
|
||||||
type ModelLoaderParams = {
|
type ModelLoaderParams = {
|
||||||
container: MedusaContainer
|
container: MedusaContainer
|
||||||
@@ -62,8 +63,9 @@ export default (
|
|||||||
// If an extension file is found, override it with that instead
|
// If an extension file is found, override it with that instead
|
||||||
if (mappedExtensionModel) {
|
if (mappedExtensionModel) {
|
||||||
const coreModel = require(modelPath)
|
const coreModel = require(modelPath)
|
||||||
const modelName =
|
const modelName = upperCaseFirst(
|
||||||
formatRegistrationNameWithoutNamespace(modelPath)
|
formatRegistrationNameWithoutNamespace(modelPath)
|
||||||
|
)
|
||||||
|
|
||||||
coreModel[modelName] = mappedExtensionModel
|
coreModel[modelName] = mappedExtensionModel
|
||||||
val = mappedExtensionModel
|
val = mappedExtensionModel
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { SearchUtils } from "@medusajs/utils"
|
import { SearchUtils, upperCaseFirst } from "@medusajs/utils"
|
||||||
import { aliasTo, asFunction, asValue, Lifetime } from "awilix"
|
import { aliasTo, asFunction, asValue, Lifetime } from "awilix"
|
||||||
import { Express } from "express"
|
import { Express } from "express"
|
||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
@@ -100,7 +100,7 @@ export default async ({
|
|||||||
function getResolvedPlugins(
|
function getResolvedPlugins(
|
||||||
rootDirectory: string,
|
rootDirectory: string,
|
||||||
configModule: ConfigModule,
|
configModule: ConfigModule,
|
||||||
extensionDirectoryPath: string = 'dist'
|
extensionDirectoryPath = "dist"
|
||||||
): undefined | PluginDetails[] {
|
): undefined | PluginDetails[] {
|
||||||
const { plugins } = configModule
|
const { plugins } = configModule
|
||||||
|
|
||||||
@@ -132,8 +132,8 @@ export async function registerPluginModels({
|
|||||||
rootDirectory,
|
rootDirectory,
|
||||||
container,
|
container,
|
||||||
configModule,
|
configModule,
|
||||||
extensionDirectoryPath = 'dist',
|
extensionDirectoryPath = "dist",
|
||||||
pathGlob = "/models/*.js"
|
pathGlob = "/models/*.js",
|
||||||
}: {
|
}: {
|
||||||
rootDirectory: string
|
rootDirectory: string
|
||||||
container: MedusaContainer
|
container: MedusaContainer
|
||||||
@@ -141,20 +141,13 @@ export async function registerPluginModels({
|
|||||||
extensionDirectoryPath?: string
|
extensionDirectoryPath?: string
|
||||||
pathGlob?: string
|
pathGlob?: string
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
const resolved = getResolvedPlugins(
|
const resolved =
|
||||||
rootDirectory,
|
getResolvedPlugins(rootDirectory, configModule, extensionDirectoryPath) ||
|
||||||
configModule,
|
[]
|
||||||
extensionDirectoryPath
|
|
||||||
) || []
|
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
resolved.map(async (pluginDetails) => {
|
resolved.map(async (pluginDetails) => {
|
||||||
registerModels(
|
registerModels(pluginDetails, container, rootDirectory, pathGlob)
|
||||||
pluginDetails,
|
|
||||||
container,
|
|
||||||
rootDirectory,
|
|
||||||
pathGlob,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -579,57 +572,74 @@ function registerRepositories(
|
|||||||
* version, id, resolved path, etc. See resolvePlugin
|
* version, id, resolved path, etc. See resolvePlugin
|
||||||
* @param {object} container - the container where the services will be
|
* @param {object} container - the container where the services will be
|
||||||
* registered
|
* registered
|
||||||
|
* @param rootDirectory
|
||||||
|
* @param pathGlob
|
||||||
* @return {void}
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
function registerModels(
|
function registerModels(
|
||||||
pluginDetails: PluginDetails,
|
pluginDetails: PluginDetails,
|
||||||
container: MedusaContainer,
|
container: MedusaContainer,
|
||||||
rootDirectory: string,
|
rootDirectory: string,
|
||||||
pathGlob: string = "/models/*.js"
|
pathGlob = "/models/*.js"
|
||||||
): void {
|
): void {
|
||||||
const pluginFullPathGlob = path.join(pluginDetails.resolve, pathGlob)
|
const pluginFullPathGlob = path.join(pluginDetails.resolve, pathGlob)
|
||||||
|
|
||||||
const modelExtensionsMap = getModelExtensionsMap({
|
const modelExtensionsMap = getModelExtensionsMap({
|
||||||
directory: rootDirectory,
|
directory: pluginDetails.resolve,
|
||||||
pathGlob: pathGlob,
|
pathGlob: pathGlob,
|
||||||
config: { register: true },
|
config: { register: true },
|
||||||
})
|
})
|
||||||
|
|
||||||
const coreOrPluginModelsPath = glob.sync(
|
const pluginModels = glob.sync(pluginFullPathGlob, {
|
||||||
pluginFullPathGlob,
|
ignore: ["index.js", "index.js.map"],
|
||||||
{ ignore: ["index.js", "index.js.map"] }
|
})
|
||||||
)
|
|
||||||
|
|
||||||
coreOrPluginModelsPath.forEach((coreOrPluginModelPath) => {
|
const coreModelsFullGlob = path.join(__dirname, "../models/*.js")
|
||||||
|
const coreModels = glob.sync(coreModelsFullGlob, {
|
||||||
|
cwd: __dirname,
|
||||||
|
ignore: ["index.js", "index.ts", "index.js.map"],
|
||||||
|
})
|
||||||
|
|
||||||
|
// Apply the extended models to the core models first to ensure that
|
||||||
|
// when relationships are created, the extended models are used
|
||||||
|
coreModels.forEach((modelPath) => {
|
||||||
|
const loaded = require(modelPath) as
|
||||||
|
| ClassConstructor<unknown>
|
||||||
|
| EntitySchema
|
||||||
|
|
||||||
|
if (loaded) {
|
||||||
|
const name = formatRegistrationName(modelPath)
|
||||||
|
const mappedExtensionModel = modelExtensionsMap.get(name)
|
||||||
|
if (mappedExtensionModel) {
|
||||||
|
const modelName = upperCaseFirst(
|
||||||
|
formatRegistrationNameWithoutNamespace(modelPath)
|
||||||
|
)
|
||||||
|
|
||||||
|
loaded[modelName] = mappedExtensionModel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
pluginModels.forEach((coreOrPluginModelPath) => {
|
||||||
const loaded = require(coreOrPluginModelPath) as
|
const loaded = require(coreOrPluginModelPath) as
|
||||||
| ClassConstructor<unknown>
|
| ClassConstructor<unknown>
|
||||||
| EntitySchema
|
| EntitySchema
|
||||||
|
|
||||||
Object.entries(loaded).map(
|
if (loaded) {
|
||||||
([, val]: [string, ClassConstructor<unknown> | EntitySchema]) => {
|
Object.entries(loaded).map(
|
||||||
if (typeof val === "function" || val instanceof EntitySchema) {
|
([, val]: [string, ClassConstructor<unknown> | EntitySchema]) => {
|
||||||
const name = formatRegistrationName(coreOrPluginModelPath)
|
if (typeof val === "function" || val instanceof EntitySchema) {
|
||||||
const mappedExtensionModel = modelExtensionsMap.get(name)
|
const name = formatRegistrationName(coreOrPluginModelPath)
|
||||||
|
|
||||||
// If an extension file is found, override it with that instead
|
container.register({
|
||||||
if (mappedExtensionModel) {
|
[name]: asValue(val),
|
||||||
const coreOrPluginModel = require(coreOrPluginModelPath)
|
})
|
||||||
const modelName = formatRegistrationNameWithoutNamespace(
|
|
||||||
coreOrPluginModelPath
|
|
||||||
)
|
|
||||||
|
|
||||||
coreOrPluginModel[modelName] = mappedExtensionModel
|
container.registerAdd("db_entities", asValue(val))
|
||||||
val = mappedExtensionModel
|
|
||||||
}
|
}
|
||||||
|
|
||||||
container.register({
|
|
||||||
[name]: asValue(val),
|
|
||||||
})
|
|
||||||
|
|
||||||
container.registerAdd("db_entities", asValue(val))
|
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
)
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user