location-layer.test.ts 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import fs from "fs/promises"
  2. import path from "path"
  3. import { describe, expect } from "bun:test"
  4. import { Effect, Layer } from "effect"
  5. import { Catalog } from "@opencode-ai/core/catalog"
  6. import { LocationServiceMap } from "@opencode-ai/core/location-layer"
  7. import { PluginBoot } from "@opencode-ai/core/plugin/boot"
  8. import { ProviderV2 } from "@opencode-ai/core/provider"
  9. import { AbsolutePath } from "@opencode-ai/core/schema"
  10. import { tmpdir } from "./fixture/tmpdir"
  11. import { testEffect } from "./lib/effect"
  12. import { FSUtil } from "../src/fs-util"
  13. import { Auth } from "../src/auth"
  14. import { EventV2 } from "../src/event"
  15. import { Global } from "../src/global"
  16. import { ModelsDev } from "../src/models-dev"
  17. import { Npm } from "../src/npm"
  18. import { Project } from "../src/project"
  19. import { ProjectReference } from "../src/project-reference"
  20. const it = testEffect(
  21. LocationServiceMap.layer.pipe(
  22. Layer.provide(
  23. Layer.mergeAll(
  24. Project.defaultLayer,
  25. EventV2.defaultLayer,
  26. Auth.defaultLayer,
  27. Npm.defaultLayer,
  28. ModelsDev.defaultLayer,
  29. FSUtil.defaultLayer,
  30. Global.defaultLayer,
  31. ),
  32. ),
  33. ),
  34. )
  35. describe("LocationServiceMap", () => {
  36. it.live("isolates location state while sharing location policy with catalog", () =>
  37. Effect.acquireRelease(
  38. Effect.promise(() => Promise.all([tmpdir(), tmpdir()])),
  39. (dirs) => Effect.promise(() => Promise.all(dirs.map((dir) => dir[Symbol.asyncDispose]())).then(() => undefined)),
  40. ).pipe(
  41. Effect.flatMap(([blocked, allowed]) =>
  42. Effect.gen(function* () {
  43. yield* Effect.promise(() =>
  44. fs.writeFile(
  45. path.join(blocked.path, "opencode.json"),
  46. JSON.stringify({
  47. experimental: { policies: [{ effect: "deny", action: "provider.use", resource: "test" }] },
  48. }),
  49. ),
  50. )
  51. const update = (directory: string) =>
  52. Effect.gen(function* () {
  53. yield* PluginBoot.Service.use((boot) => boot.wait())
  54. yield* ProjectReference.Service
  55. const catalog = yield* Catalog.Service
  56. const transform = yield* catalog.transform()
  57. yield* transform((editor) => editor.provider.update(ProviderV2.ID.make("test"), () => {}))
  58. return yield* catalog.provider.all()
  59. }).pipe(Effect.scoped, Effect.provide(LocationServiceMap.get({ directory: AbsolutePath.make(directory) })))
  60. expect((yield* update(blocked.path)).some((provider) => provider.id === ProviderV2.ID.make("test"))).toBe(
  61. false,
  62. )
  63. expect((yield* update(allowed.path)).some((provider) => provider.id === ProviderV2.ID.make("test"))).toBe(
  64. true,
  65. )
  66. }),
  67. ),
  68. ),
  69. )
  70. })