From 13ce60b9996e2766caff4898c7bde62a1833bdd2 Mon Sep 17 00:00:00 2001 From: Adrien de Peretti Date: Wed, 15 May 2024 15:46:23 +0200 Subject: [PATCH] fix(medusa, modules-sdk): Fix migrate command and fix revert support (#7340) --- packages/core/modules-sdk/src/medusa-app.ts | 99 ++++++++++++++----- packages/medusa/src/commands/migrate.js | 65 ++++-------- .../link-modules/src/initialize/index.ts | 31 +++++- .../link-modules/src/migration/index.ts | 41 ++++++++ 4 files changed, 163 insertions(+), 73 deletions(-) diff --git a/packages/core/modules-sdk/src/medusa-app.ts b/packages/core/modules-sdk/src/medusa-app.ts index 4670264f6d..e3d7fdfaaa 100644 --- a/packages/core/modules-sdk/src/medusa-app.ts +++ b/packages/core/modules-sdk/src/medusa-app.ts @@ -149,7 +149,7 @@ async function initializeLinks({ moduleExports, }) { try { - const { initialize, runMigrations } = + const { initialize, runMigrations, revertMigrations } = moduleExports ?? (await import(LinkModulePackage)) const linkResolution = await initialize( @@ -158,7 +158,12 @@ async function initializeLinks({ injectedDependencies ) - return { remoteLink: new RemoteLink(), linkResolution, runMigrations } + return { + remoteLink: new RemoteLink(), + linkResolution, + runMigrations, + revertMigrations, + } } catch (err) { console.warn("Error initializing link modules.", err) @@ -209,6 +214,7 @@ export type MedusaAppOutput = { entitiesMap?: Record notFound?: Record> runMigrations: RunMigrationFn + revertMigrations: RunMigrationFn onApplicationShutdown: () => Promise onApplicationPrepareShutdown: () => Promise } @@ -333,6 +339,9 @@ async function MedusaApp_({ runMigrations: async () => { 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, }) - const { remoteLink, runMigrations: linkModuleMigration } = - await initializeLinks({ - config: linkModuleOptions, - linkModules, - injectedDependencies, - moduleExports: isMedusaModule(linkModule) ? linkModule : undefined, - }) + const { + remoteLink, + runMigrations: linkModuleMigration, + revertMigrations: revertLinkModuleMigration, + } = await initializeLinks({ + config: linkModuleOptions, + linkModules, + injectedDependencies, + moduleExports: isMedusaModule(linkModule) ? linkModule : undefined, + }) const loadedSchema = getLoadedSchema() const { schema, notFound } = cleanAndMergeSchema(loadedSchema) @@ -366,9 +378,7 @@ async function MedusaApp_({ return await remoteQuery.query(query, variables, options) } - const runMigrations: RunMigrationFn = async ( - linkModuleOptions - ): Promise => { + const applyMigration = async (linkModuleOptions, revert = false) => { for (const moduleName of Object.keys(allModules)) { const moduleResolution = MedusaModule.getModuleResolutions(moduleName) @@ -379,12 +389,21 @@ async function MedusaApp_({ } } - await MedusaModule.migrateUp( - moduleResolution.definition.key, - moduleResolution.resolutionPath as string, - moduleResolution.options, - moduleResolution.moduleExports - ) + if (!revert) { + await MedusaModule.migrateUp( + moduleResolution.definition.key, + moduleResolution.resolutionPath as string, + moduleResolution.options, + moduleResolution.moduleExports + ) + } else { + await MedusaModule.migrateDown( + moduleResolution.definition.key, + moduleResolution.resolutionPath as string, + moduleResolution.options, + moduleResolution.moduleExports + ) + } } const linkModuleOpt = { ...(linkModuleOptions ?? {}) } @@ -392,11 +411,31 @@ async function MedusaApp_({ ...(sharedResourcesConfig?.database ?? {}), } - linkModuleMigration && - (await linkModuleMigration({ - options: linkModuleOpt, - injectedDependencies, - })) + if (!revert) { + linkModuleMigration && + (await linkModuleMigration({ + options: linkModuleOpt, + injectedDependencies, + })) + } else { + revertLinkModuleMigration && + (await revertLinkModuleMigration({ + options: linkModuleOpt, + injectedDependencies, + })) + } + } + + const runMigrations: RunMigrationFn = async ( + linkModuleOptions + ): Promise => { + await applyMigration(linkModuleOptions) + } + + const revertMigrations: RunMigrationFn = async ( + linkModuleOptions + ): Promise => { + await applyMigration(linkModuleOptions, true) } return { @@ -408,6 +447,7 @@ async function MedusaApp_({ entitiesMap: schema.getTypeMap(), notFound, runMigrations, + revertMigrations, } } @@ -433,3 +473,16 @@ export async function MedusaAppMigrateUp( await runMigrations().finally(MedusaModule.clearInstances) } + +export async function MedusaAppMigrateDown( + options: MedusaAppOptions = {} +): Promise { + const migrationOnly = true + + const { revertMigrations } = await MedusaApp_({ + ...options, + migrationOnly, + }) + + await revertMigrations().finally(MedusaModule.clearInstances) +} diff --git a/packages/medusa/src/commands/migrate.js b/packages/medusa/src/commands/migrate.js index fe24e2b097..9b9d112a71 100644 --- a/packages/medusa/src/commands/migrate.js +++ b/packages/medusa/src/commands/migrate.js @@ -1,41 +1,16 @@ -import { asValue, createContainer } from "awilix" -import getMigrations, { - getModuleSharedResources, - revertIsolatedModulesMigration, -} from "./utils/get-migrations" +import { asValue } from "awilix" +import { revertIsolatedModulesMigration } from "./utils/get-migrations" import { ContainerRegistrationKeys, createMedusaContainer, } from "@medusajs/utils" import configModuleLoader from "../loaders/config" -import databaseLoader from "../loaders/database" import featureFlagLoader from "../loaders/feature-flags" 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" - -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", - }, - }) -} +import { MedusaAppMigrateDown } from "@medusajs/modules-sdk" const runLinkMigrations = async (directory) => { const configModule = configModuleLoader(directory) @@ -72,16 +47,16 @@ const main = async function ({ directory }) { const configModule = configModuleLoader(directory) 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") { - 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( { configModule, container }, { registerInContainer: false } @@ -90,17 +65,15 @@ const main = async function ({ directory }) { Logger.info("Migrations completed.") process.exit() } else if (args[0] === "revert") { - const dataSource = await getDataSource(directory) - await dataSource.undoLastMigration({ transaction: "all" }) - await dataSource.destroy() + await MedusaAppMigrateDown( + { configModule, container }, + { registerInContainer: false } + ) await revertIsolatedModulesMigration(configModule) Logger.info("Migrations reverted.") } else if (args[0] === "show") { - const dataSource = await getDataSource(directory) - const unapplied = await dataSource.showMigrations() - Logger.info(unapplied) - await dataSource.destroy() - process.exit(unapplied ? 1 : 0) + Logger.info("not supported") + process.exit(0) } } diff --git a/packages/modules/link-modules/src/initialize/index.ts b/packages/modules/link-modules/src/initialize/index.ts index d35dabc640..ee27b86221 100644 --- a/packages/modules/link-modules/src/initialize/index.ts +++ b/packages/modules/link-modules/src/initialize/index.ts @@ -22,7 +22,7 @@ import { toPascalCase, } from "@medusajs/utils" import * as linkDefinitions from "../definitions" -import { getMigration } from "../migration" +import { getMigration, getRevertMigration } from "../migration" import { InitializeModuleInjectableDependencies } from "../types" import { composeLinkName, @@ -164,12 +164,13 @@ export const initialize = async ( return allLinks } -export async function runMigrations( +async function applyMigrationUpOrDown( { options, logger, }: Omit, "container">, - modulesDefinition?: ModuleJoinerConfig[] + modulesDefinition?: ModuleJoinerConfig[], + revert = false ) { const modulesLoadedKeys = MedusaModule.getLoadedModules().map( (mod) => Object.keys(mod)[0] @@ -215,7 +216,29 @@ export async function runMigrations( 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 }) } } + +export async function runMigrations( + { + options, + logger, + }: Omit, "container">, + modulesDefinition?: ModuleJoinerConfig[] +) { + await applyMigrationUpOrDown({ options, logger }, modulesDefinition) +} + +export async function revertMigrations( + { + options, + logger, + }: Omit, "container">, + modulesDefinition?: ModuleJoinerConfig[] +) { + await applyMigrationUpOrDown({ options, logger }, modulesDefinition, true) +} diff --git a/packages/modules/link-modules/src/migration/index.ts b/packages/modules/link-modules/src/migration/index.ts index 1e71cb4c0a..ca597488d1 100644 --- a/packages/modules/link-modules/src/migration/index.ts +++ b/packages/modules/link-modules/src/migration/index.ts @@ -84,3 +84,44 @@ export function getMigration( await orm.close() } } + +export function getRevertMigration( + joinerConfig: ModuleJoinerConfig, + serviceName: string, + primary: JoinerRelationship, + foreign: JoinerRelationship +) { + return async function revertMigrations( + { + options, + logger, + }: Pick< + LoaderOptions, + "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() + } +}