-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: generate modules mappings at runtime (#10791)
- Loading branch information
1 parent
5e9d86d
commit ecc09fd
Showing
9 changed files
with
220 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
--- | ||
"@medusajs/medusa": patch | ||
"@medusajs/modules-sdk": patch | ||
"@medusajs/types": patch | ||
"@medusajs/utils": patch | ||
--- | ||
|
||
feat: generate modules mappings at runtime |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
81 changes: 81 additions & 0 deletions
81
packages/core/utils/src/modules-sdk/__tests__/modules-to-container-types.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import { join } from "path" | ||
import { FileSystem } from "../../common" | ||
import { generateContainerTypes } from "../modules-to-container-types" | ||
|
||
const fileSystem = new FileSystem(join(__dirname, "./tmp")) | ||
|
||
afterEach(async () => { | ||
await fileSystem.cleanup() | ||
}) | ||
|
||
describe("generateContainerTypes", function () { | ||
it("should create file with types for provided modules", async function () { | ||
await generateContainerTypes( | ||
{ | ||
cache: { | ||
__definition: { | ||
key: "cache", | ||
label: "Cache", | ||
defaultPackage: "@medusajs/foo", | ||
resolvePath: "@medusajs/foo", | ||
defaultModuleDeclaration: { | ||
scope: "internal", | ||
}, | ||
}, | ||
__joinerConfig: {}, | ||
}, | ||
}, | ||
{ | ||
outputDir: fileSystem.basePath, | ||
interfaceName: "ModulesImplementations", | ||
} | ||
) | ||
|
||
expect(await fileSystem.exists("modules-bindings.d.ts")).toBeTruthy() | ||
expect(await fileSystem.contents("modules-bindings.d.ts")) | ||
.toMatchInlineSnapshot(` | ||
"import type Cache from '@medusajs/foo' | ||
declare module '@medusajs/framework/types' { | ||
interface ModulesImplementations { | ||
cache: InstanceType<(typeof Cache)['service']> | ||
} | ||
}" | ||
`) | ||
}) | ||
|
||
it("should normalize module path pointing to a relative file", async function () { | ||
await generateContainerTypes( | ||
{ | ||
cache: { | ||
__definition: { | ||
key: "cache", | ||
label: "Cache", | ||
defaultPackage: "./foo/bar", | ||
resolvePath: "./foo/bar", | ||
defaultModuleDeclaration: { | ||
scope: "internal", | ||
}, | ||
}, | ||
__joinerConfig: {}, | ||
}, | ||
}, | ||
{ | ||
outputDir: fileSystem.basePath, | ||
interfaceName: "ModulesImplementations", | ||
} | ||
) | ||
|
||
expect(await fileSystem.exists("modules-bindings.d.ts")).toBeTruthy() | ||
expect(await fileSystem.contents("modules-bindings.d.ts")) | ||
.toMatchInlineSnapshot(` | ||
"import type Cache from '../../foo/bar' | ||
declare module '@medusajs/framework/types' { | ||
interface ModulesImplementations { | ||
cache: InstanceType<(typeof Cache)['service']> | ||
} | ||
}" | ||
`) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
99 changes: 99 additions & 0 deletions
99
packages/core/utils/src/modules-sdk/modules-to-container-types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import { join } from "path" | ||
import type { LoadedModule } from "@medusajs/types" | ||
import { FileSystem } from "../common/file-system" | ||
import { toCamelCase } from "../common/to-camel-case" | ||
import { upperCaseFirst } from "../common/upper-case-first" | ||
|
||
/** | ||
* Modules registered inside the config file points to one | ||
* of the following paths. | ||
* | ||
* - A package name | ||
* - A relative application import | ||
* - Or an absolute path using `require.resolve` | ||
* | ||
* In case of a relative import, we mutate the path to resolve properly | ||
* when the output file is inside the ".medusa/types" directory. | ||
* For example: | ||
* | ||
* => "./src/modules/brand" will become "../../src/modules/brand" | ||
* | ||
* Package names and absolute paths are left as it is. | ||
*/ | ||
function normalizeModuleResolvePath(modulePath: string) { | ||
return modulePath.startsWith("./") || modulePath.startsWith("../") | ||
? join("../", "../", modulePath) | ||
: modulePath | ||
} | ||
|
||
/** | ||
* Creates the "modules-bindings.d.ts" file with container mappings | ||
* for the modules enabled inside a user's project. | ||
*/ | ||
export async function generateContainerTypes( | ||
modules: Record<string, LoadedModule | LoadedModule[]>, | ||
{ | ||
outputDir, | ||
interfaceName, | ||
}: { | ||
outputDir: string | ||
interfaceName: string | ||
} | ||
) { | ||
const { imports, mappings } = Object.keys(modules).reduce( | ||
(result, key) => { | ||
const services = Array.isArray(modules[key]) | ||
? modules[key] | ||
: [modules[key]] | ||
|
||
services.forEach((service) => { | ||
if (!service.__definition.resolvePath) { | ||
return | ||
} | ||
|
||
/** | ||
* Key registered within the container | ||
*/ | ||
const key = service.__definition.key | ||
|
||
/** | ||
* @todo. The property should exist on "LoadedModule" | ||
*/ | ||
let servicePath: string = normalizeModuleResolvePath( | ||
service.__definition.resolvePath | ||
) | ||
|
||
/** | ||
* We create the service name (aka default import name) from the | ||
* service key that is registered inside the container. | ||
*/ | ||
const serviceName = upperCaseFirst(toCamelCase(key)) | ||
|
||
result.imports.push(`import type ${serviceName} from '${servicePath}'`) | ||
result.mappings.push( | ||
`${key}: InstanceType<(typeof ${serviceName})['service']>` | ||
) | ||
}) | ||
return result | ||
}, | ||
{ | ||
imports: [], | ||
mappings: [], | ||
} as { | ||
imports: string[] | ||
mappings: string[] | ||
} | ||
) | ||
|
||
const fileSystem = new FileSystem(outputDir) | ||
const fileName = "modules-bindings.d.ts" | ||
const fileContents = `${imports.join( | ||
"\n" | ||
)}\n\ndeclare module '@medusajs/framework/types' { | ||
interface ${interfaceName} { | ||
${mappings.join(",\n ")} | ||
} | ||
}` | ||
|
||
await fileSystem.create(fileName, fileContents) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters