migration to postgres

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-26 17:42:59 +00:00
co-authored by Claude Opus 4.6
parent 7f04ecd644
commit 500a70910e
54 changed files with 4016 additions and 264 deletions
+17 -52
View File
@@ -1,11 +1,9 @@
import { createRouter } from '../../create-router';
import { mkdir } from 'node:fs/promises';
import { dirname } from 'node:path';
import { getUserSettingsFile, getUserStateFile } from '@@/data-path';
import { getUserSettings, setUserSettings, getUserState, patchUserState } from 'officerdb';
const DEFAULT_SETTINGS = {
chat: {
defaultProvider: 'claude',
defaultProvider: 'pi',
defaultModel: null,
systemPrompt: '',
temperature: 1,
@@ -16,73 +14,40 @@ const DEFAULT_SETTINGS = {
},
};
const ensureDir = (filePath: string) => mkdir(dirname(filePath), { recursive: true });
export const settingsRouter = createRouter();
// GET /settings — return settings.json, auto-create with defaults if missing
// GET /settings — return user settings from DB, default if empty
settingsRouter.get('/settings', async (ctx) => {
const email = ctx.get('user').email;
const filePath = getUserSettingsFile(email);
const file = Bun.file(filePath);
const userId = ctx.get('user').id;
const settings = await getUserSettings(userId);
if (await file.exists()) {
try {
return ctx.json(await file.json());
} catch {
// corrupted — fall through to defaults
}
if (Object.keys(settings).length === 0) {
await setUserSettings(userId, DEFAULT_SETTINGS);
return ctx.json(DEFAULT_SETTINGS);
}
await ensureDir(filePath);
await Bun.write(file, JSON.stringify(DEFAULT_SETTINGS, null, 2));
return ctx.json(DEFAULT_SETTINGS);
return ctx.json(settings);
});
// PUT /settings — full replacement
settingsRouter.put('/settings', async (ctx) => {
const email = ctx.get('user').email;
const userId = ctx.get('user').id;
const body = ctx.get('body');
const filePath = getUserSettingsFile(email);
await ensureDir(filePath);
await Bun.write(filePath, JSON.stringify(body, null, 2));
await setUserSettings(userId, body);
return ctx.json(body);
});
// GET /state — return state.json, auto-create with {} if missing
// GET /state — return user state from DB
settingsRouter.get('/state', async (ctx) => {
const email = ctx.get('user').email;
const filePath = getUserStateFile(email);
const file = Bun.file(filePath);
if (await file.exists()) {
try {
return ctx.json(await file.json());
} catch {
// corrupted — fall through to empty
}
}
await ensureDir(filePath);
await Bun.write(file, JSON.stringify({}, null, 2));
return ctx.json({});
const userId = ctx.get('user').id;
const state = await getUserState(userId);
return ctx.json(state);
});
// PATCH /state — shallow-merge incoming keys
settingsRouter.patch('/state', async (ctx) => {
const email = ctx.get('user').email;
const userId = ctx.get('user').id;
const body = ctx.get('body');
const filePath = getUserStateFile(email);
const file = Bun.file(filePath);
let existing: Record<string, unknown> = {};
if (await file.exists()) {
try { existing = await file.json(); } catch { /* corrupted — start fresh */ }
}
const merged = { ...existing, ...body };
await ensureDir(filePath);
await Bun.write(filePath, JSON.stringify(merged, null, 2));
const merged = await patchUserState(userId, body);
return ctx.json(merged);
});