- server/db.ts: sql.js with migration system (hex_maps, hexes, hex_features) - server/routes/maps.ts: CRUD for hex maps - server/routes/hexes.ts: Bulk hex upsert, region load, sparse storage - server/index.ts: Express 5, CORS, tile serving, SPA fallback - src/data/api-client.ts: Frontend HTTP client for all API endpoints - src/main.ts: Auto-save with 1s debounce, load map state on startup - Port 3002 (Kiepenkerl uses 3001) - Graceful fallback when API unavailable (works without server too) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
53 lines
1.6 KiB
TypeScript
53 lines
1.6 KiB
TypeScript
import express from 'express';
|
|
import cors from 'cors';
|
|
import { resolve, dirname } from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
import { existsSync } from 'fs';
|
|
import { initDb } from './db.js';
|
|
import mapsRouter from './routes/maps.js';
|
|
import hexesRouter from './routes/hexes.js';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const PORT = Number(process.env.PORT) || 3002;
|
|
const DIST_DIR = resolve(__dirname, '..', 'dist');
|
|
const TILES_DIR = resolve(__dirname, '..', 'tiles');
|
|
const PUBLIC_TILES_DIR = resolve(__dirname, '..', 'public', 'tiles');
|
|
|
|
async function main() {
|
|
await initDb();
|
|
|
|
const app = express();
|
|
app.use(cors());
|
|
app.use(express.json({ limit: '10mb' }));
|
|
|
|
// API routes
|
|
app.use('/api/v1/maps', mapsRouter);
|
|
app.use('/api/v1/maps', hexesRouter);
|
|
|
|
// Serve tiles (check multiple locations)
|
|
const tilesPath = existsSync(TILES_DIR) ? TILES_DIR : PUBLIC_TILES_DIR;
|
|
if (existsSync(tilesPath)) {
|
|
app.use('/tiles', express.static(tilesPath, { maxAge: '30d', immutable: true }));
|
|
console.log(`[server] Serving tiles from ${tilesPath}`);
|
|
}
|
|
|
|
// Serve static frontend
|
|
if (existsSync(DIST_DIR)) {
|
|
app.use(express.static(DIST_DIR));
|
|
// SPA fallback (Express 5 syntax)
|
|
app.get('/{*splat}', (_req, res) => {
|
|
res.sendFile(resolve(DIST_DIR, 'index.html'));
|
|
});
|
|
console.log(`[server] Serving frontend from ${DIST_DIR}`);
|
|
}
|
|
|
|
app.listen(PORT, () => {
|
|
console.log(`[server] Hexifyer running on http://localhost:${PORT}`);
|
|
});
|
|
}
|
|
|
|
main().catch(err => {
|
|
console.error('Failed to start:', err);
|
|
process.exit(1);
|
|
});
|