chore: Hide repository creation if they are not custom + add upsert support by default (#6127)

This commit is contained in:
Adrien de Peretti
2024-01-19 15:09:38 +01:00
committed by GitHub
parent 8a8a7183b8
commit 5e655dd59b
124 changed files with 1516 additions and 2559 deletions

View File

@@ -0,0 +1,8 @@
---
"@medusajs/utils": patch
"@medusajs/types": patch
"@medusajs/product": patch
"@medusajs/pricing": patch
---
chore: Hide repository creation if they are not custom + add upsert support by default

View File

@@ -1,9 +1,11 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { AuthProviderRepository } from "@repositories"
import { AuthProviderService } from "@services"
import { MikroOrmWrapper } from "../../../utils"
import { createAuthProviders } from "../../../__fixtures__/auth-provider"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -17,13 +19,12 @@ describe("AuthProvider Service", () => {
repositoryManager = await MikroOrmWrapper.forkManager()
testManager = await MikroOrmWrapper.forkManager()
const authProviderRepository = new AuthProviderRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new AuthProviderService({
authProviderRepository,
})
await ContainerLoader({ container })
service = container.resolve("authProviderService")
await createAuthProviders(testManager)
})

View File

@@ -1,10 +1,12 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { AuthUserRepository } from "@repositories"
import { AuthUserService } from "@services"
import { MikroOrmWrapper } from "../../../utils"
import { createAuthProviders } from "../../../__fixtures__/auth-provider"
import { createAuthUsers } from "../../../__fixtures__/auth-user"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -18,13 +20,12 @@ describe("AuthUser Service", () => {
repositoryManager = await MikroOrmWrapper.forkManager()
testManager = await MikroOrmWrapper.forkManager()
const authUserRepository = new AuthUserRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new AuthUserService({
authUserRepository,
})
await ContainerLoader({ container })
service = container.resolve("authUserService")
await createAuthProviders(testManager)
await createAuthUsers(testManager)

View File

@@ -11,8 +11,6 @@
"node": ">=16"
},
"bin": {
"medusa-authentication-migrations-down": "dist/scripts/bin/run-migration-down.js",
"medusa-authentication-migrations-up": "dist/scripts/bin/run-migration-up.js",
"medusa-authentication-seed": "dist/scripts/bin/run-seed.js"
},
"repository": {

View File

@@ -1,7 +1,22 @@
import { moduleDefinition } from "./module-definition"
import { Modules } from "@medusajs/modules-sdk"
import * as Models from "@models"
import { ModulesSdkUtils } from "@medusajs/utils"
export default moduleDefinition
const migrationScriptOptions = {
moduleName: Modules.AUTHENTICATION,
models: Models,
pathToMigrations: __dirname + "/migrations",
}
export const runMigrations = ModulesSdkUtils.buildMigrationScript(
migrationScriptOptions
)
export const revertMigration = ModulesSdkUtils.buildRevertMigrationScript(
migrationScriptOptions
)
export * from "./initialize"
export * from "./loaders"
export * from "./scripts"

View File

@@ -1,48 +1,10 @@
import * as defaultRepositories from "@repositories"
import * as defaultServices from "@services"
import { ModulesSdkUtils } from "@medusajs/utils"
import * as ModuleModels from "@models"
import * as ModuleRepositories from "@repositories"
import * as ModuleServices from "@services"
import { LoaderOptions } from "@medusajs/modules-sdk"
import { ModulesSdkTypes } from "@medusajs/types"
import { loadCustomRepositories } from "@medusajs/utils"
import { asClass } from "awilix"
export default async ({
container,
options,
}: LoaderOptions<
| ModulesSdkTypes.ModuleServiceInitializeOptions
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
>): Promise<void> => {
const customRepositories = (
options as ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
)?.repositories
container.register({
authUserService: asClass(defaultServices.AuthUserService).singleton(),
authProviderService: asClass(
defaultServices.AuthProviderService
).singleton(),
})
if (customRepositories) {
loadCustomRepositories({
defaultRepositories,
customRepositories,
container,
})
} else {
loadDefaultRepositories({ container })
}
}
function loadDefaultRepositories({ container }) {
container.register({
baseRepository: asClass(defaultRepositories.BaseRepository).singleton(),
authUserRepository: asClass(
defaultRepositories.AuthUserRepository
).singleton(),
authProviderRepository: asClass(
defaultRepositories.AuthProviderRepository
).singleton(),
})
}
export default ModulesSdkUtils.moduleContainerLoaderFactory({
moduleModels: ModuleModels,
moduleRepositories: ModuleRepositories,
moduleServices: ModuleServices,
})

View File

@@ -1,17 +0,0 @@
import { DALUtils } from "@medusajs/utils"
import { AuthProvider } from "@models"
import { RepositoryTypes } from "@types"
export class AuthProviderRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
AuthProvider,
{
create: RepositoryTypes.CreateAuthProviderDTO
update: RepositoryTypes.UpdateAuthProviderDTO
}
>(AuthProvider) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
}

View File

@@ -1,17 +0,0 @@
import { DALUtils } from "@medusajs/utils"
import { AuthUser } from "@models"
import { RepositoryTypes } from "@types"
export class AuthUserRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
AuthUser,
{
create: RepositoryTypes.CreateAuthUserDTO
update: RepositoryTypes.UpdateAuthUserDTO
}
>(AuthUser) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
}

View File

@@ -1,3 +1 @@
export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils"
export { AuthProviderRepository } from "./auth-provider"
export { AuthUserRepository } from "./auth-user"

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,2 +0,0 @@
export * from "./migration-up"
export * from "./migration-down"

View File

@@ -1,50 +0,0 @@
import { Modules } from "@medusajs/modules-sdk";
import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types";
import { DALUtils, ModulesSdkUtils } from "@medusajs/utils";
import { EntitySchema } from "@mikro-orm/core";
import * as AuthenticationModels from "@models";
/**
* 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(
Modules.AUTHENTICATION,
options
)!
const entities = Object.values(
AuthenticationModels
) 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("Authentication module migration executed")
} catch (error) {
logger?.error(
`Authentication module migration failed to run - Error: ${error}`
)
}
await orm.close()
}

View File

@@ -1,62 +0,0 @@
import { Modules } from "@medusajs/modules-sdk";
import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types";
import { DALUtils, ModulesSdkUtils } from "@medusajs/utils";
import { EntitySchema } from "@mikro-orm/core";
import * as AuthenticationModels 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(
Modules.AUTHENTICATION,
options
)!
const entities = Object.values(
AuthenticationModels
) 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("Authentication module migration executed")
} catch (error) {
logger.error(
`Authentication module migration failed to run - Error: ${error}`
)
}
await orm.close()
}

View File

@@ -16,7 +16,7 @@ export default class AuthUserService<
create: ServiceTypes.CreateAuthUserDTO
}
>(AuthUser)<TEntity> {
constructor({ authUserRepository }: InjectedDependencies) {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}

View File

@@ -1,2 +1,28 @@
import { AuthProvider, AuthUser } from "@models"
import { CreateAuthProviderDTO, UpdateAuthProviderDTO } from "./auth-provider"
import { DAL } from "@medusajs/types"
import { CreateAuthUserDTO, UpdateAuthUserDTO } from "./auth-user"
export * from "./auth-user"
export * from "./auth-provider"
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IAuthProviderRepository<
TEntity extends AuthProvider = AuthProvider
> extends DAL.RepositoryService<
TEntity,
{
create: CreateAuthProviderDTO
update: UpdateAuthProviderDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IAuthUserRepository<TEntity extends AuthUser = AuthUser>
extends DAL.RepositoryService<
TEntity,
{
create: CreateAuthUserDTO
update: UpdateAuthUserDTO
}
> {}

View File

@@ -1,7 +1,9 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { AddressRepository } from "../../../../src/repositories"
import { AddressService } from "../../../../src/services"
import { MikroOrmWrapper } from "../../../utils"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -15,13 +17,12 @@ describe("Address Service", () => {
repositoryManager = await MikroOrmWrapper.forkManager()
testManager = await MikroOrmWrapper.forkManager()
const addressRepository = new AddressRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new AddressService({
addressRepository: addressRepository,
})
await ContainerLoader({ container })
service = container.resolve("addressService")
})
afterEach(async () => {

View File

@@ -1,8 +1,10 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { CartRepository } from "../../../../src/repositories"
import { CartService } from "../../../../src/services"
import { createCarts } from "../../../__fixtures__/cart"
import { MikroOrmWrapper } from "../../../utils"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -16,13 +18,12 @@ describe("Cart Service", () => {
repositoryManager = await MikroOrmWrapper.forkManager()
testManager = await MikroOrmWrapper.forkManager()
const cartRepository = new CartRepository({
manager: repositoryManager
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new CartService({
cartRepository: cartRepository,
})
await ContainerLoader({ container })
service = container.resolve("cartService")
await createCarts(testManager)
})

View File

@@ -11,8 +11,6 @@
"node": ">=16"
},
"bin": {
"medusa-cart-migrations-down": "dist/scripts/bin/run-migration-down.js",
"medusa-cart-migrations-up": "dist/scripts/bin/run-migration-up.js",
"medusa-cart-seed": "dist/scripts/bin/run-seed.js"
},
"repository": {

View File

@@ -1,7 +1,22 @@
import { moduleDefinition } from "./module-definition"
import { Modules } from "@medusajs/modules-sdk"
import * as Models from "@models"
import { ModulesSdkUtils } from "@medusajs/utils"
export default moduleDefinition
const migrationScriptOptions = {
moduleName: Modules.CART,
models: Models,
pathToMigrations: __dirname + "/migrations",
}
export const runMigrations = ModulesSdkUtils.buildMigrationScript(
migrationScriptOptions
)
export const revertMigration = ModulesSdkUtils.buildRevertMigrationScript(
migrationScriptOptions
)
export * from "./initialize"
export * from "./loaders"
export * from "./scripts"

View File

@@ -1,54 +1,10 @@
import * as defaultRepositories from "@repositories"
import { ModulesSdkUtils } from "@medusajs/utils"
import * as ModuleModels from "@models"
import * as ModuleRepositories from "@repositories"
import * as ModuleServices from "@services"
import { LoaderOptions } from "@medusajs/modules-sdk"
import { ModulesSdkTypes } from "@medusajs/types"
import { loadCustomRepositories } from "@medusajs/utils"
import * as defaultServices from "@services"
import { asClass } from "awilix"
export default async ({
container,
options,
}: LoaderOptions<
| ModulesSdkTypes.ModuleServiceInitializeOptions
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
>): Promise<void> => {
const customRepositories = (
options as ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
)?.repositories
container.register({
cartService: asClass(defaultServices.CartService).singleton(),
addressService: asClass(defaultServices.AddressService).singleton(),
shippingMethodService: asClass(
defaultServices.ShippingMethodService
).singleton(),
lineItemService: asClass(defaultServices.LineItemService).singleton(),
})
if (customRepositories) {
loadCustomRepositories({
defaultRepositories,
customRepositories,
container,
})
} else {
loadDefaultRepositories({ container })
}
}
function loadDefaultRepositories({ container }) {
container.register({
baseRepository: asClass(defaultRepositories.BaseRepository).singleton(),
cartRepository: asClass(defaultRepositories.CartRepository).singleton(),
addressRepository: asClass(
defaultRepositories.AddressRepository
).singleton(),
lineItemRepository: asClass(
defaultRepositories.LineItemRepository
).singleton(),
shippingMethodRepository: asClass(
defaultRepositories.ShippingMethodRepository
).singleton(),
})
}
export default ModulesSdkUtils.moduleContainerLoaderFactory({
moduleModels: ModuleModels,
moduleRepositories: ModuleRepositories,
moduleServices: ModuleServices,
})

View File

@@ -1,16 +0,0 @@
import { DALUtils } from "@medusajs/utils"
import { Address } from "@models"
import { CreateAddressDTO, UpdateAddressDTO } from "../types"
export class AddressRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
Address,
{
create: CreateAddressDTO
update: UpdateAddressDTO
}
>(Address) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
}

View File

@@ -1,16 +0,0 @@
import { DALUtils } from "@medusajs/utils"
import { Cart } from "@models"
import { CreateCartDTO, UpdateCartDTO } from "@types"
export class CartRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
Cart,
{
create: CreateCartDTO
update: UpdateCartDTO
}
>(Cart) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
}

View File

@@ -1,6 +1 @@
export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils"
export * from "./address"
export * from "./cart"
export * from "./line-item"
export * from "./shipping-method"

View File

@@ -1,16 +0,0 @@
import { DALUtils } from "@medusajs/utils"
import { LineItem } from "@models"
import { CreateLineItemDTO, UpdateLineItemDTO } from "../types"
export class LineItemRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
LineItem,
{
create: CreateLineItemDTO
update: UpdateLineItemDTO
}
>(LineItem) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
}

View File

@@ -1,16 +0,0 @@
import { DALUtils } from "@medusajs/utils"
import { ShippingMethod } from "@models"
import { CreateShippingMethodDTO, UpdateShippingMethodDTO } from "@types"
export class ShippingMethodRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
ShippingMethod,
{
create: CreateShippingMethodDTO
update: UpdateShippingMethodDTO
}
>(ShippingMethod) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
}

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,2 +0,0 @@
export * from "./migration-up"
export * from "./migration-down"

View File

@@ -1,50 +0,0 @@
import { Modules } from "@medusajs/modules-sdk";
import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types";
import { DALUtils, ModulesSdkUtils } from "@medusajs/utils";
import { EntitySchema } from "@mikro-orm/core";
import * as CartModels from "@models";
/**
* 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(
Modules.CART,
options
)!
const entities = Object.values(
CartModels
) 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("Cart module migration executed")
} catch (error) {
logger?.error(
`Cart module migration failed to run - Error: ${error}`
)
}
await orm.close()
}

View File

@@ -1,62 +0,0 @@
import { Modules } from "@medusajs/modules-sdk";
import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types";
import { DALUtils, ModulesSdkUtils } from "@medusajs/utils";
import { EntitySchema } from "@mikro-orm/core";
import * as CartModels 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(
Modules.CART,
options
)!
const entities = Object.values(
CartModels
) 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("Cart module migration executed")
} catch (error) {
logger.error(
`Cart module migration failed to run - Error: ${error}`
)
}
await orm.close()
}

View File

@@ -1,8 +1,10 @@
import { Logger } from "@medusajs/types"
export * from "./address"
export * from "./cart"
export * from "./line-item"
export * from "./shipping-method"
export * from "./repositories"
export type InitializeModuleInjectableDependencies = {
logger?: Logger

View File

@@ -0,0 +1,50 @@
import { DAL } from "@medusajs/types"
import { Cart, LineItem, ShippingMethod } from "@models"
import { CreateAddressDTO, UpdateAddressDTO } from "./address"
import { CreateCartDTO, UpdateCartDTO } from "./cart"
import { CreateLineItemDTO, UpdateLineItemDTO } from "./line-item"
import {
CreateShippingMethodDTO,
UpdateShippingMethodDTO,
} from "./shipping-method"
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IAddressRepository<TEntity extends Cart = Cart>
extends DAL.RepositoryService<
TEntity,
{
create: CreateAddressDTO
update: UpdateAddressDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface ICartRepository<TEntity extends Cart = Cart>
extends DAL.RepositoryService<
TEntity,
{
create: CreateCartDTO
update: UpdateCartDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface ILineItemRepository<TEntity extends LineItem = LineItem>
extends DAL.RepositoryService<
TEntity,
{
create: CreateLineItemDTO
update: UpdateLineItemDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IShippingMethodRepository<
TEntity extends ShippingMethod = ShippingMethod
> extends DAL.RepositoryService<
TEntity,
{
create: CreateShippingMethodDTO
update: UpdateShippingMethodDTO
}
> {}

View File

@@ -1,39 +1,10 @@
import { LoaderOptions } from "@medusajs/modules-sdk"
import { ModulesSdkTypes } from "@medusajs/types"
import { loadCustomRepositories } from "@medusajs/utils"
import { asClass } from "awilix"
import { ModulesSdkUtils } from "@medusajs/utils"
import * as ModuleModels from "@models"
import * as ModuleRepositories from "@repositories"
import * as ModuleServices from "@services"
import * as defaultRepositories from "@repositories"
import * as defaultServices from "@services"
export default async ({
container,
options,
}: LoaderOptions<
| ModulesSdkTypes.ModuleServiceInitializeOptions
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
>): Promise<void> => {
const customRepositories = (
options as ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
)?.repositories
container.register({
// paymentService: asClass(defaultServices.PaymentService).singleton(),
})
if (customRepositories) {
loadCustomRepositories({
defaultRepositories,
customRepositories,
container,
})
} else {
loadDefaultRepositories({ container })
}
}
function loadDefaultRepositories({ container }) {
container.register({
baseRepository: asClass(defaultRepositories.BaseRepository).singleton(),
})
}
export default ModulesSdkUtils.moduleContainerLoaderFactory({
moduleModels: ModuleModels,
moduleRepositories: ModuleRepositories,
moduleServices: ModuleServices,
})

View File

@@ -1,11 +1,13 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { Currency } from "@models"
import { CurrencyRepository } from "@repositories"
import { CurrencyService } from "@services"
import { createCurrencies } from "../../../__fixtures__/currency"
import { MikroOrmWrapper } from "../../../utils"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -34,13 +36,12 @@ describe("Currency Service", () => {
await MikroOrmWrapper.setupDatabase()
repositoryManager = await MikroOrmWrapper.forkManager()
const currencyRepository = new CurrencyRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new CurrencyService({
currencyRepository,
})
await ContainerLoader({ container })
service = container.resolve("currencyService")
testManager = await MikroOrmWrapper.forkManager()

View File

@@ -1,12 +1,14 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { Currency, MoneyAmount } from "@models"
import { MoneyAmountRepository } from "@repositories"
import { MoneyAmountService } from "@services"
import { createCurrencies } from "../../../__fixtures__/currency"
import { createMoneyAmounts } from "../../../__fixtures__/money-amount"
import { MikroOrmWrapper } from "../../../utils"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -21,13 +23,12 @@ describe("MoneyAmount Service", () => {
await MikroOrmWrapper.setupDatabase()
repositoryManager = await MikroOrmWrapper.forkManager()
const moneyAmountRepository = new MoneyAmountRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new MoneyAmountService({
moneyAmountRepository,
})
await ContainerLoader({ container })
service = container.resolve("moneyAmountService")
testManager = await MikroOrmWrapper.forkManager()
currencyData = await createCurrencies(testManager)

View File

@@ -1,12 +1,13 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { PriceListRuleRepository } from "@repositories"
import { PriceListRuleService } from "@services"
import { createPriceLists } from "../../../__fixtures__/price-list"
import { createPriceListRules } from "../../../__fixtures__/price-list-rules"
import { createRuleTypes } from "../../../__fixtures__/rule-type"
import { MikroOrmWrapper } from "../../../utils"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -19,13 +20,12 @@ describe("PriceListRule Service", () => {
await MikroOrmWrapper.setupDatabase()
repositoryManager = await MikroOrmWrapper.forkManager()
const priceListRuleRepository = new PriceListRuleRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new PriceListRuleService({
priceListRuleRepository,
})
await ContainerLoader({ container })
service = container.resolve("priceListRuleService")
testManager = await MikroOrmWrapper.forkManager()
await createRuleTypes(testManager)

View File

@@ -1,8 +1,10 @@
import { MikroOrmWrapper } from "../../../utils"
import { PriceListRepository } from "@repositories"
import { PriceListService } from "@services"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { createPriceLists } from "../../../__fixtures__/price-list"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -15,13 +17,12 @@ describe("PriceList Service", () => {
await MikroOrmWrapper.setupDatabase()
repositoryManager = await MikroOrmWrapper.forkManager()
const priceListRepository = new PriceListRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new PriceListService({
priceListRepository,
})
await ContainerLoader({ container })
service = container.resolve("priceListService")
testManager = await MikroOrmWrapper.forkManager()
await createPriceLists(testManager)

View File

@@ -2,7 +2,6 @@ import { PriceSetMoneyAmount } from "@models"
import { CreatePriceRuleDTO } from "@medusajs/types"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { PriceRuleRepository } from "@repositories"
import { PriceRuleService } from "@services"
import { createCurrencies } from "../../../__fixtures__/currency"
import { createMoneyAmounts } from "../../../__fixtures__/money-amount"
@@ -12,6 +11,9 @@ import { createPriceSetMoneyAmounts } from "../../../__fixtures__/price-set-mone
import { createPriceSetMoneyAmountRules } from "../../../__fixtures__/price-set-money-amount-rules"
import { createRuleTypes } from "../../../__fixtures__/rule-type"
import { MikroOrmWrapper } from "../../../utils"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -25,13 +27,13 @@ describe("PriceRule Service", () => {
repositoryManager = await MikroOrmWrapper.forkManager()
testManager = await MikroOrmWrapper.forkManager()
const priceRuleRepository = new PriceRuleRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
await ContainerLoader({ container })
service = container.resolve("priceRuleService")
service = new PriceRuleService({
priceRuleRepository: priceRuleRepository,
})
await createCurrencies(testManager)
await createMoneyAmounts(testManager)
await createPriceSets(testManager)

View File

@@ -1,10 +1,11 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { PriceSetMoneyAmountRulesRepository } from "@repositories"
import { PriceSetMoneyAmountRulesService } from "@services"
import { seedPriceData } from "../../../__fixtures__/seed-price-data"
import { MikroOrmWrapper } from "../../../utils"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -17,14 +18,12 @@ describe("PriceSetMoneyAmountRules Service", () => {
await MikroOrmWrapper.setupDatabase()
repositoryManager = await MikroOrmWrapper.forkManager()
const priceSetMoneyAmountRulesRepository =
new PriceSetMoneyAmountRulesRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new PriceSetMoneyAmountRulesService({
priceSetMoneyAmountRulesRepository,
})
await ContainerLoader({ container })
service = container.resolve("priceSetMoneyAmountRulesService")
testManager = await MikroOrmWrapper.forkManager()

View File

@@ -1,13 +1,15 @@
import { CreatePriceSetDTO } from "@medusajs/types"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { MoneyAmount, PriceSet } from "@models"
import { PriceSetRepository } from "@repositories"
import { PriceSetService } from "@services"
import { createCurrencies } from "../../../__fixtures__/currency"
import { createMoneyAmounts } from "../../../__fixtures__/money-amount"
import { createPriceSets } from "../../../__fixtures__/price-set"
import { MikroOrmWrapper } from "../../../utils"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -54,13 +56,12 @@ describe("PriceSet Service", () => {
repositoryManager = await MikroOrmWrapper.forkManager()
testManager = await MikroOrmWrapper.forkManager()
const priceSetRepository = new PriceSetRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new PriceSetService({
priceSetRepository,
})
await ContainerLoader({ container })
service = container.resolve("priceSetService")
await createCurrencies(testManager)

View File

@@ -1,10 +1,11 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { RuleTypeRepository } from "@repositories"
import { RuleTypeService } from "@services"
import { createRuleTypes } from "../../../__fixtures__/rule-type"
import { MikroOrmWrapper } from "../../../utils"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -17,13 +18,12 @@ describe("RuleType Service", () => {
await MikroOrmWrapper.setupDatabase()
repositoryManager = await MikroOrmWrapper.forkManager()
const ruleTypeRepository = new RuleTypeRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new RuleTypeService({
ruleTypeRepository,
})
await ContainerLoader({ container })
service = container.resolve("ruleTypeService")
testManager = await MikroOrmWrapper.forkManager()

View File

@@ -11,8 +11,6 @@
"node": ">=16"
},
"bin": {
"medusa-pricing-migrations-down": "dist/scripts/bin/run-migration-down.js",
"medusa-pricing-migrations-up": "dist/scripts/bin/run-migration-up.js",
"medusa-pricing-seed": "dist/scripts/bin/run-seed.js"
},
"repository": {

View File

@@ -1,8 +1,23 @@
import { moduleDefinition } from "./module-definition"
import { Modules } from "@medusajs/modules-sdk"
import * as Models from "@models"
import { ModulesSdkUtils } from "@medusajs/utils"
export default moduleDefinition
export * from "./scripts"
const migrationScriptOptions = {
moduleName: Modules.PRICING,
models: Models,
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,95 +1,10 @@
import * as defaultRepositories from "@repositories"
import * as defaultServices from "@services"
import { ModulesSdkUtils } from "@medusajs/utils"
import * as ModuleModels from "@models"
import * as ModuleRepositories from "@repositories"
import * as ModuleServices from "@services"
import { LoaderOptions } from "@medusajs/modules-sdk"
import { ModulesSdkTypes } from "@medusajs/types"
import { loadCustomRepositories } from "@medusajs/utils"
import { asClass } from "awilix"
export default async ({
container,
options,
}: LoaderOptions<
| ModulesSdkTypes.ModuleServiceInitializeOptions
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
>): Promise<void> => {
const customRepositories = (
options as ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
)?.repositories
container.register({
currencyService: asClass(defaultServices.CurrencyService).singleton(),
moneyAmountService: asClass(defaultServices.MoneyAmountService).singleton(),
priceSetService: asClass(defaultServices.PriceSetService).singleton(),
ruleTypeService: asClass(defaultServices.RuleTypeService).singleton(),
priceSetMoneyAmountRulesService: asClass(
defaultServices.PriceSetMoneyAmountRulesService
).singleton(),
priceRuleService: asClass(defaultServices.PriceRuleService).singleton(),
priceSetRuleTypeService: asClass(
defaultServices.PriceSetRuleTypeService
).singleton(),
priceSetMoneyAmountService: asClass(
defaultServices.PriceSetMoneyAmountService
).singleton(),
priceListService: asClass(defaultServices.PriceListService).singleton(),
priceListRuleService: asClass(
defaultServices.PriceListRuleService
).singleton(),
priceListRuleValueService: asClass(
defaultServices.PriceListRuleValueService
).singleton(),
})
if (customRepositories) {
loadCustomRepositories({
defaultRepositories,
customRepositories,
container,
})
} else {
loadDefaultRepositories({ container })
}
}
function loadDefaultRepositories({ container }) {
container.register({
baseRepository: asClass(defaultRepositories.BaseRepository).singleton(),
pricingRepository: asClass(
defaultRepositories.PricingRepository
).singleton(),
currencyRepository: asClass(
defaultRepositories.CurrencyRepository
).singleton(),
moneyAmountRepository: asClass(
defaultRepositories.MoneyAmountRepository
).singleton(),
priceSetRepository: asClass(
defaultRepositories.PriceSetRepository
).singleton(),
ruleTypeRepository: asClass(
defaultRepositories.RuleTypeRepository
).singleton(),
priceSetMoneyAmountRulesRepository: asClass(
defaultRepositories.PriceSetMoneyAmountRulesRepository
).singleton(),
priceRuleRepository: asClass(
defaultRepositories.PriceRuleRepository
).singleton(),
priceSetRuleTypeRepository: asClass(
defaultRepositories.PriceSetRuleTypeRepository
).singleton(),
priceSetMoneyAmountRepository: asClass(
defaultRepositories.PriceSetMoneyAmountRepository
).singleton(),
priceListRepository: asClass(
defaultRepositories.PriceListRepository
).singleton(),
priceListRuleRepository: asClass(
defaultRepositories.PriceListRuleRepository
).singleton(),
priceListRuleValueRepository: asClass(
defaultRepositories.PriceListRuleValueRepository
).singleton(),
})
}
export default ModulesSdkUtils.moduleContainerLoaderFactory({
moduleModels: ModuleModels,
moduleRepositories: ModuleRepositories,
moduleServices: ModuleServices,
})

View File

@@ -1,17 +0,0 @@
import { DALUtils } from "@medusajs/utils"
import { Currency } from "@models"
import { RepositoryTypes } from "@types"
export class CurrencyRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
Currency,
{
create: RepositoryTypes.CreateCurrencyDTO
update: RepositoryTypes.UpdateCurrencyDTO
}
>(Currency) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
}

View File

@@ -1,13 +1,2 @@
export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils"
export { CurrencyRepository } from "./currency"
export { MoneyAmountRepository } from "./money-amount"
export { PriceListRepository } from "./price-list"
export { PriceListRuleRepository } from "./price-list-rule"
export { PriceListRuleValueRepository } from "./price-list-rule-value"
export { PriceRuleRepository } from "./price-rule"
export { PriceSetRepository } from "./price-set"
export { PriceSetMoneyAmountRepository } from "./price-set-money-amount"
export { PriceSetMoneyAmountRulesRepository } from "./price-set-money-amount-rules"
export { PriceSetRuleTypeRepository } from "./price-set-rule-type"
export { PricingRepository } from "./pricing"
export { RuleTypeRepository } from "./rule-type"

View File

@@ -1,17 +0,0 @@
import { DALUtils } from "@medusajs/utils"
import { MoneyAmount } from "@models"
import { RepositoryTypes } from "@types"
export class MoneyAmountRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
MoneyAmount,
{
create: RepositoryTypes.CreateMoneyAmountDTO
update: RepositoryTypes.UpdateMoneyAmountDTO
}
>(MoneyAmount) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
}

View File

@@ -1,35 +0,0 @@
import { Context } from "@medusajs/types"
import { DALUtils } from "@medusajs/utils"
import { PriceListRuleValue } from "@models"
import { RepositoryTypes } from "@types"
export class PriceListRuleValueRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
PriceListRuleValue,
{
update: RepositoryTypes.UpdatePriceListRuleValueDTO
}
>(PriceListRuleValue) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
async create(
data: RepositoryTypes.CreatePriceListRuleValueDTO[],
context: Context = {}
): Promise<PriceListRuleValue[]> {
const priceListRuleValues = data.map((priceRuleValueData) => {
const { price_list_rule_id: priceListRuleId, ...priceRuleValue } =
priceRuleValueData
if (priceListRuleId) {
priceRuleValue.price_list_rule = priceListRuleId
}
return priceRuleValue
})
return await super.create(priceListRuleValues, context)
}
}

View File

@@ -1,61 +0,0 @@
import { Context } from "@medusajs/types"
import { DALUtils } from "@medusajs/utils"
import { PriceListRule } from "@models"
import { RepositoryTypes } from "@types"
export class PriceListRuleRepository extends DALUtils.mikroOrmBaseRepositoryFactory(
PriceListRule
) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
async create(
data: RepositoryTypes.CreatePriceListRuleDTO[],
context: Context = {}
): Promise<PriceListRule[]> {
const priceListRule = data.map((priceListRule) => {
const {
price_list_id: priceListId,
rule_type_id: ruleTypeId,
...createData
} = priceListRule
if (priceListId) {
createData.price_list = priceListId
}
if (ruleTypeId) {
createData.rule_type = ruleTypeId
}
return createData
})
return await super.create(priceListRule, context)
}
async update(
data: RepositoryTypes.UpdatePriceListRuleDTO[],
context: Context = {}
): Promise<PriceListRule[]> {
const priceListRules = data.map((priceListRule) => {
const { price_list_id, rule_type_id, ...priceListRuleData } =
priceListRule
if (price_list_id) {
priceListRuleData.price_list = price_list_id
}
if (rule_type_id) {
priceListRuleData.rule_type = rule_type_id
}
return priceListRuleData
})
return await super.update(priceListRules, context)
}
}

View File

@@ -1,52 +0,0 @@
import { Context } from "@medusajs/types"
import { DALUtils, GetIsoStringFromDate } from "@medusajs/utils"
import { PriceList } from "@models"
import { RepositoryTypes } from "@types"
export class PriceListRepository extends DALUtils.mikroOrmBaseRepositoryFactory(
PriceList
) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
async create(
data: RepositoryTypes.CreatePriceListDTO[],
context: Context = {}
): Promise<PriceList[]> {
const priceLists = data.map((priceListData: any) => {
if (!!priceListData.starts_at) {
priceListData.starts_at = GetIsoStringFromDate(priceListData.starts_at)
}
if (!!priceListData.ends_at) {
priceListData.ends_at = GetIsoStringFromDate(priceListData.ends_at)
}
return priceListData
})
return await super.create(priceLists, context)
}
async update(
data: RepositoryTypes.UpdatePriceListDTO[],
context: Context = {}
): Promise<PriceList[]> {
const priceLists = data.map((priceListData: any) => {
if (!!priceListData.starts_at) {
priceListData.starts_at = GetIsoStringFromDate(priceListData.starts_at)
}
if (!!priceListData.ends_at) {
priceListData.ends_at = GetIsoStringFromDate(priceListData.ends_at)
}
return priceListData
})
return await super.update(priceLists, context)
}
}

View File

@@ -1,35 +0,0 @@
import { Context } from "@medusajs/types"
import { DALUtils } from "@medusajs/utils"
import { PriceRule } from "@models"
import { RepositoryTypes } from "@types"
export class PriceRuleRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
PriceRule,
{
update: RepositoryTypes.UpdatePriceRuleDTO
}
>(PriceRule) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
async create(
data: RepositoryTypes.CreatePriceRuleDTO[],
context: Context = {}
): Promise<PriceRule[]> {
const toCreate = data.map((ruleData) => {
const ruleDataClone = { ...ruleData } as any
ruleDataClone.rule_type ??= ruleData.rule_type_id
ruleDataClone.price_set ??= ruleData.price_set_id
ruleDataClone.price_set_money_amount ??=
ruleData.price_set_money_amount_id
return ruleDataClone
})
return await super.create(toCreate, context)
}
}

View File

@@ -1,17 +0,0 @@
import { DALUtils } from "@medusajs/utils"
import { PriceSetMoneyAmountRules } from "@models"
import { RepositoryTypes } from "@types"
export class PriceSetMoneyAmountRulesRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
PriceSetMoneyAmountRules,
{
create: RepositoryTypes.CreatePriceSetMoneyAmountRulesDTO
update: RepositoryTypes.UpdatePriceSetMoneyAmountRulesDTO
}
>(PriceSetMoneyAmountRules) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
}

View File

@@ -1,17 +0,0 @@
import { DALUtils } from "@medusajs/utils"
import { PriceSetMoneyAmount } from "@models"
import { RepositoryTypes } from "@types"
export class PriceSetMoneyAmountRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
PriceSetMoneyAmount,
{
create: RepositoryTypes.CreatePriceSetMoneyAmountDTO
update: RepositoryTypes.UpdatePriceSetMoneyAmountDTO
}
>(PriceSetMoneyAmount) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
}

View File

@@ -1,17 +0,0 @@
import { DALUtils } from "@medusajs/utils"
import { PriceSetRuleType } from "@models"
import { RepositoryTypes } from "@types"
export class PriceSetRuleTypeRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
PriceSetRuleType,
{
create: RepositoryTypes.CreatePriceSetRuleTypeDTO
update: RepositoryTypes.UpdatePriceSetRuleTypeDTO
}
>(PriceSetRuleType) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
}

View File

@@ -1,17 +0,0 @@
import { DALUtils } from "@medusajs/utils"
import { PriceSet } from "@models"
import { RepositoryTypes } from "@types"
export class PriceSetRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
PriceSet,
{
create: RepositoryTypes.CreatePriceSetDTO
update: RepositoryTypes.UpdatePriceSetDTO
}
>(PriceSet) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
}

View File

@@ -1,16 +0,0 @@
import { DALUtils } from "@medusajs/utils"
import { RuleType } from "@models"
import { RepositoryTypes } from "@types"
export class RuleTypeRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
RuleType,
{
create: RepositoryTypes.CreateRuleTypeDTO
update: RepositoryTypes.UpdateRuleTypeDTO
}
>(RuleType) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
}

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,2 +0,0 @@
export * from "./migration-up"
export * from "./migration-down"

View File

@@ -1,44 +0,0 @@
import * as PricingModels 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("pricing", options)!
const entities = Object.values(PricingModels) 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("Pricing module migration executed")
} catch (error) {
logger?.error(`Pricing 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 PricingModels 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("pricing", options)!
const entities = Object.values(PricingModels) 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("Pricing module migration executed")
} catch (error) {
logger.error(`Pricing module migration failed to run - Error: ${error}`)
}
await orm.close()
}

View File

@@ -16,7 +16,7 @@ export default class CurrencyService<
update: ServiceTypes.UpdateCurrencyDTO
}
>(Currency)<TEntity> {
constructor({ currencyRepository }: InjectedDependencies) {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}

View File

@@ -1,4 +1,4 @@
import { DAL } from "@medusajs/types"
import { Context, DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { PriceListRuleValue } from "@models"
import { ServiceTypes } from "@types"
@@ -12,7 +12,6 @@ export default class PriceListRuleValueService<
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: ServiceTypes.CreatePriceListRuleValueDTO
update: ServiceTypes.UpdatePriceListRuleValueDTO
},
{
@@ -24,4 +23,22 @@ export default class PriceListRuleValueService<
// @ts-ignore
super(...arguments)
}
async create(
data: ServiceTypes.CreatePriceListRuleValueDTO[],
context: Context = {}
): Promise<TEntity[]> {
const priceListRuleValues = data.map((priceRuleValueData) => {
const { price_list_rule_id: priceListRuleId, ...priceRuleValue } =
priceRuleValueData
if (priceListRuleId) {
priceRuleValue.price_list_rule = priceListRuleId
}
return priceRuleValue
})
return await super.create(priceListRuleValues, context)
}
}

View File

@@ -1,4 +1,4 @@
import { DAL } from "@medusajs/types"
import { Context, DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { PriceListRule } from "@models"
import { ServiceTypes } from "@types"
@@ -24,4 +24,51 @@ export default class PriceListRuleService<
// @ts-ignore
super(...arguments)
}
async create(
data: ServiceTypes.CreatePriceListRuleDTO[],
context: Context = {}
): Promise<TEntity[]> {
const priceListRule = data.map((priceListRule) => {
const {
price_list_id: priceListId,
rule_type_id: ruleTypeId,
...createData
} = priceListRule
if (priceListId) {
createData.price_list = priceListId
}
if (ruleTypeId) {
createData.rule_type = ruleTypeId
}
return createData
})
return await super.create(priceListRule, context)
}
async update(
data: ServiceTypes.UpdatePriceListRuleDTO[],
context: Context = {}
): Promise<TEntity[]> {
const priceListRules = data.map((priceListRule) => {
const { price_list_id, rule_type_id, ...priceListRuleData } =
priceListRule
if (price_list_id) {
priceListRuleData.price_list = price_list_id
}
if (rule_type_id) {
priceListRuleData.rule_type = rule_type_id
}
return priceListRuleData
})
return await super.update(priceListRules, context)
}
}

View File

@@ -1,5 +1,5 @@
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { Context, DAL } from "@medusajs/types"
import { GetIsoStringFromDate, ModulesSdkUtils } from "@medusajs/utils"
import { PriceList } from "@models"
import { ServiceTypes } from "@types"
@@ -11,10 +11,7 @@ export default class PriceListService<
TEntity extends PriceList = PriceList
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: ServiceTypes.CreatePriceListDTO
update: ServiceTypes.UpdatePriceListDTO
},
{},
{
list: ServiceTypes.FilterablePriceListProps
listAndCount: ServiceTypes.FilterablePriceListProps
@@ -24,4 +21,36 @@ export default class PriceListService<
// @ts-ignore
super(...arguments)
}
async create(
data: ServiceTypes.CreatePriceListDTO[],
sharedContext?: Context
): Promise<TEntity[]> {
const priceLists = this.normalizePriceListDate(data)
return await super.create(priceLists, sharedContext)
}
async update(
data: ServiceTypes.UpdatePriceListDTO[],
sharedContext?: Context
): Promise<TEntity[]> {
const priceLists = this.normalizePriceListDate(data)
return await super.update(priceLists, sharedContext)
}
protected normalizePriceListDate(
data: (ServiceTypes.UpdatePriceListDTO | ServiceTypes.CreatePriceListDTO)[]
) {
return data.map((priceListData: any) => {
if (!!priceListData.starts_at) {
priceListData.starts_at = GetIsoStringFromDate(priceListData.starts_at)
}
if (!!priceListData.ends_at) {
priceListData.ends_at = GetIsoStringFromDate(priceListData.ends_at)
}
return priceListData
})
}
}

View File

@@ -1,4 +1,4 @@
import { DAL } from "@medusajs/types"
import { Context, DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { PriceRule } from "@models"
@@ -13,7 +13,6 @@ export default class PriceRuleService<
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: ServiceTypes.CreatePriceRuleDTO
update: ServiceTypes.UpdatePriceRuleDTO
},
{
@@ -25,4 +24,22 @@ export default class PriceRuleService<
// @ts-ignore
super(...arguments)
}
async create(
data: ServiceTypes.CreatePriceRuleDTO[],
sharedContext?: Context
): Promise<TEntity[]> {
const toCreate = data.map((ruleData) => {
const ruleDataClone = { ...ruleData } as any
ruleDataClone.rule_type ??= ruleData.rule_type_id
ruleDataClone.price_set ??= ruleData.price_set_id
ruleDataClone.price_set_money_amount ??=
ruleData.price_set_money_amount_id
return ruleDataClone
})
return await super.create(toCreate, sharedContext)
}
}

View File

@@ -14,6 +14,10 @@ export default class PriceSetMoneyAmountRulesService<
{
create: ServiceTypes.CreatePriceSetMoneyAmountRulesDTO
update: ServiceTypes.UpdatePriceSetMoneyAmountRulesDTO
},
{
list: ServiceTypes.FilterablePriceSetMoneyAmountRulesProps
listAndCount: ServiceTypes.FilterablePriceSetMoneyAmountRulesProps
}
>(PriceSetMoneyAmountRules)<TEntity> {
constructor({ priceSetMoneyAmountRulesRepository }: InjectedDependencies) {

View File

@@ -1,5 +1,5 @@
import { Context, DAL, FindConfig } from "@medusajs/types"
import { InjectManager, MedusaContext, ModulesSdkUtils } from "@medusajs/utils"
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { PriceSetMoneyAmount } from "@models"
import { ServiceTypes } from "@types"
@@ -14,46 +14,14 @@ export default class PriceSetMoneyAmountService<
{
create: ServiceTypes.CreatePriceSetMoneyAmountDTO
update: ServiceTypes.UpdatePriceSetMoneyAmountDTO
},
{
list: ServiceTypes.FilterablePriceSetMoneyAmountProps
listAndCount: ServiceTypes.FilterablePriceSetMoneyAmountProps
}
>(PriceSetMoneyAmount)<TEntity> {
protected readonly priceSetMoneyAmountRepository_: DAL.RepositoryService<TEntity>
constructor({ priceSetMoneyAmountRepository }: InjectedDependencies) {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
this.priceSetMoneyAmountRepository_ = priceSetMoneyAmountRepository
}
@InjectManager("priceSetMoneyAmountRepository_")
async list<TEntityMethod = ServiceTypes.PriceSetMoneyAmountDTO>(
filters: ServiceTypes.FilterablePriceSetMoneyAmountProps = {},
config: FindConfig<TEntityMethod> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
return await this.priceSetMoneyAmountRepository_.find(
this.buildQueryForList(filters, config),
sharedContext
)
}
@InjectManager("priceSetMoneyAmountRepository_")
async listAndCount<TEntityMethod = ServiceTypes.PriceSetMoneyAmountDTO>(
filters: ServiceTypes.FilterablePriceSetMoneyAmountProps = {},
config: FindConfig<TEntityMethod> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<[TEntity[], number]> {
return await this.priceSetMoneyAmountRepository_.findAndCount(
this.buildQueryForList(filters, config),
sharedContext
)
}
private buildQueryForList<
TEntityMethod = ServiceTypes.PriceSetMoneyAmountDTO
>(
filters: ServiceTypes.FilterablePriceSetMoneyAmountProps = {},
config: FindConfig<TEntityMethod> = {}
) {
return ModulesSdkUtils.buildQuery<TEntity>(filters, config)
}
}

View File

@@ -1,5 +1,5 @@
import { Context, DAL, FindConfig } from "@medusajs/types"
import { InjectManager, MedusaContext, ModulesSdkUtils } from "@medusajs/utils"
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { PriceSetRuleType } from "@models"
import { ServiceTypes } from "@types"
@@ -14,46 +14,14 @@ export default class PriceSetRuleTypeService<
{
create: ServiceTypes.CreatePriceSetRuleTypeDTO
update: ServiceTypes.UpdatePriceSetRuleTypeDTO
},
{
list: ServiceTypes.FilterablePriceSetRuleTypeProps
listAndCount: ServiceTypes.FilterablePriceSetRuleTypeProps
}
>(PriceSetRuleType)<TEntity> {
protected readonly priceSetRuleTypeRepository_: DAL.RepositoryService<TEntity>
constructor({ priceSetRuleTypeRepository }: InjectedDependencies) {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
this.priceSetRuleTypeRepository_ = priceSetRuleTypeRepository
}
@InjectManager("priceSetRuleTypeRepository_")
async list<TEntityMethod = ServiceTypes.PriceSetMoneyAmountDTO>(
filters: ServiceTypes.FilterablePriceSetRuleTypeProps = {},
config: FindConfig<TEntityMethod> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
return await this.priceSetRuleTypeRepository_.find(
this.buildQueryForList(filters, config),
sharedContext
)
}
@InjectManager("priceSetRuleTypeRepository_")
async listAndCount<TEntityMethod = ServiceTypes.PriceSetMoneyAmountDTO>(
filters: ServiceTypes.FilterablePriceSetRuleTypeProps = {},
config: FindConfig<TEntityMethod> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<[TEntity[], number]> {
return await this.priceSetRuleTypeRepository_.findAndCount(
this.buildQueryForList(filters, config),
sharedContext
)
}
private buildQueryForList<
TEntityMethod = ServiceTypes.PriceSetMoneyAmountDTO
>(
filters: ServiceTypes.FilterablePriceSetRuleTypeProps = {},
config: FindConfig<TEntityMethod> = {}
) {
return ModulesSdkUtils.buildQuery<TEntity>(filters, config)
}
}

View File

@@ -1,3 +1,44 @@
import {
Currency,
MoneyAmount,
PriceList,
PriceListRule,
PriceListRuleValue,
PriceRule,
PriceSet,
PriceSetMoneyAmount,
PriceSetMoneyAmountRules,
PriceSetRuleType,
RuleType,
} from "@models"
import { DAL } from "@medusajs/types"
import { CreateCurrencyDTO, UpdateCurrencyDTO } from "./currency"
import { CreateMoneyAmountDTO, UpdateMoneyAmountDTO } from "./money-amount"
import {
CreatePriceListRuleValueDTO,
UpdatePriceListRuleValueDTO,
} from "./price-list-rule-value"
import {
CreatePriceListRuleDTO,
UpdatePriceListRuleDTO,
} from "./price-list-rule"
import { CreatePriceListDTO, UpdatePriceListDTO } from "./price-list"
import { CreatePriceRuleDTO, UpdatePriceRuleDTO } from "./price-rule"
import {
CreatePriceSetMoneyAmountRulesDTO,
UpdatePriceSetMoneyAmountRulesDTO,
} from "./price-set-money-amount-rules"
import {
CreatePriceSetMoneyAmountDTO,
UpdatePriceSetMoneyAmountDTO,
} from "./price-set-money-amount"
import {
CreatePriceSetRuleTypeDTO,
UpdatePriceSetRuleTypeDTO,
} from "./price-set-rule-type"
import { CreatePriceSetDTO, UpdatePriceSetDTO } from "./price-set"
import { CreateRuleTypeDTO, UpdateRuleTypeDTO } from "./rule-type"
export * from "./currency"
export * from "./money-amount"
export * from "./price-list-rule-value"
@@ -9,3 +50,119 @@ export * from "./price-set-money-amount"
export * from "./price-set-rule-type"
export * from "./price-set"
export * from "./rule-type"
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface ICurrencyRepository<TEntity extends Currency = Currency>
extends DAL.RepositoryService<
TEntity,
{
create: CreateCurrencyDTO
update: UpdateCurrencyDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IMoneyAmountRepository<
TEntity extends MoneyAmount = MoneyAmount
> extends DAL.RepositoryService<
TEntity,
{
create: CreateMoneyAmountDTO
update: UpdateMoneyAmountDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IPriceListRuleValueRepository<
TEntity extends PriceListRuleValue = PriceListRuleValue
> extends DAL.RepositoryService<
TEntity,
{
create: CreatePriceListRuleValueDTO
update: UpdatePriceListRuleValueDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IPriceListRuleRepository<
TEntity extends PriceListRule = PriceListRule
> extends DAL.RepositoryService<
TEntity,
{
create: CreatePriceListRuleDTO
update: UpdatePriceListRuleDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IPriceListRepository<TEntity extends PriceList = PriceList>
extends DAL.RepositoryService<
TEntity,
{
create: CreatePriceListDTO
update: UpdatePriceListDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IPriceRuleRepository<TEntity extends PriceRule = PriceRule>
extends DAL.RepositoryService<
TEntity,
{
create: CreatePriceRuleDTO
update: UpdatePriceRuleDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IPriceSetMoneyAmountRulesRepository<
TEntity extends PriceSetMoneyAmountRules = PriceSetMoneyAmountRules
> extends DAL.RepositoryService<
TEntity,
{
create: CreatePriceSetMoneyAmountRulesDTO
update: UpdatePriceSetMoneyAmountRulesDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IPriceSetMoneyAmountRepository<
TEntity extends PriceSetMoneyAmount = PriceSetMoneyAmount
> extends DAL.RepositoryService<
TEntity,
{
create: CreatePriceSetMoneyAmountDTO
update: UpdatePriceSetMoneyAmountDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IPriceSetRuleTypeRepository<
TEntity extends PriceSetRuleType = PriceSetRuleType
> extends DAL.RepositoryService<
TEntity,
{
create: CreatePriceSetRuleTypeDTO
update: UpdatePriceSetRuleTypeDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IPriceSetRepository<TEntity extends PriceSet = PriceSet>
extends DAL.RepositoryService<
TEntity,
{
create: CreatePriceSetDTO
update: UpdatePriceSetDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IRuleTypeRepository<TEntity extends RuleType = RuleType>
extends DAL.RepositoryService<
TEntity,
{
create: CreateRuleTypeDTO
update: UpdateRuleTypeDTO
}
> {}

View File

@@ -1,12 +1,17 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { ProductCategory } from "@models"
import { ProductCategoryRepository } from "@repositories"
import { ProductCategoryService } from "@services"
import { createProductCategories } from "../../../__fixtures__/product-category"
import { productCategoriesData, productCategoriesRankData } from "../../../__fixtures__/product-category/data"
import {
productCategoriesData,
productCategoriesRankData,
} from "../../../__fixtures__/product-category/data"
import { TestDatabase } from "../../../utils"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -20,13 +25,12 @@ describe("Product category Service", () => {
await TestDatabase.setupDatabase()
repositoryManager = await TestDatabase.forkManager()
const productCategoryRepository = new ProductCategoryRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new ProductCategoryService<ProductCategory>({
productCategoryRepository,
})
await ContainerLoader({ container })
service = container.resolve("productCategoryService")
})
afterEach(async () => {
@@ -244,13 +248,11 @@ describe("Product category Service", () => {
})
it("should return category for the given id", async () => {
const productCategoryResults = await service.retrieve(
categoryOneId,
)
const productCategoryResults = await service.retrieve(categoryOneId)
expect(productCategoryResults).toEqual(
expect.objectContaining({
id: categoryOneId
id: categoryOneId,
})
)
})
@@ -264,7 +266,9 @@ describe("Product category Service", () => {
error = e
}
expect(error.message).toEqual('ProductCategory with id: does-not-exist was not found')
expect(error.message).toEqual(
"ProductCategory with id: does-not-exist was not found"
)
})
it("should throw an error when an id is not provided", async () => {
@@ -280,44 +284,38 @@ describe("Product category Service", () => {
})
it("should return category based on config select param", async () => {
const productCategoryResults = await service.retrieve(
categoryOneId,
{
select: ["id", "parent_category_id"],
}
)
const productCategoryResults = await service.retrieve(categoryOneId, {
select: ["id", "parent_category_id"],
})
expect(productCategoryResults).toEqual(
expect.objectContaining({
id: categoryOneId,
id: categoryOneId,
parent_category_id: "category-0",
})
)
})
it("should return category based on config relation param", async () => {
const productCategoryResults = await service.retrieve(
categoryOneId,
{
select: ["id", "parent_category_id"],
relations: ["parent_category"]
}
)
const productCategoryResults = await service.retrieve(categoryOneId, {
select: ["id", "parent_category_id"],
relations: ["parent_category"],
})
expect(productCategoryResults).toEqual(
expect.objectContaining({
id: categoryOneId,
id: categoryOneId,
category_children: [
expect.objectContaining({
id: 'category-1-a',
id: "category-1-a",
}),
expect.objectContaining({
id: 'category-1-b',
})
id: "category-1-b",
}),
],
parent_category: expect.objectContaining({
id: "category-0"
})
id: "category-0",
}),
})
)
})
@@ -352,7 +350,7 @@ describe("Product category Service", () => {
{},
{
take: 1,
skip: 1
skip: 1,
}
)
@@ -377,7 +375,7 @@ describe("Product category Service", () => {
expect(productCategoryResults[0]).toEqual([
expect.objectContaining({
id: "category-0",
parent_category: null
parent_category: null,
}),
expect.objectContaining({
id: "category-1",
@@ -568,11 +566,14 @@ describe("Product category Service", () => {
parent_category_id: null,
})
const [productCategory] = await service.list({
name: "New Category"
}, {
select: ["name", "rank"]
})
const [productCategory] = await service.list(
{
name: "New Category",
},
{
select: ["name", "rank"],
}
)
expect(productCategory).toEqual(
expect.objectContaining({
@@ -586,7 +587,7 @@ describe("Product category Service", () => {
await service.create({
name: "New Category",
parent_category_id: null,
rank: 0
rank: 0,
})
await service.create({
@@ -594,11 +595,14 @@ describe("Product category Service", () => {
parent_category_id: null,
})
const [productCategoryNew] = await service.list({
name: "New Category 2"
}, {
select: ["name", "rank"]
})
const [productCategoryNew] = await service.list(
{
name: "New Category 2",
},
{
select: ["name", "rank"],
}
)
expect(productCategoryNew).toEqual(
expect.objectContaining({
@@ -612,11 +616,14 @@ describe("Product category Service", () => {
parent_category_id: productCategoryNew.id,
})
const [productCategoryWithParent] = await service.list({
name: "New Category 2.1"
}, {
select: ["name", "rank", "parent_category_id"]
})
const [productCategoryWithParent] = await service.list(
{
name: "New Category 2.1",
},
{
select: ["name", "rank", "parent_category_id"],
}
)
expect(productCategoryWithParent).toEqual(
expect.objectContaining({
@@ -655,11 +662,11 @@ describe("Product category Service", () => {
it("should update the name of the category successfully", async () => {
await service.update(productCategoryZero.id, {
name: "New Category"
name: "New Category",
})
const productCategory = await service.retrieve(productCategoryZero.id, {
select: ["name"]
select: ["name"],
})
expect(productCategory.name).toEqual("New Category")
@@ -670,13 +677,15 @@ describe("Product category Service", () => {
try {
await service.update("does-not-exist", {
name: "New Category"
name: "New Category",
})
} catch (e) {
error = e
}
expect(error.message).toEqual(`ProductCategory not found ({ id: 'does-not-exist' })`)
expect(error.message).toEqual(
`ProductCategory not found ({ id: 'does-not-exist' })`
)
})
it("should reorder rank successfully in the same parent", async () => {
@@ -684,11 +693,14 @@ describe("Product category Service", () => {
rank: 0,
})
const productCategories = await service.list({
parent_category_id: null
}, {
select: ["name", "rank"]
})
const productCategories = await service.list(
{
parent_category_id: null,
},
{
select: ["name", "rank"],
}
)
expect(productCategories).toEqual(
expect.arrayContaining([
@@ -703,7 +715,7 @@ describe("Product category Service", () => {
expect.objectContaining({
id: productCategoryOne.id,
rank: "2",
})
}),
])
)
})
@@ -711,14 +723,17 @@ describe("Product category Service", () => {
it("should reorder rank successfully when changing parent", async () => {
await service.update(productCategoryTwo.id, {
rank: 0,
parent_category_id: productCategoryZero.id
parent_category_id: productCategoryZero.id,
})
const productCategories = await service.list({
parent_category_id: productCategoryZero.id
}, {
select: ["name", "rank"]
})
const productCategories = await service.list(
{
parent_category_id: productCategoryZero.id,
},
{
select: ["name", "rank"],
}
)
expect(productCategories).toEqual(
expect.arrayContaining([
@@ -737,7 +752,7 @@ describe("Product category Service", () => {
expect.objectContaining({
id: productCategoryZeroTwo.id,
rank: "3",
})
}),
])
)
})
@@ -745,14 +760,17 @@ describe("Product category Service", () => {
it("should reorder rank successfully when changing parent and in first position", async () => {
await service.update(productCategoryTwo.id, {
rank: 0,
parent_category_id: productCategoryZero.id
parent_category_id: productCategoryZero.id,
})
const productCategories = await service.list({
parent_category_id: productCategoryZero.id
}, {
select: ["name", "rank"]
})
const productCategories = await service.list(
{
parent_category_id: productCategoryZero.id,
},
{
select: ["name", "rank"],
}
)
expect(productCategories).toEqual(
expect.arrayContaining([
@@ -771,7 +789,7 @@ describe("Product category Service", () => {
expect.objectContaining({
id: productCategoryZeroTwo.id,
rank: "3",
})
}),
])
)
})
@@ -805,7 +823,9 @@ describe("Product category Service", () => {
error = e
}
expect(error.message).toEqual(`ProductCategory not found ({ id: 'does-not-exist' })`)
expect(error.message).toEqual(
`ProductCategory not found ({ id: 'does-not-exist' })`
)
})
it("should throw an error when it has children", async () => {
@@ -817,17 +837,22 @@ describe("Product category Service", () => {
error = e
}
expect(error.message).toEqual(`Deleting ProductCategory (category-0-0) with category children is not allowed`)
expect(error.message).toEqual(
`Deleting ProductCategory (category-0-0) with category children is not allowed`
)
})
it("should reorder siblings rank successfully on deleting", async () => {
await service.delete(productCategoryOne.id)
const productCategories = await service.list({
parent_category_id: null
}, {
select: ["id", "rank"]
})
const productCategories = await service.list(
{
parent_category_id: null,
},
{
select: ["id", "rank"],
}
)
expect(productCategories).toEqual(
expect.arrayContaining([
@@ -838,7 +863,7 @@ describe("Product category Service", () => {
expect.objectContaining({
id: productCategoryTwo.id,
rank: "1",
})
}),
])
)
})

View File

@@ -1,11 +1,13 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { ProductCollection } from "@models"
import { ProductCollectionRepository } from "@repositories"
import { ProductCollectionService } from "@services"
import { createCollections } from "../../../__fixtures__/product"
import { TestDatabase } from "../../../utils"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -19,13 +21,12 @@ describe("Product collection Service", () => {
await TestDatabase.setupDatabase()
repositoryManager = await TestDatabase.forkManager()
const productCollectionRepository = new ProductCollectionRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new ProductCollectionService({
productCollectionRepository,
})
await ContainerLoader({ container })
service = container.resolve("productCollectionService")
})
afterEach(async () => {
@@ -93,7 +94,9 @@ describe("Product collection Service", () => {
})
it("list product collections by title matching string", async () => {
const productCollectionResults = await service.list({ title: "col 3 extra" })
const productCollectionResults = await service.list({
title: "col 3 extra",
})
expect(productCollectionResults).toEqual([
expect.objectContaining({
@@ -155,7 +158,9 @@ describe("Product collection Service", () => {
})
it("should return count and collections based on filter data", async () => {
const [productCollectionResults, count] = await service.listAndCount({ id: data![0].id })
const [productCollectionResults, count] = await service.listAndCount({
id: data![0].id,
})
const serialized = JSON.parse(JSON.stringify(productCollectionResults))
expect(count).toEqual(1)
@@ -168,12 +173,15 @@ describe("Product collection Service", () => {
})
it("should return count and collections based on config data", async () => {
const [productCollectionResults, count] = await service.listAndCount({}, {
relations: ['products'],
select: ['title'],
take: 1,
skip: 1,
})
const [productCollectionResults, count] = await service.listAndCount(
{},
{
relations: ["products"],
select: ["title"],
take: 1,
skip: 1,
}
)
const serialized = JSON.parse(JSON.stringify(productCollectionResults))
expect(count).toEqual(4)
@@ -181,7 +189,7 @@ describe("Product collection Service", () => {
{
id: "test-2",
title: "col 2",
products: []
products: [],
},
])
})
@@ -200,13 +208,11 @@ describe("Product collection Service", () => {
})
it("should return collection for the given id", async () => {
const productCollectionResults = await service.retrieve(
collectionData.id,
)
const productCollectionResults = await service.retrieve(collectionData.id)
expect(productCollectionResults).toEqual(
expect.objectContaining({
id: collectionData.id
id: collectionData.id,
})
)
})
@@ -220,7 +226,9 @@ describe("Product collection Service", () => {
error = e
}
expect(error.message).toEqual('ProductCollection with id: does-not-exist was not found')
expect(error.message).toEqual(
"ProductCollection with id: does-not-exist was not found"
)
})
it("should throw an error when an id is not provided", async () => {
@@ -245,12 +253,10 @@ describe("Product collection Service", () => {
const serialized = JSON.parse(JSON.stringify(productCollectionResults))
expect(serialized).toEqual(
{
id: collectionData.id,
title: collectionData.title,
}
)
expect(serialized).toEqual({
id: collectionData.id,
title: collectionData.title,
})
})
it("should return collection based on config relation param", async () => {
@@ -258,19 +264,17 @@ describe("Product collection Service", () => {
collectionData.id,
{
select: ["id", "title"],
relations: ["products"]
relations: ["products"],
}
)
const serialized = JSON.parse(JSON.stringify(productCollectionResults))
expect(serialized).toEqual(
{
id: collectionData.id,
title: collectionData.title,
products: []
}
)
expect(serialized).toEqual({
id: collectionData.id,
title: collectionData.title,
products: [],
})
})
})
@@ -288,12 +292,10 @@ describe("Product collection Service", () => {
})
it("should delete the product collection given an ID successfully", async () => {
await service.delete(
[collectionId],
)
await service.delete([collectionId])
const collections = await service.list({
id: collectionId
id: collectionId,
})
expect(collections).toHaveLength(0)
@@ -314,12 +316,12 @@ describe("Product collection Service", () => {
})
it("should update the value of the collection successfully", async () => {
await service.update(
[{
await service.update([
{
id: collectionId,
title: "New Collection"
}]
)
title: "New Collection",
},
])
const productCollection = await service.retrieve(collectionId)
@@ -331,29 +333,31 @@ describe("Product collection Service", () => {
try {
await service.update([
{
id: "does-not-exist",
title: "New Collection"
}
])
{
id: "does-not-exist",
title: "New Collection",
},
])
} catch (e) {
error = e
}
expect(error.message).toEqual('ProductCollection with id "does-not-exist" not found')
expect(error.message).toEqual(
'ProductCollection with id "does-not-exist" not found'
)
})
})
describe("create", () => {
it("should create a collection successfully", async () => {
await service.create(
[{
title: "New Collection"
}]
)
await service.create([
{
title: "New Collection",
},
])
const [productCollection] = await service.list({
title: "New Collection"
title: "New Collection",
})
expect(productCollection.title).toEqual("New Collection")

View File

@@ -1,12 +1,14 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { ProductOptionService } from "@services"
import { ProductOptionRepository } from "@repositories"
import { Product } from "@models"
import { TestDatabase } from "../../../utils"
import { createOptions } from "../../../__fixtures__/product"
import { ProductTypes } from "@medusajs/types"
import { asValue } from "awilix"
import { createMedusaContainer } from "@medusajs/utils"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -34,13 +36,12 @@ describe("ProductOption Service", () => {
await TestDatabase.setupDatabase()
repositoryManager = await TestDatabase.forkManager()
const productOptionRepository = new ProductOptionRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new ProductOptionService({
productOptionRepository,
})
await ContainerLoader({ container })
service = container.resolve("productOptionService")
testManager = await TestDatabase.forkManager()
productOne = testManager.create(Product, productOneData)

View File

@@ -1,12 +1,14 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { Product } from "@models"
import { ProductTagRepository } from "@repositories"
import { ProductTagService } from "@services"
import { ProductTypes } from "@medusajs/types"
import { createProductAndTags } from "../../../__fixtures__/product"
import { TestDatabase } from "../../../utils"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -53,13 +55,12 @@ describe("ProductTag Service", () => {
await TestDatabase.setupDatabase()
repositoryManager = await TestDatabase.forkManager()
const productTagRepository = new ProductTagRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new ProductTagService({
productTagRepository,
})
await ContainerLoader({ container })
service = container.resolve("productTagService")
testManager = await TestDatabase.forkManager()
@@ -143,7 +144,9 @@ describe("ProductTag Service", () => {
})
it("should return product tags and count when filtered", async () => {
const [tagsResults, count] = await service.listAndCount({ id: data[0].tags![0].id })
const [tagsResults, count] = await service.listAndCount({
id: data[0].tags![0].id,
})
expect(count).toEqual(1)
expect(tagsResults).toEqual([
@@ -154,7 +157,10 @@ describe("ProductTag Service", () => {
})
it("should return product tags and count when using skip and take", async () => {
const [tagsResults, count] = await service.listAndCount({}, { skip: 1, take: 2 })
const [tagsResults, count] = await service.listAndCount(
{},
{ skip: 1, take: 2 }
)
expect(count).toEqual(4)
expect(tagsResults).toEqual([
@@ -168,11 +174,14 @@ describe("ProductTag Service", () => {
})
it("should return requested fields and relations", async () => {
const [tagsResults, count] = await service.listAndCount({}, {
take: 1,
select: ["value", "products.id"],
relations: ["products"]
})
const [tagsResults, count] = await service.listAndCount(
{},
{
take: 1,
select: ["value", "products.id"],
relations: ["products"],
}
)
const serialized = JSON.parse(JSON.stringify(tagsResults))
@@ -180,9 +189,11 @@ describe("ProductTag Service", () => {
expect(serialized).toEqual([
expect.objectContaining({
id: "tag-1",
products: [{
id: "test-1"
}]
products: [
{
id: "test-1",
},
],
}),
])
})
@@ -194,13 +205,11 @@ describe("ProductTag Service", () => {
const productId = "test-1"
it("should return tag for the given id", async () => {
const tag = await service.retrieve(
tagId,
)
const tag = await service.retrieve(tagId)
expect(tag).toEqual(
expect.objectContaining({
id: tagId
id: tagId,
})
)
})
@@ -214,7 +223,9 @@ describe("ProductTag Service", () => {
error = e
}
expect(error.message).toEqual('ProductTag with id: does-not-exist was not found')
expect(error.message).toEqual(
"ProductTag with id: does-not-exist was not found"
)
})
it("should throw an error when an id is not provided", async () => {
@@ -230,43 +241,35 @@ describe("ProductTag Service", () => {
})
it("should return tag based on config select param", async () => {
const tag = await service.retrieve(
tagId,
{
select: ["id", "value"],
}
)
const tag = await service.retrieve(tagId, {
select: ["id", "value"],
})
const serialized = JSON.parse(JSON.stringify(tag))
expect(serialized).toEqual(
{
id: tagId,
value: tagValue,
}
)
expect(serialized).toEqual({
id: tagId,
value: tagValue,
})
})
it("should return tag based on config relation param", async () => {
const tag = await service.retrieve(
tagId,
{
select: ["id", "value", "products.id"],
relations: ["products"]
}
)
const tag = await service.retrieve(tagId, {
select: ["id", "value", "products.id"],
relations: ["products"],
})
const serialized = JSON.parse(JSON.stringify(tag))
expect(serialized).toEqual(
{
id: tagId,
value: tagValue,
products: [{
id: productId
}]
}
)
expect(serialized).toEqual({
id: tagId,
value: tagValue,
products: [
{
id: productId,
},
],
})
})
})
@@ -274,12 +277,10 @@ describe("ProductTag Service", () => {
const tagId = "tag-1"
it("should delete the product tag given an ID successfully", async () => {
await service.delete(
[tagId],
)
await service.delete([tagId])
const tags = await service.list({
id: tagId
id: tagId,
})
expect(tags).toHaveLength(0)
@@ -290,12 +291,12 @@ describe("ProductTag Service", () => {
const tagId = "tag-1"
it("should update the value of the tag successfully", async () => {
await service.update(
[{
await service.update([
{
id: tagId,
value: "UK"
}]
)
value: "UK",
},
])
const productTag = await service.retrieve(tagId)
@@ -307,29 +308,31 @@ describe("ProductTag Service", () => {
try {
await service.update([
{
id: "does-not-exist",
value: "UK"
}
])
{
id: "does-not-exist",
value: "UK",
},
])
} catch (e) {
error = e
}
expect(error.message).toEqual('ProductTag with id "does-not-exist" not found')
expect(error.message).toEqual(
'ProductTag with id "does-not-exist" not found'
)
})
})
describe("create", () => {
it("should create a tag successfully", async () => {
await service.create(
[{
value: "UK"
}]
)
await service.create([
{
value: "UK",
},
])
const [productTag] = await service.list({
value: "UK"
value: "UK",
})
expect(productTag.value).toEqual("UK")

View File

@@ -1,12 +1,14 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import ContainerLoader from "../../../../src/loaders/container"
import { ProductTypeService } from "@services"
import { ProductTypeRepository } from "@repositories"
import { Product } from "@models"
import { TestDatabase } from "../../../utils"
import { createProductAndTypes } from "../../../__fixtures__/product"
import { ProductTypes } from "@medusajs/types"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
jest.setTimeout(30000)
@@ -33,7 +35,7 @@ describe("ProductType Service", () => {
type: {
id: "type-2",
value: "Type 2",
}
},
},
]
@@ -41,13 +43,12 @@ describe("ProductType Service", () => {
await TestDatabase.setupDatabase()
repositoryManager = await TestDatabase.forkManager()
const productTypeRepository = new ProductTypeRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new ProductTypeService({
productTypeRepository,
})
await ContainerLoader({ container })
service = container.resolve("productTypeService")
testManager = await TestDatabase.forkManager()
@@ -115,7 +116,9 @@ describe("ProductType Service", () => {
})
it("should return product type and count when filtered", async () => {
const [typeResults, count] = await service.listAndCount({ id: data[0].type.id })
const [typeResults, count] = await service.listAndCount({
id: data[0].type.id,
})
expect(count).toEqual(1)
expect(typeResults).toEqual([
@@ -126,7 +129,10 @@ describe("ProductType Service", () => {
})
it("should return product type and count when using skip and take", async () => {
const [typeResults, count] = await service.listAndCount({}, { skip: 1, take: 1 })
const [typeResults, count] = await service.listAndCount(
{},
{ skip: 1, take: 1 }
)
expect(count).toEqual(2)
expect(typeResults).toEqual([
@@ -137,10 +143,13 @@ describe("ProductType Service", () => {
})
it("should return requested fields", async () => {
const [typeResults, count] = await service.listAndCount({}, {
take: 1,
select: ["value"],
})
const [typeResults, count] = await service.listAndCount(
{},
{
take: 1,
select: ["value"],
}
)
const serialized = JSON.parse(JSON.stringify(typeResults))
@@ -158,13 +167,11 @@ describe("ProductType Service", () => {
const typeValue = "Type 1"
it("should return type for the given id", async () => {
const type = await service.retrieve(
typeId,
)
const type = await service.retrieve(typeId)
expect(type).toEqual(
expect.objectContaining({
id: typeId
id: typeId,
})
)
})
@@ -178,7 +185,9 @@ describe("ProductType Service", () => {
error = e
}
expect(error.message).toEqual('ProductType with id: does-not-exist was not found')
expect(error.message).toEqual(
"ProductType with id: does-not-exist was not found"
)
})
it("should throw an error when an id is not provided", async () => {
@@ -194,21 +203,16 @@ describe("ProductType Service", () => {
})
it("should return type based on config select param", async () => {
const type = await service.retrieve(
typeId,
{
select: ["id", "value"],
}
)
const type = await service.retrieve(typeId, {
select: ["id", "value"],
})
const serialized = JSON.parse(JSON.stringify(type))
expect(serialized).toEqual(
{
id: typeId,
value: typeValue,
}
)
expect(serialized).toEqual({
id: typeId,
value: typeValue,
})
})
})
@@ -216,12 +220,10 @@ describe("ProductType Service", () => {
const typeId = "type-1"
it("should delete the product type given an ID successfully", async () => {
await service.delete(
[typeId],
)
await service.delete([typeId])
const types = await service.list({
id: typeId
id: typeId,
})
expect(types).toHaveLength(0)
@@ -232,12 +234,12 @@ describe("ProductType Service", () => {
const typeId = "type-1"
it("should update the value of the type successfully", async () => {
await service.update(
[{
await service.update([
{
id: typeId,
value: "UK"
}]
)
value: "UK",
},
])
const productType = await service.retrieve(typeId)
@@ -249,29 +251,31 @@ describe("ProductType Service", () => {
try {
await service.update([
{
id: "does-not-exist",
value: "UK"
}
])
{
id: "does-not-exist",
value: "UK",
},
])
} catch (e) {
error = e
}
expect(error.message).toEqual('ProductType with id "does-not-exist" not found')
expect(error.message).toEqual(
'ProductType with id "does-not-exist" not found'
)
})
})
describe("create", () => {
it("should create a type successfully", async () => {
await service.create(
[{
value: "UK"
}]
)
await service.create([
{
value: "UK",
},
])
const [productType] = await service.list({
value: "UK"
value: "UK",
})
expect(productType.value).toEqual("UK")

View File

@@ -1,6 +1,5 @@
import { TestDatabase } from "../../../utils"
import { ProductService, ProductVariantService } from "@services"
import { ProductRepository, ProductVariantRepository } from "@repositories"
import { ProductVariantService } from "@services"
import { Product, ProductTag, ProductVariant } from "@models"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { Collection } from "@mikro-orm/core"
@@ -13,6 +12,9 @@ import {
} from "../../../__fixtures__/product"
import { productsData, variantsData } from "../../../__fixtures__/product/data"
import { buildProductVariantOnlyData } from "../../../__fixtures__/variant/data/create-variant"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
describe("ProductVariant Service", () => {
let service: ProductVariantService
@@ -27,20 +29,12 @@ describe("ProductVariant Service", () => {
await TestDatabase.setupDatabase()
repositoryManager = await TestDatabase.forkManager()
const productVariantRepository = new ProductVariantRepository({
manager: repositoryManager,
})
const productRepository = new ProductRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
const productService = new ProductService({
productRepository,
})
service = new ProductVariantService({
productService,
productVariantRepository,
})
await ContainerLoader({ container })
service = container.resolve("productVariantService")
})
afterEach(async () => {

View File

@@ -21,12 +21,13 @@ import {
} from "../../../__fixtures__/product/data"
import { ProductDTO, ProductTypes } from "@medusajs/types"
import { kebabCase } from "@medusajs/utils"
import { createMedusaContainer, kebabCase } from "@medusajs/utils"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { ProductRepository } from "@repositories"
import { ProductService } from "@services"
import { createProductCategories } from "../../../__fixtures__/product-category"
import { TestDatabase } from "../../../utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -44,13 +45,12 @@ describe("Product Service", () => {
await TestDatabase.setupDatabase()
repositoryManager = await TestDatabase.forkManager()
const productRepository = new ProductRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new ProductService({
productRepository,
})
await ContainerLoader({ container })
service = container.resolve("productService")
})
afterEach(async () => {

View File

@@ -1,108 +1,10 @@
import * as DefaultRepositories from "@repositories"
import {
BaseRepository,
ProductCategoryRepository,
ProductCollectionRepository,
ProductImageRepository,
ProductOptionRepository,
ProductOptionValueRepository,
ProductRepository,
ProductTagRepository,
ProductTypeRepository,
ProductVariantRepository,
} from "@repositories"
import { Constructor, DAL, ModulesSdkTypes } from "@medusajs/types"
import {
ProductCategoryService,
ProductCollectionService,
ProductImageService,
ProductModuleService,
ProductOptionService,
ProductOptionValueService,
ProductService,
ProductTagService,
ProductTypeService,
ProductVariantService,
} from "@services"
import { ModulesSdkUtils } from "@medusajs/utils"
import * as ModuleModels from "@models"
import * as ModuleRepositories from "@repositories"
import * as ModuleServices from "@services"
import { LoaderOptions } from "@medusajs/modules-sdk"
import { asClass } from "awilix"
import { lowerCaseFirst } from "@medusajs/utils"
export default async ({
container,
options,
}: LoaderOptions<
| ModulesSdkTypes.ModuleServiceInitializeOptions
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
>): Promise<void> => {
const customRepositories = (
options as ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
)?.repositories
container.register({
productModuleService: asClass(ProductModuleService).singleton(),
productService: asClass(ProductService).singleton(),
productCategoryService: asClass(ProductCategoryService).singleton(),
productVariantService: asClass(ProductVariantService).singleton(),
productTagService: asClass(ProductTagService).singleton(),
productCollectionService: asClass(ProductCollectionService).singleton(),
productImageService: asClass(ProductImageService).singleton(),
productTypeService: asClass(ProductTypeService).singleton(),
productOptionService: asClass(ProductOptionService).singleton(),
productOptionValueService: asClass(ProductOptionValueService).singleton(),
})
if (customRepositories) {
loadCustomRepositories({ customRepositories, container })
} else {
loadDefaultRepositories({ container })
}
}
function loadDefaultRepositories({ container }) {
container.register({
baseRepository: asClass(BaseRepository).singleton(),
productImageRepository: asClass(ProductImageRepository).singleton(),
productCategoryRepository: asClass(ProductCategoryRepository).singleton(),
productCollectionRepository: asClass(
ProductCollectionRepository
).singleton(),
productRepository: asClass(ProductRepository).singleton(),
productTagRepository: asClass(ProductTagRepository).singleton(),
productTypeRepository: asClass(ProductTypeRepository).singleton(),
productOptionRepository: asClass(ProductOptionRepository).singleton(),
productOptionValueRepository: asClass(
ProductOptionValueRepository
).singleton(),
productVariantRepository: asClass(ProductVariantRepository).singleton(),
})
}
/**
* Load the repositories from the custom repositories object. If a repository is not
* present in the custom repositories object, the default repository will be used.
*
* @param customRepositories
* @param container
*/
function loadCustomRepositories({ customRepositories, container }) {
const customRepositoriesMap = new Map(Object.entries(customRepositories))
Object.entries(DefaultRepositories).forEach(([key, DefaultRepository]) => {
let finalRepository = customRepositoriesMap.get(key)
if (
!finalRepository ||
!(finalRepository as Constructor<DAL.RepositoryService>).prototype.find
) {
finalRepository = DefaultRepository
}
container.register({
[lowerCaseFirst(key)]: asClass(
finalRepository as Constructor<DAL.RepositoryService>
).singleton(),
})
})
}
export default ModulesSdkUtils.moduleContainerLoaderFactory({
moduleModels: ModuleModels,
moduleRepositories: ModuleRepositories,
moduleServices: ModuleServices,
})

View File

@@ -1,10 +1,4 @@
export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils"
export { ProductRepository } from "./product"
export { ProductTagRepository } from "./product-tag"
export { ProductVariantRepository } from "./product-variant"
export { ProductCollectionRepository } from "./product-collection"
export { ProductCategoryRepository } from "./product-category"
export { ProductImageRepository } from "./product-image"
export { ProductTypeRepository } from "./product-type"
export { ProductOptionRepository } from "./product-option"
export { ProductOptionValueRepository } from "./product-option-value"

View File

@@ -1,55 +0,0 @@
import { Context, ProductTypes } from "@medusajs/types"
import { DALUtils } from "@medusajs/utils"
import { ProductCollection } from "@models"
type UpdateProductCollection = ProductTypes.UpdateProductCollectionDTO & {
products?: string[]
}
type CreateProductCollection = ProductTypes.CreateProductCollectionDTO & {
products?: string[]
}
// eslint-disable-next-line max-len
export class ProductCollectionRepository extends DALUtils.mikroOrmBaseRepositoryFactory(
ProductCollection
) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
async create(
data: CreateProductCollection[],
context: Context = {}
): Promise<ProductCollection[]> {
const productCollections = data.map((collectionData) => {
if (collectionData.product_ids) {
collectionData.products = collectionData.product_ids
delete collectionData.product_ids
}
return collectionData
})
return await super.create(productCollections, context)
}
async update(
data: UpdateProductCollection[],
context: Context = {}
): Promise<ProductCollection[]> {
const productCollections = data.map((collectionData) => {
if (collectionData.product_ids) {
collectionData.products = collectionData.product_ids
delete collectionData.product_ids
}
return collectionData
})
return await super.update(productCollections, context)
}
}

View File

@@ -1,7 +1,6 @@
import { Context } from "@medusajs/types"
import { Image } from "@models"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { DALUtils } from "@medusajs/utils"
import { Context } from "@medusajs/types"
// eslint-disable-next-line max-len
export class ProductImageRepository extends DALUtils.mikroOrmBaseRepositoryFactory(
@@ -13,41 +12,8 @@ export class ProductImageRepository extends DALUtils.mikroOrmBaseRepositoryFacto
}
async upsert(urls: string[], context: Context = {}): Promise<Image[]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
const data = urls.map((url) => ({ url }))
const existingImages = await this.find(
{
where: {
url: {
$in: urls,
},
},
},
context
)
const existingImagesMap = new Map<string, Image>(
existingImages.map<[string, Image]>((img) => [img.url, img])
)
const upsertedImgs: Image[] = []
const imageToCreate: Image[] = []
urls.forEach((url) => {
const aImg = existingImagesMap.get(url)
if (aImg) {
upsertedImgs.push(aImg)
} else {
const newImg = (manager as SqlEntityManager).create(Image, { url })
imageToCreate.push(newImg)
}
})
if (imageToCreate.length) {
manager.persist(imageToCreate)
upsertedImgs.push(...imageToCreate)
}
return upsertedImgs
return await super.upsert(data, context)
}
}

View File

@@ -1,89 +0,0 @@
import { Context } from "@medusajs/types"
import {
CreateProductOptionValueDTO,
UpdateProductOptionValueDTO,
} from "../types/services/product-option-value"
import { DALUtils } from "@medusajs/utils"
import { ProductOptionValue } from "@models"
import { SqlEntityManager } from "@mikro-orm/postgresql"
export class ProductOptionValueRepository extends DALUtils.mikroOrmBaseRepositoryFactory(
ProductOptionValue
) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
async upsert(
optionValues: (UpdateProductOptionValueDTO | CreateProductOptionValueDTO)[],
context: Context = {}
): Promise<ProductOptionValue[]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
const optionValueIds: string[] = []
for (const optionValue of optionValues) {
if (optionValue.id) {
optionValueIds.push(optionValue.id)
}
}
const existingOptionValues = await this.find(
{
where: {
id: {
$in: optionValueIds,
},
},
},
context
)
const existingOptionValuesMap = new Map(
existingOptionValues.map<[string, ProductOptionValue]>((optionValue) => [
optionValue.id,
optionValue,
])
)
const upsertedOptionValues: ProductOptionValue[] = []
const optionValuesToCreate: ProductOptionValue[] = []
const optionValuesToUpdate: ProductOptionValue[] = []
optionValues.forEach(({ option_id, ...optionValue }) => {
const existingOptionValue = optionValue.id
? existingOptionValuesMap.get(optionValue.id)
: undefined
if (optionValue.id && existingOptionValue) {
const updatedOptionValue = manager.assign(existingOptionValue, {
option: option_id,
...optionValue,
})
optionValuesToUpdate.push(updatedOptionValue)
return
}
const newOptionValue = manager.create(ProductOptionValue, {
option: option_id,
variant: (optionValue as CreateProductOptionValueDTO).variant_id,
...optionValue,
})
optionValuesToCreate.push(newOptionValue)
})
if (optionValuesToCreate.length) {
manager.persist(optionValuesToCreate)
upsertedOptionValues.push(...optionValuesToCreate)
}
if (optionValuesToUpdate.length) {
manager.persist(optionValuesToUpdate)
upsertedOptionValues.push(...optionValuesToUpdate)
}
return upsertedOptionValues
}
}

View File

@@ -1,112 +0,0 @@
import { Context, ProductTypes } from "@medusajs/types"
import { DALUtils } from "@medusajs/utils"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { Product, ProductOption } from "@models"
// eslint-disable-next-line max-len
export class ProductOptionRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
ProductOption,
{
update: ProductTypes.UpdateProductOptionDTO
}
>(ProductOption) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
async create(
data: ProductTypes.CreateProductOptionDTO[],
context: Context = {}
): Promise<ProductOption[]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
const productIds: string[] = []
data.forEach((d) => d.product_id && productIds.push(d.product_id))
const existingProducts = await manager.find(Product, {
id: { $in: productIds },
})
const existingProductsMap = new Map<string, Product>(
existingProducts.map<[string, Product]>((product) => [
product.id,
product,
])
)
const productOptions = data.map((optionData) => {
const productId = optionData.product_id
delete optionData.product_id
if (productId) {
const product = existingProductsMap.get(productId)
optionData.product_id = product?.id
}
return optionData
})
return await super.create(productOptions, context)
}
async upsert(
data:
| ProductTypes.CreateProductOptionDTO[]
| ProductTypes.UpdateProductOptionDTO[],
context: Context = {}
): Promise<ProductOption[]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
const optionIds = data.map((optionData) => optionData.id).filter((o) => o)
let existingOptions
let existingOptionsMap = new Map()
if (optionIds.length) {
existingOptions = await this.find(
{
where: {
id: {
$in: optionIds,
},
},
},
context
)
existingOptionsMap = new Map(
existingOptions.map((option) => [option.id, option])
)
}
const upsertedOptions: ProductOption[] = []
const optionsToCreate: ProductOption[] = []
const optionsToUpdate: ProductOption[] = []
data.forEach((option) => {
const existingOption = existingOptionsMap.get(option.id)
if (existingOption) {
const updatedOption = manager.assign(existingOption, option)
optionsToUpdate.push(updatedOption)
} else {
const newOption = manager.create(ProductOption, option)
optionsToCreate.push(newOption)
}
})
if (optionsToCreate.length) {
manager.persist(optionsToCreate)
upsertedOptions.push(...optionsToCreate)
}
if (optionsToUpdate.length) {
manager.persist(optionsToUpdate)
upsertedOptions.push(...optionsToUpdate)
}
return upsertedOptions
}
}

View File

@@ -1,71 +0,0 @@
import { ProductTag } from "@models"
import {
Context,
CreateProductTagDTO,
UpdateProductTagDTO,
UpsertProductTagDTO,
} from "@medusajs/types"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { DALUtils } from "@medusajs/utils"
export class ProductTagRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
ProductTag,
{
create: CreateProductTagDTO
update: UpdateProductTagDTO
}
>(ProductTag) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
async upsert(
tags: UpsertProductTagDTO[],
context: Context = {}
): Promise<ProductTag[]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
const tagsValues = tags.map((tag) => tag.value)
const existingTags = await this.find(
{
where: {
value: {
$in: tagsValues,
},
},
},
context
)
const existingTagsMap = new Map(
existingTags.map<[string, ProductTag]>((tag) => [tag.value, tag])
)
const upsertedTags: ProductTag[] = []
const tagsToCreate: ProductTag[] = []
const tagsToUpdate: ProductTag[] = []
tags.forEach((tag) => {
const aTag = existingTagsMap.get(tag.value)
if (aTag) {
const updatedTag = manager.assign(aTag, tag)
tagsToUpdate.push(updatedTag)
} else {
const newTag = manager.create(ProductTag, tag)
tagsToCreate.push(newTag)
}
})
if (tagsToCreate.length) {
manager.persist(tagsToCreate)
upsertedTags.push(...tagsToCreate)
}
if (tagsToUpdate.length) {
manager.persist(tagsToUpdate)
upsertedTags.push(...tagsToUpdate)
}
return upsertedTags
}
}

View File

@@ -1,71 +0,0 @@
import { ProductType } from "@models"
import {
Context,
CreateProductTypeDTO,
UpdateProductTypeDTO,
} from "@medusajs/types"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { DALUtils } from "@medusajs/utils"
export class ProductTypeRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
ProductType,
{
create: CreateProductTypeDTO
update: UpdateProductTypeDTO
}
>(ProductType) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
async upsert(
types: CreateProductTypeDTO[],
context: Context = {}
): Promise<ProductType[]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
const typesValues = types.map((type) => type.value)
const existingTypes = await this.find(
{
where: {
value: {
$in: typesValues,
},
},
},
context
)
const existingTypesMap = new Map(
existingTypes.map<[string, ProductType]>((type) => [type.value, type])
)
const upsertedTypes: ProductType[] = []
const typesToCreate: ProductType[] = []
const typesToUpdate: ProductType[] = []
types.forEach((type) => {
const aType = existingTypesMap.get(type.value)
if (aType) {
const updatedType = manager.assign(aType, type)
typesToUpdate.push(updatedType)
} else {
const newType = manager.create(ProductType, type)
typesToCreate.push(newType)
}
})
if (typesToCreate.length) {
manager.persist(typesToCreate)
upsertedTypes.push(...typesToCreate)
}
if (typesToUpdate.length) {
manager.persist(typesToUpdate)
upsertedTypes.push(...typesToUpdate)
}
return upsertedTypes
}
}

View File

@@ -1,22 +0,0 @@
import { ProductVariant } from "@models"
import { DALUtils } from "@medusajs/utils"
import { RequiredEntityData } from "@mikro-orm/core"
import { WithRequiredProperty } from "@medusajs/types"
import { ProductVariantServiceTypes } from "../types/services"
// eslint-disable-next-line max-len
export class ProductVariantRepository extends DALUtils.mikroOrmBaseRepositoryFactory<
ProductVariant,
{
create: RequiredEntityData<ProductVariant>
update: WithRequiredProperty<
ProductVariantServiceTypes.UpdateProductVariantDTO,
"id"
>
}
>(ProductVariant) {
constructor(...args: any[]) {
// @ts-ignore
super(...arguments)
}
}

View File

@@ -1,7 +1,20 @@
import { Context, DAL, FindConfig, ProductTypes } from "@medusajs/types"
import { InjectManager, MedusaContext, ModulesSdkUtils } from "@medusajs/utils"
import {
InjectManager,
InjectTransactionManager,
MedusaContext,
ModulesSdkUtils,
} from "@medusajs/utils"
import { ProductCollection } from "@models"
import {
IProductCollectionRepository,
ProductCollectionServiceTypes,
} from "@types"
import {
CreateProductCollection,
UpdateProductCollection,
} from "../types/services/product-collection"
type InjectedDependencies = {
productCollectionRepository: DAL.RepositoryService
@@ -12,12 +25,12 @@ export default class ProductCollectionService<
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: ProductTypes.CreateProductCollectionDTO
update: ProductTypes.UpdateProductCollectionDTO
create: CreateProductCollection
update: UpdateProductCollection
}
>(ProductCollection)<TEntity> {
// eslint-disable-next-line max-len
protected readonly productCollectionRepository_: DAL.RepositoryService<TEntity>
protected readonly productCollectionRepository_: IProductCollectionRepository<TEntity>
constructor(container: InjectedDependencies) {
super(container)
@@ -66,4 +79,40 @@ export default class ProductCollectionService<
return queryOptions
}
@InjectTransactionManager("productCollectionRepository_")
async create(
data: ProductCollectionServiceTypes.CreateProductCollection[],
context: Context = {}
): Promise<TEntity[]> {
const productCollections = data.map((collectionData) => {
if (collectionData.product_ids) {
collectionData.products = collectionData.product_ids
delete collectionData.product_ids
}
return collectionData
})
return super.create(productCollections, context)
}
@InjectTransactionManager("productCollectionRepository_")
async update(
data: ProductCollectionServiceTypes.UpdateProductCollection[],
context: Context = {}
): Promise<TEntity[]> {
const productCollections = data.map((collectionData) => {
if (collectionData.product_ids) {
collectionData.products = collectionData.product_ids
delete collectionData.product_ids
}
return collectionData
})
return super.update(productCollections, context)
}
}

View File

@@ -1,23 +1,18 @@
import { Image } from "@models"
import { Context, DAL } from "@medusajs/types"
import { InjectTransactionManager, MedusaContext } from "@medusajs/utils"
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
type InjectedDependencies = {
productImageRepository: DAL.RepositoryService
}
export default class ProductImageService<TEntity extends Image = Image> {
protected readonly productImageRepository_: DAL.RepositoryService
constructor({ productImageRepository }: InjectedDependencies) {
this.productImageRepository_ = productImageRepository
}
@InjectTransactionManager("productImageRepository_")
async upsert(
urls: string[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
return await this.productImageRepository_.upsert!(urls, sharedContext)
export default class ProductImageService<
TEntity extends Image = Image
> extends ModulesSdkUtils.abstractServiceFactory<InjectedDependencies>(
Image
)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}

View File

@@ -1,6 +1,6 @@
import { ProductOptionValue } from "@models"
import { Context, DAL } from "@medusajs/types"
import { InjectTransactionManager, MedusaContext } from "@medusajs/utils"
import { DAL } from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { ProductOptionValueServiceTypes } from "@types"
type InjectedDependencies = {
@@ -9,30 +9,15 @@ type InjectedDependencies = {
export default class ProductOptionValueService<
TEntity extends ProductOptionValue = ProductOptionValue
> {
// eslint-disable-next-line max-len
protected readonly productOptionValueRepository_: DAL.RepositoryService<TEntity>
constructor({ productOptionValueRepository }: InjectedDependencies) {
this.productOptionValueRepository_ = productOptionValueRepository
> extends ModulesSdkUtils.abstractServiceFactory<
InjectedDependencies,
{
create: ProductOptionValueServiceTypes.CreateProductOptionValueDTO
update: ProductOptionValueServiceTypes.UpdateProductOptionValueDTO
}
@InjectTransactionManager("productOptionValueRepository_")
async delete(
ids: string[],
@MedusaContext() sharedContext: Context = {}
): Promise<void> {
return await this.productOptionValueRepository_.delete(ids, sharedContext)
}
@InjectTransactionManager("productOptionValueRepository_")
async upsert(
data: (
| ProductOptionValueServiceTypes.UpdateProductOptionValueDTO
| ProductOptionValueServiceTypes.CreateProductOptionValueDTO
)[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
return await this.productOptionValueRepository_.upsert!(data, sharedContext)
>(ProductOptionValue)<TEntity> {
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
}
}

View File

@@ -1,11 +1,7 @@
import { ProductOption } from "@models"
import { Context, DAL, FindConfig, ProductTypes } from "@medusajs/types"
import {
InjectManager,
InjectTransactionManager,
MedusaContext,
ModulesSdkUtils,
} from "@medusajs/utils"
import { InjectManager, MedusaContext, ModulesSdkUtils } from "@medusajs/utils"
import { IProductOptionRepository } from "@types"
type InjectedDependencies = {
productOptionRepository: DAL.RepositoryService
@@ -20,7 +16,7 @@ export default class ProductOptionService<
update: ProductTypes.UpdateProductOptionDTO
}
>(ProductOption)<TEntity> {
protected readonly productOptionRepository_: DAL.RepositoryService<TEntity>
protected readonly productOptionRepository_: IProductOptionRepository<TEntity>
constructor(container: InjectedDependencies) {
super(container)
@@ -65,14 +61,4 @@ export default class ProductOptionService<
return queryOptions
}
@InjectTransactionManager("productOptionRepository_")
async upsert(
data:
| ProductTypes.CreateProductOptionDTO[]
| ProductTypes.UpdateProductOptionDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
return await this.productOptionRepository_.upsert!(data, sharedContext)
}
}

View File

@@ -1,17 +1,7 @@
import { ProductTag } from "@models"
import {
Context,
DAL,
FindConfig,
ProductTypes,
UpsertProductTagDTO,
} from "@medusajs/types"
import {
InjectManager,
InjectTransactionManager,
MedusaContext,
ModulesSdkUtils,
} from "@medusajs/utils"
import { Context, DAL, FindConfig, ProductTypes } from "@medusajs/types"
import { InjectManager, MedusaContext, ModulesSdkUtils } from "@medusajs/utils"
import { IProductTagRepository } from "@types"
type InjectedDependencies = {
productTagRepository: DAL.RepositoryService
@@ -26,7 +16,7 @@ export default class ProductTagService<
update: ProductTypes.UpdateProductTagDTO
}
>(ProductTag)<TEntity> {
protected readonly productTagRepository_: DAL.RepositoryService<TEntity>
protected readonly productTagRepository_: IProductTagRepository<TEntity>
constructor(container: InjectedDependencies) {
super(container)
@@ -70,12 +60,4 @@ export default class ProductTagService<
return queryOptions
}
@InjectTransactionManager("productTagRepository_")
async upsert(
data: UpsertProductTagDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
return await this.productTagRepository_.upsert!(data, sharedContext)
}
}

View File

@@ -1,17 +1,7 @@
import { ProductType } from "@models"
import {
Context,
DAL,
FindConfig,
ProductTypes,
UpsertProductTypeDTO,
} from "@medusajs/types"
import {
InjectManager,
InjectTransactionManager,
MedusaContext,
ModulesSdkUtils,
} from "@medusajs/utils"
import { Context, DAL, FindConfig, ProductTypes } from "@medusajs/types"
import { InjectManager, MedusaContext, ModulesSdkUtils } from "@medusajs/utils"
import { IProductTypeRepository } from "@types"
type InjectedDependencies = {
productTypeRepository: DAL.RepositoryService
@@ -26,7 +16,7 @@ export default class ProductTypeService<
update: ProductTypes.UpdateProductTypeDTO
}
>(ProductType)<TEntity> {
protected readonly productTypeRepository_: DAL.RepositoryService<TEntity>
protected readonly productTypeRepository_: IProductTypeRepository<TEntity>
constructor(container: InjectedDependencies) {
super(container)
@@ -71,12 +61,4 @@ export default class ProductTypeService<
return queryOptions
}
@InjectTransactionManager("productTypeRepository_")
async upsert(
types: UpsertProductTypeDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
return await this.productTypeRepository_.upsert!(types, sharedContext)
}
}

View File

@@ -7,7 +7,7 @@ import {
} from "@medusajs/utils"
import { Product, ProductVariant } from "@models"
import { ProductVariantServiceTypes } from "@types"
import { IProductVariantRepository, ProductVariantServiceTypes } from "@types"
import ProductService from "./product"
type InjectedDependencies = {
@@ -25,7 +25,7 @@ export default class ProductVariantService<
update: ProductVariantServiceTypes.UpdateProductVariantDTO
}
>(ProductVariant)<TEntity> {
protected readonly productVariantRepository_: DAL.RepositoryService<TEntity>
protected readonly productVariantRepository_: IProductVariantRepository<TEntity>
protected readonly productService_: ProductService<TProduct>
constructor({

View File

@@ -1,7 +1,7 @@
import { Context, DAL, FindConfig, ProductTypes } from "@medusajs/types"
import { InjectManager, MedusaContext, ModulesSdkUtils } from "@medusajs/utils"
import { Product } from "@models"
import { ProductServiceTypes } from "@types"
import { IProductRepository, ProductServiceTypes } from "@types"
type InjectedDependencies = {
productRepository: DAL.RepositoryService
@@ -16,7 +16,7 @@ export default class ProductService<
update: ProductServiceTypes.UpdateProductDTO
}
>(Product)<TEntity> {
protected readonly productRepository_: DAL.RepositoryService<TEntity>
protected readonly productRepository_: IProductRepository<TEntity>
constructor({ productRepository }: InjectedDependencies) {
// @ts-ignore

View File

@@ -1,5 +1,3 @@
export * from "./services"
import { IEventBusModuleService, Logger } from "@medusajs/types"
export type InitializeModuleInjectableDependencies = {
@@ -8,3 +6,4 @@ export type InitializeModuleInjectableDependencies = {
}
export * from "./services"
export * from "./repositories"

View File

@@ -0,0 +1,100 @@
import { DAL, ProductTypes, WithRequiredProperty } from "@medusajs/types"
import {
Image,
Product,
ProductCollection,
ProductOption,
ProductOptionValue,
ProductTag,
ProductType,
ProductVariant,
} from "@models"
import { UpdateProductDTO } from "./services/product"
import {
CreateProductCollection,
UpdateProductCollection,
} from "./services/product-collection"
import {
CreateProductOptionValueDTO,
UpdateProductOptionValueDTO,
} from "./services/product-option-value"
import { UpdateProductVariantDTO } from "./services/product-variant"
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IProductRepository<TEntity extends Product = Product>
extends DAL.RepositoryService<
TEntity,
{
create: WithRequiredProperty<ProductTypes.CreateProductOnlyDTO, "status">
update: WithRequiredProperty<UpdateProductDTO, "id">
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IProductCollectionRepository<
TEntity extends ProductCollection = ProductCollection
> extends DAL.RepositoryService<
TEntity,
{
create: CreateProductCollection
update: UpdateProductCollection
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IProductImageRepository<TEntity extends Image = Image>
extends DAL.RepositoryService<TEntity> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IProductOptionRepository<
TEntity extends ProductOption = ProductOption
> extends DAL.RepositoryService<
TEntity,
{
create: ProductTypes.CreateProductOptionDTO
update: ProductTypes.UpdateProductOptionDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IProductOptionValueRepository<
TEntity extends ProductOptionValue = ProductOptionValue
> extends DAL.RepositoryService<
TEntity,
{
create: CreateProductOptionValueDTO
update: UpdateProductOptionValueDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IProductTagRepository<TEntity extends ProductTag = ProductTag>
extends DAL.RepositoryService<
TEntity,
{
create: ProductTypes.CreateProductTagDTO
update: ProductTypes.UpdateProductTagDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IProductTypeRepository<
TEntity extends ProductType = ProductType
> extends DAL.RepositoryService<
TEntity,
{
create: ProductTypes.CreateProductTypeDTO
update: ProductTypes.UpdateProductTypeDTO
}
> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IProductVariantRepository<
TEntity extends ProductVariant = ProductVariant
> extends DAL.RepositoryService<
TEntity,
{
create: ProductTypes.CreateProductVariantOnlyDTO
update: UpdateProductVariantDTO
}
> {}

View File

@@ -1,3 +1,5 @@
import { ProductTypes } from "@medusajs/types"
export type ProductCollectionEventData = {
id: string
}
@@ -7,3 +9,13 @@ export enum ProductCollectionEvents {
COLLECTION_CREATED = "product-collection.created",
COLLECTION_DELETED = "product-collection.deleted",
}
export type UpdateProductCollection =
ProductTypes.UpdateProductCollectionDTO & {
products?: string[]
}
export type CreateProductCollection =
ProductTypes.CreateProductCollectionDTO & {
products?: string[]
}

View File

@@ -1,9 +1,10 @@
import { PromotionType } from "@medusajs/utils"
import { createMedusaContainer, PromotionType } from "@medusajs/utils"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { PromotionRepository } from "@repositories"
import { PromotionService } from "@services"
import { createPromotions } from "../../../__fixtures__/promotion"
import { MikroOrmWrapper } from "../../../utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -17,13 +18,12 @@ describe("Promotion Service", () => {
repositoryManager = await MikroOrmWrapper.forkManager()
testManager = await MikroOrmWrapper.forkManager()
const promotionRepository = new PromotionRepository({
manager: repositoryManager,
})
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
service = new PromotionService({
promotionRepository: promotionRepository,
})
await ContainerLoader({ container })
service = container.resolve("promotionService")
await createPromotions(testManager)
})

View File

@@ -11,8 +11,6 @@
"node": ">=16"
},
"bin": {
"medusa-promotion-migrations-down": "dist/scripts/bin/run-migration-down.js",
"medusa-promotion-migrations-up": "dist/scripts/bin/run-migration-up.js",
"medusa-promotion-seed": "dist/scripts/bin/run-seed.js"
},
"repository": {

Some files were not shown because too many files have changed in this diff Show More