mirror of
https://github.com/anomalyco/opencode.git
synced 2026-05-21 03:15:11 +00:00
refactor: simplify workspace adapter registry
This commit is contained in:
@@ -7,27 +7,12 @@ import { type WorkspaceAdapter, WorkspaceAdapterError, type WorkspaceAdapterEntr
|
||||
import type { Interface as WorktreeService } from "@/worktree"
|
||||
import { WorktreeAdapterEntry, worktreeAdapter } from "./worktree"
|
||||
|
||||
export interface AdapterServices {
|
||||
readonly worktree: WorktreeService
|
||||
}
|
||||
const BUILTIN: WorkspaceAdapterEntry[] = [{ type: "worktree", ...WorktreeAdapterEntry }]
|
||||
|
||||
const BUILTIN: Record<string, WorkspaceAdapterEntry> = {
|
||||
worktree: { type: "worktree", ...WorktreeAdapterEntry },
|
||||
}
|
||||
export const makeBuiltinAdapters = (worktree: WorktreeService) =>
|
||||
new Map<string, WorkspaceAdapter>([["worktree", worktreeAdapter(worktree)]])
|
||||
|
||||
const builtinAdapter = (type: string, services: AdapterServices): WorkspaceAdapter | undefined => {
|
||||
if (type === "worktree") return worktreeAdapter(services.worktree)
|
||||
}
|
||||
|
||||
export const makeBuiltinAdapters = (services: AdapterServices) =>
|
||||
new Map(
|
||||
Object.keys(BUILTIN).flatMap((type) => {
|
||||
const adapter = builtinAdapter(type, services)
|
||||
return adapter ? [[type, adapter] as const] : []
|
||||
}),
|
||||
)
|
||||
|
||||
const state = new Map<ProjectID, Map<string, WorkspaceAdapter>>()
|
||||
const plugins = new Map<ProjectID, Map<string, WorkspaceAdapter>>()
|
||||
const emptyBuiltinAdapters = new Map<string, WorkspaceAdapter>()
|
||||
|
||||
export function getAdapter(
|
||||
@@ -35,7 +20,7 @@ export function getAdapter(
|
||||
type: string,
|
||||
builtin: ReadonlyMap<string, WorkspaceAdapter> = emptyBuiltinAdapters,
|
||||
): WorkspaceAdapter {
|
||||
const custom = state.get(projectID)?.get(type)
|
||||
const custom = plugins.get(projectID)?.get(type)
|
||||
if (custom) return custom
|
||||
|
||||
const adapter = builtin.get(type)
|
||||
@@ -45,20 +30,12 @@ export function getAdapter(
|
||||
}
|
||||
|
||||
export async function listAdapters(projectID: ProjectID): Promise<WorkspaceAdapterEntry[]> {
|
||||
const custom = [...(state.get(projectID)?.entries() ?? [])].map(([type, adapter]) => ({
|
||||
const custom = [...(plugins.get(projectID)?.entries() ?? [])].map(([type, adapter]) => ({
|
||||
type,
|
||||
name: adapter.name,
|
||||
description: adapter.description,
|
||||
}))
|
||||
return [...Object.values(BUILTIN), ...custom]
|
||||
}
|
||||
|
||||
// Plugins can be loaded per-project so we need to scope them. If you
|
||||
// want to install a global one pass `ProjectID.global`
|
||||
export function registerEffectAdapter(projectID: ProjectID, type: string, adapter: WorkspaceAdapter) {
|
||||
const adapters = state.get(projectID) ?? new Map<string, WorkspaceAdapter>()
|
||||
adapters.set(type, adapter)
|
||||
state.set(projectID, adapters)
|
||||
return [...BUILTIN, ...custom]
|
||||
}
|
||||
|
||||
const adapterError = (cause: unknown) => new WorkspaceAdapterError({ message: errorMessage(cause), cause })
|
||||
@@ -92,5 +69,9 @@ function fromPromiseAdapter(adapter: PluginWorkspaceAdapter): WorkspaceAdapter {
|
||||
}
|
||||
|
||||
export function registerAdapter(projectID: ProjectID, type: string, adapter: PluginWorkspaceAdapter) {
|
||||
registerEffectAdapter(projectID, type, fromPromiseAdapter(adapter))
|
||||
// Plugins can be loaded per-project so we need to scope them. If you
|
||||
// want to install a global one pass `ProjectID.global`.
|
||||
const adapters = plugins.get(projectID) ?? new Map<string, WorkspaceAdapter>()
|
||||
adapters.set(type, fromPromiseAdapter(adapter))
|
||||
plugins.set(projectID, adapters)
|
||||
}
|
||||
|
||||
@@ -176,10 +176,12 @@ export const layer = Layer.effect(
|
||||
const worktree = yield* Worktree.Service
|
||||
const connections = new Map<WorkspaceID, ConnectionStatus>()
|
||||
const syncFibers = yield* FiberMap.make<WorkspaceID, void, SyncLoopError>()
|
||||
const adapters = makeBuiltinAdapters({ worktree })
|
||||
const builtinAdapters = makeBuiltinAdapters(worktree)
|
||||
const adapterFor = (space: { projectID: ProjectID; type: string }) =>
|
||||
getAdapter(space.projectID, space.type, builtinAdapters)
|
||||
|
||||
const target = Effect.fn("Workspace.target")(function* (space: Info) {
|
||||
return yield* getAdapter(space.projectID, space.type, adapters).target(space)
|
||||
return yield* adapterFor(space).target(space)
|
||||
})
|
||||
|
||||
const setStatus = (id: WorkspaceID, status: ConnectionStatus["status"]) => {
|
||||
@@ -465,7 +467,7 @@ export const layer = Layer.effect(
|
||||
|
||||
const create = Effect.fn("Workspace.create")(function* (input: CreateInput) {
|
||||
const id = WorkspaceID.ascending(input.id)
|
||||
const adapter = getAdapter(input.projectID, input.type, adapters)
|
||||
const adapter = adapterFor(input)
|
||||
const config = yield* adapter.configure({ ...input, id, name: Slug.create(), directory: null })
|
||||
|
||||
const info: Info = {
|
||||
@@ -730,8 +732,7 @@ export const layer = Layer.effect(
|
||||
const info = fromRow(row)
|
||||
yield* Effect.catch(
|
||||
Effect.gen(function* () {
|
||||
const adapter = getAdapter(info.projectID, row.type, adapters)
|
||||
yield* adapter.remove(info)
|
||||
yield* adapterFor(info).remove(info)
|
||||
}),
|
||||
() =>
|
||||
Effect.sync(() => {
|
||||
|
||||
Reference in New Issue
Block a user