feat(): Auto generated types generation upon build (#14337)

* feat(): Auto generated types generation upon build

* Create happy-steaks-cheer.md

* test(): default types true

* improvements

* improvements

* improvements

* improvements

* improvements
This commit is contained in:
Adrien de Peretti
2025-12-19 10:13:17 +01:00
committed by GitHub
parent 125694626e
commit 181d5fa671
5 changed files with 104 additions and 6 deletions

View File

@@ -0,0 +1,8 @@
---
"@medusajs/medusa": patch
"@medusajs/framework": patch
"@medusajs/modules-sdk": patch
"@medusajs/cli": patch
---
feat(): Auto generated types generation upon build

View File

@@ -310,13 +310,18 @@ export class MedusaAppLoader {
* Load all modules and bootstrap all the modules and links to be ready to be consumed
* @param config
*/
async load(config = { registerInContainer: true }): Promise<MedusaAppOutput> {
async load(
config: { registerInContainer?: boolean; migrationOnly?: boolean } = {
registerInContainer: true,
migrationOnly: false,
}
): Promise<MedusaAppOutput> {
const configModule: ConfigModule = this.#container.resolve(
ContainerRegistrationKeys.CONFIG_MODULE
)
const { sharedResourcesConfig, injectedDependencies } =
this.prepareSharedResourcesAndDeps()
!config.migrationOnly ? this.prepareSharedResourcesAndDeps() : {}
this.#container.register(
ContainerRegistrationKeys.REMOTE_QUERY,
@@ -343,6 +348,7 @@ export class MedusaAppLoader {
injectedDependencies,
medusaConfigPath: this.#medusaConfigPath,
cwd: this.#cwd,
migrationOnly: config.migrationOnly,
})
if (!config.registerInContainer) {

View File

@@ -308,6 +308,11 @@ export type MedusaAppOptions = {
* Forces the modules bootstrapper to only run the modules loaders and return prematurely
*/
loaderOnly?: boolean
/**
* Only partially load modules to retrieve their joiner configs without running loaders.
* Useful for type generation and migrations.
*/
migrationOnly?: boolean
cwd?: string
}
@@ -325,9 +330,7 @@ async function MedusaApp_({
loaderOnly = false,
workerMode = "shared",
cwd = process.cwd(),
}: MedusaAppOptions & {
migrationOnly?: boolean
} = {}): Promise<MedusaAppOutput> {
}: MedusaAppOptions = {}): Promise<MedusaAppOutput> {
const sharedContainer_ = createMedusaContainer({}, sharedContainer)
const config = sharedContainer_.resolve(

View File

@@ -1,6 +1,7 @@
import { Compiler } from "@medusajs/framework/build-tools"
import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
import { initializeContainer } from "../loaders"
import { generateTypes } from "./utils/generate-types"
export default async function build({
directory,
@@ -14,6 +15,12 @@ export default async function build({
})
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
await generateTypes({
directory,
container,
logger,
})
logger.info("Starting build...")
const compiler = new Compiler(directory, logger)
@@ -32,7 +39,9 @@ export default async function build({
promises.push(compiler.buildAppFrontend(adminOnly, tsConfig, bundler))
const responses = await Promise.all(promises)
if (responses.every((response) => response === true)) {
const buildSucceeded = responses.every((response) => response === true)
if (buildSucceeded) {
process.exit(0)
} else {
process.exit(1)

View File

@@ -0,0 +1,72 @@
import { LinkLoader, MedusaAppLoader } from "@medusajs/framework"
import { MedusaModule } from "@medusajs/framework/modules-sdk"
import {
ContainerRegistrationKeys,
FileSystem,
generateContainerTypes,
getResolvedPlugins,
gqlSchemaToTypes,
mergePluginModules,
validateModuleName,
} from "@medusajs/framework/utils"
import { Logger, MedusaContainer } from "@medusajs/types"
import path, { join } from "path"
export async function generateTypes({
directory,
container,
logger,
}: {
directory: string
container: MedusaContainer
logger: Logger
}) {
logger.info("Generating types...")
const configModule = container.resolve(
ContainerRegistrationKeys.CONFIG_MODULE
)
const plugins = await getResolvedPlugins(directory, configModule, true)
mergePluginModules(configModule, plugins)
Object.keys(configModule.modules ?? {}).forEach((key) => {
validateModuleName(key)
})
const linksSourcePaths = plugins.map((plugin) =>
join(plugin.resolve, "links")
)
await new LinkLoader(linksSourcePaths, logger).load()
const { gqlSchema, modules } = await new MedusaAppLoader().load({
registerInContainer: false,
migrationOnly: true,
})
const typesDirectory = path.join(directory, ".medusa/types")
/**
* Cleanup existing types directory before creating new artifacts
*/
await new FileSystem(typesDirectory).cleanup({ recursive: true })
await generateContainerTypes(modules, {
outputDir: typesDirectory,
interfaceName: "ModuleImplementations",
})
logger.debug("Generated container types")
if (gqlSchema) {
await gqlSchemaToTypes({
outputDir: typesDirectory,
filename: "query-entry-points",
interfaceName: "RemoteQueryEntryPoints",
schema: gqlSchema,
joinerConfigs: MedusaModule.getAllJoinerConfigs(),
})
logger.debug("Generated modules types")
}
logger.info("Types generated successfully")
}