Files
hapi/hub/scripts/generate-embedded-web-assets.ts
weishu 37e10a831b feat: rename server package to hub
Rename the `server/` directory to `hub/` and update all references
across CLI, docs, web, and workspace configuration.
2026-01-27 19:51:21 +08:00

114 lines
3.7 KiB
TypeScript

import { dirname, extname, join, relative, sep } from 'node:path';
import { existsSync, readdirSync, writeFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
const MIME_TYPES: Record<string, string> = {
'.css': 'text/css; charset=utf-8',
'.gif': 'image/gif',
'.html': 'text/html; charset=utf-8',
'.ico': 'image/x-icon',
'.jpeg': 'image/jpeg',
'.jpg': 'image/jpeg',
'.js': 'text/javascript; charset=utf-8',
'.json': 'application/json; charset=utf-8',
'.map': 'application/json; charset=utf-8',
'.mjs': 'text/javascript; charset=utf-8',
'.otf': 'font/otf',
'.png': 'image/png',
'.svg': 'image/svg+xml',
'.ttf': 'font/ttf',
'.txt': 'text/plain; charset=utf-8',
'.wasm': 'application/wasm',
'.webmanifest': 'application/manifest+json; charset=utf-8',
'.webp': 'image/webp',
'.woff': 'font/woff',
'.woff2': 'font/woff2',
'.xml': 'application/xml; charset=utf-8'
};
function toPosixPath(filePath: string): string {
return filePath.split(sep).join('/');
}
function listFiles(rootDir: string, currentDir = rootDir): string[] {
const entries = readdirSync(currentDir, { withFileTypes: true });
const files: string[] = [];
for (const entry of entries) {
const entryPath = join(currentDir, entry.name);
if (entry.isDirectory()) {
files.push(...listFiles(rootDir, entryPath));
continue;
}
if (entry.isFile()) {
files.push(entryPath);
}
}
return files;
}
function resolveMimeType(filePath: string): string {
const ext = extname(filePath).toLowerCase();
return MIME_TYPES[ext] ?? 'application/octet-stream';
}
function main(): void {
const scriptDir = dirname(fileURLToPath(import.meta.url));
const workspaceRoot = join(scriptDir, '..', '..');
const webDistDir = join(workspaceRoot, 'web', 'dist');
const outputPath = join(workspaceRoot, 'hub', 'src', 'web', 'embeddedAssets.generated.ts');
const outputDir = dirname(outputPath);
if (!existsSync(webDistDir)) {
throw new Error(`Missing web/dist directory: ${webDistDir}. Run bun run build:web first.`);
}
const indexHtmlPath = join(webDistDir, 'index.html');
if (!existsSync(indexHtmlPath)) {
throw new Error(`Missing web/dist/index.html. Run bun run build:web first.`);
}
const files = listFiles(webDistDir).sort((a, b) => a.localeCompare(b));
if (files.length === 0) {
throw new Error(`No files found in web/dist: ${webDistDir}.`);
}
const imports: string[] = [];
const manifestLines: string[] = [];
files.forEach((filePath, index) => {
const relativeToDist = toPosixPath(relative(webDistDir, filePath));
const requestPath = `/${relativeToDist}`;
const importPath = toPosixPath(relative(outputDir, filePath));
const importName = `asset${index}`;
const mimeType = resolveMimeType(filePath);
imports.push(`import ${importName} from '${importPath}' assert { type: 'file' };`);
manifestLines.push(` { path: '${requestPath}', sourcePath: ${importName}, mimeType: '${mimeType}' },`);
});
const output = [
'// This file is generated by hub/scripts/generate-embedded-web-assets.ts.',
'// Do not edit by hand.',
'',
...imports,
'',
'export interface EmbeddedWebAsset {',
' path: string;',
' sourcePath: string;',
' mimeType: string;',
'}',
'',
'export const embeddedAssets: EmbeddedWebAsset[] = [',
...manifestLines,
'];',
''
].join('\n');
writeFileSync(outputPath, output, 'utf-8');
console.log(`[embedded-assets] Wrote ${files.length} assets to ${outputPath}`);
}
main();