From 96c1fde9732f5e62c3562e084e9733cc71e91e87 Mon Sep 17 00:00:00 2001 From: Patrick Lu Date: Tue, 25 Nov 2025 11:22:38 -0800 Subject: [PATCH 1/9] parallel builds --- package.json | 2 +- scripts/build-swc.mjs | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 3847402..df11d07 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codepress/codepress-engine", - "version": "0.7.9", + "version": "0.7.10", "packageManager": "pnpm@10.22.0", "description": "CodePress engine - Babel and SWC plug-ins", "main": "./dist/index.js", diff --git a/scripts/build-swc.mjs b/scripts/build-swc.mjs index 59a0d42..66c3ad7 100644 --- a/scripts/build-swc.mjs +++ b/scripts/build-swc.mjs @@ -206,6 +206,7 @@ function parseArgs(argv) { next: undefined, band: undefined, target: undefined, + parallel: undefined, // number of concurrent builds, 0 = unlimited listBands: false, help: false, }; @@ -224,6 +225,10 @@ function parseArgs(argv) { case "-t": args.target = argv[++i]; break; + case "--parallel": + case "-p": + args.parallel = Number(argv[++i]) || 0; + break; case "--list-bands": args.listBands = true; break; @@ -239,6 +244,27 @@ function parseArgs(argv) { return args; } +async function runWithConcurrency(tasks, concurrency) { + if (concurrency <= 0) { + // Unlimited parallelism + return Promise.all(tasks.map((fn) => fn())); + } + const results = []; + const executing = new Set(); + for (const task of tasks) { + const p = task().then((r) => { + executing.delete(p); + return r; + }); + executing.add(p); + results.push(p); + if (executing.size >= concurrency) { + await Promise.race(executing); + } + } + return Promise.all(results); +} + function parseSemver(input) { if (!input) return null; const m = String(input) @@ -275,11 +301,14 @@ function usage() { ` -n, --next Build band matching Next.js version (e.g. 15.4.0)\n` + ` -b, --band Build specific band id (one of: ${BANDS.map((b) => b.id).join(", ")})\n` + ` -t, --target Build target(s): wasip1 | wasi | all | comma-list (default: all)\n` + + ` -p, --parallel Build bands in parallel (0 = unlimited, 2 = two at a time, etc.)\n` + ` --list-bands Print available band ids and exit\n` + ` -h, --help Show this help\n\n` + `Examples:\n` + ` node scripts/build-swc.mjs --next 15.4.0\n` + ` node scripts/build-swc.mjs --band v26 --target wasip1\n` + + ` node scripts/build-swc.mjs --parallel 2 # Build 2 bands at a time\n` + + ` node scripts/build-swc.mjs --parallel 0 # Build all bands in parallel\n` + ` npm run build:rust -- --next 15.4.0\n` ); } @@ -337,6 +366,16 @@ function selectTargets(targetArg) { const targets = selectTargets(args.target); - for (const band of bands) await buildOneBand(band, targets); + if (args.parallel !== undefined) { + const concurrency = args.parallel; + console.log( + `[codepress] Building ${bands.length} band(s) in parallel` + + (concurrency > 0 ? ` (max ${concurrency} concurrent)` : " (unlimited)") + ); + const tasks = bands.map((band) => () => buildOneBand(band, targets)); + await runWithConcurrency(tasks, concurrency); + } else { + for (const band of bands) await buildOneBand(band, targets); + } console.log("Finished SWC bands built."); })(); From f2f99cb5ea56e497304c48b559b7300b700c286b Mon Sep 17 00:00:00 2001 From: Patrick Lu Date: Tue, 25 Nov 2025 11:27:20 -0800 Subject: [PATCH 2/9] default 2 --- scripts/build-swc.mjs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/scripts/build-swc.mjs b/scripts/build-swc.mjs index 66c3ad7..5ea69a6 100644 --- a/scripts/build-swc.mjs +++ b/scripts/build-swc.mjs @@ -206,7 +206,7 @@ function parseArgs(argv) { next: undefined, band: undefined, target: undefined, - parallel: undefined, // number of concurrent builds, 0 = unlimited + parallel: 2, // number of concurrent builds, 0 = unlimited listBands: false, help: false, }; @@ -301,7 +301,7 @@ function usage() { ` -n, --next Build band matching Next.js version (e.g. 15.4.0)\n` + ` -b, --band Build specific band id (one of: ${BANDS.map((b) => b.id).join(", ")})\n` + ` -t, --target Build target(s): wasip1 | wasi | all | comma-list (default: all)\n` + - ` -p, --parallel Build bands in parallel (0 = unlimited, 2 = two at a time, etc.)\n` + + ` -p, --parallel Concurrency limit (default: 2, 0 = unlimited)\n` + ` --list-bands Print available band ids and exit\n` + ` -h, --help Show this help\n\n` + `Examples:\n` + @@ -365,17 +365,15 @@ function selectTargets(targetArg) { } const targets = selectTargets(args.target); + const concurrency = args.parallel; - if (args.parallel !== undefined) { - const concurrency = args.parallel; - console.log( - `[codepress] Building ${bands.length} band(s) in parallel` + - (concurrency > 0 ? ` (max ${concurrency} concurrent)` : " (unlimited)") - ); - const tasks = bands.map((band) => () => buildOneBand(band, targets)); - await runWithConcurrency(tasks, concurrency); - } else { - for (const band of bands) await buildOneBand(band, targets); - } + console.log( + `[codepress] Building ${bands.length} band(s)` + + (concurrency > 0 + ? ` (max ${concurrency} concurrent)` + : " (unlimited parallelism)") + ); + const tasks = bands.map((band) => () => buildOneBand(band, targets)); + await runWithConcurrency(tasks, concurrency); console.log("Finished SWC bands built."); })(); From b954a1fb1289f559b28ff3f82da7cedac38cdbae Mon Sep 17 00:00:00 2001 From: Patrick Lu Date: Tue, 25 Nov 2025 15:55:14 -0800 Subject: [PATCH 3/9] updating webpack-plugin --- src/webpack-plugin.ts | 66 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/src/webpack-plugin.ts b/src/webpack-plugin.ts index c85fefd..f39a67f 100644 --- a/src/webpack-plugin.ts +++ b/src/webpack-plugin.ts @@ -78,7 +78,7 @@ export default class CodePressWebpackPlugin { } /** - * Get alias mappings from webpack's resolve configuration. + * Get alias mappings from webpack's resolve configuration AND tsconfig.json. * Returns a map of alias prefix -> resolved directory path. * * For example, with tsconfig paths: { "@/*": ["./src/*"] } @@ -86,8 +86,9 @@ export default class CodePressWebpackPlugin { */ private getAliasMap(compiler: Compiler): Map { const aliases = new Map(); - const resolveAlias = compiler.options.resolve?.alias; + // First, try webpack's resolve.alias + const resolveAlias = compiler.options.resolve?.alias; if (resolveAlias && typeof resolveAlias === "object") { for (const [alias, target] of Object.entries(resolveAlias)) { if (typeof target === "string") { @@ -105,6 +106,44 @@ export default class CodePressWebpackPlugin { } } + // If no aliases found, try reading from tsconfig.json + // Next.js doesn't always populate resolve.alias from tsconfig paths + if (aliases.size === 0) { + try { + const fs = require("fs"); + const path = require("path"); + const tsconfigPath = path.join(compiler.context, "tsconfig.json"); + + if (fs.existsSync(tsconfigPath)) { + const tsconfigContent = fs.readFileSync(tsconfigPath, "utf8"); + // Remove comments (tsconfig allows them) + const jsonContent = tsconfigContent.replace( + /\/\*[\s\S]*?\*\/|\/\/.*/g, + "" + ); + const tsconfig = JSON.parse(jsonContent); + const paths = tsconfig.compilerOptions?.paths; + + if (paths && typeof paths === "object") { + for (const [aliasPattern, targets] of Object.entries(paths)) { + // Convert "@/*" -> "@" and ["./src/*"] -> "src" + const alias = aliasPattern.replace(/\/\*$/, ""); + const targetArray = targets as string[]; + if (targetArray && targetArray[0]) { + let targetPath = targetArray[0] + .replace(/^\.\//, "") // Remove leading ./ + .replace(/\/\*$/, ""); // Remove trailing /* + aliases.set(alias, targetPath); + } + } + } + } + } catch (e) { + // Silently fail - tsconfig reading is best-effort + console.warn("[CodePress] Could not read tsconfig.json for aliases:", e); + } + } + return aliases; } @@ -363,6 +402,19 @@ export default class CodePressWebpackPlugin { ? finalExports : undefined, }; + // For index files, also add a key without /index suffix + // so imports like "@/features/dashboard" resolve to "@/features/dashboard/index" + if (aliasPath.endsWith("/index")) { + const withoutIndex = aliasPath.replace(/\/index$/, ""); + moduleMap[withoutIndex] = { + path: runtime, + moduleId: id, + exports: + Object.keys(finalExports).length > 0 + ? finalExports + : undefined, + }; + } } } } else { @@ -488,6 +540,16 @@ export default class CodePressWebpackPlugin { moduleId: id, ...(hasExportMappings ? { exports: exportMappings } : {}), }; + // For index files, also add a key without /index suffix + // so imports like "@/features/dashboard" resolve to "@/features/dashboard/index" + if (aliasPath.endsWith("/index")) { + const withoutIndex = aliasPath.replace(/\/index$/, ""); + moduleMap[withoutIndex] = { + path: runtimePath, + moduleId: id, + ...(hasExportMappings ? { exports: exportMappings } : {}), + }; + } } } }); From 340cc0da4ee41a0ca4e7c0b1e3d5c935897aa718 Mon Sep 17 00:00:00 2001 From: Patrick Lu Date: Tue, 25 Nov 2025 16:34:45 -0800 Subject: [PATCH 4/9] updating version --- src/webpack-plugin.ts | 57 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/src/webpack-plugin.ts b/src/webpack-plugin.ts index f39a67f..7359e07 100644 --- a/src/webpack-plugin.ts +++ b/src/webpack-plugin.ts @@ -109,12 +109,16 @@ export default class CodePressWebpackPlugin { // If no aliases found, try reading from tsconfig.json // Next.js doesn't always populate resolve.alias from tsconfig paths if (aliases.size === 0) { - try { - const fs = require("fs"); - const path = require("path"); - const tsconfigPath = path.join(compiler.context, "tsconfig.json"); + const fs = require("fs"); + const path = require("path"); + const tsconfigPath = path.join(compiler.context, "tsconfig.json"); + + console.log("[CodePress] Checking for tsconfig at:", tsconfigPath); + console.log("[CodePress] compiler.context:", compiler.context); + try { if (fs.existsSync(tsconfigPath)) { + console.log("[CodePress] tsconfig.json exists, reading..."); const tsconfigContent = fs.readFileSync(tsconfigPath, "utf8"); // Remove comments (tsconfig allows them) const jsonContent = tsconfigContent.replace( @@ -124,6 +128,11 @@ export default class CodePressWebpackPlugin { const tsconfig = JSON.parse(jsonContent); const paths = tsconfig.compilerOptions?.paths; + console.log( + "[CodePress] tsconfig.compilerOptions.paths:", + paths ? JSON.stringify(paths) : "undefined" + ); + if (paths && typeof paths === "object") { for (const [aliasPattern, targets] of Object.entries(paths)) { // Convert "@/*" -> "@" and ["./src/*"] -> "src" @@ -134,13 +143,49 @@ export default class CodePressWebpackPlugin { .replace(/^\.\//, "") // Remove leading ./ .replace(/\/\*$/, ""); // Remove trailing /* aliases.set(alias, targetPath); + console.log( + "[CodePress] Added alias from tsconfig:", + alias, + "->", + targetPath + ); } } + } else { + console.log("[CodePress] No paths found in tsconfig.compilerOptions"); + } + } else { + console.log("[CodePress] tsconfig.json does NOT exist at:", tsconfigPath); + // List files in compiler.context to debug + try { + const files = fs.readdirSync(compiler.context); + console.log( + "[CodePress] Files in compiler.context:", + files.filter((f: string) => f.includes("tsconfig") || f.includes("json")).join(", ") + ); + } catch (_listErr) { + console.log("[CodePress] Could not list files in compiler.context"); } } } catch (e) { - // Silently fail - tsconfig reading is best-effort - console.warn("[CodePress] Could not read tsconfig.json for aliases:", e); + console.warn("[CodePress] Error reading tsconfig.json:", e); + } + } else { + console.log( + "[CodePress] Already have aliases from resolve.alias:", + Array.from(aliases.entries()) + ); + } + + // Fallback: Next.js convention is @/* -> ./src/* + // Add this if no @ alias was found (common setup) + if (!aliases.has("@")) { + const fs = require("fs"); + const path = require("path"); + const srcDir = path.join(compiler.context, "src"); + if (fs.existsSync(srcDir)) { + aliases.set("@", "src"); + console.log("[CodePress] Using default Next.js alias: @ → src"); } } From 10b636bca6a085fa12c7b7cd8f7b8a5b16768037 Mon Sep 17 00:00:00 2001 From: Patrick Lu Date: Tue, 25 Nov 2025 16:40:23 -0800 Subject: [PATCH 5/9] build in parallel --- .github/workflows/release.yml | 77 +++++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e8b96a7..5409f41 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -95,10 +95,62 @@ jobs: echo "changed=true" >> $GITHUB_OUTPUT fi - build-and-publish: + # Build each WASM band in parallel using matrix strategy + build-wasm: needs: check-version if: needs.check-version.outputs.version_changed == 'true' runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + band: [v0_82_87, v26, v42, v48] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 10.22.0 + + - name: Setup Rust (stable + WASI) + uses: dtolnay/rust-toolchain@stable + with: + targets: wasm32-wasip1 + + - name: Cache Cargo registry + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + key: ${{ runner.os }}-cargo-${{ matrix.band }}-${{ hashFiles('codepress-swc-plugin/src/**') }} + restore-keys: | + ${{ runner.os }}-cargo-${{ matrix.band }}- + ${{ runner.os }}-cargo- + + - name: Install deps + run: pnpm install --frozen-lockfile + + - name: Build WASM band ${{ matrix.band }} + run: node scripts/build-swc.mjs --band ${{ matrix.band }} + + - name: Upload WASM artifact + uses: actions/upload-artifact@v4 + with: + name: wasm-${{ matrix.band }} + path: swc/*.wasm + retention-days: 1 + + build-and-publish: + needs: [check-version, build-wasm] + if: needs.check-version.outputs.version_changed == 'true' + runs-on: ubuntu-latest permissions: contents: write packages: write @@ -118,16 +170,26 @@ jobs: with: version: 10.22.0 - - name: Setup Rust (stable + WASI) - uses: dtolnay/rust-toolchain@stable - with: - targets: wasm32-wasip1 - - name: Install deps run: pnpm install --frozen-lockfile env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + - name: Download all WASM artifacts + uses: actions/download-artifact@v4 + with: + pattern: wasm-* + path: swc-artifacts + merge-multiple: false + + - name: Combine WASM artifacts + run: | + mkdir -p swc + for dir in swc-artifacts/wasm-*; do + cp "$dir"/*.wasm swc/ 2>/dev/null || true + done + ls -la swc/ + - name: Update package version for release env: RELEASE_VERSION: ${{ needs.check-version.outputs.release_version }} @@ -144,9 +206,6 @@ jobs: - name: Build JS run: pnpm run build - - name: Build Rust WASM plugin - run: pnpm run build:rust - - name: Run tests run: pnpm test From e37a03e27d737e543672629212d21c08ef814d1f Mon Sep 17 00:00:00 2001 From: Patrick Lu Date: Tue, 25 Nov 2025 16:51:24 -0800 Subject: [PATCH 6/9] fix release --- .github/workflows/release.yml | 4 +++- src/webpack-plugin.ts | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5409f41..151eef2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -138,7 +138,9 @@ jobs: run: pnpm install --frozen-lockfile - name: Build WASM band ${{ matrix.band }} - run: node scripts/build-swc.mjs --band ${{ matrix.band }} + run: node scripts/build-swc.mjs + env: + BAND: ${{ matrix.band }} - name: Upload WASM artifact uses: actions/upload-artifact@v4 diff --git a/src/webpack-plugin.ts b/src/webpack-plugin.ts index 7359e07..6bd0eb7 100644 --- a/src/webpack-plugin.ts +++ b/src/webpack-plugin.ts @@ -217,17 +217,26 @@ export default class CodePressWebpackPlugin { * Apply the plugin to the webpack compiler */ public apply(compiler: Compiler): void { + console.log("[CodePress] Plugin apply() called with options:", { + isServer: this.options.isServer, + dev: this.options.dev, + }); + // Skip server builds entirely if (this.options.isServer) { + console.log("[CodePress] Skipping: isServer=true"); return; } // Skip dev mode - module mapping not needed (dev has named IDs) // and env vars are handled by the SWC plugin if (this.options.dev) { + console.log("[CodePress] Skipping: dev=true"); return; } + console.log("[CodePress] Running in production mode, will build MODULE_MAP"); + // Disable optimizations that break CodePress preview in production builds. // This is REQUIRED for CodePress preview to work because: // From 95dcd13d0e0007087c78bc2b561520106e2a1def Mon Sep 17 00:00:00 2001 From: Patrick Lu Date: Tue, 25 Nov 2025 17:04:37 -0800 Subject: [PATCH 7/9] better tsconfig reading --- src/webpack-plugin.ts | 105 +++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 63 deletions(-) diff --git a/src/webpack-plugin.ts b/src/webpack-plugin.ts index 6bd0eb7..f445b36 100644 --- a/src/webpack-plugin.ts +++ b/src/webpack-plugin.ts @@ -106,86 +106,65 @@ export default class CodePressWebpackPlugin { } } - // If no aliases found, try reading from tsconfig.json - // Next.js doesn't always populate resolve.alias from tsconfig paths - if (aliases.size === 0) { - const fs = require("fs"); - const path = require("path"); - const tsconfigPath = path.join(compiler.context, "tsconfig.json"); + // Always try to read @ alias from tsconfig.json if not already present + // resolve.alias usually has Next.js internals but not the @ path alias + const fs = require("fs"); + const path = require("path"); - console.log("[CodePress] Checking for tsconfig at:", tsconfigPath); - console.log("[CodePress] compiler.context:", compiler.context); + if (!aliases.has("@")) { + const tsconfigPath = path.join(compiler.context, "tsconfig.json"); + console.log("[CodePress] Looking for @ alias in tsconfig:", tsconfigPath); try { if (fs.existsSync(tsconfigPath)) { - console.log("[CodePress] tsconfig.json exists, reading..."); const tsconfigContent = fs.readFileSync(tsconfigPath, "utf8"); - // Remove comments (tsconfig allows them) - const jsonContent = tsconfigContent.replace( - /\/\*[\s\S]*?\*\/|\/\/.*/g, - "" - ); - const tsconfig = JSON.parse(jsonContent); - const paths = tsconfig.compilerOptions?.paths; - console.log( - "[CodePress] tsconfig.compilerOptions.paths:", - paths ? JSON.stringify(paths) : "undefined" + // Extract paths directly using regex (avoids JSON parsing issues with comments/globs) + // Match: "paths": { "@/*": ["./src/*"] } or similar + const pathsMatch = tsconfigContent.match( + /"paths"\s*:\s*\{([^}]+)\}/ ); - if (paths && typeof paths === "object") { - for (const [aliasPattern, targets] of Object.entries(paths)) { - // Convert "@/*" -> "@" and ["./src/*"] -> "src" + if (pathsMatch) { + const pathsContent = pathsMatch[1]; + console.log("[CodePress] Found paths block:", pathsContent.trim()); + + // Extract individual path mappings: "@/*": ["./src/*"] + const pathPattern = /"([^"]+)"\s*:\s*\[\s*"([^"]+)"/g; + let match; + while ((match = pathPattern.exec(pathsContent)) !== null) { + const aliasPattern = match[1]; // "@/*" + const targetPattern = match[2]; // "./src/*" + + // Convert "@/*" -> "@" and "./src/*" -> "src" const alias = aliasPattern.replace(/\/\*$/, ""); - const targetArray = targets as string[]; - if (targetArray && targetArray[0]) { - let targetPath = targetArray[0] - .replace(/^\.\//, "") // Remove leading ./ - .replace(/\/\*$/, ""); // Remove trailing /* - aliases.set(alias, targetPath); - console.log( - "[CodePress] Added alias from tsconfig:", - alias, - "->", - targetPath - ); - } + const targetPath = targetPattern + .replace(/^\.\//, "") + .replace(/\/\*$/, ""); + + aliases.set(alias, targetPath); + console.log( + "[CodePress] Added alias from tsconfig:", + alias, + "->", + targetPath + ); } } else { - console.log("[CodePress] No paths found in tsconfig.compilerOptions"); - } - } else { - console.log("[CodePress] tsconfig.json does NOT exist at:", tsconfigPath); - // List files in compiler.context to debug - try { - const files = fs.readdirSync(compiler.context); - console.log( - "[CodePress] Files in compiler.context:", - files.filter((f: string) => f.includes("tsconfig") || f.includes("json")).join(", ") - ); - } catch (_listErr) { - console.log("[CodePress] Could not list files in compiler.context"); + console.log("[CodePress] No paths block found in tsconfig"); } } } catch (e) { console.warn("[CodePress] Error reading tsconfig.json:", e); } - } else { - console.log( - "[CodePress] Already have aliases from resolve.alias:", - Array.from(aliases.entries()) - ); - } - // Fallback: Next.js convention is @/* -> ./src/* - // Add this if no @ alias was found (common setup) - if (!aliases.has("@")) { - const fs = require("fs"); - const path = require("path"); - const srcDir = path.join(compiler.context, "src"); - if (fs.existsSync(srcDir)) { - aliases.set("@", "src"); - console.log("[CodePress] Using default Next.js alias: @ → src"); + // Fallback: Next.js convention is @/* -> ./src/* + if (!aliases.has("@")) { + const srcDir = path.join(compiler.context, "src"); + if (fs.existsSync(srcDir)) { + aliases.set("@", "src"); + console.log("[CodePress] Using default Next.js alias: @ → src"); + } } } From 102ea47663e386e00ebb83298cc5e0ce47f89076 Mon Sep 17 00:00:00 2001 From: Patrick Lu Date: Wed, 26 Nov 2025 16:15:38 -0800 Subject: [PATCH 8/9] package.json update --- package.json | 2 +- pnpm-lock.yaml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index df11d07..1cfe07b 100644 --- a/package.json +++ b/package.json @@ -100,6 +100,7 @@ "@babel/preset-typescript": "^7.26.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "^9.37.0", + "@swc/core": "^1.15.3", "@swc/wasm": "^1", "@types/babel__core": "^7.20.5", "@types/jest": "^30.0.0", @@ -124,7 +125,6 @@ }, "dependencies": { "@fastify/cors": "^11.0.1", - "@swc/core": "^1.15.3", "fastify": "^5.3.3", "node-fetch": "^2.6.7", "prettier": "^3.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ad4e7ac..e62bc5d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,9 +11,6 @@ importers: '@fastify/cors': specifier: ^11.0.1 version: 11.1.0 - '@swc/core': - specifier: ^1.15.3 - version: 1.15.3 fastify: specifier: ^5.3.3 version: 5.6.1 @@ -51,6 +48,9 @@ importers: '@eslint/js': specifier: ^9.37.0 version: 9.39.1 + '@swc/core': + specifier: ^1.15.3 + version: 1.15.3 '@swc/wasm': specifier: ^1 version: 1.13.20 From 95254a46fde8f60ad83a0bb971ebf5ebecb82bfc Mon Sep 17 00:00:00 2001 From: Patrick Lu Date: Sat, 29 Nov 2025 11:31:59 -0800 Subject: [PATCH 9/9] fix pr comment issue --- scripts/build-swc.mjs | 61 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/scripts/build-swc.mjs b/scripts/build-swc.mjs index 5ea69a6..71ab414 100644 --- a/scripts/build-swc.mjs +++ b/scripts/build-swc.mjs @@ -63,13 +63,35 @@ const BANDS = [ // BAND=v42 node scripts/build-swc.mjs // BANDS=v26,v42 node scripts/build-swc.mjs // node scripts/build-swc.mjs v42 v26 -const args = process.argv.slice(2).filter(Boolean); +const cliArgs = process.argv.slice(2).filter(Boolean); +// Filter out CLI flags and their values so they don't get misinterpreted as band IDs +// Flags that take values: -n, --next, -b, --band, -t, --target, -p, --parallel +const flagsWithValues = new Set([ + "-n", + "--next", + "-b", + "--band", + "-t", + "--target", + "-p", + "--parallel", +]); +const bandArgsFromCli = []; +for (let i = 0; i < cliArgs.length; i++) { + const arg = cliArgs[i]; + if (arg.startsWith("-")) { + // Skip flags; if it takes a value, skip the next arg too + if (flagsWithValues.has(arg)) i++; + continue; + } + bandArgsFromCli.push(arg); +} const bandEnvRaw = process.env.BAND || process.env.BANDS || ""; const bandIdsFromEnv = bandEnvRaw .split(",") .map((s) => s.trim()) .filter(Boolean); -const requestedIds = [...bandIdsFromEnv, ...args]; +const requestedIds = [...bandIdsFromEnv, ...bandArgsFromCli]; const validIds = new Set(BANDS.map((b) => b.id)); let BANDS_TO_BUILD = BANDS; if (requestedIds.length) { @@ -226,9 +248,23 @@ function parseArgs(argv) { args.target = argv[++i]; break; case "--parallel": - case "-p": - args.parallel = Number(argv[++i]) || 0; + case "-p": { + const raw = argv[++i]; + const n = Number(raw); + if ( + raw == null || + !Number.isFinite(n) || + !Number.isInteger(n) || + n < 0 + ) { + console.error( + `[codepress] --parallel expects a non-negative integer (0 = unlimited); received: "${raw ?? ""}"` + ); + process.exit(1); + } + args.parallel = n; break; + } case "--list-bands": args.listBands = true; break; @@ -252,14 +288,19 @@ async function runWithConcurrency(tasks, concurrency) { const results = []; const executing = new Set(); for (const task of tasks) { - const p = task().then((r) => { - executing.delete(p); - return r; - }); - executing.add(p); + const p = Promise.resolve() + .then(task) + .finally(() => { + executing.delete(p); + }); results.push(p); + executing.add(p); if (executing.size >= concurrency) { - await Promise.race(executing); + try { + await Promise.race(executing); + } catch { + // Swallow here; final Promise.all(results) will reject with the first error. + } } } return Promise.all(results);