241 lines
8.0 KiB
JavaScript
241 lines
8.0 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Configure static microsite v2 for an event using crest-novel template + site.json content.
|
|
*
|
|
* Usage:
|
|
* node scripts/setup-crest-novel-microsite.js [--publish] [--event-id=<id>] [--subdomain=<sub>]
|
|
*/
|
|
const path = require('path');
|
|
require('dotenv').config({ path: path.join(__dirname, '..', '.env') });
|
|
const fs = require('fs');
|
|
const mongoose = require('mongoose');
|
|
const { connectDB } = require('../src/config/database');
|
|
const Event = require('../src/models/Event');
|
|
const Form = require('../src/models/Form');
|
|
const MicrositeV2Template = require('../src/models/MicrositeV2Template');
|
|
const EventStaticMicrosite = require('../src/models/EventStaticMicrosite');
|
|
const User = require('../src/models/User');
|
|
const { normalizeSubdomain, subdomainAvailability } = require('../src/utils/subdomainAvailability');
|
|
const { uploadTemplateAsset } = require('../src/utils/s3MicrositeV2');
|
|
const { publishStaticMicrosite } = require('../src/utils/publishStaticMicrosite');
|
|
const { resolveConfigAssetUrls } = require('../src/utils/micrositeConfigAssets');
|
|
|
|
const DEFAULT_EVENT_ID = '6a4cb75a7475c040cc6f2dd7';
|
|
const DEFAULT_SUBDOMAIN = 'novel2026-goa-8-9-aug';
|
|
const TEMPLATE_SLUG = 'crest-novel';
|
|
const SITE_JSON = path.join(__dirname, '..', '..', 'microsites', 'crest-novel', 'site.json');
|
|
const PUBLIC_WEB_BASE = (process.env.PUBLIC_WEB_BASE || 'https://web.eventbuzz.live').replace(/\/$/, '');
|
|
|
|
function argValue(name, fallback) {
|
|
const hit = process.argv.find((a) => a.startsWith(`--${name}=`));
|
|
return hit ? hit.split('=').slice(1).join('=').trim() : fallback;
|
|
}
|
|
|
|
function deepClone(obj) {
|
|
return JSON.parse(JSON.stringify(obj));
|
|
}
|
|
|
|
function replaceEventIds(obj, oldId, newId) {
|
|
if (obj == null) return obj;
|
|
if (typeof obj === 'string') {
|
|
return obj.split(oldId).join(newId);
|
|
}
|
|
if (Array.isArray(obj)) return obj.map((v) => replaceEventIds(v, oldId, newId));
|
|
if (typeof obj === 'object') {
|
|
const out = {};
|
|
for (const [k, v] of Object.entries(obj)) out[k] = replaceEventIds(v, oldId, newId);
|
|
return out;
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
function siteJsonToConfig(site, eventId) {
|
|
const theme = site.theme || {};
|
|
const headingColor = theme.heading?.color || theme.headingColor || '#015AAA';
|
|
return {
|
|
meta: {
|
|
title: site.meta?.title || 'NOVEL Lung Health Summit',
|
|
eventId: String(eventId),
|
|
},
|
|
theme: {
|
|
accent: theme.accent || '#189A95',
|
|
headingColor,
|
|
},
|
|
sections: deepClone(site.components || {}),
|
|
};
|
|
}
|
|
|
|
async function findSeedUser() {
|
|
const userIdArg = argValue('user-id', '');
|
|
if (userIdArg) {
|
|
const u = await User.findById(userIdArg);
|
|
if (u) return u;
|
|
}
|
|
const platform = await User.findOne({ platform_admin: 'yes', isActive: { $ne: false } }).sort({ createdAt: 1 });
|
|
if (platform) return platform;
|
|
const superAdmin = await User.findOne({ role: 'super_admin' }).sort({ createdAt: 1 });
|
|
if (superAdmin) return superAdmin;
|
|
throw new Error('No user found for updatedBy/publish. Pass --user-id=<mongoId>');
|
|
}
|
|
|
|
async function findRegistrationForm(eventId) {
|
|
return Form.findOne({ event: eventId, type: 'registration', 'settings.isActive': { $ne: false } })
|
|
.sort({ createdAt: 1 })
|
|
.select('_id name')
|
|
.lean();
|
|
}
|
|
|
|
async function findFeedbackForm(eventId) {
|
|
return Form.findOne({ event: eventId, type: 'feedback', 'settings.isActive': { $ne: false } })
|
|
.sort({ createdAt: 1 })
|
|
.select('_id name')
|
|
.lean();
|
|
}
|
|
|
|
function applyEventUrls(config, eventId, registrationFormId, feedbackFormId, eventDoc) {
|
|
const regUrl = registrationFormId
|
|
? `${PUBLIC_WEB_BASE}/event/${eventId}/form/${registrationFormId}`
|
|
: `${PUBLIC_WEB_BASE}/event/${eventId}/register`;
|
|
const feedbackUrl = feedbackFormId
|
|
? `${PUBLIC_WEB_BASE}/event/${eventId}/form/${feedbackFormId}`
|
|
: null;
|
|
|
|
const sections = config.sections || {};
|
|
|
|
if (sections.hero?.cta) {
|
|
sections.hero.cta.url = regUrl;
|
|
sections.hero.cta.target = '_blank';
|
|
}
|
|
if (sections.footer?.links && Array.isArray(sections.footer.links)) {
|
|
for (const link of sections.footer.links) {
|
|
if (link.text && /register/i.test(link.text)) link.url = regUrl;
|
|
if (link.text && /feedback/i.test(link.text) && feedbackUrl) link.url = feedbackUrl;
|
|
}
|
|
}
|
|
if (sections.feedback && feedbackUrl) {
|
|
sections.feedback.url = feedbackUrl;
|
|
}
|
|
|
|
if (eventDoc?.banner && sections.hero?.image) {
|
|
sections.hero.image.url = eventDoc.banner;
|
|
}
|
|
|
|
return config;
|
|
}
|
|
|
|
async function syncTemplateSiteConfigJs() {
|
|
const siteConfigPath = path.join(
|
|
__dirname,
|
|
'..',
|
|
'microsite-v2-templates',
|
|
TEMPLATE_SLUG,
|
|
'assets',
|
|
'js',
|
|
'site-config.js',
|
|
);
|
|
if (!fs.existsSync(siteConfigPath)) {
|
|
throw new Error(`Missing site-config.js at ${siteConfigPath}`);
|
|
}
|
|
await uploadTemplateAsset(
|
|
TEMPLATE_SLUG,
|
|
'js/site-config.js',
|
|
fs.readFileSync(siteConfigPath),
|
|
'application/javascript',
|
|
);
|
|
console.log('Uploaded crest-novel site-config.js to template assets');
|
|
}
|
|
|
|
async function main() {
|
|
const eventId = argValue('event-id', DEFAULT_EVENT_ID);
|
|
const subdomainRaw = argValue('subdomain', DEFAULT_SUBDOMAIN);
|
|
const shouldPublish = process.argv.includes('--publish');
|
|
|
|
if (!mongoose.Types.ObjectId.isValid(eventId)) {
|
|
throw new Error(`Invalid event id: ${eventId}`);
|
|
}
|
|
|
|
if (!fs.existsSync(SITE_JSON)) {
|
|
throw new Error(`Missing site.json at ${SITE_JSON}`);
|
|
}
|
|
|
|
await connectDB();
|
|
|
|
const event = await Event.findById(eventId).lean();
|
|
if (!event) throw new Error(`Event not found: ${eventId}`);
|
|
|
|
const template = await MicrositeV2Template.findOne({ slug: TEMPLATE_SLUG, isActive: true });
|
|
if (!template) {
|
|
throw new Error(`Active template "${TEMPLATE_SLUG}" not found. Run: npm run seed:crest-novel-template`);
|
|
}
|
|
|
|
const user = await findSeedUser();
|
|
const subdomain = normalizeSubdomain(subdomainRaw);
|
|
if (!subdomain) throw new Error(`Invalid subdomain: ${subdomainRaw}`);
|
|
|
|
const existing = await EventStaticMicrosite.findOne({ event: eventId });
|
|
const avail = await subdomainAvailability(subdomain, eventId, existing?._id?.toString());
|
|
if (!avail.available) throw new Error(avail.message || 'Subdomain not available');
|
|
|
|
const site = JSON.parse(fs.readFileSync(SITE_JSON, 'utf8'));
|
|
const oldEventId = site.meta?.eventId || '6a43e05fdc940a0d6e057f7b';
|
|
|
|
let config = siteJsonToConfig(site, eventId);
|
|
config = replaceEventIds(config, oldEventId, eventId);
|
|
|
|
const registrationForm = await findRegistrationForm(eventId);
|
|
const feedbackForm = await findFeedbackForm(eventId);
|
|
config = applyEventUrls(config, eventId, registrationForm?._id, feedbackForm?._id, event);
|
|
config.sections = resolveConfigAssetUrls(config.sections || {}, template.assetsBaseUrl);
|
|
|
|
await syncTemplateSiteConfigJs();
|
|
|
|
const payload = {
|
|
event: event._id,
|
|
organization: event.organization,
|
|
subdomain,
|
|
template: template._id,
|
|
config,
|
|
status: 'draft',
|
|
updatedBy: user._id,
|
|
};
|
|
|
|
let siteDoc;
|
|
if (existing) {
|
|
Object.assign(existing, payload);
|
|
await existing.save();
|
|
siteDoc = existing;
|
|
console.log(`Updated EventStaticMicrosite: ${existing._id}`);
|
|
} else {
|
|
siteDoc = await EventStaticMicrosite.create(payload);
|
|
console.log(`Created EventStaticMicrosite: ${siteDoc._id}`);
|
|
}
|
|
|
|
console.log(`Event: ${event.name} (${eventId})`);
|
|
console.log(`Template: ${template.name} (${template.slug})`);
|
|
console.log(`Subdomain: ${subdomain}`);
|
|
console.log(`Reg form: ${registrationForm?._id || '(none — using /register fallback)'}`);
|
|
console.log(`Feedback: ${feedbackForm?._id || '(none)'}`);
|
|
|
|
if (shouldPublish) {
|
|
console.log('Publishing...');
|
|
const populated = await EventStaticMicrosite.findById(siteDoc._id).populate('template');
|
|
const result = await publishStaticMicrosite({
|
|
staticMicrosite: populated,
|
|
template: populated.template,
|
|
userId: user._id,
|
|
});
|
|
Object.assign(populated, result);
|
|
await populated.save();
|
|
console.log(`Published: ${result.publicUrl}`);
|
|
} else {
|
|
console.log('Saved as draft. Re-run with --publish to publish.');
|
|
}
|
|
|
|
await mongoose.disconnect();
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error(err);
|
|
process.exit(1);
|
|
});
|