90 lines · 3.2 KB · TypeScript
RawDownload
import { HttpApiBuilder } from "effect/unstable/httpapi";import { Context, Effect } from "effect"; import { addGroup, capture } from "@executor-js/api";import type { OnePasswordExtension } from "../sdk/plugin";import { OnePasswordGroup } from "./group"; // ---------------------------------------------------------------------------// Service tag//// Holds the `Captured` shape — every method's `StorageFailure` channel has// been swapped for `InternalError({ traceId })`. The host provides an// already-wrapped extension via// `Layer.succeed(OnePasswordExtensionService, withCapture(executor).onepassword)`.// Handlers see `InternalError` in the error union, which matches// `.addError(InternalError)` on the group — no per-handler translation.// --------------------------------------------------------------------------- export class OnePasswordExtensionService extends Context.Service<  OnePasswordExtensionService,  OnePasswordExtension>()("OnePasswordExtensionService") {} // ---------------------------------------------------------------------------// Composed API — core + onepassword group// --------------------------------------------------------------------------- const ExecutorApiWithOnePassword = addGroup(OnePasswordGroup); // ---------------------------------------------------------------------------// Handlers//// Each handler is exactly: yield the extension service, call the method,// return. Plugin SDK errors flow through the typed channel and are// schema-encoded (OnePasswordError -> 502) by HttpApi. Defects bubble up// and are captured + downgraded to `InternalError(traceId)` by the// observability middleware.// --------------------------------------------------------------------------- export const OnePasswordHandlers = HttpApiBuilder.group(  ExecutorApiWithOnePassword,  "onepassword",  (handlers) =>    handlers      .handle("getConfig", () =>        capture(          Effect.gen(function* () {            const ext = yield* OnePasswordExtensionService;            return yield* ext.getConfig();          }),        ),      )      .handle("configure", ({ payload }) =>        capture(          Effect.gen(function* () {            const ext = yield* OnePasswordExtensionService;            yield* ext.configure(payload);          }),        ),      )      .handle("removeConfig", () =>        capture(          Effect.gen(function* () {            const ext = yield* OnePasswordExtensionService;            yield* ext.removeConfig();          }),        ),      )      .handle("status", () =>        capture(          Effect.gen(function* () {            const ext = yield* OnePasswordExtensionService;            return yield* ext.status();          }),        ),      )      .handle("listVaults", ({ query: urlParams }) =>        capture(          Effect.gen(function* () {            const ext = yield* OnePasswordExtensionService;            const auth =              urlParams.authKind === "desktop-app"                ? { kind: "desktop-app" as const, accountName: urlParams.account }                : { kind: "service-account" as const, token: urlParams.account };            const vaults = yield* ext.listVaults(auth);            return { vaults: [...vaults] };          }),        ),      ),);