GHHG10's picture
download
raw
5.89 kB
export * as ProjectDirectories from "./directories"
import { and, asc, desc, eq, isNotNull, isNull, ne, or } from "drizzle-orm"
import { Context, Effect, Layer, Schema } from "effect"
import { Database } from "../database/database"
import { LayerNode } from "../effect/layer-node"
import { AbsolutePath, optionalOmitUndefined } from "../schema"
import { ProjectSchema } from "./schema"
import { ProjectDirectoryTable } from "./sql"
import type { EffectDrizzleSqlite } from "@opencode-ai/effect-drizzle-sqlite"
export interface Directory {
readonly directory: AbsolutePath
readonly strategy?: string
}
export const CreateInput = Schema.Struct({
projectID: ProjectSchema.ID,
directory: AbsolutePath,
strategy: Schema.optional(Schema.String),
behavior: Schema.Literals(["ignore", "replace"]).pipe(Schema.optional),
})
export type CreateInput = typeof CreateInput.Type
export const RemoveInput = Schema.Struct({
projectID: ProjectSchema.ID,
directory: AbsolutePath,
})
export type RemoveInput = typeof RemoveInput.Type
type DatabaseClient = EffectDrizzleSqlite.EffectSQLiteDatabase
export type Transaction = Parameters<Parameters<DatabaseClient["transaction"]>[0]>[0]
export const ListInput = Schema.Struct({
projectID: ProjectSchema.ID,
}).annotate({ identifier: "Project.DirectoriesInput" })
export type ListInput = typeof ListInput.Type
export const ListOutput = Schema.Array(
Schema.Struct({
directory: AbsolutePath,
strategy: optionalOmitUndefined(Schema.String),
}),
).annotate({ identifier: "Project.Directories" })
export type ListOutput = typeof ListOutput.Type
export interface Interface {
readonly list: (projectID: ProjectSchema.ID) => Effect.Effect<ReadonlyArray<Directory>>
readonly get: (input: {
projectID: ProjectSchema.ID
directory: AbsolutePath
}) => Effect.Effect<Directory | undefined>
readonly contains: (input: { projectID: ProjectSchema.ID; directory: AbsolutePath }) => Effect.Effect<boolean>
readonly create: (input: CreateInput, tx?: Transaction) => Effect.Effect<boolean>
readonly remove: (input: RemoveInput, tx?: Transaction) => Effect.Effect<boolean>
}
export class Service extends Context.Service<Service, Interface>()("@opencode/ProjectDirectories") {}
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const db = (yield* Database.Service).db
const create = Effect.fn("ProjectDirectories.create")(function* (input: CreateInput, tx?: Transaction) {
const insert = (tx ?? db)
.insert(ProjectDirectoryTable)
.values({ project_id: input.projectID, directory: input.directory, strategy: input.strategy })
const query =
input.behavior === "replace"
? insert.onConflictDoUpdate({
target: [ProjectDirectoryTable.project_id, ProjectDirectoryTable.directory],
set: { strategy: input.strategy ?? null },
setWhere: input.strategy
? or(isNull(ProjectDirectoryTable.strategy), ne(ProjectDirectoryTable.strategy, input.strategy))
: isNotNull(ProjectDirectoryTable.strategy),
})
: insert.onConflictDoNothing()
return (
(yield* query.returning({ directory: ProjectDirectoryTable.directory }).get().pipe(Effect.orDie)) !== undefined
)
})
const remove = Effect.fn("ProjectDirectories.remove")(function* (input: RemoveInput, tx?: Transaction) {
return (
(yield* (tx ?? db)
.delete(ProjectDirectoryTable)
.where(
and(
eq(ProjectDirectoryTable.project_id, input.projectID),
eq(ProjectDirectoryTable.directory, input.directory),
),
)
.returning({ directory: ProjectDirectoryTable.directory })
.get()
.pipe(Effect.orDie)) !== undefined
)
})
const list = Effect.fn("ProjectDirectories.list")(function* (projectID: ProjectSchema.ID) {
const rows = yield* db
.select({ directory: ProjectDirectoryTable.directory, strategy: ProjectDirectoryTable.strategy })
.from(ProjectDirectoryTable)
.where(eq(ProjectDirectoryTable.project_id, projectID))
.orderBy(desc(ProjectDirectoryTable.time_created), asc(ProjectDirectoryTable.directory))
.all()
.pipe(Effect.orDie)
return rows.map((row) => ({ directory: row.directory, strategy: row.strategy ?? undefined }))
})
const contains = Effect.fn("ProjectDirectories.contains")(function* (input: {
projectID: ProjectSchema.ID
directory: AbsolutePath
}) {
return (
(yield* db
.select({ directory: ProjectDirectoryTable.directory })
.from(ProjectDirectoryTable)
.where(
and(
eq(ProjectDirectoryTable.project_id, input.projectID),
eq(ProjectDirectoryTable.directory, input.directory),
),
)
.get()
.pipe(Effect.orDie)) !== undefined
)
})
const get = Effect.fn("ProjectDirectories.get")(function* (input: {
projectID: ProjectSchema.ID
directory: AbsolutePath
}) {
const row = yield* db
.select({ directory: ProjectDirectoryTable.directory, strategy: ProjectDirectoryTable.strategy })
.from(ProjectDirectoryTable)
.where(
and(
eq(ProjectDirectoryTable.project_id, input.projectID),
eq(ProjectDirectoryTable.directory, input.directory),
),
)
.get()
.pipe(Effect.orDie)
return row ? { directory: row.directory, strategy: row.strategy ?? undefined } : undefined
})
return Service.of({
list,
get,
contains,
create,
remove,
})
}),
)
export const defaultLayer = layer.pipe(Layer.provide(Database.defaultLayer))
export const node = LayerNode.make(layer, [Database.node])

Xet Storage Details

Size:
5.89 kB
·
Xet hash:
56ba41c1454bb33a4122a768948bbbc2743fb53ccf61f24015a034a12e9f2f61

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.