diff --git a/.changeset/seven-cooks-drop.md b/.changeset/seven-cooks-drop.md new file mode 100644 index 0000000000000..77cb50af056cc --- /dev/null +++ b/.changeset/seven-cooks-drop.md @@ -0,0 +1,6 @@ +--- +"@medusajs/medusa": patch +"@medusajs/framework": patch +--- + +fix: Flaky behavior of Yalc diff --git a/packages/core/framework/src/build-tools/compiler.ts b/packages/core/framework/src/build-tools/compiler.ts index fe1d254f328fe..a0f821eb204bb 100644 --- a/packages/core/framework/src/build-tools/compiler.ts +++ b/packages/core/framework/src/build-tools/compiler.ts @@ -1,7 +1,7 @@ import path from "path" import { getConfigFile } from "@medusajs/utils" import type { AdminOptions, ConfigModule, Logger } from "@medusajs/types" -import { rm, access, constants, copyFile, writeFile } from "fs/promises" +import { rm, access, constants, copyFile, writeFile, mkdir } from "fs/promises" import type tsStatic from "typescript" /** @@ -140,6 +140,16 @@ export class Compiler { await rm(path, { recursive: true }).catch(() => {}) } + /** + * Ensures a directory exists + */ + async #ensureDir(path: string, clean?: boolean) { + if (clean) { + await this.#clean(path) + } + await mkdir(path, { recursive: true }) + } + /** * Loads the medusa config file and prints the error to * the console (in case of any errors). Otherwise, the @@ -463,6 +473,7 @@ export class Compiler { * a file has changed. */ async developPluginBackend(onFileChange?: () => void) { + await this.#ensureDir(this.#pluginsDistFolder, true) await this.#createPluginOptionsFile() const ts = await this.#loadTSCompiler() diff --git a/packages/medusa/src/commands/plugin/develop.ts b/packages/medusa/src/commands/plugin/develop.ts index 91eb1d1af574b..623d8a64a9d32 100644 --- a/packages/medusa/src/commands/plugin/develop.ts +++ b/packages/medusa/src/commands/plugin/develop.ts @@ -1,4 +1,5 @@ -import * as yalc from "yalc" +import path from "path" +import { execFile } from "child_process" import { logger } from "@medusajs/framework/logger" import { Compiler } from "@medusajs/framework/build-tools" @@ -7,13 +8,43 @@ export default async function developPlugin({ }: { directory: string }) { + let isBusy = false const compiler = new Compiler(directory, logger) + const yalcBin = path.join(path.dirname(require.resolve("yalc")), "yalc.js") + await compiler.developPluginBackend(async () => { - await yalc.publishPackage({ - push: true, - workingDir: directory, - changed: true, - replace: true, - }) + /** + * Here we avoid multiple publish calls when the filesystem is + * changed too quickly. This might result in stale content in + * some edge cases. However, not preventing multiple publishes + * at the same time will result in race conditions and the old + * output might appear in the published package. + */ + if (isBusy) { + return + } + isBusy = true + + /** + * Yalc is meant to be used a binary and not as a long-lived + * module import. Therefore we will have to execute it like + * a command to get desired outcome. Otherwise, yalc behaves + * flaky. + */ + execFile( + yalcBin, + ["publish", "--push", "--no-scripts"], + { + cwd: directory, + }, + (error, stdout, stderr) => { + isBusy = false + if (error) { + console.log(error) + } + console.log(stdout) + console.error(stderr) + } + ) }) }