Buckets:
| 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.