import type { OAuthUserAgent } from "@atcute/oauth-browser-client"; import { createAppviewClient, authedGet, authedPost, type AppviewContext } from "./appview"; import type { XrpcRequestInit } from "./client"; // The spindle is a service-auth'd xrpc host just like the appview: the browser // mints a per-call token with aud = did:web: and lxm = the method. // Secrets live on the spindle (the CI runner needs them) and are keyed by the // repo's at-uri, which the spindle resolves to a repoDid. export type SpindleContext = AppviewContext; export const createSpindleClient = ( host: string, agent: OAuthUserAgent, fetch?: typeof globalThis.fetch ): SpindleContext => createAppviewClient({ apiUrl: `https://${host}`, agent, fetch }); // mirrors sh.tangled.repo.listSecrets#secret — values are never returned. export interface Secret { repo: string; key: string; createdAt: string; createdBy: string; } const LIST_SECRETS = "sh.tangled.repo.listSecrets"; const ADD_SECRET = "sh.tangled.repo.addSecret"; const REMOVE_SECRET = "sh.tangled.repo.removeSecret"; export const listSecrets = async ( ctx: SpindleContext, repoUri: string, init?: XrpcRequestInit ): Promise => { const res = await authedGet<{ secrets?: Secret[] }>(ctx, LIST_SECRETS, { repo: repoUri }, init); return res.secrets ?? []; }; export const addSecret = ( ctx: SpindleContext, repoUri: string, key: string, value: string, init?: XrpcRequestInit ): Promise => authedPost(ctx, ADD_SECRET, { repo: repoUri, key, value }, init).then(() => undefined); export const removeSecret = ( ctx: SpindleContext, repoUri: string, key: string, init?: XrpcRequestInit ): Promise => authedPost(ctx, REMOVE_SECRET, { repo: repoUri, key }, init).then(() => undefined);