chore(utils, product): Attempt to simplify module scripts export (#6021)

This commit is contained in:
Adrien de Peretti
2024-01-09 20:20:05 +01:00
committed by GitHub
parent 90db656000
commit a9b4214503
16 changed files with 298 additions and 227 deletions

View File

@@ -0,0 +1,6 @@
---
"@medusajs/product": patch
"@medusajs/utils": patch
---
chore(utils, product): Attempt to simplify module scripts export

View File

@@ -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": {

View File

@@ -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"

View File

@@ -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()
})()

View File

@@ -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()
})()

View File

@@ -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 })
})()

View File

@@ -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<ModulesSdkTypes.ModuleServiceInitializeOptions>,
"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()
}

View File

@@ -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<ModulesSdkTypes.ModuleServiceInitializeOptions>,
"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()
}

View File

@@ -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<ProductCategory[]> {
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
}

View File

@@ -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<ModulesSdkTypes.ModuleServiceInitializeOptions>,
"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<ProductCategory[]> {
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
}

View File

@@ -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"

View File

@@ -1,2 +1,3 @@
export * from "./migration-up"
export * from "./migration-down"
export * from "./migration-up"
export * from "./seed"

View File

@@ -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<ModulesSdkTypes.ModuleServiceInitializeOptions>,
"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()
}
}

View File

@@ -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<ModulesSdkTypes.ModuleServiceInitializeOptions>,
"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()
}
}

View File

@@ -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<string, unknown>
pathToMigrations: string
seedHandler: (args: {
manager: any
logger: Logger
data: any
}) => Promise<void>
}) {
return async function ({
options,
logger,
path,
}: Partial<
Pick<
LoaderOptions<ModulesSdkTypes.ModuleServiceInitializeOptions>,
"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)
}
}

View File

@@ -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