feat: Complete CouchDB migration and Docker configuration

- Add comprehensive CouchDB setup and configuration
- Update Docker files for CouchDB compatibility
- Create Kubernetes manifests for CouchDB deployment
- Add migration scripts and documentation
- Update seeding scripts to support both CouchDB and MongoDB
- Add docker-compose for local development
- Create comprehensive setup and deployment guides

🤖 Generated with [AI Assistant]

Co-Authored-By: AI Assistant <noreply@ai-assistant.com>
This commit is contained in:
William Valentin
2025-11-01 13:32:39 -07:00
parent df94c17e1f
commit 5aca521c52
949 changed files with 214621 additions and 8 deletions

View File

@@ -15,8 +15,8 @@ COPY . .
# --- Production stage ---
FROM oven/bun:1-alpine
# Install curl for health checks
RUN apk add --no-cache curl
# Install curl for health checks and other utilities
RUN apk add --no-cache curl wget
WORKDIR /app

View File

@@ -9,7 +9,8 @@
"test:verbose": "cross-env NODE_ENV=test bun test --verbose",
"start": "bun server.js",
"dev": "bunx nodemon server.js",
"seed:badges": "bun scripts/seedBadges.js"
"seed:badges": "bun scripts/seedBadges.js",
"setup:couchdb": "node ../scripts/setup-couchdb.js"
},
"keywords": [],
"author": "",

View File

@@ -1,6 +1,23 @@
require("dotenv").config();
const mongoose = require("mongoose");
const Badge = require("../models/Badge");
const Nano = require("nano");
// Check if we should use CouchDB or MongoDB
const useCouchDB = process.env.COUCHDB_URL && !process.env.MONGO_URI;
let db;
let Badge;
if (useCouchDB) {
// CouchDB setup
const couchdbUrl = process.env.COUCHDB_URL;
const dbName = process.env.COUCHDB_DB_NAME || 'adopt-a-street';
const nano = Nano(couchdbUrl);
db = nano.use(dbName);
} else {
// MongoDB setup (legacy)
const mongoose = require("mongoose");
Badge = require("../models/Badge");
}
/**
* Initial badge definitions
@@ -228,10 +245,64 @@ const badges = [
];
/**
* Seed badges into the database
* Seed badges into CouchDB
*/
async function seedBadges() {
async function seedBadgesCouchDB() {
try {
console.log("Connected to CouchDB");
// Clear existing badges
const existingBadges = await db.find({
selector: { type: 'badge' },
fields: ['_id', '_rev']
});
for (const badge of existingBadges.docs) {
await db.destroy(badge._id, badge._rev);
}
console.log("Cleared existing badges");
// Insert new badges
const couchdbBadges = badges.map((badge, index) => ({
_id: `badge_${Date.now()}_${index}`,
type: 'badge',
name: badge.name,
description: badge.description,
icon: badge.icon,
criteria: badge.criteria,
rarity: badge.rarity,
order: badge.order,
isActive: true,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
}));
const results = await db.bulk({ docs: couchdbBadges });
const successCount = results.filter(r => !r.error).length;
console.log(`Successfully seeded ${successCount} badges`);
// Display created badges
couchdbBadges.forEach((badge) => {
console.log(
` ${badge.icon} ${badge.name} (${badge.rarity}) - ${badge.description}`
);
});
console.log("\nDatabase seeding completed");
process.exit(0);
} catch (error) {
console.error("Error seeding badges to CouchDB:", error);
process.exit(1);
}
}
/**
* Seed badges into MongoDB (legacy)
*/
async function seedBadgesMongoDB() {
try {
const mongoose = require("mongoose");
// Connect to MongoDB
await mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
@@ -260,10 +331,21 @@ async function seedBadges() {
console.log("\nDatabase connection closed");
process.exit(0);
} catch (error) {
console.error("Error seeding badges:", error);
console.error("Error seeding badges to MongoDB:", error);
process.exit(1);
}
}
/**
* Seed badges into the database
*/
async function seedBadges() {
if (useCouchDB) {
await seedBadgesCouchDB();
} else {
await seedBadgesMongoDB();
}
}
// Run the seeder
seedBadges();