index.ts 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import { z } from "zod"
  2. import { Global } from "../global"
  3. import { Log } from "../util/log"
  4. import path from "path"
  5. import { NamedError } from "../util/error"
  6. export namespace BunProc {
  7. const log = Log.create({ service: "bun" })
  8. export async function run(
  9. cmd: string[],
  10. options?: Bun.SpawnOptions.OptionsObject<any, any, any>,
  11. ) {
  12. log.info("running", {
  13. cmd: [which(), ...cmd],
  14. ...options,
  15. })
  16. const result = Bun.spawnSync([which(), ...cmd], {
  17. ...options,
  18. stdout: "pipe",
  19. stderr: "pipe",
  20. env: {
  21. ...process.env,
  22. ...options?.env,
  23. BUN_BE_BUN: "1",
  24. },
  25. })
  26. const stdout = result.stdout!.toString()
  27. const stderr = result.stderr!.toString()
  28. const code = result.exitCode
  29. log.info("done", {
  30. code,
  31. stdout,
  32. stderr,
  33. })
  34. if (code !== 0) {
  35. throw new Error(`Command failed with exit code ${result.exitCode}`)
  36. }
  37. return result
  38. }
  39. export function which() {
  40. return process.execPath
  41. }
  42. export const InstallFailedError = NamedError.create(
  43. "BunInstallFailedError",
  44. z.object({
  45. pkg: z.string(),
  46. version: z.string(),
  47. }),
  48. )
  49. export async function install(pkg: string, version = "latest") {
  50. const mod = path.join(Global.Path.cache, "node_modules", pkg)
  51. const pkgjson = Bun.file(path.join(Global.Path.cache, "package.json"))
  52. const parsed = await pkgjson.json().catch(() => ({
  53. dependencies: {},
  54. }))
  55. if (parsed.dependencies[pkg] === version) return mod
  56. parsed.dependencies[pkg] = version
  57. await Bun.write(pkgjson, JSON.stringify(parsed, null, 2))
  58. await BunProc.run(["install", "--registry=https://registry.npmjs.org"], {
  59. cwd: Global.Path.cache,
  60. }).catch((e) => {
  61. new InstallFailedError(
  62. { pkg, version },
  63. {
  64. cause: e,
  65. },
  66. )
  67. })
  68. return mod
  69. }
  70. }