import JSZip from 'jszip';
import type { FormSchema, LayoutState } from 'shared';
import {
generateFieldsJson,
generateModuleHtml,
generateModuleCss,
generateModuleJs,
} from './moduleGenerators';
function sanitizeModuleName(name: string): string {
return name
.trim()
.replace(/[^a-zA-Z0-9-_\s]/g, '')
.replace(/\s+/g, '-')
.toLowerCase();
}
function generateMetaJson(schema: FormSchema) {
const moduleId = crypto.randomUUID();
return {
label: schema.name,
icon: 'form',
css_assets: [],
external_dependencies: [],
extra_body_html: '',
global: false,
help_text: '',
host_template_types: ['PAGE', 'BLOG_POST', 'BLOG_LISTING'],
js_assets: [],
module_id: moduleId,
other_assets: [],
smart_type: 'NOT_SMART',
tags: [],
is_available_for_new_content: true,
};
}
export async function generateModule(schema: FormSchema, layout: LayoutState): Promise<Blob> {
const zip = new JSZip();
const moduleName = sanitizeModuleName(schema.name);
const moduleFolder = zip.folder(`${moduleName}.module`);
if (!moduleFolder) {
throw new Error('Failed to create module folder in ZIP');
}
// Generate all files
const fieldsJson = generateFieldsJson(schema, layout);
const moduleHtml = generateModuleHtml();
const moduleCss = generateModuleCss();
const moduleJs = generateModuleJs();
const metaJson = generateMetaJson(schema);
// Add files to ZIP
moduleFolder.file('fields.json', JSON.stringify(fieldsJson, null, 2));
moduleFolder.file('module.html', moduleHtml);
moduleFolder.file('module.css', moduleCss);
moduleFolder.file('module.js', moduleJs);
moduleFolder.file('meta.json', JSON.stringify(metaJson, null, 2));
// Generate blob
const blob = await zip.generateAsync({
type: 'blob',
compression: 'DEFLATE',
compressionOptions: { level: 6 },
});
return blob;
}
export function downloadModule(blob: Blob, moduleName: string): void {
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = `${sanitizeModuleName(moduleName)}.zip`;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
setTimeout(() => {
document.body.removeChild(link);
URL.revokeObjectURL(url);
}, 100);
}