Ka-Note/ka-note/server/src/routes/sync.ts

46 lines
1.9 KiB
TypeScript

import { Hono } from 'hono';
import { pushChanges, pullChanges, ensureDailyLog, getStatus } from '../lib/sync-service.js';
import { isLocked } from '../lib/ai-export-service.js';
import { handle } from '../lib/route-utils.js';
import type { SyncPushRequest } from '@ka-note/shared';
import type { AuthEnv } from '../middleware/auth.js';
const sync = new Hono<AuthEnv>();
sync.post('/push', handle('sync/push', async (c) => {
const { userId } = c.get('auth');
const lock = await isLocked(userId);
if (lock) return c.json({ error: 'AI lock active — unlock at /api/ai/unlock' }, 423);
await ensureDailyLog(userId);
const body = await c.req.json<SyncPushRequest>();
const counts = {
contexts: body.changes.contexts?.length ?? 0,
topics: body.changes.topics?.length ?? 0,
historyEntries: body.changes.historyEntries?.length ?? 0,
ratings: body.changes.ratings?.length ?? 0,
};
const clientId = c.req.header('x-client-id') ?? 'unknown';
console.log('[sync/push] incoming', { client: clientId, userId, counts });
const result = await pushChanges(body, userId);
console.log('[sync/push] done', { client: clientId, accepted: result.accepted, conflicts: result.conflicts.length });
return c.json(result);
}));
sync.get('/pull', handle('sync/pull', async (c) => {
const { userId } = c.get('auth');
await ensureDailyLog(userId);
const since = c.req.query('since') ?? '';
const clientId = c.req.header('x-client-id') ?? 'unknown';
const result = await pullChanges({ since }, userId);
console.log('[sync/pull] done', { client: clientId, changes: Object.values(result.changes).reduce((s: number, a) => s + (Array.isArray(a) ? a.length : 0), 0) });
return c.json(result);
}));
sync.get('/status', handle('sync/status', async (c) => {
const { userId } = c.get('auth');
const result = await getStatus(userId);
return c.json(result);
}));
export default sync;