From 710c81984aa38618ca7106b9521100a9964ae51d Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Wed, 15 Apr 2026 22:13:56 -0400 Subject: [PATCH] feat: unwrap uauth namespace to flat exports + barrel (#22699) --- packages/opencode/src/auth/auth.ts | 89 +++++++++++++++++++++++++++ packages/opencode/src/auth/index.ts | 93 +---------------------------- 2 files changed, 91 insertions(+), 91 deletions(-) create mode 100644 packages/opencode/src/auth/auth.ts diff --git a/packages/opencode/src/auth/auth.ts b/packages/opencode/src/auth/auth.ts new file mode 100644 index 0000000000..fb9d2b1495 --- /dev/null +++ b/packages/opencode/src/auth/auth.ts @@ -0,0 +1,89 @@ +import path from "path" +import { Effect, Layer, Record, Result, Schema, Context } from "effect" +import { zod } from "@/util/effect-zod" +import { Global } from "../global" +import { AppFileSystem } from "@opencode-ai/shared/filesystem" + +export const OAUTH_DUMMY_KEY = "opencode-oauth-dummy-key" + +const file = path.join(Global.Path.data, "auth.json") + +const fail = (message: string) => (cause: unknown) => new AuthError({ message, cause }) + +export class Oauth extends Schema.Class("OAuth")({ + type: Schema.Literal("oauth"), + refresh: Schema.String, + access: Schema.String, + expires: Schema.Number, + accountId: Schema.optional(Schema.String), + enterpriseUrl: Schema.optional(Schema.String), +}) {} + +export class Api extends Schema.Class("ApiAuth")({ + type: Schema.Literal("api"), + key: Schema.String, + metadata: Schema.optional(Schema.Record(Schema.String, Schema.String)), +}) {} + +export class WellKnown extends Schema.Class("WellKnownAuth")({ + type: Schema.Literal("wellknown"), + key: Schema.String, + token: Schema.String, +}) {} + +const _Info = Schema.Union([Oauth, Api, WellKnown]).annotate({ discriminator: "type", identifier: "Auth" }) +export const Info = Object.assign(_Info, { zod: zod(_Info) }) +export type Info = Schema.Schema.Type + +export class AuthError extends Schema.TaggedErrorClass()("AuthError", { + message: Schema.String, + cause: Schema.optional(Schema.Defect), +}) {} + +export interface Interface { + readonly get: (providerID: string) => Effect.Effect + readonly all: () => Effect.Effect, AuthError> + readonly set: (key: string, info: Info) => Effect.Effect + readonly remove: (key: string) => Effect.Effect +} + +export class Service extends Context.Service()("@opencode/Auth") {} + +export const layer = Layer.effect( + Service, + Effect.gen(function* () { + const fsys = yield* AppFileSystem.Service + const decode = Schema.decodeUnknownOption(Info) + + const all = Effect.fn("Auth.all")(function* () { + const data = (yield* fsys.readJson(file).pipe(Effect.orElseSucceed(() => ({})))) as Record + return Record.filterMap(data, (value) => Result.fromOption(decode(value), () => undefined)) + }) + + const get = Effect.fn("Auth.get")(function* (providerID: string) { + return (yield* all())[providerID] + }) + + const set = Effect.fn("Auth.set")(function* (key: string, info: Info) { + const norm = key.replace(/\/+$/, "") + const data = yield* all() + if (norm !== key) delete data[key] + delete data[norm + "/"] + yield* fsys + .writeJson(file, { ...data, [norm]: info }, 0o600) + .pipe(Effect.mapError(fail("Failed to write auth data"))) + }) + + const remove = Effect.fn("Auth.remove")(function* (key: string) { + const norm = key.replace(/\/+$/, "") + const data = yield* all() + delete data[key] + delete data[norm] + yield* fsys.writeJson(file, data, 0o600).pipe(Effect.mapError(fail("Failed to write auth data"))) + }) + + return Service.of({ get, all, set, remove }) + }), +) + +export const defaultLayer = layer.pipe(Layer.provide(AppFileSystem.defaultLayer)) diff --git a/packages/opencode/src/auth/index.ts b/packages/opencode/src/auth/index.ts index b287ce551e..9174745fd8 100644 --- a/packages/opencode/src/auth/index.ts +++ b/packages/opencode/src/auth/index.ts @@ -1,91 +1,2 @@ -import path from "path" -import { Effect, Layer, Record, Result, Schema, Context } from "effect" -import { zod } from "@/util/effect-zod" -import { Global } from "../global" -import { AppFileSystem } from "@opencode-ai/shared/filesystem" - -export const OAUTH_DUMMY_KEY = "opencode-oauth-dummy-key" - -const file = path.join(Global.Path.data, "auth.json") - -const fail = (message: string) => (cause: unknown) => new Auth.AuthError({ message, cause }) - -export namespace Auth { - export class Oauth extends Schema.Class("OAuth")({ - type: Schema.Literal("oauth"), - refresh: Schema.String, - access: Schema.String, - expires: Schema.Number, - accountId: Schema.optional(Schema.String), - enterpriseUrl: Schema.optional(Schema.String), - }) {} - - export class Api extends Schema.Class("ApiAuth")({ - type: Schema.Literal("api"), - key: Schema.String, - metadata: Schema.optional(Schema.Record(Schema.String, Schema.String)), - }) {} - - export class WellKnown extends Schema.Class("WellKnownAuth")({ - type: Schema.Literal("wellknown"), - key: Schema.String, - token: Schema.String, - }) {} - - const _Info = Schema.Union([Oauth, Api, WellKnown]).annotate({ discriminator: "type", identifier: "Auth" }) - export const Info = Object.assign(_Info, { zod: zod(_Info) }) - export type Info = Schema.Schema.Type - - export class AuthError extends Schema.TaggedErrorClass()("AuthError", { - message: Schema.String, - cause: Schema.optional(Schema.Defect), - }) {} - - export interface Interface { - readonly get: (providerID: string) => Effect.Effect - readonly all: () => Effect.Effect, AuthError> - readonly set: (key: string, info: Info) => Effect.Effect - readonly remove: (key: string) => Effect.Effect - } - - export class Service extends Context.Service()("@opencode/Auth") {} - - export const layer = Layer.effect( - Service, - Effect.gen(function* () { - const fsys = yield* AppFileSystem.Service - const decode = Schema.decodeUnknownOption(Info) - - const all = Effect.fn("Auth.all")(function* () { - const data = (yield* fsys.readJson(file).pipe(Effect.orElseSucceed(() => ({})))) as Record - return Record.filterMap(data, (value) => Result.fromOption(decode(value), () => undefined)) - }) - - const get = Effect.fn("Auth.get")(function* (providerID: string) { - return (yield* all())[providerID] - }) - - const set = Effect.fn("Auth.set")(function* (key: string, info: Info) { - const norm = key.replace(/\/+$/, "") - const data = yield* all() - if (norm !== key) delete data[key] - delete data[norm + "/"] - yield* fsys - .writeJson(file, { ...data, [norm]: info }, 0o600) - .pipe(Effect.mapError(fail("Failed to write auth data"))) - }) - - const remove = Effect.fn("Auth.remove")(function* (key: string) { - const norm = key.replace(/\/+$/, "") - const data = yield* all() - delete data[key] - delete data[norm] - yield* fsys.writeJson(file, data, 0o600).pipe(Effect.mapError(fail("Failed to write auth data"))) - }) - - return Service.of({ get, all, set, remove }) - }), - ) - - export const defaultLayer = layer.pipe(Layer.provide(AppFileSystem.defaultLayer)) -} +export * as Auth from "./auth" +export { OAUTH_DUMMY_KEY } from "./auth"