feat(medusa): BatchJobStrategy and loaders (#1434)
* add batch job strategy interface * update plugin loaders * remove comment * make map async * ensure that only one of each strategy is registered * register strategies plural * add identifier and batchType properties * extend batch job strategy identification method * initial test * update loaders to accomodate different ways of accessing batch job strategies * identifier batch type field * redo merge in plugins * update interface and load only js files * use switches instead of elif * remove comments * use static properties for strategy registration * update tests * fix unit tests * update test names * update isBatchJobStrategy method * add check for TransactionBaseService in services for plugins * update interfaces export * update batchjob strategy interface with a prepare script * update loaders * update batchjob strategy interface * remove everything but public interface methods from batchJobStrategy * add default implementation to prepareBathJobForProcessing * remove unused import
This commit is contained in:
@@ -11,7 +11,12 @@ const INVALID_REQUEST_ERROR = "invalid_request_error"
|
||||
const INVALID_STATE_ERROR = "invalid_state_error"
|
||||
|
||||
export default () => {
|
||||
return (err: MedusaError, req: Request, res: Response, next: NextFunction) => {
|
||||
return (
|
||||
err: MedusaError,
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) => {
|
||||
const logger: Logger = req.scope.resolve("logger")
|
||||
logger.error(err)
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ import {
|
||||
} from "class-validator"
|
||||
import PriceListService from "../../../../services/price-list"
|
||||
import {
|
||||
AdminPriceListPricesCreateReq, CreatePriceListInput,
|
||||
AdminPriceListPricesCreateReq,
|
||||
CreatePriceListInput,
|
||||
PriceListStatus,
|
||||
PriceListType,
|
||||
} from "../../../../types/price-list"
|
||||
|
||||
56
packages/medusa/src/interfaces/batch-job-strategy.ts
Normal file
56
packages/medusa/src/interfaces/batch-job-strategy.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { TransactionBaseService } from "./transaction-base-service"
|
||||
|
||||
export interface IBatchJobStrategy<T extends TransactionBaseService<any>>
|
||||
extends TransactionBaseService<T> {
|
||||
/**
|
||||
* Method for preparing a batch job for processing
|
||||
*/
|
||||
prepareBatchJobForProcessing(
|
||||
batchJobEntity: object,
|
||||
req: Express.Request
|
||||
): Promise<object>
|
||||
|
||||
/**
|
||||
* Method for pre-processing a batch job
|
||||
*/
|
||||
preProcessBatchJob(batchJobId: string): Promise<void>
|
||||
|
||||
/**
|
||||
* Method does the actual processing of the job. Should report back on the progress of the operation.
|
||||
*/
|
||||
processJob(batchJobId: string): Promise<void>
|
||||
|
||||
/**
|
||||
* Builds and returns a template file that can be downloaded and filled in
|
||||
*/
|
||||
buildTemplate()
|
||||
}
|
||||
|
||||
export abstract class AbstractBatchJobStrategy<
|
||||
T extends TransactionBaseService<any>
|
||||
>
|
||||
extends TransactionBaseService<T>
|
||||
implements IBatchJobStrategy<T>
|
||||
{
|
||||
static identifier: string
|
||||
static batchType: string
|
||||
|
||||
async prepareBatchJobForProcessing(
|
||||
batchJob: object,
|
||||
req: Express.Request
|
||||
): Promise<object> {
|
||||
return batchJob
|
||||
}
|
||||
|
||||
public abstract preProcessBatchJob(batchJobId: string): Promise<void>
|
||||
|
||||
public abstract processJob(batchJobId: string): Promise<void>
|
||||
|
||||
public abstract buildTemplate(): Promise<string>
|
||||
}
|
||||
|
||||
export function isBatchJobStrategy(
|
||||
object: unknown
|
||||
): object is IBatchJobStrategy<any> {
|
||||
return object instanceof AbstractBatchJobStrategy
|
||||
}
|
||||
@@ -2,6 +2,7 @@ export * from "./tax-calculation-strategy"
|
||||
export * from "./cart-completion-strategy"
|
||||
export * from "./tax-service"
|
||||
export * from "./transaction-base-service"
|
||||
export * from "./batch-job-strategy"
|
||||
export * from "./file-service"
|
||||
export * from "./models/base-entity"
|
||||
export * from "./models/soft-deletable-entity"
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
import { createContainer, asValue } from "awilix"
|
||||
import { mkdirSync, rmSync, rmdirSync, writeFileSync } from "fs"
|
||||
import {
|
||||
createContainer,
|
||||
asValue,
|
||||
Resolver,
|
||||
ClassOrFunctionReturning,
|
||||
asFunction,
|
||||
AwilixContainer,
|
||||
} from "awilix"
|
||||
import { mkdirSync, rmSync, writeFileSync } from "fs"
|
||||
import { resolve } from "path"
|
||||
import Logger from "../logger"
|
||||
import { registerServices } from "../plugins"
|
||||
import { registerServices, registerStrategies } from "../plugins"
|
||||
import { MedusaContainer } from "../../types/global"
|
||||
|
||||
const distTestTargetDirectorPath = resolve(__dirname, "__pluginsLoaderTest__")
|
||||
const servicesTestTargetDirectoryPath = resolve(distTestTargetDirectorPath, "services")
|
||||
const buildServiceTemplate = (name: string) => {
|
||||
// ***** TEMPLATES *****
|
||||
const buildServiceTemplate = (name: string): string => {
|
||||
return `
|
||||
import { BaseService } from "medusa-interfaces"
|
||||
export default class ${name}Service extends BaseService {}
|
||||
@@ -15,13 +21,120 @@ const buildServiceTemplate = (name: string) => {
|
||||
}
|
||||
const buildTransactionBaseServiceServiceTemplate = (name: string) => {
|
||||
return `
|
||||
import { TransactionBaseService } from "${resolve(__dirname, "../../interfaces")}"
|
||||
import { TransactionBaseService } from "${resolve(
|
||||
__dirname,
|
||||
"../../interfaces"
|
||||
)}"
|
||||
export default class ${name}Service extends TransactionBaseService {}
|
||||
`
|
||||
}
|
||||
|
||||
describe('plugins loader', () => {
|
||||
const buildBatchJobStrategyTemplate = (name: string, type: string): string => {
|
||||
return `
|
||||
import { AbstractBatchJobStrategy } from "../../../../interfaces/batch-job-strategy"
|
||||
|
||||
class ${name}BatchStrategy extends AbstractBatchJobStrategy{
|
||||
static identifier = '${name}-identifier';
|
||||
static batchType = '${type}';
|
||||
|
||||
manager_
|
||||
transactionManager_
|
||||
|
||||
validateContext(context) {
|
||||
throw new Error("Method not implemented.")
|
||||
}
|
||||
processJob(batchJobId) {
|
||||
throw new Error("Method not implemented.")
|
||||
}
|
||||
completeJob(batchJobId) {
|
||||
throw new Error("Method not implemented.")
|
||||
}
|
||||
validateFile(fileLocation) {
|
||||
throw new Error("Method not implemented.")
|
||||
}
|
||||
async buildTemplate() {
|
||||
throw new Error("Method not implemented.")
|
||||
}
|
||||
}
|
||||
|
||||
export default ${name}BatchStrategy
|
||||
`
|
||||
}
|
||||
|
||||
const buildPriceSelectionStrategyTemplate = (name: string): string => {
|
||||
return `
|
||||
import { AbstractPriceSelectionStrategy } from "../../../../interfaces/price-selection-strategy"
|
||||
|
||||
class ${name}PriceSelectionStrategy extends AbstractPriceSelectionStrategy {
|
||||
withTransaction() {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
calculateVariantPrice(variant_id, context) {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
}
|
||||
|
||||
export default ${name}PriceSelectionStrategy
|
||||
`
|
||||
}
|
||||
|
||||
const buildTaxCalcStrategyTemplate = (name: string): string => {
|
||||
return `
|
||||
class ${name}TaxCalculationStrategy {
|
||||
calculate(items, taxLines, calculationContext) {
|
||||
throw new Error("Method not implemented.")
|
||||
}
|
||||
}
|
||||
|
||||
export default ${name}TaxCalculationStrategy
|
||||
`
|
||||
}
|
||||
|
||||
// ***** UTILS *****
|
||||
|
||||
const distTestTargetDirectorPath = resolve(__dirname, "__pluginsLoaderTest__")
|
||||
|
||||
const getFolderTestTargetDirectoryPath = (folderName: string): string => {
|
||||
return resolve(distTestTargetDirectorPath, folderName)
|
||||
}
|
||||
|
||||
function asArray(
|
||||
resolvers: (ClassOrFunctionReturning<unknown> | Resolver<unknown>)[]
|
||||
): { resolve: (container: AwilixContainer) => unknown[] } {
|
||||
return {
|
||||
resolve: (container: AwilixContainer): unknown[] =>
|
||||
resolvers.map((resolver) => container.build(resolver)),
|
||||
}
|
||||
}
|
||||
|
||||
// ***** TESTS *****
|
||||
|
||||
describe("plugins loader", () => {
|
||||
const container = createContainer() as MedusaContainer
|
||||
container.registerAdd = function (
|
||||
this: MedusaContainer,
|
||||
name: string,
|
||||
registration: typeof asFunction | typeof asValue
|
||||
): MedusaContainer {
|
||||
const storeKey = name + "_STORE"
|
||||
|
||||
if (this.registrations[storeKey] === undefined) {
|
||||
this.register(storeKey, asValue([] as Resolver<unknown>[]))
|
||||
}
|
||||
const store = this.resolve(storeKey) as (
|
||||
| ClassOrFunctionReturning<unknown>
|
||||
| Resolver<unknown>
|
||||
)[]
|
||||
|
||||
if (this.registrations[name] === undefined) {
|
||||
this.register(name, asArray(store))
|
||||
}
|
||||
store.unshift(registration)
|
||||
|
||||
return this
|
||||
}.bind(container)
|
||||
|
||||
container.register("logger", asValue(Logger))
|
||||
const pluginsDetails = {
|
||||
resolve: resolve(__dirname, "__pluginsLoaderTest__"),
|
||||
name: `project-plugin`,
|
||||
@@ -29,25 +142,154 @@ describe('plugins loader', () => {
|
||||
options: {},
|
||||
version: '"fakeVersion',
|
||||
}
|
||||
let err
|
||||
|
||||
describe("registerServices", function() {
|
||||
beforeAll(() => {
|
||||
container.register("logger", asValue(Logger))
|
||||
mkdirSync(servicesTestTargetDirectoryPath, { mode: "777", recursive: true })
|
||||
writeFileSync(resolve(servicesTestTargetDirectoryPath, "test.js"), buildServiceTemplate("test"))
|
||||
writeFileSync(resolve(servicesTestTargetDirectoryPath, "test2.js"), buildServiceTemplate("test2"))
|
||||
writeFileSync(resolve(servicesTestTargetDirectoryPath, "test3.js"), buildTransactionBaseServiceServiceTemplate("test3"))
|
||||
writeFileSync(resolve(servicesTestTargetDirectoryPath, "test2.js.map"), "map:file")
|
||||
writeFileSync(resolve(servicesTestTargetDirectoryPath, "test2.d.ts"), "export interface Test {}")
|
||||
afterAll(() => {
|
||||
rmSync(distTestTargetDirectorPath, { recursive: true, force: true })
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
describe("registerStrategies", function () {
|
||||
beforeAll(async () => {
|
||||
mkdirSync(getFolderTestTargetDirectoryPath("strategies"), {
|
||||
mode: "777",
|
||||
recursive: true,
|
||||
})
|
||||
writeFileSync(
|
||||
resolve(
|
||||
getFolderTestTargetDirectoryPath("strategies"),
|
||||
"test-batch-1.js"
|
||||
),
|
||||
buildBatchJobStrategyTemplate("testBatch1", "type-1")
|
||||
)
|
||||
writeFileSync(
|
||||
resolve(
|
||||
getFolderTestTargetDirectoryPath("strategies"),
|
||||
"test-price-selection.js"
|
||||
),
|
||||
buildPriceSelectionStrategyTemplate("test")
|
||||
)
|
||||
writeFileSync(
|
||||
resolve(
|
||||
getFolderTestTargetDirectoryPath("strategies"),
|
||||
"test-batch-2.js"
|
||||
),
|
||||
buildBatchJobStrategyTemplate("testBatch2", "type-1")
|
||||
)
|
||||
writeFileSync(
|
||||
resolve(
|
||||
getFolderTestTargetDirectoryPath("strategies"),
|
||||
"test-batch-3.js"
|
||||
),
|
||||
buildBatchJobStrategyTemplate("testBatch3", "type-2")
|
||||
)
|
||||
writeFileSync(
|
||||
resolve(getFolderTestTargetDirectoryPath("strategies"), "test-tax.js"),
|
||||
buildTaxCalcStrategyTemplate("test")
|
||||
)
|
||||
|
||||
try {
|
||||
await registerStrategies(pluginsDetails, container)
|
||||
} catch (e) {
|
||||
err = e
|
||||
}
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
rmSync(distTestTargetDirectorPath, { recursive: true, force: true })
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should load the services from the services directory but only js files', async () => {
|
||||
let err;
|
||||
it("err should be falsy", () => {
|
||||
expect(err).toBeFalsy()
|
||||
})
|
||||
|
||||
it("registers price selection strategy", () => {
|
||||
const priceSelectionStrategy: (...args: unknown[]) => any =
|
||||
container.resolve("priceSelectionStrategy")
|
||||
|
||||
expect(priceSelectionStrategy).toBeTruthy()
|
||||
expect(priceSelectionStrategy.constructor.name).toBe(
|
||||
"testPriceSelectionStrategy"
|
||||
)
|
||||
})
|
||||
|
||||
it("registers tax calculation strategy", () => {
|
||||
const taxCalculationStrategy: (...args: unknown[]) => any =
|
||||
container.resolve("taxCalculationStrategy")
|
||||
|
||||
expect(taxCalculationStrategy).toBeTruthy()
|
||||
expect(taxCalculationStrategy.constructor.name).toBe(
|
||||
"testTaxCalculationStrategy"
|
||||
)
|
||||
})
|
||||
|
||||
it("registers batch job strategies as single array", () => {
|
||||
const batchJobStrategies: (...args: unknown[]) => any =
|
||||
container.resolve("batchJobStrategies")
|
||||
|
||||
expect(batchJobStrategies).toBeTruthy()
|
||||
expect(Array.isArray(batchJobStrategies)).toBeTruthy()
|
||||
expect(batchJobStrategies.length).toBe(3)
|
||||
})
|
||||
|
||||
it("registers batch job strategies by type and only keep the last", () => {
|
||||
const batchJobStrategy: (...args: unknown[]) => any =
|
||||
container.resolve("batchType_type-1")
|
||||
|
||||
expect(batchJobStrategy).toBeTruthy()
|
||||
expect(batchJobStrategy.constructor.name).toBe("testBatch2BatchStrategy")
|
||||
expect((batchJobStrategy.constructor as any).batchType).toBe("type-1")
|
||||
expect((batchJobStrategy.constructor as any).identifier).toBe(
|
||||
"testBatch2-identifier"
|
||||
)
|
||||
})
|
||||
|
||||
it("registers batch job strategies by identifier", () => {
|
||||
const batchJobStrategy: (...args: unknown[]) => any = container.resolve(
|
||||
"batch_testBatch3-identifier"
|
||||
)
|
||||
|
||||
expect(batchJobStrategy).toBeTruthy()
|
||||
expect(Array.isArray(batchJobStrategy)).toBeFalsy()
|
||||
expect(batchJobStrategy.constructor.name).toBe("testBatch3BatchStrategy")
|
||||
})
|
||||
})
|
||||
|
||||
describe("registerServices", function () {
|
||||
beforeAll(() => {
|
||||
container.register("logger", asValue(Logger))
|
||||
mkdirSync(getFolderTestTargetDirectoryPath("services"), {
|
||||
mode: "777",
|
||||
recursive: true,
|
||||
})
|
||||
writeFileSync(
|
||||
resolve(getFolderTestTargetDirectoryPath("services"), "test.js"),
|
||||
buildServiceTemplate("test")
|
||||
)
|
||||
writeFileSync(
|
||||
resolve(getFolderTestTargetDirectoryPath("services"), "test2.js"),
|
||||
buildServiceTemplate("test2")
|
||||
)
|
||||
writeFileSync(
|
||||
resolve(getFolderTestTargetDirectoryPath("services"), "test3.js"),
|
||||
buildTransactionBaseServiceServiceTemplate("test3")
|
||||
)
|
||||
writeFileSync(
|
||||
resolve(getFolderTestTargetDirectoryPath("services"), "test2.js.map"),
|
||||
"map:file"
|
||||
)
|
||||
writeFileSync(
|
||||
resolve(getFolderTestTargetDirectoryPath("services"), "test2.d.ts"),
|
||||
"export interface Test {}"
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it("should load the services from the services directory but only js files", async () => {
|
||||
let err
|
||||
try {
|
||||
await registerServices(pluginsDetails, container)
|
||||
} catch (e) {
|
||||
@@ -56,9 +298,12 @@ describe('plugins loader', () => {
|
||||
|
||||
expect(err).toBeFalsy()
|
||||
|
||||
const testService: (...args: unknown[]) => any = container.resolve("testService")
|
||||
const test2Service: (...args: unknown[]) => any = container.resolve("test2Service")
|
||||
const test3Service: (...args: unknown[]) => any = container.resolve("test3Service")
|
||||
const testService: (...args: unknown[]) => any =
|
||||
container.resolve("testService")
|
||||
const test2Service: (...args: unknown[]) => any =
|
||||
container.resolve("test2Service")
|
||||
const test3Service: (...args: unknown[]) => any =
|
||||
container.resolve("test3Service")
|
||||
|
||||
expect(testService).toBeTruthy()
|
||||
expect(testService.constructor.name).toBe("testService")
|
||||
@@ -68,4 +313,4 @@ describe('plugins loader', () => {
|
||||
expect(test3Service.constructor.name).toBe("test3Service")
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -30,6 +30,9 @@ import {
|
||||
MedusaContainer,
|
||||
} from "../types/global"
|
||||
import { MiddlewareService } from "../services"
|
||||
import { isBatchJobStrategy } from "../interfaces/batch-job-strategy"
|
||||
import { isPriceSelectionStrategy } from "../interfaces/price-selection-strategy"
|
||||
import logger from "./logger"
|
||||
|
||||
type Options = {
|
||||
rootDirectory: string
|
||||
@@ -63,7 +66,7 @@ export default async ({
|
||||
resolved.map(async (pluginDetails) => {
|
||||
registerRepositories(pluginDetails, container)
|
||||
await registerServices(pluginDetails, container)
|
||||
registerMedusaApi(pluginDetails, container)
|
||||
await registerMedusaApi(pluginDetails, container)
|
||||
registerApi(pluginDetails, app, rootDirectory, container, activityId)
|
||||
registerCoreRouters(pluginDetails, container)
|
||||
registerSubscribers(pluginDetails, container)
|
||||
@@ -144,42 +147,81 @@ async function runLoaders(
|
||||
)
|
||||
}
|
||||
|
||||
function registerMedusaApi(
|
||||
async function registerMedusaApi(
|
||||
pluginDetails: PluginDetails,
|
||||
container: MedusaContainer
|
||||
): void {
|
||||
): Promise<void> {
|
||||
registerMedusaMiddleware(pluginDetails, container)
|
||||
registerStrategies(pluginDetails, container)
|
||||
}
|
||||
|
||||
function registerStrategies(
|
||||
export function registerStrategies(
|
||||
pluginDetails: PluginDetails,
|
||||
container: MedusaContainer
|
||||
): void {
|
||||
let module
|
||||
try {
|
||||
const path = `${pluginDetails.resolve}/strategies/tax-calculation`
|
||||
if (existsSync(path)) {
|
||||
module = require(path).default
|
||||
} else {
|
||||
return
|
||||
}
|
||||
} catch (err) {
|
||||
return
|
||||
}
|
||||
const files = glob.sync(`${pluginDetails.resolve}/strategies/[!__]*.js`, {})
|
||||
const registeredServices = {}
|
||||
|
||||
if (isTaxCalculationStrategy(module.prototype)) {
|
||||
container.register({
|
||||
taxCalculationStrategy: asFunction(
|
||||
(cradle) => new module(cradle, pluginDetails.options)
|
||||
).singleton(),
|
||||
})
|
||||
} else {
|
||||
const logger = container.resolve<Logger>("logger")
|
||||
logger.warn(
|
||||
`${pluginDetails.resolve}/strategies/tax-calculation did not export a class that implements ITaxCalculationStrategy. Your Medusa server will still work, but if you have written custom tax calculation logic it will not be used. Make sure to implement the ITaxCalculationStrategy interface.`
|
||||
)
|
||||
}
|
||||
files.map((file) => {
|
||||
const module = require(file).default
|
||||
|
||||
switch (true) {
|
||||
case isTaxCalculationStrategy(module.prototype): {
|
||||
if (!("taxCalculationStrategy" in registeredServices)) {
|
||||
container.register({
|
||||
taxCalculationStrategy: asFunction(
|
||||
(cradle) => new module(cradle, pluginDetails.options)
|
||||
).singleton(),
|
||||
})
|
||||
registeredServices["taxCalculationStrategy"] = file
|
||||
} else {
|
||||
logger.warn(
|
||||
`Cannot register ${file}. A tax calculation strategy is already registered`
|
||||
)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
case isBatchJobStrategy(module.prototype): {
|
||||
container.registerAdd(
|
||||
"batchJobStrategies",
|
||||
asFunction((cradle) => new module(cradle, pluginDetails.options))
|
||||
)
|
||||
|
||||
const name = formatRegistrationName(file)
|
||||
container.register({
|
||||
[name]: asFunction(
|
||||
(cradle) => new module(cradle, pluginDetails.options)
|
||||
).singleton(),
|
||||
[`batch_${module.identifier}`]: aliasTo(name),
|
||||
[`batchType_${module.batchType}`]: aliasTo(name),
|
||||
})
|
||||
break
|
||||
}
|
||||
|
||||
case isPriceSelectionStrategy(module.prototype): {
|
||||
if (!("priceSelectionStrategy" in registeredServices)) {
|
||||
container.register({
|
||||
priceSelectionStrategy: asFunction(
|
||||
(cradle) => new module(cradle, pluginDetails.options)
|
||||
).singleton(),
|
||||
})
|
||||
|
||||
registeredServices["priceSelectionStrategy"] = file
|
||||
} else {
|
||||
logger.warn(
|
||||
`Cannot register ${file}. A price selection strategy is already registered`
|
||||
)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
default:
|
||||
logger.warn(
|
||||
`${file} did not export a class that implements a strategy interface. Your Medusa server will still work, but if you have written custom strategy logic it will not be used. Make sure to implement the proper interface.`
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function registerMedusaMiddleware(
|
||||
@@ -362,16 +404,10 @@ export async function registerServices(
|
||||
).singleton(),
|
||||
[`noti_${loaded.identifier}`]: aliasTo(name),
|
||||
})
|
||||
} else if (loaded.prototype instanceof FileService) {
|
||||
// Add the service directly to the container in order to make simple
|
||||
// resolution if we already know which file storage provider we need to use
|
||||
container.register({
|
||||
[name]: asFunction(
|
||||
(cradle) => new loaded(cradle, pluginDetails.options)
|
||||
),
|
||||
[`fileService`]: aliasTo(name),
|
||||
})
|
||||
} else if (isFileService(loaded.prototype)) {
|
||||
} else if (
|
||||
loaded.prototype instanceof FileService ||
|
||||
isFileService(loaded.prototype)
|
||||
) {
|
||||
// Add the service directly to the container in order to make simple
|
||||
// resolution if we already know which file storage provider we need to use
|
||||
container.register({
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import glob from "glob"
|
||||
import path from "path"
|
||||
import { AwilixContainer, asFunction } from "awilix"
|
||||
import { AwilixContainer, asFunction, aliasTo } from "awilix"
|
||||
|
||||
import formatRegistrationName from "../utils/format-registration-name"
|
||||
import { isBatchJobStrategy } from "../interfaces"
|
||||
import { MedusaContainer } from "../types/global"
|
||||
|
||||
type LoaderOptions = {
|
||||
container: AwilixContainer
|
||||
container: MedusaContainer
|
||||
configModule: object
|
||||
isTest?: boolean
|
||||
}
|
||||
@@ -19,19 +21,40 @@ export default ({ container, configModule, isTest }: LoaderOptions): void => {
|
||||
typeof isTest !== "undefined" ? isTest : process.env.NODE_ENV === "test"
|
||||
|
||||
const corePath = useMock
|
||||
? "../strategies/__mocks__/*.js"
|
||||
: "../strategies/*.js"
|
||||
? "../strategies/__mocks__/[!__]*.js"
|
||||
: "../strategies/**/[!__]*.js"
|
||||
|
||||
const coreFull = path.join(__dirname, corePath)
|
||||
|
||||
const core = glob.sync(coreFull, { cwd: __dirname })
|
||||
const core = glob.sync(coreFull, {
|
||||
cwd: __dirname,
|
||||
ignore: ["**/__fixtures__/**", "index.js", "index.ts"],
|
||||
})
|
||||
|
||||
core.forEach((fn) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const loaded = require(fn).default
|
||||
const name = formatRegistrationName(fn)
|
||||
container.register({
|
||||
[name]: asFunction(
|
||||
(cradle) => new loaded(cradle, configModule)
|
||||
).singleton(),
|
||||
})
|
||||
|
||||
if (isBatchJobStrategy(loaded.prototype)) {
|
||||
container.registerAdd(
|
||||
"batchJobStrategies",
|
||||
asFunction((cradle) => new loaded(cradle, configModule))
|
||||
)
|
||||
|
||||
container.register({
|
||||
[name]: asFunction(
|
||||
(cradle) => new loaded(cradle, configModule)
|
||||
).singleton(),
|
||||
[`batch_${loaded.identifier}`]: aliasTo(name),
|
||||
[`batchType_${loaded.batchType}`]: aliasTo(name),
|
||||
})
|
||||
} else {
|
||||
container.register({
|
||||
[name]: asFunction(
|
||||
(cradle) => new loaded(cradle, configModule)
|
||||
).singleton(),
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -15,7 +15,12 @@ import { CartRepository } from "../repositories/cart"
|
||||
import { LineItemRepository } from "../repositories/line-item"
|
||||
import { PaymentSessionRepository } from "../repositories/payment-session"
|
||||
import { ShippingMethodRepository } from "../repositories/shipping-method"
|
||||
import { CartCreateProps, CartUpdateProps, FilterableCartProps, LineItemUpdate } from "../types/cart"
|
||||
import {
|
||||
CartCreateProps,
|
||||
CartUpdateProps,
|
||||
FilterableCartProps,
|
||||
LineItemUpdate,
|
||||
} from "../types/cart"
|
||||
import { AddressPayload, FindConfig, TotalField } from "../types/common"
|
||||
import { buildQuery, setMetadata, validateId } from "../utils"
|
||||
import CustomShippingOptionService from "./custom-shipping-option"
|
||||
|
||||
Reference in New Issue
Block a user