refactor(repo): переход на pnpm monorepo с shadcn/ui и Fastify+Drizzle

Frontend:
- apps/web (Vite+TS, TanStack Router/Query, shadcn/ui @cfdm/ui base-nova)
- 10 страниц в routes/_auth/, Recharts через shadcn Chart, lucide-react
- формы на RHF + Zod (FormSheet/FormField)
- удалены Tabler, Chart.js, react-router-dom

Backend (параллельный трек):
- apps/api (Fastify 5 + Drizzle + better-sqlite3)
- packages/db: Drizzle-схема и repositories по сущностям
- packages/shared: Zod-контракты
- роуты с валидацией и единым форматом ошибок { error: { code, message } }
- sync/backup — заглушки 501 (billmanager-адаптеры переносятся отдельно)
- legacy Express оставлен как runtime по умолчанию (RUNTIME=express)

Infra:
- Dockerfile multi-stage под pnpm workspaces
- .dockerignore и docker-compose обновлены под monorepo

Rules:
- удалены нерелевантные правила (rust, cloudflare, server/frontend-conventions)
- project-structure.mdc и AGENTS.md переписаны под monorepo
- frontend-shadcn.mdc, shadcn-ui-production.mdc, sqlite.mdc обновлены

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Denozordec
2026-06-26 13:42:05 +07:00
co-authored by Cursor
parent 8408155be6
commit 6fbd1a9113
202 changed files with 16734 additions and 12145 deletions
+54
View File
@@ -0,0 +1,54 @@
/**
* Запуск синхронизации BILLmanager с записью в sync_log (для API и планировщика)
*/
import { getDb } from './db.js'
import { syncFromBillmanager } from './adapters/billmanager/index.js'
/**
* @param {object} account - строка provider_accounts
* @param {object} [opts] - { skipTariffs, skipVpsPayments }
* @returns {Promise<object>} результат syncFromBillmanager + ok, logId
*/
export async function runBillmanagerAccountSync(account, opts = {}) {
const db = getDb()
const logId = `sync-${account.id}-${Date.now()}`
db.prepare(`
INSERT INTO sync_log (id, accountId, startedAt, status)
VALUES (?, ?, ?, ?)
`).run(logId, account.id, new Date().toISOString(), 'running')
try {
const result = await syncFromBillmanager(account, db, opts)
const summaryPayload = {
...(result.syncSummary || {}),
vpsCount: result.vpsCount,
paymentsCount: result.paymentsCount,
tariffsCount: result.tariffsCount ?? 0,
}
db.prepare(`
UPDATE sync_log SET finishedAt=?, status=?, vpsCount=?, paymentsCount=?, summary=?
WHERE id=?
`).run(
new Date().toISOString(),
'ok',
result.vpsCount,
result.paymentsCount,
JSON.stringify(summaryPayload),
logId,
)
return { ok: true, logId, ...result }
} catch (err) {
db.prepare(`
UPDATE sync_log SET finishedAt=?, status=?, error=?, summary=?
WHERE id=?
`).run(
new Date().toISOString(),
'error',
err.message || 'Unknown error',
JSON.stringify({ error: err.message || 'Unknown error' }),
logId,
)
throw err
}
}