import nodePath from "path" import { customType } from "drizzle-orm/sqlite-core" import { Schema } from "effect" import { AbsolutePath } from "../schema" function storagePath(input: string) { if (process.platform !== "win32") return input return input.replaceAll("\\", "/") } function isWindowsStoragePath(input: string) { return /^[A-Za-z]:\//.test(input) || input.startsWith("//") } function absolute(input: string) { const result = storagePath(input) if (!nodePath.posix.isAbsolute(result) && !(process.platform === "win32" && isWindowsStoragePath(result))) { throw new Error(`Path is not absolute: ${input}`) } return result } function toPlatform(input: string) { if (process.platform !== "win32" || !isWindowsStoragePath(input)) return input return input.replaceAll("/", "\\") } export const absoluteColumn = customType<{ data: AbsolutePath driverData: string driverOutput: string }>({ dataType() { return "text" }, toDriver(input) { return absolute(input) }, fromDriver(input) { return AbsolutePath.make(toPlatform(absolute(input))) }, }) // Legacy sessions may persist an empty directory. Keep that existing value // readable while normalizing and validating every real directory. export const directoryColumn = customType<{ data: string driverData: string driverOutput: string }>({ dataType() { return "text" }, toDriver(input) { return input ? absolute(input) : input }, fromDriver(input) { return input ? toPlatform(absolute(input)) : input }, }) export const pathColumn = customType<{ data: string driverData: string driverOutput: string }>({ dataType() { return "text" }, toDriver(input) { return storagePath(input) }, fromDriver(input) { return storagePath(input) }, }) const decodeAbsoluteArray = Schema.decodeUnknownSync(Schema.fromJsonString(Schema.Array(Schema.String))) export const absoluteArrayColumn = customType<{ data: AbsolutePath[] driverData: string driverOutput: string }>({ dataType() { return "text" }, toDriver(input) { return JSON.stringify(input.map(absolute)) }, fromDriver(input) { return decodeAbsoluteArray(input).map((item) => AbsolutePath.make(toPlatform(absolute(item)))) }, })