Files
landing-builder/lib/exporter/zip.ts
2025-11-15 00:11:05 +09:00

43 lines
1.3 KiB
TypeScript

import JSZip from 'jszip'
export type BuildZipInput = {
html: string
css: string
js: string
assets?: Record<string, Uint8Array>
// root-level extra files like favicon.ico, site.webmanifest, robots.txt
extras?: Record<string, Uint8Array>
}
export async function buildZip(input: BuildZipInput): Promise<Uint8Array> {
const zip = new JSZip()
zip.file('index.html', input.html)
zip.file('styles.css', input.css)
zip.file('app.js', input.js)
if (input.assets) {
for (const [path, bytes] of Object.entries(input.assets)) {
// In Node/Vitest, use Buffer for robust binary handling
const buf = Buffer.from(bytes)
zip.file(path, buf as unknown as Buffer)
}
}
if (input.extras) {
// validate manifest if present
if (Object.prototype.hasOwnProperty.call(input.extras, 'site.webmanifest')) {
try {
const manifestBytes = input.extras['site.webmanifest']
const manifestStr = Buffer.from(manifestBytes).toString('utf8')
JSON.parse(manifestStr)
} catch {
throw new Error('Invalid site.webmanifest JSON')
}
}
for (const [path, bytes] of Object.entries(input.extras)) {
const buf = Buffer.from(bytes)
zip.file(path, buf as unknown as Buffer)
}
}
const content = await zip.generateAsync({ type: 'uint8array' })
return content
}