import assert from "node:assert/strict" import path from "node:path" import test from "node:test" import { buildNexeArgs, createConfiguredEntrypointSource, getStagedModuleRelativePath, parseBuildArgs, rewriteModuleSpecifiers, toImportSpecifier, } from "../src/build/build-as-tool.js" test("parseBuildArgs extracts config and preserves nexe args", () => { const cwd = "/tmp/rhedyn-project" const { configPath, forwardedArgs, outputName } = parseBuildArgs( [ "--config", "./site/rhedyn.config.js", "--target", "linux-x64-20.0.0", "-o", "dist/custom", ], cwd, ) assert.equal(configPath, path.join(cwd, "site/rhedyn.config.js")) assert.equal(outputName, null) assert.deepEqual(forwardedArgs, [ "--target", "linux-x64-20.0.0", "-o", "dist/custom", ]) }) test("parseBuildArgs supports inline --config syntax", () => { const cwd = "/tmp/rhedyn-project" const { configPath, forwardedArgs, outputName } = parseBuildArgs( [ "--config=./rhedyn.config.js", "--python", "python3.12", ], cwd, ) assert.equal(configPath, path.join(cwd, "rhedyn.config.js")) assert.equal(outputName, null) assert.deepEqual(forwardedArgs, ["--python", "python3.12"]) }) test("parseBuildArgs extracts output name without forwarding it to nexe", () => { const { outputName, forwardedArgs } = parseBuildArgs([ "--name", "md2doc", "--target", "linux-x64-22.16.0", ]) assert.equal(outputName, "md2doc") assert.deepEqual(forwardedArgs, [ "--target", "linux-x64-22.16.0", ]) }) test("parseBuildArgs supports inline --name syntax", () => { const { outputName, forwardedArgs } = parseBuildArgs([ "--name=md2doc", "--python", "python3.12", ]) assert.equal(outputName, "md2doc") assert.deepEqual(forwardedArgs, ["--python", "python3.12"]) }) test("toImportSpecifier prefixes sibling paths", () => { assert.equal( toImportSpecifier("/tmp/build-entry", "/tmp/build-entry/entry.js"), "./entry.js", ) }) test("createConfiguredEntrypointSource loads config and runner with relative literal imports", () => { const entryDir = "/tmp/build-entry" const stagedConfigPath = "/tmp/build-entry/modules/_root/tmp/project/config/rhedyn.config.mjs" const stagedRunnerPath = "/tmp/build-entry/modules/_root/home/me/rhedyn/src/run.mjs" const source = createConfiguredEntrypointSource({ entryDir, stagedConfigPath, stagedRunnerPath, }) assert.match(source, /const configModule = await import\("\.\/modules\/_root\/tmp\/project\/config\/rhedyn\.config\.mjs"\)/) assert.match(source, /const \{ runWithConfig \} = await import\("\.\/modules\/_root\/home\/me\/rhedyn\/src\/run\.mjs"\)/) assert.match(source, /const config = configModule\.default \|\| configModule/) assert.match(source, /await runWithConfig\(config\)/) }) test("getStagedModuleRelativePath mirrors absolute paths under the staging root", () => { assert.equal( getStagedModuleRelativePath("/tmp/project/config/rhedyn.config.js"), path.join("_root", "tmp/project/config/rhedyn.config.mjs"), ) }) test("rewriteModuleSpecifiers retargets staged local imports and exports", () => { const source = [ "import { smokeAction } from \"./actions/smoke.js\"", "export { helper } from \"../shared/helper.js\"", "const extra = import(\"./dynamic.js\")", ].join("\n") const filePath = "/tmp/project/config/rhedyn.config.js" const currentStagedPath = "/tmp/build/modules/_root/tmp/project/config/rhedyn.config.mjs" const stagedPathsByOriginalPath = new Map([ [ "/tmp/project/config/actions/smoke.js", "/tmp/build/modules/_root/tmp/project/config/actions/smoke.mjs", ], [ "/tmp/project/shared/helper.js", "/tmp/build/modules/_root/tmp/project/shared/helper.mjs", ], [ "/tmp/project/config/dynamic.js", "/tmp/build/modules/_root/tmp/project/config/dynamic.mjs", ], ]) const rewritten = rewriteModuleSpecifiers({ source, filePath, currentStagedPath, fileRecord: { deps: { "./actions/smoke.js": { absPath: "/tmp/project/config/actions/smoke.js" }, "../shared/helper.js": { absPath: "/tmp/project/shared/helper.js" }, "./dynamic.js": { absPath: "/tmp/project/config/dynamic.js" }, }, }, stagedPathsByOriginalPath, }) assert.match(rewritten, /"\.\/actions\/smoke\.mjs"/) assert.match(rewritten, /"\.\.\/shared\/helper\.mjs"/) assert.match(rewritten, /"\.\/dynamic\.mjs"/) }) test("rewriteModuleSpecifiers falls back to local path resolution when dependency metadata is absent", () => { const source = "export * from \"./file-system.js\"\n" const rewritten = rewriteModuleSpecifiers({ source, filePath: "/tmp/project/util/index.js", currentStagedPath: "/tmp/build/modules/_root/tmp/project/util/index.mjs", fileRecord: { deps: {} }, stagedPathsByOriginalPath: new Map([ [ "/tmp/project/util/file-system.js", "/tmp/build/modules/_root/tmp/project/util/file-system.mjs", ], ]), }) assert.match(rewritten, /"\.\/file-system\.mjs"/) }) test("buildNexeArgs injects the entrypoint plugin by default", () => { const args = buildNexeArgs("/tmp/build-entry/entry.js", []) assert.match(args.join(" "), /--plugin .*nexe-entrypoint-compat\.cjs/) }) test("buildNexeArgs uses --name for the default output path", () => { const args = buildNexeArgs("/tmp/build-entry/entry.js", [], "md2doc") const outputIndex = args.indexOf("-o") assert.equal(args[outputIndex + 1], path.join("/home/leakypixel/code/rhedyn", "dist/md2doc")) }) test("buildNexeArgs ignores --name when an explicit output path is provided", () => { const args = buildNexeArgs("/tmp/build-entry/entry.js", ["-o", "dist/custom"], "md2doc") const outputIndex = args.indexOf("-o") assert.equal(args[outputIndex + 1], "dist/custom") })