fix(db): bootstrap полной схемы на чистой установке и логи Docker
Docker / build (push) Failing after 18s
Docker / build (push) Failing after 18s
Пустой volume больше не отдаёт 500 на /api/data из-за отсутствующих таблиц. В compose добавлены json-file логи с ротацией и LOG_LEVEL для Fastify. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -43,7 +43,9 @@ export async function buildApp(opts: BuildAppOptions = {}) {
|
||||
getDb()
|
||||
|
||||
const app = Fastify({
|
||||
logger: process.env.NODE_ENV !== 'production',
|
||||
logger: {
|
||||
level: process.env.LOG_LEVEL ?? 'info',
|
||||
},
|
||||
})
|
||||
|
||||
await app.register(cors, { origin: true })
|
||||
|
||||
@@ -47,6 +47,7 @@ services:
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
tag: "{{.Name}}"
|
||||
|
||||
app:
|
||||
image: ${VPS_TRACKER_IMAGE:-ghcr.io/denozordec/vps-tracker}:${VPS_TRACKER_IMAGE_TAG:-latest}
|
||||
@@ -60,6 +61,7 @@ services:
|
||||
PORT: "3001"
|
||||
RUNTIME: "fastify"
|
||||
NODE_ENV: production
|
||||
LOG_LEVEL: ${LOG_LEVEL:-info}
|
||||
AUTH_REQUIRED: ${AUTH_REQUIRED:-false}
|
||||
AUTH_JWT_SECRET: ${AUTH_JWT_SECRET:-}
|
||||
AUTH_ISSUER: ${AUTH_ISSUER:-https://auth.shnt.top}
|
||||
@@ -93,6 +95,7 @@ services:
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
tag: "{{.Name}}"
|
||||
|
||||
volumes:
|
||||
traefik_letsencrypt:
|
||||
|
||||
@@ -9,6 +9,7 @@ VPS_DOMAIN=vps.example.com
|
||||
# TRAEFIK_HTTP_PORT=80
|
||||
# TRAEFIK_HTTPS_PORT=443
|
||||
# TRAEFIK_LOG_LEVEL=INFO
|
||||
# LOG_LEVEL=info
|
||||
|
||||
# --- Image ---
|
||||
# Default: GHCR. For Gitea registry, e.g.:
|
||||
|
||||
@@ -8,12 +8,20 @@ services:
|
||||
environment:
|
||||
PORT: "3001"
|
||||
RUNTIME: "fastify"
|
||||
NODE_ENV: production
|
||||
LOG_LEVEL: ${LOG_LEVEL:-info}
|
||||
AUTH_REQUIRED: ${AUTH_REQUIRED:-false}
|
||||
AUTH_JWT_SECRET: ${AUTH_JWT_SECRET:-dev-secret-change-me}
|
||||
AUTH_ISSUER: ${AUTH_ISSUER:-https://auth.shnt.top}
|
||||
AUTH_PORTAL_URL: ${AUTH_PORTAL_URL:-http://localhost:8080}
|
||||
volumes:
|
||||
- ./data:/app/data
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
tag: "{{.Name}}"
|
||||
|
||||
# Раскомментируйте для локальной сборки вместо pull образа:
|
||||
# app-build:
|
||||
@@ -27,3 +35,8 @@ services:
|
||||
# RUNTIME: "express"
|
||||
# volumes:
|
||||
# - ./data:/app/data
|
||||
# logging:
|
||||
# driver: json-file
|
||||
# options:
|
||||
# max-size: "10m"
|
||||
# max-file: "3"
|
||||
|
||||
@@ -196,14 +196,18 @@ docker run --rm -v vps_tracker_traefik_letsencrypt:/data -v "$PWD:/backup" alpin
|
||||
| ACME / браузер ругается на сертификат | `CF_DNS_API_TOKEN`, Zone:DNS:Edit, DNS only (не orange cloud), логи Traefik |
|
||||
| `invalid credentials` | Не Global Key; зона в scope токена; нет пробелов/кавычек в `.env` |
|
||||
| Gateway Timeout / 404 | `docker compose ps`; labels; сеть `vps-tracker`; `VPS_DOMAIN` |
|
||||
| `/health` OK, `/api/data` 500 | Старые образы без bootstrap схемы — `docker compose pull && up -d`; смотрите `docker compose logs app` (`no such table`) |
|
||||
| `/health` OK, UI пустой | образ / кэш CDN; смотрите `docker compose logs app` |
|
||||
| SSO 401 / issuer mismatch | `AUTH_JWT_SECRET` = `JWT_SECRET` портала; `AUTH_ISSUER` |
|
||||
|
||||
```bash
|
||||
docker compose logs traefik 2>&1 | grep -iE 'acme|certificate|cloudflare|error'
|
||||
docker compose logs app --tail=80
|
||||
docker compose logs -f app # follow
|
||||
```
|
||||
|
||||
Логи контейнеров: драйвер `json-file`, ротация `max-size=10m`, `max-file=3`. Уровень приложения — `LOG_LEVEL` (по умолчанию `info`).
|
||||
|
||||
---
|
||||
|
||||
## Простой compose без Traefik
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import { mkdtempSync, rmSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { closeDb, getDb, getSqlite } from './index.js'
|
||||
import { resetRuntimeMigrate } from './runtime-migrate.js'
|
||||
import { getSnapshot } from './repositories/snapshot.js'
|
||||
import { runWithSpace, MAIN_SPACE_ID } from './space-context.js'
|
||||
|
||||
describe('ensureRuntimeSchema (empty DB)', () => {
|
||||
let dir: string
|
||||
|
||||
afterEach(() => {
|
||||
closeDb()
|
||||
resetRuntimeMigrate()
|
||||
delete process.env.DB_PATH
|
||||
if (dir) rmSync(dir, { recursive: true, force: true })
|
||||
})
|
||||
|
||||
it('bootstraps core tables and serves empty snapshot', () => {
|
||||
dir = mkdtempSync(join(tmpdir(), 'vps-tracker-db-'))
|
||||
process.env.DB_PATH = join(dir, 'fresh.db')
|
||||
resetRuntimeMigrate()
|
||||
closeDb()
|
||||
|
||||
getDb()
|
||||
const tables = getSqlite()
|
||||
.prepare(
|
||||
`SELECT name FROM sqlite_master WHERE type='table' AND name IN ('vps','settings','providers','spaces')`,
|
||||
)
|
||||
.all() as { name: string }[]
|
||||
expect(tables.map((t) => t.name).sort()).toEqual([
|
||||
'providers',
|
||||
'settings',
|
||||
'spaces',
|
||||
'vps',
|
||||
])
|
||||
|
||||
const snap = runWithSpace(MAIN_SPACE_ID, () => getSnapshot())
|
||||
expect(snap.spaceId).toBe(MAIN_SPACE_ID)
|
||||
expect(snap.vps).toEqual([])
|
||||
expect(snap.settings.length).toBeGreaterThanOrEqual(1)
|
||||
})
|
||||
})
|
||||
@@ -2,41 +2,11 @@ import type Database from 'better-sqlite3'
|
||||
|
||||
const MAIN_SPACE_ID = 'space-main'
|
||||
|
||||
const COLUMN_MIGRATIONS: string[] = [
|
||||
`ALTER TABLE vps ADD COLUMN customData TEXT`,
|
||||
`ALTER TABLE vps ADD COLUMN last_health_status TEXT`,
|
||||
`ALTER TABLE vps ADD COLUMN last_health_checked_at TEXT`,
|
||||
`ALTER TABLE settings ADD COLUMN notifyVpsDownEnabled INTEGER`,
|
||||
`ALTER TABLE settings ADD COLUMN webhookUrl TEXT`,
|
||||
`ALTER TABLE settings ADD COLUMN webhookEnabled INTEGER`,
|
||||
`ALTER TABLE settings ADD COLUMN notifyIntervalMinutes INTEGER`,
|
||||
`ALTER TABLE settings ADD COLUMN uptimeCheckIntervalMinutes INTEGER`,
|
||||
`ALTER TABLE settings ADD COLUMN appSwitcherJson TEXT`,
|
||||
`ALTER TABLE settings ADD COLUMN integrationToken TEXT`,
|
||||
`ALTER TABLE settings ADD COLUMN integrationEnabled INTEGER`,
|
||||
`ALTER TABLE settings ADD COLUMN integrationLastSyncAt TEXT`,
|
||||
`ALTER TABLE settings ADD COLUMN cfdmApiUrl TEXT`,
|
||||
`ALTER TABLE settings ADD COLUMN showQuickActions INTEGER`,
|
||||
`ALTER TABLE vps_domains ADD COLUMN targetIps TEXT`,
|
||||
`ALTER TABLE providers ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE provider_accounts ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE server_projects ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE vps ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE payments ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE balance_ledger ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE settings ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE vps_domains ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE notification_log ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE notification_state ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE vps_health_checks ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE audit_log ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE audit_log ADD COLUMN actorUserId TEXT`,
|
||||
`ALTER TABLE sync_log ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE active_tariffs ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE tariff_sync_options ADD COLUMN spaceId TEXT`,
|
||||
]
|
||||
|
||||
const TABLE_MIGRATIONS: string[] = [
|
||||
/**
|
||||
* Full bootstrap for empty DB (clean Docker install).
|
||||
* CREATE IF NOT EXISTS — safe on existing databases; column upgrades stay in COLUMN_MIGRATIONS.
|
||||
*/
|
||||
const CORE_TABLE_MIGRATIONS: string[] = [
|
||||
`CREATE TABLE IF NOT EXISTS spaces (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
@@ -52,8 +22,195 @@ const TABLE_MIGRATIONS: string[] = [
|
||||
createdAt TEXT NOT NULL,
|
||||
UNIQUE(spaceId, userId)
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS providers (
|
||||
id TEXT PRIMARY KEY,
|
||||
spaceId TEXT NOT NULL DEFAULT 'space-main',
|
||||
name TEXT NOT NULL,
|
||||
website TEXT,
|
||||
contact TEXT,
|
||||
baseCurrency TEXT,
|
||||
usdRate TEXT,
|
||||
eurRate TEXT,
|
||||
notes TEXT,
|
||||
apiType TEXT,
|
||||
apiBaseUrl TEXT
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS provider_accounts (
|
||||
id TEXT PRIMARY KEY,
|
||||
spaceId TEXT NOT NULL DEFAULT 'space-main',
|
||||
providerId TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
panelUrl TEXT,
|
||||
currency TEXT,
|
||||
billingMode TEXT,
|
||||
notes TEXT,
|
||||
apiType TEXT,
|
||||
apiBaseUrl TEXT,
|
||||
apiCredentials TEXT,
|
||||
balance_api REAL,
|
||||
balance_currency TEXT,
|
||||
balance_updated_at TEXT,
|
||||
enoughmoneyto TEXT,
|
||||
balance_alert_below REAL,
|
||||
FOREIGN KEY (providerId) REFERENCES providers(id)
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS server_projects (
|
||||
id TEXT PRIMARY KEY,
|
||||
spaceId TEXT NOT NULL DEFAULT 'space-main',
|
||||
name TEXT NOT NULL,
|
||||
color TEXT,
|
||||
sortOrder INTEGER DEFAULT 0,
|
||||
notes TEXT,
|
||||
createdAt TEXT
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS vps (
|
||||
id TEXT PRIMARY KEY,
|
||||
spaceId TEXT NOT NULL DEFAULT 'space-main',
|
||||
ip TEXT,
|
||||
ipv6 TEXT,
|
||||
additionalIps TEXT,
|
||||
dns TEXT,
|
||||
providerId TEXT,
|
||||
providerAccountId TEXT,
|
||||
country TEXT,
|
||||
city TEXT,
|
||||
datacenter TEXT,
|
||||
os TEXT,
|
||||
vcpu INTEGER,
|
||||
ramGb REAL,
|
||||
diskGb INTEGER,
|
||||
diskType TEXT,
|
||||
virtualization TEXT,
|
||||
bandwidthTb INTEGER,
|
||||
sshPort INTEGER,
|
||||
rootUser TEXT,
|
||||
purpose TEXT,
|
||||
environment TEXT,
|
||||
project TEXT,
|
||||
projectId TEXT,
|
||||
monitoringEnabled INTEGER,
|
||||
backupEnabled INTEGER,
|
||||
status TEXT,
|
||||
tariffType TEXT,
|
||||
currency TEXT,
|
||||
dailyRate REAL,
|
||||
monthlyRate REAL,
|
||||
createdAt TEXT,
|
||||
paidUntil TEXT,
|
||||
notes TEXT,
|
||||
userOverrides TEXT,
|
||||
customData TEXT,
|
||||
last_health_status TEXT,
|
||||
last_health_checked_at TEXT,
|
||||
FOREIGN KEY (providerId) REFERENCES providers(id),
|
||||
FOREIGN KEY (providerAccountId) REFERENCES provider_accounts(id)
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS payments (
|
||||
id TEXT PRIMARY KEY,
|
||||
spaceId TEXT NOT NULL DEFAULT 'space-main',
|
||||
type TEXT NOT NULL,
|
||||
date TEXT NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
currency TEXT,
|
||||
providerAccountId TEXT,
|
||||
vpsId TEXT,
|
||||
note TEXT,
|
||||
FOREIGN KEY (providerAccountId) REFERENCES provider_accounts(id),
|
||||
FOREIGN KEY (vpsId) REFERENCES vps(id)
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS balance_ledger (
|
||||
id TEXT PRIMARY KEY,
|
||||
spaceId TEXT NOT NULL DEFAULT 'space-main',
|
||||
type TEXT NOT NULL,
|
||||
date TEXT NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
currency TEXT,
|
||||
direction TEXT,
|
||||
providerAccountId TEXT,
|
||||
vpsId TEXT,
|
||||
note TEXT,
|
||||
FOREIGN KEY (providerAccountId) REFERENCES provider_accounts(id),
|
||||
FOREIGN KEY (vpsId) REFERENCES vps(id)
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS settings (
|
||||
id TEXT PRIMARY KEY,
|
||||
spaceId TEXT NOT NULL DEFAULT 'space-main',
|
||||
baseCurrency TEXT,
|
||||
ratesUrl TEXT,
|
||||
autoConvert INTEGER,
|
||||
ratesUpdatedAt TEXT,
|
||||
syncEnabled INTEGER,
|
||||
syncIntervalMinutes INTEGER,
|
||||
syncTariffsIntervalMinutes INTEGER,
|
||||
customFields TEXT,
|
||||
telegramBotToken TEXT,
|
||||
telegramChatId TEXT,
|
||||
notifyPaymentExpiryEnabled INTEGER,
|
||||
notifyNewTariffsEnabled INTEGER,
|
||||
telegramMessageThreadId TEXT,
|
||||
notifyLowBalanceEnabled INTEGER,
|
||||
notifySyncDigestEnabled INTEGER,
|
||||
notifyVpsDownEnabled INTEGER,
|
||||
webhookUrl TEXT,
|
||||
webhookEnabled INTEGER,
|
||||
notifyIntervalMinutes INTEGER,
|
||||
uptimeCheckIntervalMinutes INTEGER,
|
||||
appSwitcherJson TEXT,
|
||||
integrationToken TEXT,
|
||||
integrationEnabled INTEGER,
|
||||
integrationLastSyncAt TEXT,
|
||||
cfdmApiUrl TEXT,
|
||||
showQuickActions INTEGER
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS sync_log (
|
||||
id TEXT PRIMARY KEY,
|
||||
spaceId TEXT NOT NULL DEFAULT 'space-main',
|
||||
accountId TEXT NOT NULL,
|
||||
startedAt TEXT NOT NULL,
|
||||
finishedAt TEXT,
|
||||
status TEXT,
|
||||
vpsCount INTEGER,
|
||||
paymentsCount INTEGER,
|
||||
error TEXT,
|
||||
summary TEXT,
|
||||
FOREIGN KEY (accountId) REFERENCES provider_accounts(id)
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS active_tariffs (
|
||||
id TEXT PRIMARY KEY,
|
||||
spaceId TEXT NOT NULL DEFAULT 'space-main',
|
||||
providerAccountId TEXT NOT NULL,
|
||||
providerId TEXT NOT NULL,
|
||||
externalId TEXT NOT NULL,
|
||||
datacenterKey TEXT,
|
||||
datacenterName TEXT,
|
||||
name TEXT,
|
||||
desc TEXT,
|
||||
vcpu INTEGER,
|
||||
ramGb REAL,
|
||||
diskGb INTEGER,
|
||||
diskType TEXT,
|
||||
virtualization TEXT,
|
||||
channel TEXT,
|
||||
location TEXT,
|
||||
country TEXT,
|
||||
cpuModel TEXT,
|
||||
orderAvailable INTEGER,
|
||||
price TEXT,
|
||||
syncedAt TEXT,
|
||||
FOREIGN KEY (providerAccountId) REFERENCES provider_accounts(id),
|
||||
FOREIGN KEY (providerId) REFERENCES providers(id)
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS tariff_sync_options (
|
||||
providerAccountId TEXT PRIMARY KEY,
|
||||
spaceId TEXT NOT NULL DEFAULT 'space-main',
|
||||
datacenters TEXT,
|
||||
periods TEXT,
|
||||
syncedAt TEXT,
|
||||
FOREIGN KEY (providerAccountId) REFERENCES provider_accounts(id)
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS vps_health_checks (
|
||||
id TEXT PRIMARY KEY,
|
||||
spaceId TEXT NOT NULL DEFAULT 'space-main',
|
||||
vpsId TEXT NOT NULL REFERENCES vps(id),
|
||||
checkedAt TEXT NOT NULL,
|
||||
status TEXT NOT NULL,
|
||||
@@ -62,14 +219,17 @@ const TABLE_MIGRATIONS: string[] = [
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS audit_log (
|
||||
id TEXT PRIMARY KEY,
|
||||
spaceId TEXT NOT NULL DEFAULT 'space-main',
|
||||
entity TEXT NOT NULL,
|
||||
entityId TEXT NOT NULL,
|
||||
action TEXT NOT NULL,
|
||||
diff TEXT,
|
||||
actorUserId TEXT,
|
||||
createdAt TEXT NOT NULL
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS notification_log (
|
||||
id TEXT PRIMARY KEY,
|
||||
spaceId TEXT NOT NULL DEFAULT 'space-main',
|
||||
event TEXT NOT NULL,
|
||||
channel TEXT NOT NULL,
|
||||
status TEXT NOT NULL,
|
||||
@@ -80,20 +240,14 @@ const TABLE_MIGRATIONS: string[] = [
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS notification_state (
|
||||
key TEXT PRIMARY KEY,
|
||||
spaceId TEXT NOT NULL DEFAULT 'space-main',
|
||||
lastFingerprint TEXT,
|
||||
lastSentAt TEXT,
|
||||
lastStatus TEXT
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS server_projects (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
color TEXT,
|
||||
sortOrder INTEGER DEFAULT 0,
|
||||
notes TEXT,
|
||||
createdAt TEXT
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS vps_domains (
|
||||
id TEXT PRIMARY KEY,
|
||||
spaceId TEXT NOT NULL DEFAULT 'space-main',
|
||||
vpsId TEXT REFERENCES vps(id) ON DELETE SET NULL,
|
||||
fqdn TEXT NOT NULL,
|
||||
zoneName TEXT NOT NULL,
|
||||
@@ -128,6 +282,54 @@ const TABLE_MIGRATIONS: string[] = [
|
||||
)`,
|
||||
]
|
||||
|
||||
/** Additive columns for DBs created before spaces / notifications / etc. */
|
||||
const COLUMN_MIGRATIONS: string[] = [
|
||||
`ALTER TABLE vps ADD COLUMN customData TEXT`,
|
||||
`ALTER TABLE vps ADD COLUMN last_health_status TEXT`,
|
||||
`ALTER TABLE vps ADD COLUMN last_health_checked_at TEXT`,
|
||||
`ALTER TABLE settings ADD COLUMN notifyVpsDownEnabled INTEGER`,
|
||||
`ALTER TABLE settings ADD COLUMN webhookUrl TEXT`,
|
||||
`ALTER TABLE settings ADD COLUMN webhookEnabled INTEGER`,
|
||||
`ALTER TABLE settings ADD COLUMN notifyIntervalMinutes INTEGER`,
|
||||
`ALTER TABLE settings ADD COLUMN uptimeCheckIntervalMinutes INTEGER`,
|
||||
`ALTER TABLE settings ADD COLUMN appSwitcherJson TEXT`,
|
||||
`ALTER TABLE settings ADD COLUMN integrationToken TEXT`,
|
||||
`ALTER TABLE settings ADD COLUMN integrationEnabled INTEGER`,
|
||||
`ALTER TABLE settings ADD COLUMN integrationLastSyncAt TEXT`,
|
||||
`ALTER TABLE settings ADD COLUMN cfdmApiUrl TEXT`,
|
||||
`ALTER TABLE settings ADD COLUMN showQuickActions INTEGER`,
|
||||
`ALTER TABLE settings ADD COLUMN telegramBotToken TEXT`,
|
||||
`ALTER TABLE settings ADD COLUMN telegramChatId TEXT`,
|
||||
`ALTER TABLE settings ADD COLUMN notifyPaymentExpiryEnabled INTEGER`,
|
||||
`ALTER TABLE settings ADD COLUMN notifyNewTariffsEnabled INTEGER`,
|
||||
`ALTER TABLE settings ADD COLUMN telegramMessageThreadId TEXT`,
|
||||
`ALTER TABLE settings ADD COLUMN notifyLowBalanceEnabled INTEGER`,
|
||||
`ALTER TABLE settings ADD COLUMN notifySyncDigestEnabled INTEGER`,
|
||||
`ALTER TABLE vps_domains ADD COLUMN targetIps TEXT`,
|
||||
`ALTER TABLE providers ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE provider_accounts ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE provider_accounts ADD COLUMN balance_api REAL`,
|
||||
`ALTER TABLE provider_accounts ADD COLUMN balance_currency TEXT`,
|
||||
`ALTER TABLE provider_accounts ADD COLUMN balance_updated_at TEXT`,
|
||||
`ALTER TABLE provider_accounts ADD COLUMN enoughmoneyto TEXT`,
|
||||
`ALTER TABLE provider_accounts ADD COLUMN balance_alert_below REAL`,
|
||||
`ALTER TABLE server_projects ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE vps ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE payments ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE balance_ledger ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE settings ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE vps_domains ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE notification_log ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE notification_state ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE vps_health_checks ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE audit_log ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE audit_log ADD COLUMN actorUserId TEXT`,
|
||||
`ALTER TABLE sync_log ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE sync_log ADD COLUMN summary TEXT`,
|
||||
`ALTER TABLE active_tariffs ADD COLUMN spaceId TEXT`,
|
||||
`ALTER TABLE tariff_sync_options ADD COLUMN spaceId TEXT`,
|
||||
]
|
||||
|
||||
const SPACE_BACKFILL_TABLES = [
|
||||
'providers',
|
||||
'provider_accounts',
|
||||
@@ -165,6 +367,13 @@ function ensureMainSpace(sqlite: Database.Database): void {
|
||||
)
|
||||
.run(MAIN_SPACE_ID, owner, now)
|
||||
}
|
||||
|
||||
sqlite
|
||||
.prepare(
|
||||
`INSERT OR IGNORE INTO settings (id, spaceId, baseCurrency, autoConvert, syncEnabled)
|
||||
VALUES ('settings-main', ?, 'USD', 1, 0)`,
|
||||
)
|
||||
.run(MAIN_SPACE_ID)
|
||||
}
|
||||
|
||||
function backfillSpaceIds(sqlite: Database.Database): void {
|
||||
@@ -189,7 +398,7 @@ export function resetRuntimeMigrate(): void {
|
||||
|
||||
export function ensureRuntimeSchema(sqlite: Database.Database): void {
|
||||
if (migrated) return
|
||||
for (const sql of TABLE_MIGRATIONS) {
|
||||
for (const sql of CORE_TABLE_MIGRATIONS) {
|
||||
sqlite.exec(sql)
|
||||
}
|
||||
for (const sql of COLUMN_MIGRATIONS) {
|
||||
|
||||
Reference in New Issue
Block a user