UNPKG

@ima/cli

Version:

IMA.js CLI tool to build, develop and work with IMA.js applications.

125 lines (124 loc) 4.59 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.builder = exports.handler = exports.describe = exports.command = void 0; const child_process_1 = require("child_process"); const promises_1 = __importDefault(require("fs/promises")); const path_1 = __importDefault(require("path")); const logger_1 = require("@ima/dev-utils/logger"); const cli_1 = require("../lib/cli"); const utils_1 = require("../webpack/utils/utils"); /** * Wait for the server to start. */ async function waitForServer(port, maxAttempts = 30) { for (let i = 0; i < maxAttempts; i++) { try { await fetch(`http://localhost:${port}`); return; } catch { await new Promise(resolve => setTimeout(resolve, 1000)); } } throw new Error('Server failed to start'); } /** * Prerender a single URL: * - Fetch the HTML content * - Return the URL and HTML content */ async function preRenderPath(path, baseUrl) { const url = new URL(path, baseUrl); const response = await fetch(url.toString()); const html = await response.text(); return { url: url.toString(), html }; } /** * Convert URL to filename: * - Remove leading and trailing slashes * - Replace remaining slashes with underscores * - Add mode and .html extension */ function getOutputFilename(url, mode) { const pathname = new URL(url).pathname; const urlPath = pathname === '/' ? '' : pathname.replace(/^\/|\/$/g, '').replace(/\//g, '_'); return `${mode}${urlPath ? `-${urlPath}` : ''}.html`; } const prerender = async (args) => { try { // Parse paths to prerender const paths = args.paths ? Array.isArray(args.paths) ? args.paths : [args.paths] : ['/']; // Build the application first logger_1.logger.info('Building application...'); await (0, cli_1.runCommand)('ima', ['build'], { ...args, }); // Load environment to get the application port const environment = (0, utils_1.resolveEnvironment)(args.rootDir); // Start the server with appropriate mode const { preRenderMode } = args; if (!preRenderMode) { throw new Error('Prerender mode is required'); } logger_1.logger.info(`Starting server in ${preRenderMode.toUpperCase()} mode...`); const port = environment.$Server.port ?? 3001; const hostname = environment.$Server.host ?? 'localhost'; const serverProcess = (0, child_process_1.spawn)('ima', ['start'], { stdio: 'inherit', env: { ...process.env, ...(preRenderMode === 'spa' ? { IMA_CLI_FORCE_SPA: 'true' } : {}), }, }); // Wait for server to start await waitForServer(port); const baseUrl = `http://${hostname}:${port}`; // Create output directory if it doesn't exist const outputDir = path_1.default.resolve(args.rootDir, 'build'); await promises_1.default.mkdir(outputDir, { recursive: true }); // Prerender all URLs logger_1.logger.info(`Prerendering ${paths.length} Path(s)...`); const results = await Promise.all(paths.map(path => preRenderPath(path, baseUrl))); // Write results to disk for (const result of results) { const outputPath = path_1.default.join(outputDir, getOutputFilename(result.url, preRenderMode)); await promises_1.default.writeFile(outputPath, result.html); logger_1.logger.info(`Prerendered ${result.url} -> ${outputPath}`); } // Clean up serverProcess.kill(); process.exit(0); } catch (error) { logger_1.logger.error(error instanceof Error ? error : new Error('Unknown prerender error')); process.exit(1); } }; const CMD = 'prerender'; exports.command = CMD; exports.describe = 'Prerender application as static HTML'; exports.handler = (0, cli_1.handlerFactory)(prerender); exports.builder = { ...(0, cli_1.sharedArgsFactory)(CMD), preRenderMode: { desc: 'Prerender mode (spa or ssr)', type: 'string', choices: ['spa', 'ssr'], default: 'spa', }, paths: { desc: 'Path(s) to prerender (defaults to /)', type: 'array', string: true, }, ...(0, cli_1.resolveCliPluginArgs)(CMD), };