EventBuzz_Backend/scripts/seed-crest-novel-template.js

186 lines
6.5 KiB
JavaScript

#!/usr/bin/env node
/**
* Seed the CREST NOVEL microsite-v2 template.
*
* Usage: node scripts/seed-crest-novel-template.js [--user-id=<mongoId>] [--db-only]
*/
require('dotenv').config();
const fs = require('fs');
const path = require('path');
const mongoose = require('mongoose');
const { connectDB } = require('../src/config/database');
const MicrositeV2Template = require('../src/models/MicrositeV2Template');
const User = require('../src/models/User');
const {
uploadTemplateFile,
uploadTemplateAsset,
templateAssetsBaseUrl,
} = require('../src/utils/s3MicrositeV2');
const { parseTemplateSchema } = require('../src/utils/templateSchema');
const SLUG = 'crest-novel';
const TEMPLATE_DIR = path.join(__dirname, '..', 'microsite-v2-templates', SLUG);
const TEMPLATE_ASSETS = path.join(TEMPLATE_DIR, 'assets');
const SOURCE_ASSETS = path.join(__dirname, '..', '..', 'microsites', 'crest-novel', 'assets');
async function findSeedUser(userIdArg) {
if (userIdArg) {
const u = await User.findById(userIdArg);
if (u) return u;
}
const superAdmin = await User.findOne({ role: 'super_admin' }).sort({ createdAt: 1 });
if (superAdmin) return superAdmin;
throw new Error('No super_admin user found. Pass --user-id=<mongoId>');
}
function walkDir(dir, base = dir) {
const files = [];
if (!fs.existsSync(dir)) return files;
for (const name of fs.readdirSync(dir)) {
const full = path.join(dir, name);
const stat = fs.statSync(full);
if (stat.isDirectory()) {
files.push(...walkDir(full, base));
} else {
files.push({ full, rel: path.relative(base, full).replace(/\\/g, '/') });
}
}
return files;
}
function mimeFor(filePath) {
if (filePath.endsWith('.css')) return 'text/css';
if (filePath.endsWith('.js')) return 'application/javascript';
if (filePath.endsWith('.woff')) return 'font/woff';
if (filePath.endsWith('.woff2')) return 'font/woff2';
if (filePath.endsWith('.ttf')) return 'font/ttf';
if (filePath.endsWith('.eot')) return 'application/vnd.ms-fontobject';
if (filePath.endsWith('.png')) return 'image/png';
if (filePath.endsWith('.jpg') || filePath.endsWith('.jpeg')) return 'image/jpeg';
if (filePath.endsWith('.svg')) return 'image/svg+xml';
return 'application/octet-stream';
}
/** IcoMoon exports use filenames like LineIcons.woff?y2l643 — normalize for S3 keys. */
function normalizeAssetRelPath(rel) {
const base = String(rel).replace(/\\/g, '/');
const fontsMatch = base.match(/^fonts\/LineIcons\.(woff2?|ttf|eot|svg)\?/i);
if (fontsMatch) {
return `fonts/LineIcons.${fontsMatch[1].toLowerCase()}`;
}
return base;
}
async function main() {
const dbOnly = process.argv.includes('--db-only');
const userIdArg = (process.argv.find((a) => a.startsWith('--user-id=')) || '').split('=')[1];
await connectDB();
const user = await findSeedUser(userIdArg);
console.log(`Using user: ${user.email || user._id}`);
const htmlPath = path.join(TEMPLATE_DIR, 'template.html');
const jsonPath = path.join(TEMPLATE_DIR, 'template.json');
if (!fs.existsSync(htmlPath) || !fs.existsSync(jsonPath)) {
throw new Error(`Missing template files in ${TEMPLATE_DIR}`);
}
const htmlBuf = fs.readFileSync(htmlPath);
const jsonBuf = fs.readFileSync(jsonPath);
const schema = parseTemplateSchema(jsonBuf);
let htmlS3Key;
let schemaS3Key;
let thumbnailUrl;
let assetsBaseUrl = templateAssetsBaseUrl(SLUG);
if (!dbOnly && process.env.AWS_BUCKET) {
console.log('Uploading template.html...');
const htmlUp = await uploadTemplateFile(SLUG, 'template.html', htmlBuf, 'text/html; charset=utf-8');
htmlS3Key = htmlUp.s3Key;
console.log('Uploading template.json...');
const jsonUp = await uploadTemplateFile(SLUG, 'template.json', jsonBuf, 'application/json');
schemaS3Key = jsonUp.s3Key;
const thumbCandidates = [
path.join(TEMPLATE_DIR, 'thumbnail.jpg'),
path.join(TEMPLATE_DIR, 'thumbnail.png'),
path.join(SOURCE_ASSETS, 'img', 'hero.jpg'),
path.join(SOURCE_ASSETS, 'img', 'novel-logo.png'),
];
for (const tp of thumbCandidates) {
if (fs.existsSync(tp)) {
const ext = path.extname(tp).slice(1) || 'jpg';
const thumbUp = await uploadTemplateFile(
SLUG,
`thumbnail.${ext}`,
fs.readFileSync(tp),
`image/${ext === 'jpg' ? 'jpeg' : ext}`,
);
thumbnailUrl = thumbUp.url;
break;
}
}
if (!thumbnailUrl) {
const placeholder = Buffer.from(
'<svg xmlns="http://www.w3.org/2000/svg" width="400" height="240"><rect fill="#015AAA" width="400" height="240"/><text x="50%" y="50%" fill="#fff" text-anchor="middle" dy=".3em" font-family="sans-serif" font-size="22">CREST NOVEL</text></svg>',
);
const thumbUp = await uploadTemplateFile(SLUG, 'thumbnail.svg', placeholder, 'image/svg+xml');
thumbnailUrl = thumbUp.url;
}
const assetRoots = [TEMPLATE_ASSETS, SOURCE_ASSETS];
for (const root of assetRoots) {
if (!fs.existsSync(root)) continue;
console.log(`Uploading assets from ${root}...`);
for (const { full, rel } of walkDir(root)) {
const normalizedRel = normalizeAssetRelPath(rel);
if (normalizedRel !== rel && fs.existsSync(path.join(root, normalizedRel))) {
continue;
}
await uploadTemplateAsset(SLUG, normalizedRel, fs.readFileSync(full), mimeFor(normalizedRel));
}
}
assetsBaseUrl = templateAssetsBaseUrl(SLUG);
console.log('S3 upload complete.');
} else {
console.log('Skipping S3 upload (--db-only or AWS_BUCKET not set).');
}
const existing = await MicrositeV2Template.findOne({ slug: SLUG });
const doc = {
slug: SLUG,
name: 'CREST NOVEL',
description:
'CREST / NOVEL lung health summit microsite — marketing popup, dual about sections, expert videos, tabbed speakers, schedule, sponsors, contact form, and feedback FAB.',
thumbnailUrl: thumbnailUrl || '',
htmlS3Key: htmlS3Key || '',
schemaS3Key: schemaS3Key || '',
schema,
assetsBaseUrl,
assetsS3Prefix: `templates/${SLUG}/assets`,
isActive: Boolean(htmlS3Key && schemaS3Key),
version: 1,
createdBy: user._id,
};
if (existing) {
Object.assign(existing, doc);
await existing.save();
console.log(`Updated MicrositeV2Template: ${existing._id}`);
} else {
const created = await MicrositeV2Template.create(doc);
console.log(`Created MicrositeV2Template: ${created._id}`);
}
await mongoose.disconnect();
console.log('Done.');
}
main().catch((err) => {
console.error(err);
process.exit(1);
});