@monitoro/herd
Version:
Automate your browser, build AI web tools and MCP servers with Monitoro Herd
134 lines (133 loc) • 5.11 kB
JavaScript
import { fileURLToPath } from 'url';
import { dirname, join, relative } from 'path';
import * as fs from 'fs';
import * as esbuild from 'esbuild';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
export async function buildTrail(trailPath, options = {}) {
const { outDir = join(trailPath, '.build'), format = 'esm', platform = 'node', target = 'node18', silent = false, minify = true, treeShaking = true } = options;
// Ensure trailPath is absolute
trailPath = fs.realpathSync(trailPath);
// Create build directory if it doesn't exist
if (!fs.existsSync(outDir)) {
fs.mkdirSync(outDir, { recursive: true });
}
// Common build options
const commonOptions = {
format,
platform,
target,
bundle: true,
sourcemap: true,
outdir: outDir,
external: ['@monitoro/herd'],
define: {
'process.env.NODE_ENV': '"production"'
},
logLevel: silent ? 'silent' : 'info',
color: true,
minify,
minifyWhitespace: minify,
minifyIdentifiers: minify,
minifySyntax: minify,
treeShaking,
legalComments: 'none',
ignoreAnnotations: false,
};
// Build each file
const files = ['actions.ts', 'urls.ts', 'selectors.ts'];
const buildPromises = files.map(async (file) => {
const entryPoint = join(trailPath, file);
if (!fs.existsSync(entryPoint)) {
if (!silent) {
console.warn(`⚠️ Warning: ${file} not found in trail directory`);
}
return;
}
try {
// Get source file size for comparison
const sourceStats = fs.statSync(entryPoint);
const sourceSize = sourceStats.size;
await esbuild.build({
...commonOptions,
entryPoints: [entryPoint],
outdir: outDir
});
// Get built file size
const outputFile = join(outDir, file.replace('.ts', '.js'));
if (fs.existsSync(outputFile)) {
const outputStats = fs.statSync(outputFile);
const outputSize = outputStats.size;
const reductionPercent = sourceSize > 0
? Math.round((1 - (outputSize / sourceSize)) * 100)
: 0;
if (!silent) {
console.log(`✨ Built ${relative(trailPath, entryPoint)} (${formatFileSize(sourceSize)} → ${formatFileSize(outputSize)}, ${reductionPercent > 0 ? '-' : '+'}${Math.abs(reductionPercent)}%)`);
}
}
else {
if (!silent) {
console.log(`✨ Built ${relative(trailPath, entryPoint)}`);
}
}
}
catch (error) {
if (!silent) {
console.error(`❌ Failed to build ${relative(trailPath, entryPoint)}:`, error);
}
throw error;
}
});
await Promise.all(buildPromises);
// Process package.json if it exists
const packageJsonPath = join(trailPath, 'package.json');
if (fs.existsSync(packageJsonPath)) {
try {
// Read and parse the existing package.json
const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8');
const packageJson = JSON.parse(packageJsonContent);
// Ensure type module is set
packageJson.type = "module";
// Write the modified package.json to the output directory
fs.writeFileSync(join(outDir, 'package.json'), JSON.stringify(packageJson, null, 2));
if (!silent) {
console.log(`✨ Processed package.json (ensured type: module is set)`);
}
}
catch (error) {
if (!silent) {
console.error(`⚠️ Warning: Failed to process package.json:`, error);
// Fall back to direct copy if parsing fails
fs.copyFileSync(packageJsonPath, join(outDir, 'package.json'));
console.log(`✨ Copied package.json (fallback)`);
}
}
}
return outDir;
}
export function getBuiltTrailPath(trailPath) {
// Ensure trailPath is absolute
trailPath = fs.realpathSync(trailPath);
return join(trailPath, '.build');
}
export function isTrailBuilt(trailPath) {
// Ensure trailPath is absolute
trailPath = fs.realpathSync(trailPath);
const builtPath = getBuiltTrailPath(trailPath);
return fs.existsSync(builtPath) &&
fs.existsSync(join(builtPath, 'actions.js')) &&
fs.existsSync(join(builtPath, 'urls.js')) &&
fs.existsSync(join(builtPath, 'selectors.js'));
}
// Helper function to format file size in a human-readable format
function formatFileSize(bytes) {
if (bytes < 1024) {
return `${bytes} B`;
}
else if (bytes < 1024 * 1024) {
return `${(bytes / 1024).toFixed(1)} KB`;
}
else {
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}
}