workspace-adaptor.test.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import { afterAll, afterEach, describe, expect, test } from "bun:test"
  2. import { Effect } from "effect"
  3. import path from "path"
  4. import { pathToFileURL } from "url"
  5. import { tmpdir } from "../fixture/fixture"
  6. const disableDefault = process.env.OPENCODE_DISABLE_DEFAULT_PLUGINS
  7. process.env.OPENCODE_DISABLE_DEFAULT_PLUGINS = "1"
  8. const { Flag } = await import("../../src/flag/flag")
  9. const { Plugin } = await import("../../src/plugin/index")
  10. const { Workspace } = await import("../../src/control-plane/workspace")
  11. const { Instance } = await import("../../src/project/instance")
  12. const experimental = Flag.OPENCODE_EXPERIMENTAL_WORKSPACES
  13. Flag.OPENCODE_EXPERIMENTAL_WORKSPACES = true
  14. afterEach(async () => {
  15. await Instance.disposeAll()
  16. })
  17. afterAll(() => {
  18. if (disableDefault === undefined) {
  19. delete process.env.OPENCODE_DISABLE_DEFAULT_PLUGINS
  20. } else {
  21. process.env.OPENCODE_DISABLE_DEFAULT_PLUGINS = disableDefault
  22. }
  23. Flag.OPENCODE_EXPERIMENTAL_WORKSPACES = experimental
  24. })
  25. describe("plugin.workspace", () => {
  26. test("plugin can install a workspace adaptor", async () => {
  27. await using tmp = await tmpdir({
  28. init: async (dir) => {
  29. const type = `plug-${Math.random().toString(36).slice(2)}`
  30. const file = path.join(dir, "plugin.ts")
  31. const mark = path.join(dir, "created.json")
  32. const space = path.join(dir, "space")
  33. await Bun.write(
  34. file,
  35. [
  36. "export default async ({ experimental_workspace }) => {",
  37. ` experimental_workspace.register(${JSON.stringify(type)}, {`,
  38. ' name: "plug",',
  39. ' description: "plugin workspace adaptor",',
  40. " configure(input) {",
  41. ` return { ...input, name: "plug", branch: "plug/main", directory: ${JSON.stringify(space)} }`,
  42. " },",
  43. " async create(input) {",
  44. ` await Bun.write(${JSON.stringify(mark)}, JSON.stringify(input))`,
  45. " },",
  46. " async remove() {},",
  47. " target(input) {",
  48. ' return { type: "local", directory: input.directory }',
  49. " },",
  50. " })",
  51. " return {}",
  52. "}",
  53. "",
  54. ].join("\n"),
  55. )
  56. await Bun.write(
  57. path.join(dir, "opencode.json"),
  58. JSON.stringify(
  59. {
  60. $schema: "https://opencode.ai/config.json",
  61. plugin: [pathToFileURL(file).href],
  62. },
  63. null,
  64. 2,
  65. ),
  66. )
  67. return { mark, space, type }
  68. },
  69. })
  70. const info = await Instance.provide({
  71. directory: tmp.path,
  72. fn: async () =>
  73. Effect.gen(function* () {
  74. const plugin = yield* Plugin.Service
  75. yield* plugin.init()
  76. return Workspace.create({
  77. type: tmp.extra.type,
  78. branch: null,
  79. extra: { key: "value" },
  80. projectID: Instance.project.id,
  81. })
  82. }).pipe(Effect.provide(Plugin.defaultLayer), Effect.runPromise),
  83. })
  84. expect(info.type).toBe(tmp.extra.type)
  85. expect(info.name).toBe("plug")
  86. expect(info.branch).toBe("plug/main")
  87. expect(info.directory).toBe(tmp.extra.space)
  88. expect(info.extra).toEqual({ key: "value" })
  89. expect(JSON.parse(await Bun.file(tmp.extra.mark).text())).toMatchObject({
  90. type: tmp.extra.type,
  91. name: "plug",
  92. branch: "plug/main",
  93. directory: tmp.extra.space,
  94. extra: { key: "value" },
  95. })
  96. })
  97. })