88 lines
2.8 KiB
TypeScript
88 lines
2.8 KiB
TypeScript
export * as PermissionSaved from "./saved"
|
|
|
|
import { eq } from "drizzle-orm"
|
|
import { Context, Effect, Layer, Schema } from "effect"
|
|
import { Database } from "../database/database"
|
|
import { ProjectV2 } from "../project"
|
|
import { withStatics } from "../schema"
|
|
import { Identifier } from "../util/identifier"
|
|
import { PermissionTable } from "./sql"
|
|
|
|
export const ID = Schema.String.pipe(
|
|
Schema.brand("PermissionSaved.ID"),
|
|
withStatics((schema) => ({ create: () => schema.make("psv_" + Identifier.ascending()) })),
|
|
)
|
|
export type ID = typeof ID.Type
|
|
|
|
export const Info = Schema.Struct({
|
|
id: ID,
|
|
projectID: ProjectV2.ID,
|
|
action: Schema.String,
|
|
resource: Schema.String,
|
|
}).annotate({ identifier: "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<ReadonlyArray<Info>>
|
|
readonly add: (input: AddInput) => Effect.Effect<void>
|
|
readonly remove: (id: ID) => Effect.Effect<void>
|
|
}
|
|
|
|
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/PermissionSaved") {}
|
|
|
|
export 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 defaultLayer = layer.pipe(Layer.provide(Database.defaultLayer))
|