Feat: Improvements to the migrations CLI and workflow (#8060)

This commit is contained in:
Harminder Virk
2024-07-11 16:52:34 +05:30
committed by GitHub
parent bb0303cd6a
commit 45c573b03a
10 changed files with 257 additions and 144 deletions
+6 -1
View File
@@ -170,13 +170,18 @@ function buildLocalCommands(cli, isLocalProject) {
), ),
}) })
.command({ .command({
command: `migrations [action]`, command: `migrations [action] [modules...]`,
desc: `Manage migrations from the core and your own project`, desc: `Manage migrations from the core and your own project`,
builder: { builder: {
action: { action: {
demand: true, demand: true,
description: "The action to perform on migrations",
choices: ["run", "revert", "show"], choices: ["run", "revert", "show"],
}, },
modules: {
description: "Revert migrations for defined modules",
demand: false,
},
}, },
handler: handlerP( handler: handlerP(
getCommandHandler(`migrate`, (args, cmd) => { getCommandHandler(`migrate`, (args, cmd) => {
@@ -180,7 +180,6 @@ export async function loadModuleMigrations(
let runMigrations = loadedModule.runMigrations let runMigrations = loadedModule.runMigrations
let revertMigration = loadedModule.revertMigration let revertMigration = loadedModule.revertMigration
// Generate migration scripts if they are not present
if (!runMigrations || !revertMigration) { if (!runMigrations || !revertMigration) {
const moduleResources = await loadResources( const moduleResources = await loadResources(
resolution, resolution,
@@ -190,8 +189,7 @@ export async function loadModuleMigrations(
const migrationScriptOptions = { const migrationScriptOptions = {
moduleName: resolution.definition.key, moduleName: resolution.definition.key,
models: moduleResources.models, pathToMigrations: join(moduleResources.normalizedPath, "migrations"),
pathToMigrations: moduleResources.normalizedPath + "/migrations",
} }
runMigrations ??= ModulesSdkUtils.buildMigrationScript( runMigrations ??= ModulesSdkUtils.buildMigrationScript(
+95 -46
View File
@@ -8,6 +8,7 @@ import type {
LoadedModule, LoadedModule,
Logger, Logger,
MedusaContainer, MedusaContainer,
ModuleBootstrapDeclaration,
ModuleDefinition, ModuleDefinition,
ModuleExports, ModuleExports,
ModuleJoinerConfig, ModuleJoinerConfig,
@@ -21,6 +22,7 @@ import {
createMedusaContainer, createMedusaContainer,
isObject, isObject,
isString, isString,
MedusaError,
ModuleRegistrationName, ModuleRegistrationName,
Modules, Modules,
ModulesSdkUtils, ModulesSdkUtils,
@@ -47,10 +49,8 @@ declare module "@medusajs/types" {
} }
} }
export type RunMigrationFn = ( export type RunMigrationFn = () => Promise<void>
options?: ModuleServiceInitializeOptions, export type RevertMigrationFn = (moduleNames: string[]) => Promise<void>
injectedDependencies?: Record<any, any>
) => Promise<void>
export type MedusaModuleConfig = { export type MedusaModuleConfig = {
[key: string | Modules]: [key: string | Modules]:
@@ -176,11 +176,11 @@ async function initializeLinks({
} }
} catch (err) { } catch (err) {
console.warn("Error initializing link modules.", err) console.warn("Error initializing link modules.", err)
return { return {
remoteLink: undefined, remoteLink: undefined,
linkResolution: undefined, linkResolution: undefined,
runMigrations: undefined, runMigrations: () => void 0,
revertMigrations: () => void 0,
} }
} }
} }
@@ -224,7 +224,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 revertMigrations: RevertMigrationFn
onApplicationShutdown: () => Promise<void> onApplicationShutdown: () => Promise<void>
onApplicationPrepareShutdown: () => Promise<void> onApplicationPrepareShutdown: () => Promise<void>
sharedContainer?: MedusaContainer sharedContainer?: MedusaContainer
@@ -317,10 +317,12 @@ async function MedusaApp_({
delete modules[LinkModulePackage] delete modules[LinkModulePackage]
delete modules[Modules.LINK] delete modules[Modules.LINK]
let linkModuleOptions = {} let linkModuleOrOptions:
| Partial<ModuleServiceInitializeOptions>
| Partial<ModuleBootstrapDeclaration> = {}
if (isObject(linkModule)) { if (isObject(linkModule)) {
linkModuleOptions = linkModule linkModuleOrOptions = linkModule
} }
for (const injectedDependency of Object.keys(injectedDependencies)) { for (const injectedDependency of Object.keys(injectedDependencies)) {
@@ -380,7 +382,7 @@ async function MedusaApp_({
runMigrations: linkModuleMigration, runMigrations: linkModuleMigration,
revertMigrations: revertLinkModuleMigration, revertMigrations: revertLinkModuleMigration,
} = await initializeLinks({ } = await initializeLinks({
config: linkModuleOptions, config: linkModuleOrOptions,
linkModules, linkModules,
injectedDependencies, injectedDependencies,
moduleExports: isMedusaModule(linkModule) ? linkModule : undefined, moduleExports: isMedusaModule(linkModule) ? linkModule : undefined,
@@ -402,10 +404,38 @@ async function MedusaApp_({
return await remoteQuery.query(query, variables, options) return await remoteQuery.query(query, variables, options)
} }
const applyMigration = async (linkModuleOptions, revert = false) => { const applyMigration = async ({
for (const moduleName of Object.keys(allModules)) { modulesNames,
const moduleResolution = MedusaModule.getModuleResolutions(moduleName) revert = false,
}: {
modulesNames: string[]
revert?: boolean
}) => {
const moduleResolutions = modulesNames.map((moduleName) => {
return {
moduleName,
resolution: MedusaModule.getModuleResolutions(moduleName),
}
})
const missingModules = moduleResolutions
.filter(({ resolution }) => !resolution)
.map(({ moduleName }) => moduleName)
if (missingModules.length) {
const action = revert ? "revert" : "run"
const error = new MedusaError(
MedusaError.Types.UNKNOWN_MODULES,
`Cannot ${action} migrations for unknown module(s) ${missingModules.join(
","
)}`,
MedusaError.Codes.UNKNOWN_MODULES
)
error["allModules"] = Object.keys(allModules)
throw error
}
for (const { resolution: moduleResolution } of moduleResolutions) {
if (!moduleResolution.options?.database) { if (!moduleResolution.options?.database) {
moduleResolution.options ??= {} moduleResolution.options ??= {}
moduleResolution.options.database = { moduleResolution.options.database = {
@@ -417,6 +447,7 @@ async function MedusaApp_({
await MedusaModule.migrateDown( await MedusaModule.migrateDown(
moduleResolution.definition.key, moduleResolution.definition.key,
moduleResolution.resolutionPath as string, moduleResolution.resolutionPath as string,
sharedContainer,
moduleResolution.options, moduleResolution.options,
moduleResolution.moduleExports moduleResolution.moduleExports
) )
@@ -424,48 +455,65 @@ async function MedusaApp_({
await MedusaModule.migrateUp( await MedusaModule.migrateUp(
moduleResolution.definition.key, moduleResolution.definition.key,
moduleResolution.resolutionPath as string, moduleResolution.resolutionPath as string,
sharedContainer,
moduleResolution.options, moduleResolution.options,
moduleResolution.moduleExports moduleResolution.moduleExports
) )
} }
} }
const linkModuleOpt = { ...(linkModuleOptions ?? {}) }
linkModuleOpt.database ??= {
...(sharedResourcesConfig?.database ?? {}),
}
if (revert) {
revertLinkModuleMigration &&
(await revertLinkModuleMigration(
{
options: linkModuleOpt,
injectedDependencies,
},
linkModules
))
} else {
linkModuleMigration &&
(await linkModuleMigration(
{
options: linkModuleOpt,
injectedDependencies,
},
linkModules
))
}
} }
const runMigrations: RunMigrationFn = async ( const runMigrations: RunMigrationFn = async (): Promise<void> => {
linkModuleOptions await applyMigration({
): Promise<void> => { modulesNames: Object.keys(allModules),
await applyMigration(linkModuleOptions) })
const options: Partial<ModuleServiceInitializeOptions> =
"scope" in linkModuleOrOptions
? { ...linkModuleOrOptions.options }
: {
...(linkModuleOrOptions as Partial<ModuleServiceInitializeOptions>),
}
options.database ??= {
...sharedResourcesConfig?.database,
}
await linkModuleMigration(
{
options,
injectedDependencies,
},
linkModules
)
} }
const revertMigrations: RunMigrationFn = async ( const revertMigrations: RevertMigrationFn = async (
linkModuleOptions modulesNames
): Promise<void> => { ): Promise<void> => {
await applyMigration(linkModuleOptions, true) await applyMigration({
modulesNames,
revert: true,
})
const options: Partial<ModuleServiceInitializeOptions> =
"scope" in linkModuleOrOptions
? { ...linkModuleOrOptions.options }
: {
...(linkModuleOrOptions as Partial<ModuleServiceInitializeOptions>),
}
options.database ??= {
...sharedResourcesConfig?.database,
}
await revertLinkModuleMigration(
{
options,
injectedDependencies,
},
linkModules
)
} }
return { return {
@@ -506,6 +554,7 @@ export async function MedusaAppMigrateUp(
} }
export async function MedusaAppMigrateDown( export async function MedusaAppMigrateDown(
moduleNames: string[],
options: MedusaAppOptions = {} options: MedusaAppOptions = {}
): Promise<void> { ): Promise<void> {
const migrationOnly = true const migrationOnly = true
@@ -515,5 +564,5 @@ export async function MedusaAppMigrateDown(
migrationOnly, migrationOnly,
}) })
await revertMigrations().finally(MedusaModule.clearInstances) await revertMigrations(moduleNames).finally(MedusaModule.clearInstances)
} }
+21 -4
View File
@@ -12,6 +12,7 @@ import {
ModuleResolution, ModuleResolution,
} from "@medusajs/types" } from "@medusajs/types"
import { import {
ContainerRegistrationKeys,
createMedusaContainer, createMedusaContainer,
promiseAll, promiseAll,
simpleHash, simpleHash,
@@ -344,7 +345,9 @@ class MedusaModule {
) )
const logger_ = const logger_ =
container.resolve("logger", { allowUnregistered: true }) ?? logger container.resolve(ContainerRegistrationKeys.LOGGER, {
allowUnregistered: true,
}) ?? logger
try { try {
await moduleLoader({ await moduleLoader({
@@ -475,7 +478,9 @@ class MedusaModule {
) )
const logger_ = const logger_ =
container.resolve("logger", { allowUnregistered: true }) ?? logger container.resolve(ContainerRegistrationKeys.LOGGER, {
allowUnregistered: true,
}) ?? logger
try { try {
await moduleLoader({ await moduleLoader({
@@ -534,6 +539,7 @@ class MedusaModule {
public static async migrateUp( public static async migrateUp(
moduleKey: string, moduleKey: string,
modulePath: string, modulePath: string,
container?: MedusaContainer,
options?: Record<string, any>, options?: Record<string, any>,
moduleExports?: ModuleExports moduleExports?: ModuleExports
): Promise<void> { ): Promise<void> {
@@ -544,6 +550,11 @@ class MedusaModule {
options, options,
}) })
const logger_ =
container?.resolve(ContainerRegistrationKeys.LOGGER, {
allowUnregistered: true,
}) ?? logger
for (const mod in moduleResolutions) { for (const mod in moduleResolutions) {
const [migrateUp] = await loadModuleMigrations( const [migrateUp] = await loadModuleMigrations(
moduleResolutions[mod], moduleResolutions[mod],
@@ -553,7 +564,7 @@ class MedusaModule {
if (typeof migrateUp === "function") { if (typeof migrateUp === "function") {
await migrateUp({ await migrateUp({
options, options,
logger, logger: logger_,
}) })
} }
} }
@@ -562,6 +573,7 @@ class MedusaModule {
public static async migrateDown( public static async migrateDown(
moduleKey: string, moduleKey: string,
modulePath: string, modulePath: string,
container?: MedusaContainer,
options?: Record<string, any>, options?: Record<string, any>,
moduleExports?: ModuleExports moduleExports?: ModuleExports
): Promise<void> { ): Promise<void> {
@@ -572,6 +584,11 @@ class MedusaModule {
options, options,
}) })
const logger_ =
container?.resolve(ContainerRegistrationKeys.LOGGER, {
allowUnregistered: true,
}) ?? logger
for (const mod in moduleResolutions) { for (const mod in moduleResolutions) {
const [, migrateDown] = await loadModuleMigrations( const [, migrateDown] = await loadModuleMigrations(
moduleResolutions[mod], moduleResolutions[mod],
@@ -581,7 +598,7 @@ class MedusaModule {
if (typeof migrateDown === "function") { if (typeof migrateDown === "function") {
await migrateDown({ await migrateDown({
options, options,
logger, logger: logger_,
}) })
} }
} }
+2
View File
@@ -13,6 +13,7 @@ export const MedusaErrorTypes = {
NOT_ALLOWED: "not_allowed", NOT_ALLOWED: "not_allowed",
UNEXPECTED_STATE: "unexpected_state", UNEXPECTED_STATE: "unexpected_state",
CONFLICT: "conflict", CONFLICT: "conflict",
UNKNOWN_MODULES: "unknown_modules",
PAYMENT_AUTHORIZATION_ERROR: "payment_authorization_error", PAYMENT_AUTHORIZATION_ERROR: "payment_authorization_error",
PAYMENT_REQUIRES_MORE_ERROR: "payment_requires_more_error", PAYMENT_REQUIRES_MORE_ERROR: "payment_requires_more_error",
} }
@@ -20,6 +21,7 @@ export const MedusaErrorTypes = {
export const MedusaErrorCodes = { export const MedusaErrorCodes = {
INSUFFICIENT_INVENTORY: "insufficient_inventory", INSUFFICIENT_INVENTORY: "insufficient_inventory",
CART_INCOMPATIBLE_STATE: "cart_incompatible_state", CART_INCOMPATIBLE_STATE: "cart_incompatible_state",
UNKNOWN_MODULES: "unknown_modules",
} }
/** /**
+12 -5
View File
@@ -5,6 +5,7 @@ import {
UmzugMigration, UmzugMigration,
} from "@mikro-orm/migrations" } from "@mikro-orm/migrations"
import { MikroORM, MikroORMOptions } from "@mikro-orm/core" import { MikroORM, MikroORMOptions } from "@mikro-orm/core"
import { PostgreSqlDriver } from "@mikro-orm/postgresql"
/** /**
* Events emitted by the migrations class * Events emitted by the migrations class
@@ -20,11 +21,13 @@ export type MigrationsEvents = {
* Exposes the API to programmatically manage Mikro ORM migrations * Exposes the API to programmatically manage Mikro ORM migrations
*/ */
export class Migrations extends EventEmitter<MigrationsEvents> { export class Migrations extends EventEmitter<MigrationsEvents> {
#config: Partial<MikroORMOptions> #configOrConnection: Partial<MikroORMOptions> | MikroORM<PostgreSqlDriver>
constructor(config: Partial<MikroORMOptions>) { constructor(
configOrConnection: Partial<MikroORMOptions> | MikroORM<PostgreSqlDriver>
) {
super() super()
this.#config = config this.#configOrConnection = configOrConnection
} }
/** /**
@@ -32,10 +35,14 @@ export class Migrations extends EventEmitter<MigrationsEvents> {
* one * one
*/ */
async #getConnection() { async #getConnection() {
if ("connect" in this.#configOrConnection) {
return this.#configOrConnection as MikroORM<PostgreSqlDriver>
}
return await MikroORM.init({ return await MikroORM.init({
...this.#config, ...this.#configOrConnection,
migrations: { migrations: {
...this.#config.migrations, ...this.#configOrConnection.migrations,
silent: true, silent: true,
}, },
}) })
@@ -1,23 +1,17 @@
import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types" import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types"
import { EntitySchema } from "@mikro-orm/core"
import { upperCaseFirst } from "../../common"
import { mikroOrmCreateConnection } from "../../dal" import { mikroOrmCreateConnection } from "../../dal"
import { DmlEntity, toMikroORMEntity } from "../../dml"
import { loadDatabaseConfig } from "../load-module-database-config" import { loadDatabaseConfig } from "../load-module-database-config"
import { Migrations } from "../../migrations"
const TERMINAL_SIZE = process.stdout.columns
/** /**
* Utility function to build a migration script that will revert the migrations. * Utility function to build a migration script that will revert the migrations.
* Only used in mikro orm based modules. * Only used in mikro orm based modules.
* @param moduleName * @param moduleName
* @param models
* @param pathToMigrations * @param pathToMigrations
*/ */
export function buildRevertMigrationScript({ export function buildRevertMigrationScript({ moduleName, pathToMigrations }) {
moduleName,
models,
pathToMigrations,
}) {
/** /**
* This script is only valid for mikro orm managers. If a user provide a custom manager * This script is only valid for mikro orm managers. If a user provide a custom manager
* he is in charge of reverting the migrations. * he is in charge of reverting the migrations.
@@ -34,34 +28,30 @@ export function buildRevertMigrationScript({
> = {}) { > = {}) {
logger ??= console as unknown as Logger logger ??= console as unknown as Logger
console.log(new Array(TERMINAL_SIZE).join("-"))
console.log("")
logger.info(`MODULE: ${moduleName}`)
const dbData = loadDatabaseConfig(moduleName, options)! const dbData = loadDatabaseConfig(moduleName, options)!
const entities = Object.values(models).map((model) => { const orm = await mikroOrmCreateConnection(dbData, [], pathToMigrations)
if (DmlEntity.isDmlEntity(model)) { const migrations = new Migrations(orm)
return toMikroORMEntity(model)
}
return model migrations.on("reverting", (migration) => {
}) as unknown as EntitySchema[] logger.info(` ● Reverting ${migration.name}`)
})
const orm = await mikroOrmCreateConnection( migrations.on("reverted", (migration) => {
dbData, logger.info(` ✔ Reverted ${migration.name}`)
entities, })
pathToMigrations
)
try { try {
const migrator = orm.getMigrator() const result = await migrations.revert()
await migrator.down() if (result.length) {
logger.info("Reverted successfully")
logger?.info(`${upperCaseFirst(moduleName)} module migration executed`) } else {
logger.info("Skipped. Nothing to revert")
}
} catch (error) { } catch (error) {
logger?.error( logger.error(`Failed with error ${error.message}`, error)
`${upperCaseFirst(
moduleName
)} module migration failed to run - Error: ${error.errros ?? error}`
)
} }
await orm.close()
} }
} }
@@ -1,18 +1,17 @@
import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types" import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types"
import { EntitySchema } from "@mikro-orm/core"
import { upperCaseFirst } from "../../common"
import { mikroOrmCreateConnection } from "../../dal" import { mikroOrmCreateConnection } from "../../dal"
import { DmlEntity, toMikroORMEntity } from "../../dml"
import { loadDatabaseConfig } from "../load-module-database-config" import { loadDatabaseConfig } from "../load-module-database-config"
import { Migrations } from "../../migrations"
const TERMINAL_SIZE = process.stdout.columns
/** /**
* Utility function to build a migration script that will run the migrations. * Utility function to build a migration script that will run the migrations.
* Only used in mikro orm based modules. * Only used in mikro orm based modules.
* @param moduleName * @param moduleName
* @param models
* @param pathToMigrations * @param pathToMigrations
*/ */
export function buildMigrationScript({ moduleName, models, pathToMigrations }) { export function buildMigrationScript({ moduleName, pathToMigrations }) {
/** /**
* This script is only valid for mikro orm managers. If a user provide a custom manager * This script is only valid for mikro orm managers. If a user provide a custom manager
* he is in charge of running the migrations. * he is in charge of running the migrations.
@@ -29,48 +28,30 @@ export function buildMigrationScript({ moduleName, models, pathToMigrations }) {
> = {}) { > = {}) {
logger ??= console as unknown as Logger logger ??= console as unknown as Logger
console.log(new Array(TERMINAL_SIZE).join("-"))
console.log("")
logger.info(`MODULE: ${moduleName}`)
const dbData = loadDatabaseConfig(moduleName, options)! const dbData = loadDatabaseConfig(moduleName, options)!
const entities = Object.values(models).map((model) => { const orm = await mikroOrmCreateConnection(dbData, [], pathToMigrations)
if (DmlEntity.isDmlEntity(model)) { const migrations = new Migrations(orm)
return toMikroORMEntity(model)
}
return model migrations.on("migrating", (migration) => {
}) as unknown as EntitySchema[] logger.info(` ● Migrating ${migration.name}`)
})
const orm = await mikroOrmCreateConnection( migrations.on("migrated", (migration) => {
dbData, logger.info(` ✔ Migrated ${migration.name}`)
entities, })
pathToMigrations
)
try { try {
const migrator = orm.getMigrator() const result = await migrations.run()
const pendingMigrations = await migrator.getPendingMigrations() if (result.length) {
logger.info("Completed successfully")
if (pendingMigrations.length) { } else {
logger.info( logger.info("Skipped. Database is upto-date")
`Pending migrations: ${JSON.stringify(pendingMigrations, null, 2)}`
)
await migrator.up({
migrations: pendingMigrations.map((m) => m.name),
})
logger.info(
`${upperCaseFirst(moduleName)} module: ${
pendingMigrations.length
} migration files executed`
)
} }
} catch (error) { } catch (error) {
logger.error( logger.error(`Failed with error ${error.message}`, error)
`${upperCaseFirst(
moduleName
)} module migration failed to run - Error: ${error.errros ?? error}`
)
} }
await orm.close()
} }
} }
+45 -8
View File
@@ -1,16 +1,19 @@
import Logger from "../loaders/logger" import Logger from "../loaders/logger"
import { migrateMedusaApp, revertMedusaApp } from "../loaders/medusa-app" import { migrateMedusaApp, revertMedusaApp } from "../loaders/medusa-app"
import { initializeContainer } from "../loaders" import { initializeContainer } from "../loaders"
import { ContainerRegistrationKeys } 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 { resolvePluginsLinks } from "../loaders/helpers/resolve-plugins-links"
const TERMINAL_SIZE = process.stdout.columns
const main = async function ({ directory }) { const main = async function ({ directory }) {
const args = process.argv const args = process.argv
args.shift() args.shift()
args.shift() args.shift()
args.shift() args.shift()
const action = args[0]
const container = await initializeContainer(directory) const container = await initializeContainer(directory)
const configModule = container.resolve( const configModule = container.resolve(
@@ -20,21 +23,55 @@ const main = async function ({ directory }) {
const plugins = getResolvedPlugins(directory, configModule, true) || [] const plugins = getResolvedPlugins(directory, configModule, true) || []
const pluginLinks = await resolvePluginsLinks(plugins, container) const pluginLinks = await resolvePluginsLinks(plugins, container)
if (args[0] === "run") { if (action === "run") {
Logger.info("Running migrations...")
await migrateMedusaApp({ await migrateMedusaApp({
configModule, configModule,
linkModules: pluginLinks, linkModules: pluginLinks,
container, container,
}) })
Logger.info("Migrations completed.") console.log(new Array(TERMINAL_SIZE).join("-"))
Logger.info("Migrations completed")
process.exit() process.exit()
} else if (args[0] === "revert") { } else if (action === "revert") {
await revertMedusaApp({ configModule, linkModules: pluginLinks, container }) const modulesToRevert = args.slice(1)
if (!modulesToRevert.length) {
Logger.error(
"Please provide the modules for which you want to revert migrations"
)
Logger.error(`For example: "npx medusa migration revert <moduleName>"`)
process.exit(1)
}
Logger.info("Migrations reverted.") Logger.info("Reverting migrations...")
} else if (args[0] === "show") {
Logger.info("not supported") try {
await revertMedusaApp({
modulesToRevert,
configModule,
linkModules: pluginLinks,
container,
})
console.log(new Array(TERMINAL_SIZE).join("-"))
Logger.info("Migrations reverted")
process.exit()
} catch (error) {
console.log(new Array(TERMINAL_SIZE).join("-"))
if (error.code && error.code === MedusaError.Codes.UNKNOWN_MODULES) {
Logger.error(error.message)
const modulesList = error.allModules.map(
(name: string) => ` - ${name}`
)
Logger.error(`Available modules:\n${modulesList.join("\n")}`)
} else {
Logger.error(error.message, error)
}
process.exit(1)
}
} else if (action === "show") {
Logger.info("Action not supported yet")
process.exit(0) process.exit(0)
} }
} }
+30 -3
View File
@@ -60,6 +60,7 @@ export function mergeDefaultModules(
async function runMedusaAppMigrations({ async function runMedusaAppMigrations({
configModule, configModule,
container, container,
moduleNames,
revert = false, revert = false,
linkModules, linkModules,
}: { }: {
@@ -69,8 +70,16 @@ async function runMedusaAppMigrations({
} }
linkModules?: MedusaAppOptions["linkModules"] linkModules?: MedusaAppOptions["linkModules"]
container: MedusaContainer container: MedusaContainer
revert?: boolean } & (
}): Promise<void> { | {
moduleNames?: never
revert: false
}
| {
moduleNames: string[]
revert: true
}
)): Promise<void> {
const injectedDependencies = { const injectedDependencies = {
[ContainerRegistrationKeys.PG_CONNECTION]: container.resolve( [ContainerRegistrationKeys.PG_CONNECTION]: container.resolve(
ContainerRegistrationKeys.PG_CONNECTION ContainerRegistrationKeys.PG_CONNECTION
@@ -93,7 +102,7 @@ async function runMedusaAppMigrations({
const configModules = mergeDefaultModules(configModule.modules) const configModules = mergeDefaultModules(configModule.modules)
if (revert) { if (revert) {
await MedusaAppMigrateDown({ await MedusaAppMigrateDown(moduleNames!, {
modulesConfig: configModules, modulesConfig: configModules,
sharedContainer: container, sharedContainer: container,
linkModules, linkModules,
@@ -111,6 +120,12 @@ async function runMedusaAppMigrations({
} }
} }
/**
*
* @param configModule The config module
* @param linkModules Custom links from the plugins
* @param container The medusa container
*/
export async function migrateMedusaApp({ export async function migrateMedusaApp({
configModule, configModule,
linkModules, linkModules,
@@ -127,14 +142,25 @@ export async function migrateMedusaApp({
configModule, configModule,
container, container,
linkModules, linkModules,
revert: false,
}) })
} }
/**
*
* @param modulesToRevert An array of modules for which you want to revert
* migrations
* @param configModule The config module
* @param linkModules Custom links from the plugins
* @param container The medusa container
*/
export async function revertMedusaApp({ export async function revertMedusaApp({
modulesToRevert,
configModule, configModule,
linkModules, linkModules,
container, container,
}: { }: {
modulesToRevert: string[]
configModule: { configModule: {
modules?: CommonTypes.ConfigModule["modules"] modules?: CommonTypes.ConfigModule["modules"]
projectConfig: CommonTypes.ConfigModule["projectConfig"] projectConfig: CommonTypes.ConfigModule["projectConfig"]
@@ -143,6 +169,7 @@ export async function revertMedusaApp({
linkModules?: MedusaAppOptions["linkModules"] linkModules?: MedusaAppOptions["linkModules"]
}): Promise<void> { }): Promise<void> {
await runMedusaAppMigrations({ await runMedusaAppMigrations({
moduleNames: modulesToRevert,
configModule, configModule,
container, container,
revert: true, revert: true,