@ideal-photography/shared
Version:
Shared GraphQL (Apollo Server v5) and Mongoose logic for Ideal Photography PWAs: users, products, services, bookings, orders/cart, galleries, reviews, notifications, campaigns, settings, and audit logs.
149 lines (136 loc) • 4.59 kB
JavaScript
import mongoose from 'mongoose';
// Import all models
import User from './models/User.js';
import Admin from './models/Admin.js';
import AdminInvite from './models/AdminInvite.js';
import RefreshToken from './models/RefreshToken.js';
import Product from './models/Product.js';
import Booking from './models/Booking.js';
import Service from './models/Service.js';
import Gallery from './models/Gallery.js';
import Review from './models/Review.js';
import Campaign from './models/Campaign.js';
import Notification from './models/Notification.js';
import Order from './models/Order.js';
import Transaction from './models/Transaction.js';
import AuditLog from './models/AuditLog.js';
import Settings from './models/Settings.js';
import PushSubscription from './models/PushSubscription.js';
import Media from './models/Media.js';
import EmailTemplate from './models/EmailTemplate.js';
import EmailCampaign from './models/EmailCampaign.js';
// Database connection helper
const connectDB = async (uri, options = {}) => {
try {
const defaultOptions = {
maxPoolSize: 10,
serverSelectionTimeoutMS: 5000,
socketTimeoutMS: 45000,
};
await mongoose.connect(uri, { ...defaultOptions, ...options });
console.log('✅ MongoDB connected successfully');
return mongoose.connection;
} catch (error) {
console.error('❌ MongoDB connection error:', error);
throw error;
}
};
// Database initialization helper
const initializeDB = async () => {
try {
// Create default settings if they don't exist
const settingsCount = await Settings.countDocuments();
if (settingsCount === 0) {
await Settings.createDefaults();
console.log('✅ Default settings created');
}
// TODO: Temporarily disable index creation to avoid conflicts
// Create indexes for all models
// await Promise.all([
// User.createIndexes(),
// Product.createIndexes(),
// Booking.createIndexes(),
// Service.createIndexes(),
// Gallery.createIndexes(),
// Review.createIndexes(),
// Campaign.createIndexes(),
// Notification.createIndexes(),
// Order.createIndexes(),
// AuditLog.createIndexes(),
// Settings.createIndexes()
// ]);
// Seed first super admin if configured and none exists
const hasAnyAdmin = await Admin.countDocuments();
const defaultUser = process.env.DEFAULT_ADMIN_USER;
const defaultPass = process.env.DEFAULT_ADMIN_PASS;
if (!hasAnyAdmin && defaultUser && defaultPass) {
const admin = await Admin.create({
username: String(defaultUser).trim(),
password: String(defaultPass),
role: 'super_admin',
permissions: ['admins.manage'],
isVerified: true,
isActive: true
});
console.log(`✅ Seeded default super admin '${admin.username}'`);
}
console.log('✅ Database initialized (indexes skipped for development)');
} catch (error) {
console.error('❌ Database initialization error:', error);
throw error;
}
};
export {
mongoose,
connectDB,
initializeDB
};
export const models = {
User,
Admin,
AdminInvite,
RefreshToken,
Product,
Booking,
Service,
Gallery,
Review,
Campaign,
Notification,
Order,
Transaction,
AuditLog,
Settings,
PushSubscription,
Media,
EmailTemplate,
EmailCampaign,
};
// Convenience exports for common operations
export const utils = {
// Create audit log entry
createAuditLog: (action, actor, target, result, details = {}) => {
return AuditLog.create({
action,
actor,
target,
result,
details,
category: details.category || 'technical'
});
},
// Get setting value
getSetting: (key, defaultValue = null) => {
return Settings.get(key, defaultValue);
},
// Set setting value
setSetting: (key, value, changedBy, reason = '') => {
return Settings.set(key, value, changedBy, reason);
},
// Send notification
sendNotification: async (notificationData) => {
const notification = await Notification.create(notificationData);
// TODO: Integrate with actual notification delivery system
return notification;
}
};