export * as PermissionSaved from "./saved" import { eq } from "drizzle-orm" import { Context, Effect, Layer, Schema } from "effect" import { Database } from "../database/database" import { makeGlobalNode } from "../effect/app-node" import { ProjectV2 } from "../project" import { PermissionTable } from "./sql" import { PermissionSaved } from "@opencode-ai/schema/permission-saved" export const ID = PermissionSaved.ID export type ID = typeof ID.Type export const Info = PermissionSaved.Info export type Info = typeof Info.Type export const ListInput = Schema.Struct({ projectID: ProjectV2.ID.pipe(Schema.optional), }).annotate({ identifier: "PermissionSaved.ListInput" }) export type ListInput = typeof ListInput.Type export const AddInput = Schema.Struct({ projectID: ProjectV2.ID, action: Schema.String, resources: Schema.Array(Schema.String), }).annotate({ identifier: "PermissionSaved.AddInput" }) export type AddInput = typeof AddInput.Type export interface Interface { readonly list: (input?: ListInput) => Effect.Effect> readonly add: (input: AddInput) => Effect.Effect readonly remove: (id: ID) => Effect.Effect } export class Service extends Context.Service()("@opencode/v2/PermissionSaved") {} const layer = Layer.effect( Service, Effect.gen(function* () { const { db } = yield* Database.Service const list = Effect.fn("PermissionSaved.list")(function* (input?: ListInput) { const rows = yield* db .select() .from(PermissionTable) .where(input?.projectID ? eq(PermissionTable.project_id, input.projectID) : undefined) .all() .pipe(Effect.orDie) return rows.map( (row): Info => ({ id: row.id, projectID: row.project_id, action: row.action, resource: row.resource }), ) }) const add = Effect.fn("PermissionSaved.add")(function* (input: AddInput) { if (!input.resources.length) return yield* db .insert(PermissionTable) .values( input.resources.map((resource) => ({ id: ID.create(), project_id: input.projectID, action: input.action, resource, })), ) .onConflictDoNothing() .run() .pipe(Effect.orDie) }) const remove = Effect.fn("PermissionSaved.remove")(function* (id: ID) { yield* db.delete(PermissionTable).where(eq(PermissionTable.id, id)).run().pipe(Effect.orDie) }) return Service.of({ list, add, remove }) }), ) export const node = makeGlobalNode({ service: Service, layer, deps: [Database.node] })