UNPKG

polen

Version:

A framework for delightful GraphQL developer portals

110 lines 4.24 kB
import { TinyGlobby } from '#dep/tiny-globby/index'; import { Fs, Path } from '@wollybeard/kit'; import { Err } from '@wollybeard/kit'; import { buildManifest } from './manifest.js'; export const rebase = async (plan) => { // 1. Validate source is a Polen build const manifestResult = await buildManifest.read(plan.sourcePath); if (Err.is(manifestResult)) { throw new Error(`Polen build manifest not found at: ${Path.join(plan.sourcePath, `.polen`, `build.json`)}`); } const manifest = manifestResult; // 2. Validate newBasePath is valid URL path if (!isValidUrlPath(plan.newBasePath)) { throw new Error(`Invalid base path: ${plan.newBasePath}`); } // 3. Handle copy vs mutate let workingPath; if (plan.changeMode === `copy`) { if (await Fs.exists(plan.targetPath)) { const isEmpty = await Fs.isEmptyDir(plan.targetPath); if (!isEmpty) { throw new Error(`Target path already exists and is not empty: ${plan.targetPath}`); } } await Fs.copyDir({ from: plan.sourcePath, to: plan.targetPath }); workingPath = plan.targetPath; } else { workingPath = plan.sourcePath; } // 4. Update HTML files with new base path await updateHtmlFiles(workingPath, manifest.basePath, plan.newBasePath); // 5. Update manifest await updateManifest(workingPath, { basePath: plan.newBasePath }); }; // // // // // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ • Local Helpers // // // TODO: this is very generic, factor out to kit-temp const isValidUrlPath = (path) => { // URL path should start with / and not contain invalid characters if (!path.startsWith(`/`)) return false; if (!path.endsWith(`/`)) return false; // Basic validation - no spaces, proper URL characters const urlPathRegex = /^\/[a-zA-Z0-9\-._~:/?#[\]@!$&'()*+,;=%]*\/$/; return urlPathRegex.test(path); }; const updateHtmlFiles = async (buildPath, oldBasePath, newBasePath) => { // Find all HTML files recursively const htmlFiles = await findHtmlFiles(buildPath); for (const htmlFile of htmlFiles) { await updateHtmlFile(htmlFile, oldBasePath, newBasePath); } }; const findHtmlFiles = async (dir) => { return await TinyGlobby.glob(`**/*.html`, { absolute: true, cwd: dir, onlyFiles: true, }); }; const updateHtmlFile = async (filePath, oldBasePath, newBasePath) => { const content = await Fs.read(filePath); if (content === null) { throw new Error(`Could not read HTML file: ${filePath}`); } // Simple regex-based approach to update base tag // Look for existing base tag first const baseTagRegex = /<base\s+href\s*=\s*["']([^"']*)["'][^>]*>/i; let updatedContent; if (baseTagRegex.test(content)) { // Update existing base tag updatedContent = content.replace(baseTagRegex, `<base href="${newBasePath}">`); } else { // Insert new base tag in head const headRegex = /<head[^>]*>/i; const headMatch = headRegex.exec(content); if (headMatch) { const insertPosition = headMatch.index + headMatch[0].length; updatedContent = content.slice(0, insertPosition) + `\n <base href="${newBasePath}">` + content.slice(insertPosition); } else { throw new Error(`Could not find <head> tag in HTML file: ${filePath}`); } } await Fs.write({ path: filePath, content: updatedContent }); }; const updateManifest = async (buildPath, updates) => { const manifestPath = Path.join(buildPath, `.polen`, `build.json`); const manifestResult = await buildManifest.read(buildPath); if (Err.is(manifestResult)) { throw new Error(`Polen build manifest not found at: ${manifestPath}`); } const currentManifest = manifestResult; const updatedManifest = { ...currentManifest, ...updates }; await Fs.write({ path: manifestPath, content: JSON.stringify(updatedManifest, null, 2), }); }; //# sourceMappingURL=rebase.js.map