feat: implement DB-driven architecture with SQLite persistence and file-generator compilation service
All checks were successful
Production Build & Deploy / build-and-deploy (push) Successful in 50s
All checks were successful
Production Build & Deploy / build-and-deploy (push) Successful in 50s
This commit is contained in:
132
src/db/index.ts
Normal file
132
src/db/index.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import { DatabaseSync } from 'node:sqlite';
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
|
||||
const DATA_DIR = process.env.DATA_DIR || path.join(process.cwd(), 'app', 'data');
|
||||
const DB_PATH = path.join(DATA_DIR, 'waas.db');
|
||||
|
||||
let dbInstance: DatabaseSync | null = null;
|
||||
|
||||
export function getDb(): DatabaseSync {
|
||||
if (dbInstance) return dbInstance;
|
||||
|
||||
if (!fs.existsSync(DATA_DIR)) {
|
||||
fs.mkdirSync(DATA_DIR, { recursive: true });
|
||||
}
|
||||
|
||||
dbInstance = new DatabaseSync(DB_PATH);
|
||||
initSchema(dbInstance);
|
||||
return dbInstance;
|
||||
}
|
||||
|
||||
function initSchema(db: DatabaseSync) {
|
||||
// 1. site_settings
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS site_settings (
|
||||
key TEXT PRIMARY KEY,
|
||||
value_json TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
`);
|
||||
|
||||
// 2. pages
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS pages (
|
||||
id TEXT PRIMARY KEY,
|
||||
slug TEXT NOT NULL UNIQUE,
|
||||
title TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'published',
|
||||
homepage_id TEXT,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
`);
|
||||
|
||||
// 3. page_sections
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS page_sections (
|
||||
id TEXT PRIMARY KEY,
|
||||
page_id TEXT NOT NULL,
|
||||
section_type TEXT NOT NULL,
|
||||
order_index INTEGER NOT NULL DEFAULT 0,
|
||||
content_draft_json TEXT NOT NULL,
|
||||
content_published_json TEXT NOT NULL,
|
||||
styles_json TEXT,
|
||||
FOREIGN KEY (page_id) REFERENCES pages (id) ON DELETE CASCADE
|
||||
);
|
||||
`);
|
||||
|
||||
// Initial Seeding falls DB leer
|
||||
seedInitialData(db);
|
||||
}
|
||||
|
||||
function seedInitialData(db: DatabaseSync) {
|
||||
const checkPages = db.prepare('SELECT COUNT(*) as count FROM pages').get() as { count: number };
|
||||
if (checkPages.count > 0) return;
|
||||
|
||||
const now = new Date().toISOString();
|
||||
|
||||
// Seed site_settings
|
||||
const initialSettings = {
|
||||
siteName: 'N&D IT Solutions',
|
||||
metaDescription: 'High-Performance Webdesign & Digital Solutions - 100% DSGVO-konform.',
|
||||
is_demo_mode: false,
|
||||
header: {
|
||||
brandName: 'N&D',
|
||||
brandHighlight: 'i-t SOLUTIONS',
|
||||
ctaText: 'Erstgespräch buchen',
|
||||
ctaLink: '#contact',
|
||||
showThemeToggle: true,
|
||||
glassEffect: true
|
||||
},
|
||||
footer: {
|
||||
brandDescription: 'Ihr Partner für professionelles Webdesign, Website-Entwicklung und lokale SEO.',
|
||||
copyrightText: 'N&D i-t SOLUTIONS. Alle Rechte vorbehalten.',
|
||||
showLegalLinks: true
|
||||
},
|
||||
site_info: {
|
||||
title: 'N&D IT Solutions',
|
||||
homepage_id: 'page_home'
|
||||
}
|
||||
};
|
||||
|
||||
db.prepare('INSERT INTO site_settings (key, value_json, updated_at) VALUES (?, ?, ?)').run(
|
||||
'site_config',
|
||||
JSON.stringify(initialSettings),
|
||||
now
|
||||
);
|
||||
|
||||
// Seed default pages & sections
|
||||
db.prepare('INSERT INTO pages (id, slug, title, status, homepage_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)').run(
|
||||
'page_home',
|
||||
'/',
|
||||
'Startseite (Hauptseite)',
|
||||
'published',
|
||||
'page_home',
|
||||
now,
|
||||
now
|
||||
);
|
||||
|
||||
const heroDraft = JSON.stringify({
|
||||
title: 'Maßgeschneiderte Webseiten. Digital im Griff.',
|
||||
subtitle: 'Wir entwickeln blitzschnelle, DSGVO-konforme High-End Webseiten für Ihr Unternehmen.',
|
||||
ctaPrimaryText: 'Projekt anfragen',
|
||||
ctaPrimaryLink: '#contact'
|
||||
});
|
||||
|
||||
const bentoDraft = JSON.stringify({
|
||||
sectionTitle: 'High-End Features & Leistung',
|
||||
sectionSubtitle: 'Modernste Technologie & Höchster Datenschutz vereint.'
|
||||
});
|
||||
|
||||
const contactDraft = JSON.stringify({
|
||||
title: 'Bereit für Ihr Projekt?',
|
||||
subtitle: 'Schreiben Sie uns direkt. Wir antworten innerhalb von 24 Stunden persönlich.'
|
||||
});
|
||||
|
||||
const stmt = db.prepare('INSERT INTO page_sections (id, page_id, section_type, order_index, content_draft_json, content_published_json, styles_json) VALUES (?, ?, ?, ?, ?, ?, ?)');
|
||||
|
||||
stmt.run('sec_hero_1', 'page_home', 'HeroSection', 0, heroDraft, heroDraft, JSON.stringify({ bg_color: '#0b0f19' }));
|
||||
stmt.run('sec_bento_1', 'page_home', 'BentoGrid', 1, bentoDraft, bentoDraft, JSON.stringify({}));
|
||||
stmt.run('sec_contact_1', 'page_home', 'ContactSection', 2, contactDraft, contactDraft, JSON.stringify({}));
|
||||
}
|
||||
Reference in New Issue
Block a user