chore(framework): Move and improve links loader (#8367)
**What** Refactor and move links loader FIXES FRMW-2637
This commit is contained in:
@@ -13,6 +13,7 @@
|
|||||||
"./logger": "./dist/logger/index.js",
|
"./logger": "./dist/logger/index.js",
|
||||||
"./database": "./dist/database/index.js",
|
"./database": "./dist/database/index.js",
|
||||||
"./subscribers": "./dist/subscribers/index.js",
|
"./subscribers": "./dist/subscribers/index.js",
|
||||||
|
"./links": "./dist/links/index.js",
|
||||||
"./jobs": "./dist/jobs/index.js"
|
"./jobs": "./dist/jobs/index.js"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -47,6 +48,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@medusajs/medusa-cli": "^1.3.22",
|
"@medusajs/medusa-cli": "^1.3.22",
|
||||||
|
"@medusajs/modules-sdk": "^1.12.11",
|
||||||
"@medusajs/utils": "^1.11.9",
|
"@medusajs/utils": "^1.11.9",
|
||||||
"@medusajs/workflows-sdk": "^0.1.6",
|
"@medusajs/workflows-sdk": "^0.1.6",
|
||||||
"awilix": "^8.0.0",
|
"awilix": "^8.0.0",
|
||||||
|
|||||||
@@ -1,3 +1,36 @@
|
|||||||
import { createMedusaContainer } from "@medusajs/utils"
|
import { createMedusaContainer } from "@medusajs/utils"
|
||||||
|
import { AwilixContainer, ResolveOptions } from "awilix"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The following interface acts as a bucket that other modules or the
|
||||||
|
* utils package can fill using declaration merging
|
||||||
|
*/
|
||||||
|
export interface ModuleImplementations {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Medusa Container extends [Awilix](https://github.com/jeffijoe/awilix) to
|
||||||
|
* provide dependency injection functionalities.
|
||||||
|
*/
|
||||||
|
export type MedusaContainer<Cradle extends object = ModuleImplementations> =
|
||||||
|
Omit<AwilixContainer, "resolve"> & {
|
||||||
|
resolve<K extends keyof Cradle>(
|
||||||
|
key: K,
|
||||||
|
resolveOptions?: ResolveOptions
|
||||||
|
): Cradle[K]
|
||||||
|
resolve<T>(key: string, resolveOptions?: ResolveOptions): T
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
registerAdd: <T>(name: string, registration: T) => MedusaContainer
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
createScope: () => MedusaContainer
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ContainerLike = {
|
||||||
|
resolve<T = unknown>(key: string): T
|
||||||
|
}
|
||||||
|
|
||||||
export const container = createMedusaContainer()
|
export const container = createMedusaContainer()
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ export function pgConnectionLoader(): ReturnType<
|
|||||||
typeof ModulesSdkUtils.createPgConnection
|
typeof ModulesSdkUtils.createPgConnection
|
||||||
> {
|
> {
|
||||||
if (container.hasRegistration(ContainerRegistrationKeys.PG_CONNECTION)) {
|
if (container.hasRegistration(ContainerRegistrationKeys.PG_CONNECTION)) {
|
||||||
return container.resolve(ContainerRegistrationKeys.PG_CONNECTION)
|
return container.resolve(
|
||||||
|
ContainerRegistrationKeys.PG_CONNECTION
|
||||||
|
) as unknown as ReturnType<typeof ModulesSdkUtils.createPgConnection>
|
||||||
}
|
}
|
||||||
|
|
||||||
const configModule = configManager.config
|
const configModule = configManager.config
|
||||||
|
|||||||
@@ -4,5 +4,6 @@ export * from "./http"
|
|||||||
export * from "./database"
|
export * from "./database"
|
||||||
export * from "./container"
|
export * from "./container"
|
||||||
export * from "./subscribers"
|
export * from "./subscribers"
|
||||||
|
export * from "./links"
|
||||||
export * from "./jobs"
|
export * from "./jobs"
|
||||||
export * from "./feature-flags"
|
export * from "./feature-flags"
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ export class MockSchedulerStorage implements IDistributedSchedulerStorage {
|
|||||||
jobDefinition: string | { jobId: string },
|
jobDefinition: string | { jobId: string },
|
||||||
schedulerOptions: SchedulerOptions
|
schedulerOptions: SchedulerOptions
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return Promise.resolve()
|
return await Promise.resolve()
|
||||||
}
|
}
|
||||||
|
|
||||||
async remove(jobId: string): Promise<void> {
|
async remove(jobId: string): Promise<void> {
|
||||||
return Promise.resolve()
|
return await Promise.resolve()
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeAll(): Promise<void> {
|
async removeAll(): Promise<void> {
|
||||||
return Promise.resolve()
|
return await Promise.resolve()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { defineLink, MedusaService, model, Module } from "@medusajs/utils"
|
||||||
|
|
||||||
|
const model1 = model.define("model-1", {
|
||||||
|
id: model.id().primaryKey(),
|
||||||
|
})
|
||||||
|
|
||||||
|
const model2 = model.define("model-2", {
|
||||||
|
id: model.id().primaryKey(),
|
||||||
|
})
|
||||||
|
|
||||||
|
const module1 = Module("module-1", {
|
||||||
|
service: class Service1 extends MedusaService({ model1 }) {},
|
||||||
|
})
|
||||||
|
|
||||||
|
const module2 = Module("module-2", {
|
||||||
|
service: class Service2 extends MedusaService({ model2 }) {},
|
||||||
|
})
|
||||||
|
|
||||||
|
export const module1And2Link = defineLink(
|
||||||
|
module1.linkable.model1,
|
||||||
|
module2.linkable.model2
|
||||||
|
)
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { defineLink, MedusaService, model, Module } from "@medusajs/utils"
|
||||||
|
|
||||||
|
const model3 = model.define("model-3", {
|
||||||
|
id: model.id().primaryKey(),
|
||||||
|
})
|
||||||
|
|
||||||
|
const model4 = model.define("model-4", {
|
||||||
|
id: model.id().primaryKey(),
|
||||||
|
})
|
||||||
|
|
||||||
|
const module3 = Module("module-3", {
|
||||||
|
service: class Service3 extends MedusaService({ model3 }) {},
|
||||||
|
})
|
||||||
|
|
||||||
|
const module4 = Module("module-4", {
|
||||||
|
service: class Service4 extends MedusaService({ model4 }) {},
|
||||||
|
})
|
||||||
|
|
||||||
|
export const module3And4Link = defineLink(
|
||||||
|
module3.linkable.model3,
|
||||||
|
module4.linkable.model4
|
||||||
|
)
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { join } from "path"
|
||||||
|
import { LinkLoader } from "../link-loader"
|
||||||
|
import { MedusaModule } from "@medusajs/modules-sdk"
|
||||||
|
|
||||||
|
describe("LinkLoader", () => {
|
||||||
|
const rootDir = join(__dirname, "../__fixtures__", "links")
|
||||||
|
|
||||||
|
it("should register each link in the '/links' folder and sub folder", async () => {
|
||||||
|
let links = MedusaModule.getCustomLinks()
|
||||||
|
|
||||||
|
expect(links.length).toBe(0)
|
||||||
|
|
||||||
|
await new LinkLoader(rootDir).load()
|
||||||
|
|
||||||
|
links = MedusaModule.getCustomLinks()
|
||||||
|
|
||||||
|
expect(links.length).toBe(2)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from "./link-loader"
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import { promiseAll } from "@medusajs/utils"
|
||||||
|
import { logger } from "../logger"
|
||||||
|
import { access, readdir } from "fs/promises"
|
||||||
|
import { join } from "path"
|
||||||
|
|
||||||
|
export class LinkLoader {
|
||||||
|
/**
|
||||||
|
* The directory from which to load the links
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
#sourceDir: string | string[]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of file names to exclude from the subscriber scan
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
#excludes: RegExp[] = [
|
||||||
|
/index\.js/,
|
||||||
|
/index\.ts/,
|
||||||
|
/\.DS_Store/,
|
||||||
|
/(\.ts\.map|\.js\.map|\.d\.ts|\.md)/,
|
||||||
|
/^_[^/\\]*(\.[^/\\]+)?$/,
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor(sourceDir: string | string[]) {
|
||||||
|
this.#sourceDir = sourceDir
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load links from the source paths, links are registering themselves,
|
||||||
|
* therefore we only need to import them
|
||||||
|
*/
|
||||||
|
async load() {
|
||||||
|
const normalizedSourcePath = Array.isArray(this.#sourceDir)
|
||||||
|
? this.#sourceDir
|
||||||
|
: [this.#sourceDir]
|
||||||
|
|
||||||
|
const promises = normalizedSourcePath.map(async (sourcePath) => {
|
||||||
|
try {
|
||||||
|
await access(sourcePath)
|
||||||
|
} catch {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return await readdir(sourcePath, {
|
||||||
|
recursive: true,
|
||||||
|
withFileTypes: true,
|
||||||
|
}).then(async (entries) => {
|
||||||
|
const fileEntries = entries.filter((entry) => {
|
||||||
|
return (
|
||||||
|
!entry.isDirectory() &&
|
||||||
|
!this.#excludes.some((exclude) => exclude.test(entry.name))
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
logger.debug(`Registering links from ${sourcePath}.`)
|
||||||
|
|
||||||
|
return await promiseAll(
|
||||||
|
fileEntries.map(async (entry) => {
|
||||||
|
const fullPath = join(entry.path, entry.name)
|
||||||
|
return await import(fullPath)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
await promiseAll(promises)
|
||||||
|
|
||||||
|
logger.debug(`Links registered.`)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,13 +2,13 @@ import boxen from "boxen"
|
|||||||
import chalk from "chalk"
|
import chalk from "chalk"
|
||||||
import checkbox from "@inquirer/checkbox"
|
import checkbox from "@inquirer/checkbox"
|
||||||
|
|
||||||
import { logger } from "@medusajs/framework"
|
import { LinkLoader, logger } from "@medusajs/framework"
|
||||||
import { initializeContainer } from "../loaders"
|
import { initializeContainer } from "../loaders"
|
||||||
import { ContainerRegistrationKeys } from "@medusajs/utils"
|
import { ContainerRegistrationKeys } from "@medusajs/utils"
|
||||||
import { getResolvedPlugins } from "../loaders/helpers/resolve-plugins"
|
import { getResolvedPlugins } from "../loaders/helpers/resolve-plugins"
|
||||||
import { resolvePluginsLinks } from "../loaders/helpers/resolve-plugins-links"
|
|
||||||
import { getLinksExecutionPlanner } from "../loaders/medusa-app"
|
import { getLinksExecutionPlanner } from "../loaders/medusa-app"
|
||||||
import { LinkMigrationsPlannerAction } from "@medusajs/types"
|
import { LinkMigrationsPlannerAction } from "@medusajs/types"
|
||||||
|
import { join } from "path"
|
||||||
|
|
||||||
type Action = "sync"
|
type Action = "sync"
|
||||||
|
|
||||||
@@ -103,11 +103,13 @@ const main = async function ({ directory }) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const plugins = getResolvedPlugins(directory, configModule, true) || []
|
const plugins = getResolvedPlugins(directory, configModule, true) || []
|
||||||
const pluginLinks = await resolvePluginsLinks(plugins, container)
|
const linksSourcePaths = plugins.map((plugin) =>
|
||||||
|
join(plugin.resolve, "links")
|
||||||
|
)
|
||||||
|
await new LinkLoader(linksSourcePaths).load()
|
||||||
|
|
||||||
const planner = await getLinksExecutionPlanner({
|
const planner = await getLinksExecutionPlanner({
|
||||||
configModule,
|
configModule,
|
||||||
linkModules: pluginLinks,
|
|
||||||
container,
|
container,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { logger } from "@medusajs/framework"
|
import { LinkLoader, logger } from "@medusajs/framework"
|
||||||
import { runMedusaAppMigrations } from "../loaders/medusa-app"
|
import { runMedusaAppMigrations } from "../loaders/medusa-app"
|
||||||
import { initializeContainer } from "../loaders"
|
import { initializeContainer } from "../loaders"
|
||||||
import { ContainerRegistrationKeys, MedusaError } from "@medusajs/utils"
|
import { ContainerRegistrationKeys, MedusaError } from "@medusajs/utils"
|
||||||
import { getResolvedPlugins } from "../loaders/helpers/resolve-plugins"
|
import { getResolvedPlugins } from "../loaders/helpers/resolve-plugins"
|
||||||
import { resolvePluginsLinks } from "../loaders/helpers/resolve-plugins-links"
|
import { join } from "path"
|
||||||
|
|
||||||
const TERMINAL_SIZE = process.stdout.columns
|
const TERMINAL_SIZE = process.stdout.columns
|
||||||
|
|
||||||
@@ -52,14 +52,16 @@ const main = async function ({ directory }) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const plugins = getResolvedPlugins(directory, configModule, true) || []
|
const plugins = getResolvedPlugins(directory, configModule, true) || []
|
||||||
const pluginLinks = await resolvePluginsLinks(plugins, container)
|
const linksSourcePaths = plugins.map((plugin) =>
|
||||||
|
join(plugin.resolve, "links")
|
||||||
|
)
|
||||||
|
await new LinkLoader(linksSourcePaths).load()
|
||||||
|
|
||||||
if (action === "run") {
|
if (action === "run") {
|
||||||
logger.info("Running migrations...")
|
logger.info("Running migrations...")
|
||||||
|
|
||||||
await runMedusaAppMigrations({
|
await runMedusaAppMigrations({
|
||||||
configModule,
|
configModule,
|
||||||
linkModules: pluginLinks,
|
|
||||||
container,
|
container,
|
||||||
action: "run",
|
action: "run",
|
||||||
})
|
})
|
||||||
@@ -74,7 +76,6 @@ const main = async function ({ directory }) {
|
|||||||
await runMedusaAppMigrations({
|
await runMedusaAppMigrations({
|
||||||
moduleNames: modules,
|
moduleNames: modules,
|
||||||
configModule,
|
configModule,
|
||||||
linkModules: pluginLinks,
|
|
||||||
container,
|
container,
|
||||||
action: "revert",
|
action: "revert",
|
||||||
})
|
})
|
||||||
@@ -100,7 +101,6 @@ const main = async function ({ directory }) {
|
|||||||
await runMedusaAppMigrations({
|
await runMedusaAppMigrations({
|
||||||
moduleNames: modules,
|
moduleNames: modules,
|
||||||
configModule,
|
configModule,
|
||||||
linkModules: pluginLinks,
|
|
||||||
container,
|
container,
|
||||||
action: "generate",
|
action: "generate",
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
import { mkdirSync, rmSync, writeFileSync } from "fs"
|
|
||||||
import { resolve } from "path"
|
|
||||||
import { resolvePluginsLinks } from "../helpers/resolve-plugins-links"
|
|
||||||
import { createMedusaContainer } from "@medusajs/utils"
|
|
||||||
import { asValue } from "awilix"
|
|
||||||
|
|
||||||
const distTestTargetDirectorPath = resolve(__dirname, "__links__")
|
|
||||||
|
|
||||||
const getFolderTestTargetDirectoryPath = (folderName: string): string => {
|
|
||||||
return resolve(distTestTargetDirectorPath, folderName)
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("resolve plugins links", () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
jest.resetModules()
|
|
||||||
jest.clearAllMocks()
|
|
||||||
|
|
||||||
rmSync(distTestTargetDirectorPath, { recursive: true, force: true })
|
|
||||||
|
|
||||||
mkdirSync(getFolderTestTargetDirectoryPath("links"), {
|
|
||||||
mode: "777",
|
|
||||||
recursive: true,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(() => {
|
|
||||||
rmSync(distTestTargetDirectorPath, { recursive: true, force: true })
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should load the custom links from the links directory", async () => {
|
|
||||||
writeFileSync(
|
|
||||||
resolve(getFolderTestTargetDirectoryPath("links"), "link.js"),
|
|
||||||
`
|
|
||||||
export default {
|
|
||||||
isLink: true
|
|
||||||
}
|
|
||||||
`
|
|
||||||
)
|
|
||||||
|
|
||||||
writeFileSync(
|
|
||||||
resolve(getFolderTestTargetDirectoryPath("links"), "empty-link.js"),
|
|
||||||
`
|
|
||||||
export default 'string'
|
|
||||||
`
|
|
||||||
)
|
|
||||||
|
|
||||||
const loggerMock = { warn: jest.fn() }
|
|
||||||
const container = createMedusaContainer()
|
|
||||||
container.register({
|
|
||||||
logger: asValue(loggerMock),
|
|
||||||
})
|
|
||||||
|
|
||||||
const links = await resolvePluginsLinks(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
resolve: distTestTargetDirectorPath,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
container
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(loggerMock.warn).toHaveBeenCalledTimes(1)
|
|
||||||
expect(loggerMock.warn).toHaveBeenCalledWith(
|
|
||||||
`Links file ${distTestTargetDirectorPath}/links/empty-link.js does not export a default object`
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(links).toEqual([
|
|
||||||
{
|
|
||||||
isLink: true,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
import { glob } from "glob"
|
|
||||||
import {
|
|
||||||
MedusaContainer,
|
|
||||||
ModuleJoinerConfig,
|
|
||||||
PluginDetails,
|
|
||||||
} from "@medusajs/types"
|
|
||||||
import {
|
|
||||||
ContainerRegistrationKeys,
|
|
||||||
DefineLinkSymbol,
|
|
||||||
isObject,
|
|
||||||
} from "@medusajs/utils"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* import files from the links directory to retrieve the links to be loaded
|
|
||||||
* @param plugins
|
|
||||||
* @param container
|
|
||||||
*/
|
|
||||||
export async function resolvePluginsLinks(
|
|
||||||
plugins: PluginDetails[],
|
|
||||||
container: MedusaContainer
|
|
||||||
): Promise<ModuleJoinerConfig[]> {
|
|
||||||
const logger =
|
|
||||||
container.resolve(ContainerRegistrationKeys.LOGGER, {
|
|
||||||
allowUnregistered: true,
|
|
||||||
}) ?? console
|
|
||||||
return (
|
|
||||||
await Promise.all(
|
|
||||||
plugins.map(async (pluginDetails) => {
|
|
||||||
const files = glob.sync(
|
|
||||||
`${pluginDetails.resolve}/links/*.{ts,js,mjs,mts}`,
|
|
||||||
{
|
|
||||||
ignore: ["**/*.d.ts", "**/*.map"],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
return (
|
|
||||||
await Promise.all(
|
|
||||||
files.map(async (file) => {
|
|
||||||
const import_ = await import(file)
|
|
||||||
if (import_.default && !isObject(import_.default)) {
|
|
||||||
logger.warn(
|
|
||||||
`Links file ${file} does not export a default object`
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return import_.default
|
|
||||||
})
|
|
||||||
)
|
|
||||||
).filter((value) => {
|
|
||||||
return isObject(value) && !value[DefineLinkSymbol]
|
|
||||||
})
|
|
||||||
})
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.flat(Infinity)
|
|
||||||
.filter(Boolean)
|
|
||||||
}
|
|
||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
container,
|
container,
|
||||||
expressLoader,
|
expressLoader,
|
||||||
featureFlagsLoader,
|
featureFlagsLoader,
|
||||||
|
LinkLoader,
|
||||||
JobLoader,
|
JobLoader,
|
||||||
logger,
|
logger,
|
||||||
pgConnectionLoader,
|
pgConnectionLoader,
|
||||||
@@ -20,7 +21,6 @@ import {
|
|||||||
} from "@medusajs/framework"
|
} from "@medusajs/framework"
|
||||||
import { registerWorkflows } from "./helpers/register-workflows"
|
import { registerWorkflows } from "./helpers/register-workflows"
|
||||||
import { getResolvedPlugins } from "./helpers/resolve-plugins"
|
import { getResolvedPlugins } from "./helpers/resolve-plugins"
|
||||||
import { resolvePluginsLinks } from "./helpers/resolve-plugins-links"
|
|
||||||
import loadMedusaApp from "./medusa-app"
|
import loadMedusaApp from "./medusa-app"
|
||||||
|
|
||||||
type Options = {
|
type Options = {
|
||||||
@@ -151,7 +151,10 @@ export default async ({
|
|||||||
)
|
)
|
||||||
|
|
||||||
const plugins = getResolvedPlugins(rootDirectory, configModule, true) || []
|
const plugins = getResolvedPlugins(rootDirectory, configModule, true) || []
|
||||||
const pluginLinks = await resolvePluginsLinks(plugins, container)
|
const linksSourcePaths = plugins.map((plugin) =>
|
||||||
|
join(plugin.resolve, "links")
|
||||||
|
)
|
||||||
|
await new LinkLoader(linksSourcePaths).load()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
onApplicationStart,
|
onApplicationStart,
|
||||||
@@ -159,7 +162,6 @@ export default async ({
|
|||||||
onApplicationPrepareShutdown,
|
onApplicationPrepareShutdown,
|
||||||
} = await loadMedusaApp({
|
} = await loadMedusaApp({
|
||||||
container,
|
container,
|
||||||
linkModules: pluginLinks,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await registerWorkflows(plugins)
|
await registerWorkflows(plugins)
|
||||||
|
|||||||
@@ -4610,6 +4610,7 @@ __metadata:
|
|||||||
resolution: "@medusajs/framework@workspace:packages/framework/framework"
|
resolution: "@medusajs/framework@workspace:packages/framework/framework"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@medusajs/medusa-cli": ^1.3.22
|
"@medusajs/medusa-cli": ^1.3.22
|
||||||
|
"@medusajs/modules-sdk": ^1.12.11
|
||||||
"@medusajs/types": ^1.11.16
|
"@medusajs/types": ^1.11.16
|
||||||
"@medusajs/utils": ^1.11.9
|
"@medusajs/utils": ^1.11.9
|
||||||
"@medusajs/workflows-sdk": ^0.1.6
|
"@medusajs/workflows-sdk": ^0.1.6
|
||||||
|
|||||||
Reference in New Issue
Block a user