fix(medusa, modules-sdk): Fix migrate command and fix revert support (#7340)
This commit is contained in:
@@ -149,7 +149,7 @@ async function initializeLinks({
|
|||||||
moduleExports,
|
moduleExports,
|
||||||
}) {
|
}) {
|
||||||
try {
|
try {
|
||||||
const { initialize, runMigrations } =
|
const { initialize, runMigrations, revertMigrations } =
|
||||||
moduleExports ?? (await import(LinkModulePackage))
|
moduleExports ?? (await import(LinkModulePackage))
|
||||||
|
|
||||||
const linkResolution = await initialize(
|
const linkResolution = await initialize(
|
||||||
@@ -158,7 +158,12 @@ async function initializeLinks({
|
|||||||
injectedDependencies
|
injectedDependencies
|
||||||
)
|
)
|
||||||
|
|
||||||
return { remoteLink: new RemoteLink(), linkResolution, runMigrations }
|
return {
|
||||||
|
remoteLink: new RemoteLink(),
|
||||||
|
linkResolution,
|
||||||
|
runMigrations,
|
||||||
|
revertMigrations,
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn("Error initializing link modules.", err)
|
console.warn("Error initializing link modules.", err)
|
||||||
|
|
||||||
@@ -209,6 +214,7 @@ export type MedusaAppOutput = {
|
|||||||
entitiesMap?: Record<string, any>
|
entitiesMap?: Record<string, any>
|
||||||
notFound?: Record<string, Record<string, string>>
|
notFound?: Record<string, Record<string, string>>
|
||||||
runMigrations: RunMigrationFn
|
runMigrations: RunMigrationFn
|
||||||
|
revertMigrations: RunMigrationFn
|
||||||
onApplicationShutdown: () => Promise<void>
|
onApplicationShutdown: () => Promise<void>
|
||||||
onApplicationPrepareShutdown: () => Promise<void>
|
onApplicationPrepareShutdown: () => Promise<void>
|
||||||
}
|
}
|
||||||
@@ -333,6 +339,9 @@ async function MedusaApp_({
|
|||||||
runMigrations: async () => {
|
runMigrations: async () => {
|
||||||
throw new Error("Migrations not allowed in loaderOnly mode")
|
throw new Error("Migrations not allowed in loaderOnly mode")
|
||||||
},
|
},
|
||||||
|
revertMigrations: async () => {
|
||||||
|
throw new Error("Revert migrations not allowed in loaderOnly mode")
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,13 +351,16 @@ async function MedusaApp_({
|
|||||||
allowUnregistered: true,
|
allowUnregistered: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const { remoteLink, runMigrations: linkModuleMigration } =
|
const {
|
||||||
await initializeLinks({
|
remoteLink,
|
||||||
config: linkModuleOptions,
|
runMigrations: linkModuleMigration,
|
||||||
linkModules,
|
revertMigrations: revertLinkModuleMigration,
|
||||||
injectedDependencies,
|
} = await initializeLinks({
|
||||||
moduleExports: isMedusaModule(linkModule) ? linkModule : undefined,
|
config: linkModuleOptions,
|
||||||
})
|
linkModules,
|
||||||
|
injectedDependencies,
|
||||||
|
moduleExports: isMedusaModule(linkModule) ? linkModule : undefined,
|
||||||
|
})
|
||||||
|
|
||||||
const loadedSchema = getLoadedSchema()
|
const loadedSchema = getLoadedSchema()
|
||||||
const { schema, notFound } = cleanAndMergeSchema(loadedSchema)
|
const { schema, notFound } = cleanAndMergeSchema(loadedSchema)
|
||||||
@@ -366,9 +378,7 @@ async function MedusaApp_({
|
|||||||
return await remoteQuery.query(query, variables, options)
|
return await remoteQuery.query(query, variables, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
const runMigrations: RunMigrationFn = async (
|
const applyMigration = async (linkModuleOptions, revert = false) => {
|
||||||
linkModuleOptions
|
|
||||||
): Promise<void> => {
|
|
||||||
for (const moduleName of Object.keys(allModules)) {
|
for (const moduleName of Object.keys(allModules)) {
|
||||||
const moduleResolution = MedusaModule.getModuleResolutions(moduleName)
|
const moduleResolution = MedusaModule.getModuleResolutions(moduleName)
|
||||||
|
|
||||||
@@ -379,12 +389,21 @@ async function MedusaApp_({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await MedusaModule.migrateUp(
|
if (!revert) {
|
||||||
moduleResolution.definition.key,
|
await MedusaModule.migrateUp(
|
||||||
moduleResolution.resolutionPath as string,
|
moduleResolution.definition.key,
|
||||||
moduleResolution.options,
|
moduleResolution.resolutionPath as string,
|
||||||
moduleResolution.moduleExports
|
moduleResolution.options,
|
||||||
)
|
moduleResolution.moduleExports
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
await MedusaModule.migrateDown(
|
||||||
|
moduleResolution.definition.key,
|
||||||
|
moduleResolution.resolutionPath as string,
|
||||||
|
moduleResolution.options,
|
||||||
|
moduleResolution.moduleExports
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const linkModuleOpt = { ...(linkModuleOptions ?? {}) }
|
const linkModuleOpt = { ...(linkModuleOptions ?? {}) }
|
||||||
@@ -392,11 +411,31 @@ async function MedusaApp_({
|
|||||||
...(sharedResourcesConfig?.database ?? {}),
|
...(sharedResourcesConfig?.database ?? {}),
|
||||||
}
|
}
|
||||||
|
|
||||||
linkModuleMigration &&
|
if (!revert) {
|
||||||
(await linkModuleMigration({
|
linkModuleMigration &&
|
||||||
options: linkModuleOpt,
|
(await linkModuleMigration({
|
||||||
injectedDependencies,
|
options: linkModuleOpt,
|
||||||
}))
|
injectedDependencies,
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
revertLinkModuleMigration &&
|
||||||
|
(await revertLinkModuleMigration({
|
||||||
|
options: linkModuleOpt,
|
||||||
|
injectedDependencies,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const runMigrations: RunMigrationFn = async (
|
||||||
|
linkModuleOptions
|
||||||
|
): Promise<void> => {
|
||||||
|
await applyMigration(linkModuleOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
const revertMigrations: RunMigrationFn = async (
|
||||||
|
linkModuleOptions
|
||||||
|
): Promise<void> => {
|
||||||
|
await applyMigration(linkModuleOptions, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -408,6 +447,7 @@ async function MedusaApp_({
|
|||||||
entitiesMap: schema.getTypeMap(),
|
entitiesMap: schema.getTypeMap(),
|
||||||
notFound,
|
notFound,
|
||||||
runMigrations,
|
runMigrations,
|
||||||
|
revertMigrations,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -433,3 +473,16 @@ export async function MedusaAppMigrateUp(
|
|||||||
|
|
||||||
await runMigrations().finally(MedusaModule.clearInstances)
|
await runMigrations().finally(MedusaModule.clearInstances)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function MedusaAppMigrateDown(
|
||||||
|
options: MedusaAppOptions = {}
|
||||||
|
): Promise<void> {
|
||||||
|
const migrationOnly = true
|
||||||
|
|
||||||
|
const { revertMigrations } = await MedusaApp_({
|
||||||
|
...options,
|
||||||
|
migrationOnly,
|
||||||
|
})
|
||||||
|
|
||||||
|
await revertMigrations().finally(MedusaModule.clearInstances)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,41 +1,16 @@
|
|||||||
import { asValue, createContainer } from "awilix"
|
import { asValue } from "awilix"
|
||||||
import getMigrations, {
|
import { revertIsolatedModulesMigration } from "./utils/get-migrations"
|
||||||
getModuleSharedResources,
|
|
||||||
revertIsolatedModulesMigration,
|
|
||||||
} from "./utils/get-migrations"
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ContainerRegistrationKeys,
|
ContainerRegistrationKeys,
|
||||||
createMedusaContainer,
|
createMedusaContainer,
|
||||||
} from "@medusajs/utils"
|
} from "@medusajs/utils"
|
||||||
import configModuleLoader from "../loaders/config"
|
import configModuleLoader from "../loaders/config"
|
||||||
import databaseLoader from "../loaders/database"
|
|
||||||
import featureFlagLoader from "../loaders/feature-flags"
|
import featureFlagLoader from "../loaders/feature-flags"
|
||||||
import Logger from "../loaders/logger"
|
import Logger from "../loaders/logger"
|
||||||
import { migrateMedusaApp, loadMedusaApp } from "../loaders/medusa-app"
|
import { loadMedusaApp, migrateMedusaApp } from "../loaders/medusa-app"
|
||||||
import pgConnectionLoader from "../loaders/pg-connection"
|
import pgConnectionLoader from "../loaders/pg-connection"
|
||||||
|
import { MedusaAppMigrateDown } from "@medusajs/modules-sdk"
|
||||||
const getDataSource = async (directory) => {
|
|
||||||
const configModule = configModuleLoader(directory)
|
|
||||||
const featureFlagRouter = featureFlagLoader(configModule)
|
|
||||||
const { coreMigrations } = getMigrations(directory, featureFlagRouter)
|
|
||||||
const { migrations: moduleMigrations } = getModuleSharedResources(
|
|
||||||
configModule,
|
|
||||||
featureFlagRouter
|
|
||||||
)
|
|
||||||
|
|
||||||
const container = createContainer()
|
|
||||||
container.register("db_entities", asValue([]))
|
|
||||||
|
|
||||||
return await databaseLoader({
|
|
||||||
container,
|
|
||||||
configModule,
|
|
||||||
customOptions: {
|
|
||||||
migrations: coreMigrations.concat(moduleMigrations),
|
|
||||||
logging: "all",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const runLinkMigrations = async (directory) => {
|
const runLinkMigrations = async (directory) => {
|
||||||
const configModule = configModuleLoader(directory)
|
const configModule = configModuleLoader(directory)
|
||||||
@@ -72,16 +47,16 @@ const main = async function ({ directory }) {
|
|||||||
const configModule = configModuleLoader(directory)
|
const configModule = configModuleLoader(directory)
|
||||||
const featureFlagRouter = featureFlagLoader(configModule)
|
const featureFlagRouter = featureFlagLoader(configModule)
|
||||||
|
|
||||||
|
const container = createMedusaContainer()
|
||||||
|
const pgConnection = await pgConnectionLoader({ configModule, container })
|
||||||
|
container.register({
|
||||||
|
[ContainerRegistrationKeys.CONFIG_MODULE]: asValue(configModule),
|
||||||
|
[ContainerRegistrationKeys.LOGGER]: asValue(Logger),
|
||||||
|
[ContainerRegistrationKeys.PG_CONNECTION]: asValue(pgConnection),
|
||||||
|
[ContainerRegistrationKeys.FEATURE_FLAG_ROUTER]: asValue(featureFlagRouter),
|
||||||
|
})
|
||||||
|
|
||||||
if (args[0] === "run") {
|
if (args[0] === "run") {
|
||||||
const container = createMedusaContainer()
|
|
||||||
const pgConnection = await pgConnectionLoader({ configModule, container })
|
|
||||||
container.register({
|
|
||||||
[ContainerRegistrationKeys.CONFIG_MODULE]: asValue(configModule),
|
|
||||||
[ContainerRegistrationKeys.LOGGER]: asValue(Logger),
|
|
||||||
[ContainerRegistrationKeys.PG_CONNECTION]: asValue(pgConnection),
|
|
||||||
[ContainerRegistrationKeys.FEATURE_FLAG_ROUTER]:
|
|
||||||
asValue(featureFlagRouter),
|
|
||||||
})
|
|
||||||
await migrateMedusaApp(
|
await migrateMedusaApp(
|
||||||
{ configModule, container },
|
{ configModule, container },
|
||||||
{ registerInContainer: false }
|
{ registerInContainer: false }
|
||||||
@@ -90,17 +65,15 @@ const main = async function ({ directory }) {
|
|||||||
Logger.info("Migrations completed.")
|
Logger.info("Migrations completed.")
|
||||||
process.exit()
|
process.exit()
|
||||||
} else if (args[0] === "revert") {
|
} else if (args[0] === "revert") {
|
||||||
const dataSource = await getDataSource(directory)
|
await MedusaAppMigrateDown(
|
||||||
await dataSource.undoLastMigration({ transaction: "all" })
|
{ configModule, container },
|
||||||
await dataSource.destroy()
|
{ registerInContainer: false }
|
||||||
|
)
|
||||||
await revertIsolatedModulesMigration(configModule)
|
await revertIsolatedModulesMigration(configModule)
|
||||||
Logger.info("Migrations reverted.")
|
Logger.info("Migrations reverted.")
|
||||||
} else if (args[0] === "show") {
|
} else if (args[0] === "show") {
|
||||||
const dataSource = await getDataSource(directory)
|
Logger.info("not supported")
|
||||||
const unapplied = await dataSource.showMigrations()
|
process.exit(0)
|
||||||
Logger.info(unapplied)
|
|
||||||
await dataSource.destroy()
|
|
||||||
process.exit(unapplied ? 1 : 0)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import {
|
|||||||
toPascalCase,
|
toPascalCase,
|
||||||
} from "@medusajs/utils"
|
} from "@medusajs/utils"
|
||||||
import * as linkDefinitions from "../definitions"
|
import * as linkDefinitions from "../definitions"
|
||||||
import { getMigration } from "../migration"
|
import { getMigration, getRevertMigration } from "../migration"
|
||||||
import { InitializeModuleInjectableDependencies } from "../types"
|
import { InitializeModuleInjectableDependencies } from "../types"
|
||||||
import {
|
import {
|
||||||
composeLinkName,
|
composeLinkName,
|
||||||
@@ -164,12 +164,13 @@ export const initialize = async (
|
|||||||
return allLinks
|
return allLinks
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function runMigrations(
|
async function applyMigrationUpOrDown(
|
||||||
{
|
{
|
||||||
options,
|
options,
|
||||||
logger,
|
logger,
|
||||||
}: Omit<LoaderOptions<ModuleServiceInitializeOptions>, "container">,
|
}: Omit<LoaderOptions<ModuleServiceInitializeOptions>, "container">,
|
||||||
modulesDefinition?: ModuleJoinerConfig[]
|
modulesDefinition?: ModuleJoinerConfig[],
|
||||||
|
revert = false
|
||||||
) {
|
) {
|
||||||
const modulesLoadedKeys = MedusaModule.getLoadedModules().map(
|
const modulesLoadedKeys = MedusaModule.getLoadedModules().map(
|
||||||
(mod) => Object.keys(mod)[0]
|
(mod) => Object.keys(mod)[0]
|
||||||
@@ -215,7 +216,29 @@ export async function runMigrations(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const migrate = getMigration(definition, serviceKey, primary, foreign)
|
const migrate = revert
|
||||||
|
? getRevertMigration(definition, serviceKey, primary, foreign)
|
||||||
|
: getMigration(definition, serviceKey, primary, foreign)
|
||||||
await migrate({ options, logger })
|
await migrate({ options, logger })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function runMigrations(
|
||||||
|
{
|
||||||
|
options,
|
||||||
|
logger,
|
||||||
|
}: Omit<LoaderOptions<ModuleServiceInitializeOptions>, "container">,
|
||||||
|
modulesDefinition?: ModuleJoinerConfig[]
|
||||||
|
) {
|
||||||
|
await applyMigrationUpOrDown({ options, logger }, modulesDefinition)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function revertMigrations(
|
||||||
|
{
|
||||||
|
options,
|
||||||
|
logger,
|
||||||
|
}: Omit<LoaderOptions<ModuleServiceInitializeOptions>, "container">,
|
||||||
|
modulesDefinition?: ModuleJoinerConfig[]
|
||||||
|
) {
|
||||||
|
await applyMigrationUpOrDown({ options, logger }, modulesDefinition, true)
|
||||||
|
}
|
||||||
|
|||||||
@@ -84,3 +84,44 @@ export function getMigration(
|
|||||||
await orm.close()
|
await orm.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getRevertMigration(
|
||||||
|
joinerConfig: ModuleJoinerConfig,
|
||||||
|
serviceName: string,
|
||||||
|
primary: JoinerRelationship,
|
||||||
|
foreign: JoinerRelationship
|
||||||
|
) {
|
||||||
|
return async function revertMigrations(
|
||||||
|
{
|
||||||
|
options,
|
||||||
|
logger,
|
||||||
|
}: Pick<
|
||||||
|
LoaderOptions<ModuleServiceInitializeOptions>,
|
||||||
|
"options" | "logger"
|
||||||
|
> = {} as any
|
||||||
|
) {
|
||||||
|
logger ??= console as unknown as Logger
|
||||||
|
|
||||||
|
const dbData = ModulesSdkUtils.loadDatabaseConfig("link_modules", options)
|
||||||
|
const entity = generateEntity(joinerConfig, primary, foreign)
|
||||||
|
const pathToMigrations = __dirname + "/../migrations"
|
||||||
|
|
||||||
|
const orm = await DALUtils.mikroOrmCreateConnection(
|
||||||
|
dbData,
|
||||||
|
[entity],
|
||||||
|
pathToMigrations
|
||||||
|
)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const migrator = orm.getMigrator()
|
||||||
|
await migrator.down()
|
||||||
|
logger.info(`Link module "${serviceName}" migration executed`)
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(
|
||||||
|
`Link module "${serviceName}" migration failed to run - Error: ${error}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
await orm.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user