- Add express-pouchdb for self-hosted PouchDB sync server - Public databases (/db/public/:db) accessible without auth - Add auth middleware for public/private database access - Simplify share button to copy current URL to clipboard - Move feature config from static JSON to dynamic API endpoint - Add PouchDB sync to PouchData class for real-time collaboration - Fix Express 5 compatibility by patching req.query - Skip express.json() for /pouchdb routes (stream handling) - Remove unused PouchdbPersistenceManager and old share system 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
93 lines
2.9 KiB
JavaScript
93 lines
2.9 KiB
JavaScript
import express from "express";
|
|
import ViteExpress from "vite-express";
|
|
import cors from "cors";
|
|
import dotenv from "dotenv";
|
|
import apiRoutes from "./server/api/index.js";
|
|
import { pouchApp, PouchDB } from "./server/services/databaseService.js";
|
|
import { dbAuthMiddleware } from "./server/middleware/dbAuth.js";
|
|
|
|
// Load .env.local first, then fall back to .env
|
|
dotenv.config({ path: '.env.local' });
|
|
dotenv.config();
|
|
|
|
const app = express();
|
|
|
|
// CORS configuration for split deployment
|
|
// In combined mode, same-origin requests don't need CORS
|
|
const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(",") || [];
|
|
if (allowedOrigins.length > 0) {
|
|
app.use(cors({
|
|
origin: allowedOrigins,
|
|
credentials: true,
|
|
}));
|
|
}
|
|
|
|
// Parse JSON for all routes EXCEPT /pouchdb (express-pouchdb handles its own body parsing)
|
|
app.use((req, res, next) => {
|
|
if (req.path.startsWith('/pouchdb')) {
|
|
return next();
|
|
}
|
|
express.json()(req, res, next);
|
|
});
|
|
|
|
// API routes
|
|
app.use("/api", apiRoutes);
|
|
|
|
// Test endpoint to verify PouchDB is working
|
|
app.get("/pouchdb-test/:dbname", async (req, res) => {
|
|
try {
|
|
const dbName = req.params.dbname;
|
|
console.log(`[Test] Creating database: ${dbName}`);
|
|
const db = new PouchDB(dbName);
|
|
const info = await db.info();
|
|
console.log(`[Test] Database info:`, info);
|
|
|
|
// Try to add a test doc
|
|
const result = await db.put({ _id: 'test-doc', hello: 'world' });
|
|
console.log(`[Test] Added doc:`, result);
|
|
|
|
// Read it back
|
|
const doc = await db.get('test-doc');
|
|
console.log(`[Test] Got doc:`, doc);
|
|
|
|
res.json({ success: true, info, doc });
|
|
} catch (err) {
|
|
console.error(`[Test] Error:`, err);
|
|
res.status(500).json({ error: err.message, stack: err.stack });
|
|
}
|
|
});
|
|
|
|
// PouchDB database sync endpoint with auth middleware
|
|
// Public databases (/pouchdb/public-*) are accessible without auth
|
|
// Private databases (/pouchdb/private-*) require authentication
|
|
// Patch req.query for Express 5 compatibility with express-pouchdb
|
|
app.use("/pouchdb", dbAuthMiddleware, (req, res, next) => {
|
|
// Express 5 makes req.query read-only, but express-pouchdb needs to write to it
|
|
// Redefine as writable property
|
|
Object.defineProperty(req, 'query', {
|
|
value: { ...req.query },
|
|
writable: true,
|
|
configurable: true
|
|
});
|
|
next();
|
|
}, pouchApp, (err, req, res, next) => {
|
|
// Error handler for express-pouchdb
|
|
console.error('[PouchDB Error]', err);
|
|
res.status(500).json({ error: err.message, stack: err.stack });
|
|
});
|
|
|
|
// Check if running in API-only mode (split deployment)
|
|
const apiOnly = process.env.API_ONLY === "true";
|
|
|
|
if (apiOnly) {
|
|
// API-only mode: no static file serving
|
|
app.listen(process.env.PORT || 3000, () => {
|
|
console.log(`API server running on port ${process.env.PORT || 3000}`);
|
|
});
|
|
} else {
|
|
// Combined mode: Vite handles static files + SPA
|
|
ViteExpress.listen(app, process.env.PORT || 3001, () => {
|
|
console.log(`Server running on port ${process.env.PORT || 3001}`);
|
|
});
|
|
}
|