chore(framework): Move and improve links loader (#8367)
**What** Refactor and move links loader FIXES FRMW-2637
This commit is contained in:
committed by
GitHub
parent
8a6e172dec
commit
12c6a1a022
@@ -13,6 +13,7 @@
|
||||
"./logger": "./dist/logger/index.js",
|
||||
"./database": "./dist/database/index.js",
|
||||
"./subscribers": "./dist/subscribers/index.js",
|
||||
"./links": "./dist/links/index.js",
|
||||
"./jobs": "./dist/jobs/index.js"
|
||||
},
|
||||
"engines": {
|
||||
@@ -47,6 +48,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@medusajs/medusa-cli": "^1.3.22",
|
||||
"@medusajs/modules-sdk": "^1.12.11",
|
||||
"@medusajs/utils": "^1.11.9",
|
||||
"@medusajs/workflows-sdk": "^0.1.6",
|
||||
"awilix": "^8.0.0",
|
||||
|
||||
@@ -1,3 +1,36 @@
|
||||
import { createMedusaContainer } from "@medusajs/utils"
|
||||
import { AwilixContainer, ResolveOptions } from "awilix"
|
||||
|
||||
/**
|
||||
* The following interface acts as a bucket that other modules or the
|
||||
* utils package can fill using declaration merging
|
||||
*/
|
||||
export interface ModuleImplementations {}
|
||||
|
||||
/**
|
||||
* The Medusa Container extends [Awilix](https://github.com/jeffijoe/awilix) to
|
||||
* provide dependency injection functionalities.
|
||||
*/
|
||||
export type MedusaContainer<Cradle extends object = ModuleImplementations> =
|
||||
Omit<AwilixContainer, "resolve"> & {
|
||||
resolve<K extends keyof Cradle>(
|
||||
key: K,
|
||||
resolveOptions?: ResolveOptions
|
||||
): Cradle[K]
|
||||
resolve<T>(key: string, resolveOptions?: ResolveOptions): T
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
registerAdd: <T>(name: string, registration: T) => MedusaContainer
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
createScope: () => MedusaContainer
|
||||
}
|
||||
|
||||
export type ContainerLike = {
|
||||
resolve<T = unknown>(key: string): T
|
||||
}
|
||||
|
||||
export const container = createMedusaContainer()
|
||||
|
||||
@@ -10,7 +10,9 @@ export function pgConnectionLoader(): ReturnType<
|
||||
typeof ModulesSdkUtils.createPgConnection
|
||||
> {
|
||||
if (container.hasRegistration(ContainerRegistrationKeys.PG_CONNECTION)) {
|
||||
return container.resolve(ContainerRegistrationKeys.PG_CONNECTION)
|
||||
return container.resolve(
|
||||
ContainerRegistrationKeys.PG_CONNECTION
|
||||
) as unknown as ReturnType<typeof ModulesSdkUtils.createPgConnection>
|
||||
}
|
||||
|
||||
const configModule = configManager.config
|
||||
|
||||
@@ -4,5 +4,6 @@ export * from "./http"
|
||||
export * from "./database"
|
||||
export * from "./container"
|
||||
export * from "./subscribers"
|
||||
export * from "./links"
|
||||
export * from "./jobs"
|
||||
export * from "./feature-flags"
|
||||
|
||||
@@ -8,14 +8,14 @@ export class MockSchedulerStorage implements IDistributedSchedulerStorage {
|
||||
jobDefinition: string | { jobId: string },
|
||||
schedulerOptions: SchedulerOptions
|
||||
): Promise<void> {
|
||||
return Promise.resolve()
|
||||
return await Promise.resolve()
|
||||
}
|
||||
|
||||
async remove(jobId: string): Promise<void> {
|
||||
return Promise.resolve()
|
||||
return await Promise.resolve()
|
||||
}
|
||||
|
||||
async removeAll(): Promise<void> {
|
||||
return Promise.resolve()
|
||||
return await Promise.resolve()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { defineLink, MedusaService, model, Module } from "@medusajs/utils"
|
||||
|
||||
const model1 = model.define("model-1", {
|
||||
id: model.id().primaryKey(),
|
||||
})
|
||||
|
||||
const model2 = model.define("model-2", {
|
||||
id: model.id().primaryKey(),
|
||||
})
|
||||
|
||||
const module1 = Module("module-1", {
|
||||
service: class Service1 extends MedusaService({ model1 }) {},
|
||||
})
|
||||
|
||||
const module2 = Module("module-2", {
|
||||
service: class Service2 extends MedusaService({ model2 }) {},
|
||||
})
|
||||
|
||||
export const module1And2Link = defineLink(
|
||||
module1.linkable.model1,
|
||||
module2.linkable.model2
|
||||
)
|
||||
@@ -0,0 +1,22 @@
|
||||
import { defineLink, MedusaService, model, Module } from "@medusajs/utils"
|
||||
|
||||
const model3 = model.define("model-3", {
|
||||
id: model.id().primaryKey(),
|
||||
})
|
||||
|
||||
const model4 = model.define("model-4", {
|
||||
id: model.id().primaryKey(),
|
||||
})
|
||||
|
||||
const module3 = Module("module-3", {
|
||||
service: class Service3 extends MedusaService({ model3 }) {},
|
||||
})
|
||||
|
||||
const module4 = Module("module-4", {
|
||||
service: class Service4 extends MedusaService({ model4 }) {},
|
||||
})
|
||||
|
||||
export const module3And4Link = defineLink(
|
||||
module3.linkable.model3,
|
||||
module4.linkable.model4
|
||||
)
|
||||
@@ -0,0 +1,19 @@
|
||||
import { join } from "path"
|
||||
import { LinkLoader } from "../link-loader"
|
||||
import { MedusaModule } from "@medusajs/modules-sdk"
|
||||
|
||||
describe("LinkLoader", () => {
|
||||
const rootDir = join(__dirname, "../__fixtures__", "links")
|
||||
|
||||
it("should register each link in the '/links' folder and sub folder", async () => {
|
||||
let links = MedusaModule.getCustomLinks()
|
||||
|
||||
expect(links.length).toBe(0)
|
||||
|
||||
await new LinkLoader(rootDir).load()
|
||||
|
||||
links = MedusaModule.getCustomLinks()
|
||||
|
||||
expect(links.length).toBe(2)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./link-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 LinkLoader {
|
||||
/**
|
||||
* The directory from which to load the links
|
||||
* @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 links from the source paths, links 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 links 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(`Links registered.`)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user