xedoc-cli 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xedoc-cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Local web UI for Codex account, chat, execution, and workspace management.",
5
5
  "author": "Edward Nguyen <monokaijs@gmail.com>",
6
6
  "type": "module",
@@ -4,7 +4,7 @@ generator client {
4
4
 
5
5
  datasource db {
6
6
  provider = "sqlite"
7
- url = env("DATABASE_URL")
7
+ url = "file:../.xedoc/xedoc.db"
8
8
  }
9
9
 
10
10
  enum AccountStatus {
package/server/index.mjs CHANGED
@@ -1,7 +1,8 @@
1
1
  import "dotenv/config"
2
2
  import { createHmac, createHash, timingSafeEqual } from "node:crypto"
3
- import { createReadStream, statSync } from "node:fs"
3
+ import { createReadStream, mkdirSync, statSync } from "node:fs"
4
4
  import { createServer } from "node:http"
5
+ import { homedir } from "node:os"
5
6
  import { dirname, extname, join, normalize, resolve } from "node:path"
6
7
  import { fileURLToPath } from "node:url"
7
8
  import { PrismaClient } from "@prisma/client"
@@ -14,8 +15,15 @@ const DEFAULT_PORT = "6354"
14
15
  const SERVER_AUTH_ID = "server"
15
16
  const serverRoot = dirname(fileURLToPath(import.meta.url))
16
17
  const packageRoot = resolve(serverRoot, "..")
17
- const prisma = new PrismaClient()
18
18
  const options = parseArgs(process.argv.slice(2))
19
+ const workspaceRoot = resolveHomePath(process.env.CODEX_WORKSPACE_ROOT ?? homedir())
20
+ const databasePath = join(workspaceRoot, ".xedoc", "xedoc.db")
21
+ const databaseUrl = sqliteDatabaseUrl(databasePath)
22
+ process.env.DATABASE_URL = databaseUrl
23
+ mkdirSync(dirname(databasePath), { recursive: true, mode: 0o700 })
24
+ const prisma = new PrismaClient({
25
+ datasources: { db: { url: databaseUrl } },
26
+ })
19
27
  const build = await import(join(packageRoot, "build/server/index.js"))
20
28
  const clientRoot = join(packageRoot, "build/client")
21
29
  const requestListener = createRequestListener({
@@ -75,6 +83,20 @@ function fail(message) {
75
83
  process.exit(1)
76
84
  }
77
85
 
86
+ function resolveHomePath(path) {
87
+ if (path === "~") {
88
+ return homedir()
89
+ }
90
+ if (path.startsWith("~/")) {
91
+ return join(homedir(), path.slice(2))
92
+ }
93
+ return resolve(path)
94
+ }
95
+
96
+ function sqliteDatabaseUrl(path) {
97
+ return `file:${path}?connection_limit=1&pool_timeout=30`
98
+ }
99
+
78
100
  function installSocketServer(httpServer) {
79
101
  const io = new SocketServer(httpServer, {
80
102
  path: "/socket.io",
@@ -1,18 +1,21 @@
1
1
  import "dotenv/config"
2
2
  import { mkdir } from "node:fs/promises"
3
- import { dirname, isAbsolute, resolve } from "node:path"
4
- import { fileURLToPath } from "node:url"
5
-
6
- const schemaDirectory = dirname(
7
- fileURLToPath(new URL("../prisma/schema.prisma", import.meta.url)),
8
- )
3
+ import { homedir } from "node:os"
4
+ import { dirname, join, resolve } from "node:path"
9
5
 
10
6
  export async function setupSqliteDatabase() {
11
- await ensureSqliteDirectory()
7
+ const databasePath = workspaceDatabasePath()
8
+ const databaseUrl = sqliteDatabaseUrl(databasePath)
9
+ process.env.DATABASE_URL = databaseUrl
10
+ await mkdir(dirname(databasePath), { recursive: true, mode: 0o700 })
12
11
  const { PrismaClient } = await import("@prisma/client")
13
- const prisma = new PrismaClient()
12
+ const prisma = new PrismaClient({
13
+ datasources: { db: { url: databaseUrl } },
14
+ })
14
15
  try {
15
16
  await prisma.$executeRawUnsafe("PRAGMA foreign_keys = ON")
17
+ await prisma.$queryRawUnsafe("PRAGMA journal_mode = WAL")
18
+ await prisma.$queryRawUnsafe("PRAGMA busy_timeout = 30000")
16
19
  for (const statement of schemaStatements) {
17
20
  try {
18
21
  await prisma.$executeRawUnsafe(statement)
@@ -32,19 +35,26 @@ function isDuplicateColumnError(error) {
32
35
  return message.toLowerCase().includes("duplicate column name")
33
36
  }
34
37
 
35
- async function ensureSqliteDirectory() {
36
- const databaseUrl = process.env.DATABASE_URL
37
- if (!databaseUrl?.startsWith("file:")) {
38
- return
38
+ function workspaceDatabasePath() {
39
+ return join(
40
+ resolveHomePath(process.env.CODEX_WORKSPACE_ROOT?.trim() || homedir()),
41
+ ".xedoc",
42
+ "xedoc.db",
43
+ )
44
+ }
45
+
46
+ function resolveHomePath(path) {
47
+ if (path === "~") {
48
+ return homedir()
39
49
  }
40
- const filePath = databaseUrl.slice("file:".length)
41
- if (!filePath || filePath === ":memory:" || filePath.includes("?")) {
42
- return
50
+ if (path.startsWith("~/")) {
51
+ return join(homedir(), path.slice(2))
43
52
  }
44
- const resolvedPath = isAbsolute(filePath)
45
- ? filePath
46
- : resolve(schemaDirectory, filePath)
47
- await mkdir(dirname(resolvedPath), { recursive: true })
53
+ return resolve(path)
54
+ }
55
+
56
+ function sqliteDatabaseUrl(path) {
57
+ return `file:${path}?connection_limit=1&pool_timeout=30`
48
58
  }
49
59
 
50
60
  const schemaStatements = [
@@ -1 +0,0 @@
1
- import{j as r,t as s}from"./jsx-runtime-B9QlDcuB.js";import{t}from"./app-shell-Bcxy4tS4.js";var a=s(),o=r(function(){return(0,a.jsx)(t,{})});export{o as default};