buildAsTool.test.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. import assert from "node:assert/strict"
  2. import path from "node:path"
  3. import test from "node:test"
  4. import {
  5. buildNexeArgs,
  6. createConfiguredEntrypointSource,
  7. getStagedModuleRelativePath,
  8. parseBuildArgs,
  9. rewriteModuleSpecifiers,
  10. toImportSpecifier,
  11. } from "../src/build/build-as-tool.js"
  12. test("parseBuildArgs extracts config and preserves nexe args", () => {
  13. const cwd = "/tmp/rhedyn-project"
  14. const { configPath, forwardedArgs, outputName } = parseBuildArgs(
  15. [
  16. "--config",
  17. "./site/rhedyn.config.js",
  18. "--target",
  19. "linux-x64-20.0.0",
  20. "-o",
  21. "dist/custom",
  22. ],
  23. cwd,
  24. )
  25. assert.equal(configPath, path.join(cwd, "site/rhedyn.config.js"))
  26. assert.equal(outputName, null)
  27. assert.deepEqual(forwardedArgs, [
  28. "--target",
  29. "linux-x64-20.0.0",
  30. "-o",
  31. "dist/custom",
  32. ])
  33. })
  34. test("parseBuildArgs supports inline --config syntax", () => {
  35. const cwd = "/tmp/rhedyn-project"
  36. const { configPath, forwardedArgs, outputName } = parseBuildArgs(
  37. [
  38. "--config=./rhedyn.config.js",
  39. "--python",
  40. "python3.12",
  41. ],
  42. cwd,
  43. )
  44. assert.equal(configPath, path.join(cwd, "rhedyn.config.js"))
  45. assert.equal(outputName, null)
  46. assert.deepEqual(forwardedArgs, ["--python", "python3.12"])
  47. })
  48. test("parseBuildArgs extracts output name without forwarding it to nexe", () => {
  49. const { outputName, forwardedArgs } = parseBuildArgs([
  50. "--name",
  51. "md2doc",
  52. "--target",
  53. "linux-x64-22.16.0",
  54. ])
  55. assert.equal(outputName, "md2doc")
  56. assert.deepEqual(forwardedArgs, [
  57. "--target",
  58. "linux-x64-22.16.0",
  59. ])
  60. })
  61. test("parseBuildArgs supports inline --name syntax", () => {
  62. const { outputName, forwardedArgs } = parseBuildArgs([
  63. "--name=md2doc",
  64. "--python",
  65. "python3.12",
  66. ])
  67. assert.equal(outputName, "md2doc")
  68. assert.deepEqual(forwardedArgs, ["--python", "python3.12"])
  69. })
  70. test("toImportSpecifier prefixes sibling paths", () => {
  71. assert.equal(
  72. toImportSpecifier("/tmp/build-entry", "/tmp/build-entry/entry.js"),
  73. "./entry.js",
  74. )
  75. })
  76. test("createConfiguredEntrypointSource loads config and runner with relative literal imports", () => {
  77. const entryDir = "/tmp/build-entry"
  78. const stagedConfigPath = "/tmp/build-entry/modules/_root/tmp/project/config/rhedyn.config.mjs"
  79. const stagedRunnerPath = "/tmp/build-entry/modules/_root/home/me/rhedyn/src/run.mjs"
  80. const source = createConfiguredEntrypointSource({
  81. entryDir,
  82. stagedConfigPath,
  83. stagedRunnerPath,
  84. })
  85. assert.match(source, /const configModule = await import\("\.\/modules\/_root\/tmp\/project\/config\/rhedyn\.config\.mjs"\)/)
  86. assert.match(source, /const \{ runWithConfig \} = await import\("\.\/modules\/_root\/home\/me\/rhedyn\/src\/run\.mjs"\)/)
  87. assert.match(source, /const config = configModule\.default \|\| configModule/)
  88. assert.match(source, /await runWithConfig\(config\)/)
  89. })
  90. test("getStagedModuleRelativePath mirrors absolute paths under the staging root", () => {
  91. assert.equal(
  92. getStagedModuleRelativePath("/tmp/project/config/rhedyn.config.js"),
  93. path.join("_root", "tmp/project/config/rhedyn.config.mjs"),
  94. )
  95. })
  96. test("rewriteModuleSpecifiers retargets staged local imports and exports", () => {
  97. const source = [
  98. "import { smokeAction } from \"./actions/smoke.js\"",
  99. "export { helper } from \"../shared/helper.js\"",
  100. "const extra = import(\"./dynamic.js\")",
  101. ].join("\n")
  102. const filePath = "/tmp/project/config/rhedyn.config.js"
  103. const currentStagedPath = "/tmp/build/modules/_root/tmp/project/config/rhedyn.config.mjs"
  104. const stagedPathsByOriginalPath = new Map([
  105. [
  106. "/tmp/project/config/actions/smoke.js",
  107. "/tmp/build/modules/_root/tmp/project/config/actions/smoke.mjs",
  108. ],
  109. [
  110. "/tmp/project/shared/helper.js",
  111. "/tmp/build/modules/_root/tmp/project/shared/helper.mjs",
  112. ],
  113. [
  114. "/tmp/project/config/dynamic.js",
  115. "/tmp/build/modules/_root/tmp/project/config/dynamic.mjs",
  116. ],
  117. ])
  118. const rewritten = rewriteModuleSpecifiers({
  119. source,
  120. filePath,
  121. currentStagedPath,
  122. fileRecord: {
  123. deps: {
  124. "./actions/smoke.js": { absPath: "/tmp/project/config/actions/smoke.js" },
  125. "../shared/helper.js": { absPath: "/tmp/project/shared/helper.js" },
  126. "./dynamic.js": { absPath: "/tmp/project/config/dynamic.js" },
  127. },
  128. },
  129. stagedPathsByOriginalPath,
  130. })
  131. assert.match(rewritten, /"\.\/actions\/smoke\.mjs"/)
  132. assert.match(rewritten, /"\.\.\/shared\/helper\.mjs"/)
  133. assert.match(rewritten, /"\.\/dynamic\.mjs"/)
  134. })
  135. test("rewriteModuleSpecifiers falls back to local path resolution when dependency metadata is absent", () => {
  136. const source = "export * from \"./file-system.js\"\n"
  137. const rewritten = rewriteModuleSpecifiers({
  138. source,
  139. filePath: "/tmp/project/util/index.js",
  140. currentStagedPath: "/tmp/build/modules/_root/tmp/project/util/index.mjs",
  141. fileRecord: { deps: {} },
  142. stagedPathsByOriginalPath: new Map([
  143. [
  144. "/tmp/project/util/file-system.js",
  145. "/tmp/build/modules/_root/tmp/project/util/file-system.mjs",
  146. ],
  147. ]),
  148. })
  149. assert.match(rewritten, /"\.\/file-system\.mjs"/)
  150. })
  151. test("buildNexeArgs injects the entrypoint plugin by default", () => {
  152. const args = buildNexeArgs("/tmp/build-entry/entry.js", [])
  153. assert.match(args.join(" "), /--plugin .*nexe-entrypoint-compat\.cjs/)
  154. })
  155. test("buildNexeArgs uses --name for the default output path", () => {
  156. const args = buildNexeArgs("/tmp/build-entry/entry.js", [], "md2doc")
  157. const outputIndex = args.indexOf("-o")
  158. assert.equal(args[outputIndex + 1], path.join("/home/leakypixel/code/rhedyn", "dist/md2doc"))
  159. })
  160. test("buildNexeArgs ignores --name when an explicit output path is provided", () => {
  161. const args = buildNexeArgs("/tmp/build-entry/entry.js", ["-o", "dist/custom"], "md2doc")
  162. const outputIndex = args.indexOf("-o")
  163. assert.equal(args[outputIndex + 1], "dist/custom")
  164. })