chore(framework): Move and improve workflows loader (#8363)
**What** Refactoring Workflows loader and move FIXES FRMW-2627
This commit is contained in:
1 parent
22a629670b
commit
56602d215b
15 files changed
+192
-42
No files matched your search
@@ -13,6 +13,7 @@
|
|||||||
"./logger": "./dist/logger/index.js",
|
"./logger": "./dist/logger/index.js",
|
||||||
"./database": "./dist/database/index.js",
|
"./database": "./dist/database/index.js",
|
||||||
"./subscribers": "./dist/subscribers/index.js",
|
"./subscribers": "./dist/subscribers/index.js",
|
||||||
|
"./workflows": "./dist/workflows/index.js",
|
||||||
"./links": "./dist/links/index.js",
|
"./links": "./dist/links/index.js",
|
||||||
"./jobs": "./dist/jobs/index.js"
|
"./jobs": "./dist/jobs/index.js"
|
||||||
},
|
},
|
||||||
@@ -49,6 +50,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@medusajs/medusa-cli": "^1.3.22",
|
"@medusajs/medusa-cli": "^1.3.22",
|
||||||
"@medusajs/modules-sdk": "^1.12.11",
|
"@medusajs/modules-sdk": "^1.12.11",
|
||||||
|
"@medusajs/orchestration": "^0.5.7",
|
||||||
"@medusajs/utils": "^1.11.9",
|
"@medusajs/utils": "^1.11.9",
|
||||||
"@medusajs/workflows-sdk": "^0.1.6",
|
"@medusajs/workflows-sdk": "^0.1.6",
|
||||||
"awilix": "^8.0.0",
|
"awilix": "^8.0.0",
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { defineConfig } from "@medusajs/utils"
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
projectConfig: {
|
||||||
|
databaseName: "foo",
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { defineConfig } from "@medusajs/utils"
|
||||||
|
|
||||||
|
export default defineConfig()
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import { configLoader } from "../loader"
|
||||||
|
import { join } from "path"
|
||||||
|
import { container } from "../../container"
|
||||||
|
import { ContainerRegistrationKeys } from "@medusajs/utils"
|
||||||
|
|
||||||
|
describe("configLoader", () => {
|
||||||
|
const entryDirectory = join(__dirname, "../__fixtures__")
|
||||||
|
|
||||||
|
it("should load the config properly", async () => {
|
||||||
|
let configModule = container.resolve(
|
||||||
|
ContainerRegistrationKeys.CONFIG_MODULE
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(configModule).toBeUndefined()
|
||||||
|
|
||||||
|
configLoader(entryDirectory, "medusa-config.js")
|
||||||
|
|
||||||
|
configModule = container.resolve(ContainerRegistrationKeys.CONFIG_MODULE)
|
||||||
|
|
||||||
|
expect(configModule).toBeDefined()
|
||||||
|
expect(configModule.projectConfig.databaseName).toBeUndefined()
|
||||||
|
|
||||||
|
configLoader(entryDirectory, "medusa-config-2.js")
|
||||||
|
|
||||||
|
configModule = container.resolve(ContainerRegistrationKeys.CONFIG_MODULE)
|
||||||
|
|
||||||
|
expect(configModule).toBeDefined()
|
||||||
|
expect(configModule.projectConfig.databaseName).toBe("foo")
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -13,12 +13,11 @@ const handleConfigError = (error: Error): void => {
|
|||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Later on we could store the config manager into the unique container
|
|
||||||
export const configManager = new ConfigManager()
|
export const configManager = new ConfigManager()
|
||||||
|
|
||||||
container.register(
|
container.register(
|
||||||
ContainerRegistrationKeys.CONFIG_MODULE,
|
ContainerRegistrationKeys.CONFIG_MODULE,
|
||||||
asFunction(() => configManager)
|
asFunction(() => configManager.config)
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -7,3 +7,4 @@ export * from "./subscribers"
|
|||||||
export * from "./links"
|
export * from "./links"
|
||||||
export * from "./jobs"
|
export * from "./jobs"
|
||||||
export * from "./feature-flags"
|
export * from "./feature-flags"
|
||||||
|
export * from "./workflows"
|
||||||
@@ -33,6 +33,8 @@ export class SubscriberLoader {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
#excludes: RegExp[] = [
|
#excludes: RegExp[] = [
|
||||||
|
/index\.js/,
|
||||||
|
/index\.ts/,
|
||||||
/\.DS_Store/,
|
/\.DS_Store/,
|
||||||
/(\.ts\.map|\.js\.map|\.d\.ts|\.md)/,
|
/(\.ts\.map|\.js\.map|\.d\.ts|\.md)/,
|
||||||
/^_[^/\\]*(\.[^/\\]+)?$/,
|
/^_[^/\\]*(\.[^/\\]+)?$/,
|
||||||
@@ -129,17 +131,17 @@ export class SubscriberLoader {
|
|||||||
recursive: true,
|
recursive: true,
|
||||||
withFileTypes: true,
|
withFileTypes: true,
|
||||||
}).then(async (entries) => {
|
}).then(async (entries) => {
|
||||||
return entries.flatMap(async (entry) => {
|
const fileEntries = entries.filter((entry) => {
|
||||||
if (this.#excludes.some((exclude) => exclude.test(entry.name))) {
|
return (
|
||||||
return
|
!entry.isDirectory() &&
|
||||||
}
|
!this.#excludes.some((exclude) => exclude.test(entry.name))
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
const fullPath = join(dirPath, entry.name)
|
logger.debug(`Registering subscribers from ${dirPath}.`)
|
||||||
|
|
||||||
if (entry.isDirectory()) {
|
|
||||||
return await this.createMap(fullPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return fileEntries.flatMap(async (entry) => {
|
||||||
|
const fullPath = join(entry.path, entry.name)
|
||||||
return await this.createDescriptor(fullPath)
|
return await this.createDescriptor(fullPath)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -237,6 +239,8 @@ export class SubscriberLoader {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.debug(`Subscribers registered.`)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the file paths of the registered subscribers, to prevent the
|
* Return the file paths of the registered subscribers, to prevent the
|
||||||
* backwards compatible loader from trying to register them.
|
* backwards compatible loader from trying to register them.
|
||||||
|
|||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
import {
|
||||||
|
createStep,
|
||||||
|
createWorkflow,
|
||||||
|
WorkflowResponse,
|
||||||
|
} from "@medusajs/workflows-sdk"
|
||||||
|
|
||||||
|
export const productWorkflowId = "product-notifier-workflow"
|
||||||
|
|
||||||
|
const step = createStep("product-step", () => {
|
||||||
|
return {} as any
|
||||||
|
})
|
||||||
|
|
||||||
|
export const productUpdatedWorkflow = createWorkflow(productWorkflowId, () => {
|
||||||
|
step()
|
||||||
|
return new WorkflowResponse(void 0)
|
||||||
|
})
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import {
|
||||||
|
createStep,
|
||||||
|
createWorkflow,
|
||||||
|
WorkflowResponse,
|
||||||
|
} from "@medusajs/workflows-sdk"
|
||||||
|
|
||||||
|
export const orderWorkflowId = "order-notifier-workflow"
|
||||||
|
|
||||||
|
const step = createStep("order-step", () => {
|
||||||
|
return {} as any
|
||||||
|
})
|
||||||
|
|
||||||
|
export const orderNotifierWorkflow = createWorkflow(orderWorkflowId, () => {
|
||||||
|
step()
|
||||||
|
return new WorkflowResponse(void 0)
|
||||||
|
})
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { join } from "path"
|
||||||
|
import { WorkflowLoader } from "../workflow-loader"
|
||||||
|
import { WorkflowManager } from "@medusajs/orchestration"
|
||||||
|
import { orderWorkflowId } from "../__fixtures__/workflows/order-notifier"
|
||||||
|
import { productWorkflowId } from "../__fixtures__/workflows/deep-workflows/product-updater"
|
||||||
|
|
||||||
|
describe("WorkflowLoader", () => {
|
||||||
|
const rootDir = join(__dirname, "../__fixtures__", "workflows")
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await new WorkflowLoader(rootDir).load()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should register each workflow in the '/workflows' folder and sub folder", async () => {
|
||||||
|
const registeredWorkflows = WorkflowManager.getWorkflows()
|
||||||
|
|
||||||
|
expect(registeredWorkflows.size).toBe(2)
|
||||||
|
expect(registeredWorkflows.has(orderWorkflowId)).toBe(true)
|
||||||
|
expect(registeredWorkflows.has(productWorkflowId)).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from "./workflow-loader"
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import { promiseAll } from "@medusajs/utils"
|
||||||
|
import { logger } from "../logger"
|
||||||
|
import { access, readdir } from "fs/promises"
|
||||||
|
import { join } from "path"
|
||||||
|
|
||||||
|
export class WorkflowLoader {
|
||||||
|
/**
|
||||||
|
* The directory from which to load the workflows
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
#sourceDir: string | string[]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of file names to exclude from the subscriber scan
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
#excludes: RegExp[] = [
|
||||||
|
/index\.js/,
|
||||||
|
/index\.ts/,
|
||||||
|
/\.DS_Store/,
|
||||||
|
/(\.ts\.map|\.js\.map|\.d\.ts|\.md)/,
|
||||||
|
/^_[^/\\]*(\.[^/\\]+)?$/,
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor(sourceDir: string | string[]) {
|
||||||
|
this.#sourceDir = sourceDir
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load workflows from the source paths, workflows are registering themselves,
|
||||||
|
* therefore we only need to import them
|
||||||
|
*/
|
||||||
|
async load() {
|
||||||
|
const normalizedSourcePath = Array.isArray(this.#sourceDir)
|
||||||
|
? this.#sourceDir
|
||||||
|
: [this.#sourceDir]
|
||||||
|
|
||||||
|
const promises = normalizedSourcePath.map(async (sourcePath) => {
|
||||||
|
try {
|
||||||
|
await access(sourcePath)
|
||||||
|
} catch {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return await readdir(sourcePath, {
|
||||||
|
recursive: true,
|
||||||
|
withFileTypes: true,
|
||||||
|
}).then(async (entries) => {
|
||||||
|
const fileEntries = entries.filter((entry) => {
|
||||||
|
return (
|
||||||
|
!entry.isDirectory() &&
|
||||||
|
!this.#excludes.some((exclude) => exclude.test(entry.name))
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
logger.debug(`Registering workflows from ${sourcePath}.`)
|
||||||
|
|
||||||
|
return await promiseAll(
|
||||||
|
fileEntries.map(async (entry) => {
|
||||||
|
const fullPath = join(entry.path, entry.name)
|
||||||
|
return await import(fullPath)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
await promiseAll(promises)
|
||||||
|
|
||||||
|
logger.debug(`Workflows registered.`)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import { glob } from "glob"
|
|
||||||
import { PluginDetails } from "@medusajs/types"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* import files from the workflows directory to run the registration of the wofklows
|
|
||||||
* @param pluginDetails
|
|
||||||
*/
|
|
||||||
export async function registerWorkflows(
|
|
||||||
plugins: PluginDetails[]
|
|
||||||
): Promise<void> {
|
|
||||||
await Promise.all(
|
|
||||||
plugins.map(async (pluginDetails) => {
|
|
||||||
const files = glob.sync(
|
|
||||||
`${pluginDetails.resolve}/workflows/*.{ts,js,mjs,mts}`,
|
|
||||||
{
|
|
||||||
ignore: ["**/*.d.ts", "**/*.map"],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
return Promise.all(files.map(async (file) => import(file)))
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -13,13 +13,13 @@ import {
|
|||||||
container,
|
container,
|
||||||
expressLoader,
|
expressLoader,
|
||||||
featureFlagsLoader,
|
featureFlagsLoader,
|
||||||
LinkLoader,
|
|
||||||
JobLoader,
|
JobLoader,
|
||||||
|
LinkLoader,
|
||||||
logger,
|
logger,
|
||||||
pgConnectionLoader,
|
pgConnectionLoader,
|
||||||
SubscriberLoader,
|
SubscriberLoader,
|
||||||
|
WorkflowLoader,
|
||||||
} from "@medusajs/framework"
|
} from "@medusajs/framework"
|
||||||
import { registerWorkflows } from "./helpers/register-workflows"
|
|
||||||
import { getResolvedPlugins } from "./helpers/resolve-plugins"
|
import { getResolvedPlugins } from "./helpers/resolve-plugins"
|
||||||
import loadMedusaApp from "./medusa-app"
|
import loadMedusaApp from "./medusa-app"
|
||||||
|
|
||||||
@@ -45,6 +45,7 @@ async function subscribersLoader(plugins: PluginDetails[]) {
|
|||||||
*/
|
*/
|
||||||
await new SubscriberLoader(join(__dirname, "../subscribers")).load()
|
await new SubscriberLoader(join(__dirname, "../subscribers")).load()
|
||||||
|
|
||||||
|
// TODO: make it the same as the other loaders, taking an array of paths to load from
|
||||||
/**
|
/**
|
||||||
* Load subscribers from all the plugins.
|
* Load subscribers from all the plugins.
|
||||||
*/
|
*/
|
||||||
@@ -121,15 +122,11 @@ async function loadEntrypoints(
|
|||||||
export async function initializeContainer(
|
export async function initializeContainer(
|
||||||
rootDirectory: string
|
rootDirectory: string
|
||||||
): Promise<MedusaContainer> {
|
): Promise<MedusaContainer> {
|
||||||
const configModule = configLoader(rootDirectory, "medusa-config.js")
|
configLoader(rootDirectory, "medusa-config.js")
|
||||||
const featureFlagRouter = await featureFlagsLoader(
|
await featureFlagsLoader(join(__dirname, "feature-flags"))
|
||||||
join(__dirname, "feature-flags")
|
|
||||||
)
|
|
||||||
|
|
||||||
container.register({
|
container.register({
|
||||||
[ContainerRegistrationKeys.LOGGER]: asValue(logger),
|
[ContainerRegistrationKeys.LOGGER]: asValue(logger),
|
||||||
[ContainerRegistrationKeys.FEATURE_FLAG_ROUTER]: asValue(featureFlagRouter),
|
|
||||||
[ContainerRegistrationKeys.CONFIG_MODULE]: asValue(configModule),
|
|
||||||
[ContainerRegistrationKeys.REMOTE_QUERY]: asValue(null),
|
[ContainerRegistrationKeys.REMOTE_QUERY]: asValue(null),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -164,7 +161,10 @@ export default async ({
|
|||||||
container,
|
container,
|
||||||
})
|
})
|
||||||
|
|
||||||
await registerWorkflows(plugins)
|
const workflowsSourcePaths = plugins.map((p) => join(p.resolve, "workflows"))
|
||||||
|
const workflowLoader = new WorkflowLoader(workflowsSourcePaths)
|
||||||
|
await workflowLoader.load()
|
||||||
|
|
||||||
const entrypointsShutdown = await loadEntrypoints(
|
const entrypointsShutdown = await loadEntrypoints(
|
||||||
plugins,
|
plugins,
|
||||||
container,
|
container,
|
||||||
|
|||||||
@@ -4611,6 +4611,7 @@ __metadata:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@medusajs/medusa-cli": ^1.3.22
|
"@medusajs/medusa-cli": ^1.3.22
|
||||||
"@medusajs/modules-sdk": ^1.12.11
|
"@medusajs/modules-sdk": ^1.12.11
|
||||||
|
"@medusajs/orchestration": ^0.5.7
|
||||||
"@medusajs/types": ^1.11.16
|
"@medusajs/types": ^1.11.16
|
||||||
"@medusajs/utils": ^1.11.9
|
"@medusajs/utils": ^1.11.9
|
||||||
"@medusajs/workflows-sdk": ^0.1.6
|
"@medusajs/workflows-sdk": ^0.1.6
|
||||||
|
|||||||
Reference in new issue
Block a user