Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions WebContainerGitService.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,16 +193,18 @@ export class WebContainerGitService {
async wipeDir(dir) {
try {
const entries = await this.fs.readdir(dir);
for (const entry of entries) {
const path = `${dir}/${entry}`;
const stat = await this.fs.stat(path);
if (stat.isDirectory()) {
await this.wipeDir(path);
await this.fs.rmdir(path);
} else {
await this.fs.unlink(path);
}
}
await Promise.all(
entries.map(async (entry) => {
const path = `${dir}/${entry}`;
const stat = await this.fs.stat(path);
if (stat.isDirectory()) {
await this.wipeDir(path);
await this.fs.rmdir(path);
} else {
await this.fs.unlink(path);
}
})
);
} catch (e) {
// Base directory likely doesn't exist yet
}
Expand Down
78 changes: 78 additions & 0 deletions benchmark_wipe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import fs from 'fs';
import path from 'path';

async function generateDummyDir(dirPath, depth, filesPerDir) {
await fs.promises.mkdir(dirPath, { recursive: true }).catch(() => {});
if (depth === 0) return;

const promises = [];
for (let i = 0; i < filesPerDir; i++) {
const fileNum = i;
promises.push(fs.promises.writeFile(path.join(dirPath, `file_${fileNum}.txt`), `hello ${fileNum}`));
}
for (let i = 0; i < filesPerDir; i++) {
const subDir = path.join(dirPath, `dir_${i}`);
promises.push(generateDummyDir(subDir, depth - 1, filesPerDir));
}
await Promise.all(promises);
}

// Current implementation
async function wipeDirOriginal(dir) {
try {
const entries = await fs.promises.readdir(dir);
for (const entry of entries) {
const p = path.join(dir, entry);
const stat = await fs.promises.stat(p);
if (stat.isDirectory()) {
await wipeDirOriginal(p);
await fs.promises.rmdir(p);
} else {
await fs.promises.unlink(p);
}
}
} catch (e) {
}
}

// Optimized implementation
async function wipeDirOptimized(dir) {
try {
const entries = await fs.promises.readdir(dir);
await Promise.all(entries.map(async (entry) => {
const p = path.join(dir, entry);
const stat = await fs.promises.stat(p);
if (stat.isDirectory()) {
await wipeDirOptimized(p);
await fs.promises.rmdir(p);
} else {
await fs.promises.unlink(p);
}
}));
} catch (e) {
}
}

async function runBenchmark() {
const dir1 = './testdir1';
const dir2 = './testdir2';

console.log("Generating dummy directories...");
await generateDummyDir(dir1, 4, 5); // 5 files + 5 dirs, depth 4
await generateDummyDir(dir2, 4, 5);
console.log("Generation complete.");

console.log("Testing original...");
const t1 = performance.now();
await wipeDirOriginal(dir1);
const t2 = performance.now();
console.log(`Original: ${t2 - t1}ms`);

console.log("Testing optimized...");
const t3 = performance.now();
await wipeDirOptimized(dir2);
const t4 = performance.now();
console.log(`Optimized: ${t4 - t3}ms`);
}

runBenchmark().catch(console.error);
62 changes: 58 additions & 4 deletions build.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,38 @@ import { join } from "node:path";
const DIST = "dist";
const ASSETS = join(DIST, "assets");

import { exec } from "node:child_process";
import { promisify } from "node:util";

const execAsync = promisify(exec);

async function build() {
console.log("πŸš€ Starting ZeroCMS Production Build (via Bun)...");

// 0. Ensure Tagger WASM is built
console.log("πŸ¦€ Checking for Super Tagger WASM...");
try {
await readdir("lib");
let hasWasm = false;
let hasJs = false;
try {
const dirContents = await readdir("lib");
hasWasm = dirContents.includes("zerocms_tagger_bg.wasm");
hasJs = dirContents.includes("zerocms_tagger.js");
} catch (e) {}

if (!hasWasm || !hasJs) {
console.log("⚠️ WASM files missing in lib/. Building them now...");
const buildOutput = await execAsync("bash scripts/build_tagger.sh");
console.log(buildOutput.stdout);
} else {
console.log("βœ… WASM files found.");
}
} catch (error) {
console.error("❌ Failed to build WASM tagger:", error);
process.exit(1);
}

// 1. Clean and Create Directories
await rm(DIST, { recursive: true, force: true });
await mkdir(ASSETS, { recursive: true });
Expand All @@ -31,11 +60,36 @@ async function build() {

// 3. Copy Static Libraries
console.log("πŸ“‚ Copying libraries...");
const libs = await readdir("lib");
const libs = await readdir("lib", { withFileTypes: true });
for (const lib of libs) {
const src = join("lib", lib);
const dest = join(DIST, "lib", lib);
await Bun.write(dest, Bun.file(src));
const src = join("lib", lib.name);
const dest = join(DIST, "lib", lib.name);
if (lib.isDirectory()) {
await mkdir(dest, { recursive: true });
// Very basic recursive copy for directories
// Note: Node 18+ does not have recursive readdir natively unless node version >= 20.1
// If CI is on Node < 20, recursive: true on readdir will fail.
const getFiles = async (dir) => {
const dirents = await readdir(dir, { withFileTypes: true });
const files = await Promise.all(dirents.map((dirent) => {
const res = join(dir, dirent.name);
return dirent.isDirectory() ? getFiles(res) : res;
}));
return Array.prototype.concat(...files);
};

const allFiles = await getFiles(src);
for (const filePath of allFiles) {
// Create target dir based on relative path
const relativePath = filePath.substring("lib/".length);
const subDest = join(DIST, "lib", relativePath);
const parentDir = join(DIST, "lib", relativePath.substring(0, relativePath.lastIndexOf("/")));
await mkdir(parentDir, { recursive: true });
await Bun.write(subDest, Bun.file(filePath));
}
} else {
await Bun.write(dest, Bun.file(src));
}
}

// Extract the generated hashed file name from Bun's output
Expand Down