Files
anomalyco_opencode/packages/opencode/src/provider/auth.ts
T
Kit Langton fedaeea9da refactor(state): add effectful ScopedState
Add a real effect-style scoped state data type built on ScopedCache and cover its caching, invalidation, concurrency, and scope-finalization semantics with focused tests. Move ProviderAuthService onto the new abstraction so the service no longer depends on Instance.state directly.
2026-03-12 16:33:50 -04:00

72 lines
2.0 KiB
TypeScript

import { Effect, ManagedRuntime } from "effect"
import z from "zod"
import { fn } from "@/util/fn"
import * as S from "./auth-service"
import { ProviderID } from "./schema"
// Separate runtime: ProviderAuthService can't join the shared runtime because
// runtime.ts → auth-service.ts → provider/auth.ts creates a circular import.
// AuthService is stateless file I/O so the duplicate instance is harmless.
const rt = ManagedRuntime.make(S.ProviderAuthService.defaultLayer)
function runPromise<A>(f: (service: S.ProviderAuthService.Service) => Effect.Effect<A, S.ProviderAuthError>) {
return rt.runPromise(S.ProviderAuthService.use(f))
}
export namespace ProviderAuth {
export const Method = z
.object({
type: z.union([z.literal("oauth"), z.literal("api")]),
label: z.string(),
})
.meta({
ref: "ProviderAuthMethod",
})
export type Method = z.infer<typeof Method>
export async function methods() {
return runPromise((service) => service.methods())
}
export const Authorization = z
.object({
url: z.string(),
method: z.union([z.literal("auto"), z.literal("code")]),
instructions: z.string(),
})
.meta({
ref: "ProviderAuthAuthorization",
})
export type Authorization = z.infer<typeof Authorization>
export const authorize = fn(
z.object({
providerID: ProviderID.zod,
method: z.number(),
}),
async (input): Promise<Authorization | undefined> => runPromise((service) => service.authorize(input)),
)
export const callback = fn(
z.object({
providerID: ProviderID.zod,
method: z.number(),
code: z.string().optional(),
}),
async (input) => runPromise((service) => service.callback(input)),
)
export const api = fn(
z.object({
providerID: ProviderID.zod,
key: z.string(),
}),
async (input) => runPromise((service) => service.api(input)),
)
export import OauthMissing = S.OauthMissing
export import OauthCodeMissing = S.OauthCodeMissing
export import OauthCallbackFailed = S.OauthCallbackFailed
}