UNPKG

sb-mig

Version:

CLI to rule the world. (and handle stuff related to Storyblok CMS)

145 lines (144 loc) 4.89 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.extractComponentName = void 0; exports.precompile = precompile; exports.getCompiledPath = getCompiledPath; const promises_1 = require("fs/promises"); const path_1 = __importDefault(require("path")); const plugin_swc_1 = __importDefault(require("@rollup/plugin-swc")); const rollup_1 = require("rollup"); /** * Extract the component name from a file path. * Handles both POSIX (`/`) and Windows (`\`) separators because glob v11 * and node's `fs` APIs return native paths on Windows. * * e.g., "/path/to/my-component.sb.ts" -> "my-component.sb" * "C:\\path\\to\\my-component.sb.ts" -> "my-component.sb" */ const extractComponentName = (filePath) => { const normalized = filePath.replace(/\\/g, "/"); const lastElement = normalized.substring(normalized.lastIndexOf("/") + 1); return lastElement.replace(/\.ts$/, ""); }; exports.extractComponentName = extractComponentName; /** * Build a single file using Rollup */ async function buildFile(inputPath, outputCjs, outputEsm) { const inputOptions = { input: inputPath, plugins: [ (0, plugin_swc_1.default)({ swc: { jsc: { parser: { syntax: "typescript", }, }, }, }), ], }; const outputOptionsList = [ { file: outputCjs, format: "cjs" }, { file: outputEsm, format: "es" }, ]; let bundle; try { bundle = await (0, rollup_1.rollup)(inputOptions); for (const outputOptions of outputOptionsList) { await bundle.write(outputOptions); } } finally { if (bundle) { await bundle.close(); } } } /** * Precompile TypeScript schema files to JavaScript * * This uses Rollup with SWC for fast transpilation, producing * both CommonJS (.cjs) and ESM (.js) outputs. * * @param files - Array of TypeScript file paths to compile * @param options - Precompile options * @returns Result with compiled files and any errors * * @example * ```ts * const result = await precompile([ * '/path/to/hero.sb.ts', * '/path/to/card.sb.ts', * ], { cacheDir: '.cache/sb-mig' }); * * // Use compiled CJS files * for (const compiled of result.compiled) { * const content = require(compiled.outputCjs); * } * ``` */ async function precompile(files, options = {}) { const { cacheDir = ".sb-mig-cache", flushCache = true, projectDir = process.cwd(), } = options; const fullCacheDir = path_1.default.join(projectDir, cacheDir, "sb-mig"); // Optionally clear cache if (flushCache) { try { await (0, promises_1.rm)(fullCacheDir, { recursive: true, force: true }); } catch { // Ignore if doesn't exist } } // Ensure cache directory exists await (0, promises_1.mkdir)(fullCacheDir, { recursive: true }); const result = { compiled: [], errors: [], }; // Filter to only TypeScript files const tsFiles = files.filter((f) => f.endsWith(".ts")); if (tsFiles.length === 0) { return result; } // Compile all files in parallel await Promise.all(tsFiles.map(async (inputPath) => { const componentName = (0, exports.extractComponentName)(inputPath); const outputCjs = path_1.default.join(fullCacheDir, `${componentName}.cjs`); const outputEsm = path_1.default.join(fullCacheDir, `${componentName}.js`); try { await buildFile(inputPath, outputCjs, outputEsm); result.compiled.push({ input: inputPath, outputCjs, outputEsm, }); } catch (error) { result.errors.push({ input: inputPath, error: error instanceof Error ? error.message : String(error), }); } })); return result; } /** * Get the compiled file path for a TypeScript source file * * @param tsFilePath - Original .ts file path * @param options - Options with cacheDir and projectDir * @param format - Output format ('cjs' or 'esm') * @returns Path to the compiled file */ function getCompiledPath(tsFilePath, options = {}, format = "cjs") { const { cacheDir = ".sb-mig-cache", projectDir = process.cwd() } = options; const fullCacheDir = path_1.default.join(projectDir, cacheDir, "sb-mig"); const componentName = (0, exports.extractComponentName)(tsFilePath); const ext = format === "cjs" ? ".cjs" : ".js"; return path_1.default.join(fullCacheDir, `${componentName}${ext}`); }