diff --git a/.changeset/funny-rocks-brake.md b/.changeset/funny-rocks-brake.md new file mode 100644 index 0000000000..190e542b33 --- /dev/null +++ b/.changeset/funny-rocks-brake.md @@ -0,0 +1,6 @@ +--- +"@medusajs/product": patch +"@medusajs/utils": patch +--- + +chore(utils, product): Attempt to simplify module scripts export diff --git a/packages/product/package.json b/packages/product/package.json index 96cfc916ec..20c058dc9b 100644 --- a/packages/product/package.json +++ b/packages/product/package.json @@ -8,8 +8,6 @@ "dist" ], "bin": { - "medusa-product-migrations-down": "dist/scripts/bin/run-migration-down.js", - "medusa-product-migrations-up": "dist/scripts/bin/run-migration-up.js", "medusa-product-seed": "dist/scripts/bin/run-seed.js" }, "engines": { diff --git a/packages/product/src/index.ts b/packages/product/src/index.ts index 45da1e739d..e8df9fb52e 100644 --- a/packages/product/src/index.ts +++ b/packages/product/src/index.ts @@ -1,8 +1,23 @@ import { moduleDefinition } from "./module-definition" +import { ModulesSdkUtils } from "@medusajs/utils" +import { Modules } from "@medusajs/modules-sdk" +import * as ProductModels from "@models" export default moduleDefinition -export * from "./scripts" +const migrationScriptOptions = { + moduleName: Modules.PRODUCT, + models: ProductModels, + pathToMigrations: __dirname + "/migrations", +} + +export const runMigrations = ModulesSdkUtils.buildMigrationScript( + migrationScriptOptions +) +export const revertMigration = ModulesSdkUtils.buildRevertMigrationScript( + migrationScriptOptions +) + export * from "./initialize" export * from "./types" export * from "./loaders" diff --git a/packages/product/src/scripts/bin/run-migration-down.ts b/packages/product/src/scripts/bin/run-migration-down.ts deleted file mode 100644 index e352048fd4..0000000000 --- a/packages/product/src/scripts/bin/run-migration-down.ts +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env node - -export default (async () => { - const { revertMigration } = await import("../migration-down") - const { config } = await import("dotenv") - config() - await revertMigration() -})() diff --git a/packages/product/src/scripts/bin/run-migration-up.ts b/packages/product/src/scripts/bin/run-migration-up.ts deleted file mode 100644 index 35f3bee853..0000000000 --- a/packages/product/src/scripts/bin/run-migration-up.ts +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env node - -export default (async () => { - const { runMigrations } = await import("../migration-up") - const { config } = await import("dotenv") - config() - await runMigrations() -})() diff --git a/packages/product/src/scripts/bin/run-seed.ts b/packages/product/src/scripts/bin/run-seed.ts index 0b4a242d6f..ce168bede0 100644 --- a/packages/product/src/scripts/bin/run-seed.ts +++ b/packages/product/src/scripts/bin/run-seed.ts @@ -1,6 +1,13 @@ #!/usr/bin/env node -import { run } from "../seed" +import { ModulesSdkUtils } from "@medusajs/utils" +import { Modules } from "@medusajs/modules-sdk" +import * as ProductModels from "@models" +import { + createProductCategories, + createProducts, + createProductVariants, +} from "../seed-utils" import { EOL } from "os" const args = process.argv @@ -15,5 +22,16 @@ export default (async () => { ) } + const run = ModulesSdkUtils.buildSeedScript({ + moduleName: Modules.PRODUCT, + models: ProductModels, + pathToMigrations: __dirname + "/../../migrations", + seedHandler: async ({ manager, data }) => { + const { productCategoriesData, productsData, variantsData } = data + await createProductCategories(manager, productCategoriesData) + await createProducts(manager, productsData) + await createProductVariants(manager, variantsData) + }, + }) await run({ path }) })() diff --git a/packages/product/src/scripts/migration-down.ts b/packages/product/src/scripts/migration-down.ts deleted file mode 100644 index 3ee0534378..0000000000 --- a/packages/product/src/scripts/migration-down.ts +++ /dev/null @@ -1,44 +0,0 @@ -import * as ProductModels from "@models" - -import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types" - -import { DALUtils, ModulesSdkUtils } from "@medusajs/utils" -import { EntitySchema } from "@mikro-orm/core" - -/** - * This script is only valid for mikro orm managers. If a user provide a custom manager - * he is in charge of reverting the migrations. - * @param options - * @param logger - * @param moduleDeclaration - */ -export async function revertMigration({ - options, - logger, -}: Pick< - LoaderOptions, - "options" | "logger" -> = {}) { - logger ??= console as unknown as Logger - - const dbData = ModulesSdkUtils.loadDatabaseConfig("product", options)! - const entities = Object.values(ProductModels) as unknown as EntitySchema[] - const pathToMigrations = __dirname + "/../migrations" - - const orm = await DALUtils.mikroOrmCreateConnection( - dbData, - entities, - pathToMigrations - ) - - try { - const migrator = orm.getMigrator() - await migrator.down() - - logger?.info("Product module migration executed") - } catch (error) { - logger?.error(`Product module migration failed to run - Error: ${error}`) - } - - await orm.close() -} diff --git a/packages/product/src/scripts/migration-up.ts b/packages/product/src/scripts/migration-up.ts deleted file mode 100644 index ec73d90f61..0000000000 --- a/packages/product/src/scripts/migration-up.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types" -import { DALUtils, ModulesSdkUtils } from "@medusajs/utils" -import { EntitySchema } from "@mikro-orm/core" -import * as ProductModels from "@models" - -/** - * This script is only valid for mikro orm managers. If a user provide a custom manager - * he is in charge of running the migrations. - * @param options - * @param logger - * @param moduleDeclaration - */ -export async function runMigrations({ - options, - logger, -}: Pick< - LoaderOptions, - "options" | "logger" -> = {}) { - logger ??= console as unknown as Logger - - const dbData = ModulesSdkUtils.loadDatabaseConfig("product", options)! - const entities = Object.values(ProductModels) as unknown as EntitySchema[] - const pathToMigrations = __dirname + "/../migrations" - - const orm = await DALUtils.mikroOrmCreateConnection( - dbData, - entities, - pathToMigrations - ) - - try { - const migrator = orm.getMigrator() - - const pendingMigrations = await migrator.getPendingMigrations() - logger.info( - `Running pending migrations: ${JSON.stringify( - pendingMigrations, - null, - 2 - )}` - ) - - await migrator.up({ - migrations: pendingMigrations.map((m) => m.name), - }) - - logger.info("Product module migration executed") - } catch (error) { - logger.error(`Product module migration failed to run - Error: ${error}`) - } - - await orm.close() -} diff --git a/packages/product/src/scripts/seed-utils.ts b/packages/product/src/scripts/seed-utils.ts new file mode 100644 index 0000000000..829ad271b9 --- /dev/null +++ b/packages/product/src/scripts/seed-utils.ts @@ -0,0 +1,54 @@ +import { SqlEntityManager } from "@mikro-orm/postgresql" +import { Product, ProductCategory, ProductVariant } from "@models" + +export async function createProductCategories( + manager: SqlEntityManager, + categoriesData: any[] +): Promise { + const categories: ProductCategory[] = [] + + for (let categoryData of categoriesData) { + let categoryDataClone = { ...categoryData } + let parentCategory: ProductCategory | null = null + const parentCategoryId = categoryDataClone.parent_category_id as string + delete categoryDataClone.parent_category_id + + if (parentCategoryId) { + parentCategory = await manager.findOne(ProductCategory, parentCategoryId) + } + + const category = manager.create(ProductCategory, { + ...categoryDataClone, + parent_category: parentCategory, + }) + + categories.push(category) + } + + await manager.persistAndFlush(categories) + + return categories +} + +export async function createProducts(manager: SqlEntityManager, data: any[]) { + const products: any[] = data.map((productData) => { + return manager.create(Product, productData) + }) + + await manager.persistAndFlush(products) + + return products +} + +export async function createProductVariants( + manager: SqlEntityManager, + data: any[] +) { + const variants: any[] = data.map((variantsData) => { + return manager.create(ProductVariant, variantsData) + }) + + await manager.persistAndFlush(variants) + + return variants +} diff --git a/packages/product/src/scripts/seed.ts b/packages/product/src/scripts/seed.ts deleted file mode 100644 index 31bd14b28e..0000000000 --- a/packages/product/src/scripts/seed.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types" -import { DALUtils, ModulesSdkUtils } from "@medusajs/utils" -import { EntitySchema } from "@mikro-orm/core" -import { SqlEntityManager } from "@mikro-orm/postgresql" -import * as ProductModels from "@models" -import { Product, ProductCategory, ProductVariant } from "@models" -import { EOL } from "os" -import { resolve } from "path" - -export async function run({ - options, - logger, - path, -}: Partial< - Pick< - LoaderOptions, - "options" | "logger" - > -> & { - path: string -}) { - logger?.info(`Loading seed data from ${path}...`) - const { productCategoriesData, productsData, variantsData } = await import( - resolve(process.cwd(), path) - ).catch((e) => { - logger?.error( - `Failed to load seed data from ${path}. Please, provide a relative path and check that you export the following productCategoriesData, productsData, variantsData.${EOL}${e}` - ) - throw e - }) - - logger ??= console as unknown as Logger - - const dbData = ModulesSdkUtils.loadDatabaseConfig("product", options)! - const entities = Object.values(ProductModels) as unknown as EntitySchema[] - const pathToMigrations = __dirname + "/../migrations" - - const orm = await DALUtils.mikroOrmCreateConnection( - dbData, - entities, - pathToMigrations - ) - const manager = orm.em.fork() - - try { - logger?.info("Inserting product categories, products and variants...") - await createProductCategories(manager, productCategoriesData) - await createProducts(manager, productsData) - await createProductVariants(manager, variantsData) - } catch (e) { - logger?.error( - `Failed to insert the seed data in the PostgreSQL database ${dbData.clientUrl}.${EOL}${e}` - ) - } - - await orm.close(true) -} - -async function createProductCategories( - manager: SqlEntityManager, - categoriesData: any[] -): Promise { - const categories: ProductCategory[] = [] - - for (let categoryData of categoriesData) { - let categoryDataClone = { ...categoryData } - let parentCategory: ProductCategory | null = null - const parentCategoryId = categoryDataClone.parent_category_id as string - delete categoryDataClone.parent_category_id - - if (parentCategoryId) { - parentCategory = await manager.findOne(ProductCategory, parentCategoryId) - } - - const category = manager.create(ProductCategory, { - ...categoryDataClone, - parent_category: parentCategory, - }) - - categories.push(category) - } - - await manager.persistAndFlush(categories) - - return categories -} - -async function createProducts(manager: SqlEntityManager, data: any[]) { - const products: any[] = data.map((productData) => { - return manager.create(Product, productData) - }) - - await manager.persistAndFlush(products) - - return products -} - -async function createProductVariants(manager: SqlEntityManager, data: any[]) { - const variants: any[] = data.map((variantsData) => { - return manager.create(ProductVariant, variantsData) - }) - - await manager.persistAndFlush(variants) - - return variants -} diff --git a/packages/utils/src/modules-sdk/index.ts b/packages/utils/src/modules-sdk/index.ts index 3e318d0aa2..96948c7bff 100644 --- a/packages/utils/src/modules-sdk/index.ts +++ b/packages/utils/src/modules-sdk/index.ts @@ -4,3 +4,4 @@ export * from "./build-query" export * from "./retrieve-entity" export * from "./loaders/mikro-orm-connection-loader" export * from "./create-pg-connection" +export * from "./migration-scripts" diff --git a/packages/product/src/scripts/index.ts b/packages/utils/src/modules-sdk/migration-scripts/index.ts similarity index 73% rename from packages/product/src/scripts/index.ts rename to packages/utils/src/modules-sdk/migration-scripts/index.ts index cfa5c5ddf5..125b5cdbe6 100644 --- a/packages/product/src/scripts/index.ts +++ b/packages/utils/src/modules-sdk/migration-scripts/index.ts @@ -1,2 +1,3 @@ -export * from "./migration-up" export * from "./migration-down" +export * from "./migration-up" +export * from "./seed" diff --git a/packages/utils/src/modules-sdk/migration-scripts/migration-down.ts b/packages/utils/src/modules-sdk/migration-scripts/migration-down.ts new file mode 100644 index 0000000000..c4ea90dd8d --- /dev/null +++ b/packages/utils/src/modules-sdk/migration-scripts/migration-down.ts @@ -0,0 +1,60 @@ +import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types" + +import { EntitySchema } from "@mikro-orm/core" +import { upperCaseFirst } from "../../common" +import { loadDatabaseConfig } from "../load-module-database-config" +import { mikroOrmCreateConnection } from "../../dal" + +/** + * Utility function to build a migration script that will revert the migrations. + * Only used in mikro orm based modules. + * @param moduleName + * @param models + * @param pathToMigrations + */ +export function buildRevertMigrationScript({ + moduleName, + models, + pathToMigrations, +}) { + /** + * This script is only valid for mikro orm managers. If a user provide a custom manager + * he is in charge of reverting the migrations. + * @param options + * @param logger + * @param moduleDeclaration + */ + return async function ({ + options, + logger, + }: Pick< + LoaderOptions, + "options" | "logger" + > = {}) { + logger ??= console as unknown as Logger + + const dbData = loadDatabaseConfig(moduleName, options)! + const entities = Object.values(models) as unknown as EntitySchema[] + + const orm = await mikroOrmCreateConnection( + dbData, + entities, + pathToMigrations + ) + + try { + const migrator = orm.getMigrator() + await migrator.down() + + logger?.info(`${upperCaseFirst(moduleName)} module migration executed`) + } catch (error) { + logger?.error( + `${upperCaseFirst( + moduleName + )} module migration failed to run - Error: ${error}` + ) + } + + await orm.close() + } +} diff --git a/packages/utils/src/modules-sdk/migration-scripts/migration-up.ts b/packages/utils/src/modules-sdk/migration-scripts/migration-up.ts new file mode 100644 index 0000000000..1e04c4c353 --- /dev/null +++ b/packages/utils/src/modules-sdk/migration-scripts/migration-up.ts @@ -0,0 +1,67 @@ +import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types" +import { EntitySchema } from "@mikro-orm/core" +import { upperCaseFirst } from "../../common" +import { loadDatabaseConfig } from "../load-module-database-config" +import { mikroOrmCreateConnection } from "../../dal" + +/** + * Utility function to build a migration script that will run the migrations. + * Only used in mikro orm based modules. + * @param moduleName + * @param models + * @param pathToMigrations + */ +export function buildMigrationScript({ moduleName, models, pathToMigrations }) { + /** + * This script is only valid for mikro orm managers. If a user provide a custom manager + * he is in charge of running the migrations. + * @param options + * @param logger + * @param moduleDeclaration + */ + return async function ({ + options, + logger, + }: Pick< + LoaderOptions, + "options" | "logger" + > = {}) { + logger ??= console as unknown as Logger + + const dbData = loadDatabaseConfig(moduleName, options)! + const entities = Object.values(models) as unknown as EntitySchema[] + + const orm = await mikroOrmCreateConnection( + dbData, + entities, + pathToMigrations + ) + + try { + const migrator = orm.getMigrator() + + const pendingMigrations = await migrator.getPendingMigrations() + logger.info( + `Running pending migrations: ${JSON.stringify( + pendingMigrations, + null, + 2 + )}` + ) + + await migrator.up({ + migrations: pendingMigrations.map((m) => m.name), + }) + + logger.info(`${upperCaseFirst(moduleName)} module migration executed`) + } catch (error) { + logger.error( + `${upperCaseFirst( + moduleName + )} module migration failed to run - Error: ${error}` + ) + } + + await orm.close() + } +} diff --git a/packages/utils/src/modules-sdk/migration-scripts/seed.ts b/packages/utils/src/modules-sdk/migration-scripts/seed.ts new file mode 100644 index 0000000000..a0d538fc0b --- /dev/null +++ b/packages/utils/src/modules-sdk/migration-scripts/seed.ts @@ -0,0 +1,73 @@ +import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types" +import { EntitySchema } from "@mikro-orm/core" +import { EOL } from "os" +import { resolve } from "path" +import { mikroOrmCreateConnection } from "../../dal" +import { loadDatabaseConfig } from "../load-module-database-config" + +/** + * Utility function to build a seed script that will insert the seed data. + * @param moduleName + * @param models + * @param pathToMigrations + * @param seedHandler + */ +export function buildSeedScript({ + moduleName, + models, + pathToMigrations, + seedHandler, +}: { + moduleName: string + models: Record + pathToMigrations: string + seedHandler: (args: { + manager: any + logger: Logger + data: any + }) => Promise +}) { + return async function ({ + options, + logger, + path, + }: Partial< + Pick< + LoaderOptions, + "options" | "logger" + > + > & { + path: string + }) { + const logger_ = (logger ?? console) as unknown as Logger + + logger_.info(`Loading seed data from ${path}...`) + const dataSeed = await import(resolve(process.cwd(), path)).catch((e) => { + logger_.error( + `Failed to load seed data from ${path}. Please, provide a relative path and check that you export the following productCategoriesData, productsData, variantsData.${EOL}${e}` + ) + throw e + }) + + const dbData = loadDatabaseConfig(moduleName, options)! + const entities = Object.values(models) as unknown as EntitySchema[] + + const orm = await mikroOrmCreateConnection( + dbData, + entities, + pathToMigrations + ) + const manager = orm.em.fork() + + try { + logger_.info(`Inserting ${moduleName} data...`) + seedHandler({ manager, logger: logger_, data: dataSeed }) + } catch (e) { + logger_.error( + `Failed to insert the seed data in the PostgreSQL database ${dbData.clientUrl}.${EOL}${e}` + ) + } + + await orm.close(true) + } +} diff --git a/yarn.lock b/yarn.lock index c6f283fb8c..1a9b7e1666 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8413,8 +8413,6 @@ __metadata: tsc-alias: ^1.8.6 typescript: ^5.1.6 bin: - medusa-product-migrations-down: dist/scripts/bin/run-migration-down.js - medusa-product-migrations-up: dist/scripts/bin/run-migration-up.js medusa-product-seed: dist/scripts/bin/run-seed.js languageName: unknown linkType: soft