chore: reduce production bundle below 5 MB (#1130)

* chore: reduce production bundle below 5 MB

* test: support npm paths in bundle assertion

* test: stabilize OpenCode history retry coverage
This commit is contained in:
Yishen Tu
2026-08-21 12:32:22 +08:00
committed by GitHub
parent 3ff99928dd
commit 07bbec7a90
16 changed files with 400 additions and 63 deletions
+10 -1
View File
@@ -46,6 +46,7 @@
"jsdom": "^26.1.0",
"obsidian": "1.13.0",
"stylelint": "^17.14.1",
"terser": "^5.50.0",
"ts-jest": "^29.4.9",
"tsx": "^4.23.1",
"typescript": "^6.0.2",
@@ -358,6 +359,8 @@
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
"@jridgewell/source-map": ["@jridgewell/source-map@0.3.11", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" } }, "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA=="],
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
@@ -678,6 +681,8 @@
"comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
"commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
"content-disposition": ["content-disposition@1.1.0", "", {}, "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g=="],
@@ -1480,7 +1485,7 @@
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"source-map-support": ["source-map-support@0.5.13", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w=="],
"source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
"space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
@@ -1542,6 +1547,8 @@
"tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="],
"terser": ["terser@5.50.0", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-CN9BVxWhgS/hRxtUMjtC2uRWSTcSfQFHMDWma6sKKfIivCD91sM+FOPfvwoaRMqCSrUpe1nv3jDamd9eEQ4y+w=="],
"test-exclude": ["test-exclude@6.0.0", "", { "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", "minimatch": "^3.0.4" } }, "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w=="],
"thunky": ["thunky@1.1.0", "", {}, "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA=="],
@@ -1816,6 +1823,8 @@
"jest-message-util/picomatch": ["picomatch@4.0.5", "", {}, "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A=="],
"jest-runner/source-map-support": ["source-map-support@0.5.13", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w=="],
"jest-runtime/strip-bom": ["strip-bom@4.0.0", "", {}, "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w=="],
"jest-snapshot/synckit": ["synckit@0.11.13", "", { "dependencies": { "@pkgr/core": "^0.3.6" } }, "sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg=="],
+9 -1
View File
@@ -12,6 +12,8 @@ import {
} from 'fs';
import rendererSafeUnrefHelpers from './scripts/rendererSafeUnref.js';
import desktopRuntimeAliasHelpers from './scripts/desktopRuntimeAliases.js';
import sourcePackageAliasHelpers from './scripts/sourcePackageAliases.js';
import terserProductionBundleHelpers from './scripts/terserProductionBundle.js';
import pierreShikiBundleHelpers from './scripts/pierreShikiBundle.js';
import compressedStaticAssetsHelpers from './scripts/compressedStaticAssets.js';
@@ -20,6 +22,8 @@ const {
patchRendererUnsafeUnrefSites,
} = rendererSafeUnrefHelpers;
const { createDesktopRuntimeAliases } = desktopRuntimeAliasHelpers;
const { createSourcePackageAliases } = sourcePackageAliasHelpers;
const { createTerserProductionBundlePlugin } = terserProductionBundleHelpers;
const { createPierreShikiBundlePlugin } = pierreShikiBundleHelpers;
const { createCompressedStaticAssetsPlugin } = compressedStaticAssetsHelpers;
@@ -189,12 +193,16 @@ const external = [
const mainContext = await esbuild.context({
entryPoints: ['src/main.ts'],
alias: createDesktopRuntimeAliases(),
alias: {
...createDesktopRuntimeAliases(),
...createSourcePackageAliases(),
},
bundle: true,
plugins: [
patchSdkImportMeta,
createCompressedStaticAssetsPlugin(),
createPierreShikiBundlePlugin(),
...(prod ? [createTerserProductionBundlePlugin(['main.js'])] : []),
createPatchRendererUnsafeUnref(['main.js']),
copyToObsidian,
],
+49
View File
@@ -54,6 +54,7 @@
"jsdom": "^26.1.0",
"obsidian": "1.13.0",
"stylelint": "^17.14.1",
"terser": "^5.50.0",
"ts-jest": "^29.4.9",
"tsx": "^4.23.1",
"typescript": "^6.0.2"
@@ -2474,6 +2475,17 @@
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/source-map": {
"version": "0.3.11",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz",
"integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
@@ -4635,6 +4647,13 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true,
"license": "MIT"
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -11845,6 +11864,36 @@
"url": "https://opencollective.com/webpack"
}
},
"node_modules/terser": {
"version": "5.50.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.50.0.tgz",
"integrity": "sha512-CN9BVxWhgS/hRxtUMjtC2uRWSTcSfQFHMDWma6sKKfIivCD91sM+FOPfvwoaRMqCSrUpe1nv3jDamd9eEQ4y+w==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
"acorn": "^8.15.0",
"commander": "^2.20.0",
"source-map-support": "~0.5.20"
},
"bin": {
"terser": "bin/terser"
},
"engines": {
"node": ">=10"
}
},
"node_modules/terser/node_modules/source-map-support": {
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
"dev": true,
"license": "MIT",
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"node_modules/test-exclude": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+1
View File
@@ -76,6 +76,7 @@
"jsdom": "^26.1.0",
"obsidian": "1.13.0",
"stylelint": "^17.14.1",
"terser": "^5.50.0",
"ts-jest": "^29.4.9",
"tsx": "^4.23.1",
"typescript": "^6.0.2"
+17 -19
View File
@@ -7,11 +7,10 @@ import ts from 'typescript';
import {
evaluationIndicatorMs,
evaluationReviewThresholdMs,
historicalMainWarningBytes,
inspectArtifactSize,
inspectEvaluationDuration,
inspectPluginArtifactReferences,
mainReviewThresholdBytes,
mainBudgetBytes,
preCollabReferenceMainBytes,
} from './check-startup-performance.mjs';
@@ -417,16 +416,19 @@ test('ordinary main evaluation cannot reach Collab runtime foundations', () => {
sourceImport.dynamic && sourceImport.specifier === './app/collab'
)),
);
const collabReviewRoot = path.join(featuresRoot, 'collab', 'detail', 'review');
assert.ok(
listSourceImports(path.join(
featuresRoot,
'collab',
'detail',
'review',
'CollabDiffRenderer.ts',
))
listSourceImports(path.join(collabReviewRoot, 'CollabDiffRenderer.ts'))
.some(sourceImport => (
sourceImport.dynamic && sourceImport.specifier === '@pierre/diffs'
sourceImport.dynamic
&& sourceImport.specifier === './CollabPierreDiffModule'
)),
);
assert.ok(
listSourceImports(path.join(collabReviewRoot, 'CollabPierreDiffModule.ts'))
.some(sourceImport => (
!sourceImport.dynamic
&& sourceImport.specifier === '@pierre/diffs'
)),
);
});
@@ -824,16 +826,12 @@ test('source-only typecheck resolves the canonical collab protocol source', () =
);
});
test('performance policy reports the pre-Collab delta and review thresholds', () => {
assert.deepEqual(inspectArtifactSize(historicalMainWarningBytes + 1), {
historicalNotice: true,
referenceDeltaBytes: historicalMainWarningBytes + 1 - preCollabReferenceMainBytes,
reviewRequired: false,
test('performance policy enforces the main bundle budget and reports the pre-Collab delta', () => {
assert.deepEqual(inspectArtifactSize(mainBudgetBytes), {
budgetExceeded: false,
referenceDeltaBytes: mainBudgetBytes - preCollabReferenceMainBytes,
});
assert.equal(
inspectArtifactSize(mainReviewThresholdBytes + 1).reviewRequired,
true,
);
assert.equal(inspectArtifactSize(mainBudgetBytes + 1).budgetExceeded, true);
assert.equal(inspectEvaluationDuration(evaluationIndicatorMs), 'within-indicator');
assert.equal(inspectEvaluationDuration(evaluationIndicatorMs + 1), 'warning');
assert.equal(
+18 -12
View File
@@ -10,17 +10,15 @@ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
const mainPath = path.join(root, 'main.js');
const requiredArtifacts = ['main.js', 'manifest.json', 'styles.css'];
export const preCollabReferenceMainBytes = 3_739_584;
export const historicalMainWarningBytes = 5_000_000;
export const mainReviewThresholdBytes = 20_000_000;
export const mainBudgetBytes = 5_000_000;
export const evaluationIndicatorMs = 50;
export const evaluationReviewThresholdMs = 150;
const pluginArtifactNames = ['main.js', 'manifest.json'];
export function inspectArtifactSize(mainBytes) {
return {
historicalNotice: mainBytes > historicalMainWarningBytes,
budgetExceeded: mainBytes > mainBudgetBytes,
referenceDeltaBytes: mainBytes - preCollabReferenceMainBytes,
reviewRequired: mainBytes > mainReviewThresholdBytes,
};
}
@@ -80,14 +78,9 @@ function run() {
const mainBytes = statSync(mainPath).size;
const artifact = inspectArtifactSize(mainBytes);
if (artifact.reviewRequired) {
if (artifact.budgetExceeded) {
throw new Error(
`main.js is ${mainBytes} bytes; the ${mainReviewThresholdBytes}-byte review threshold requires an explicit dependency decision.`,
);
}
if (artifact.historicalNotice) {
console.warn(
`Bundle size notice: main.js is ${mainBytes} bytes; ${historicalMainWarningBytes} bytes is a historical warning, not a hard limit.`,
`main.js is ${mainBytes} bytes; the production bundle budget is ${mainBudgetBytes} bytes.`,
);
}
@@ -144,7 +137,13 @@ Module._load = function (request, parent, isMain) {
return originalLoad.call(this, request, parent, isMain);
};
const startedAt = performance.now();
require(mainPath);
try {
require(mainPath);
} catch (error) {
const message = error instanceof Error ? (error.stack ?? error.message) : String(error);
process.stderr.write('Module evaluation failed: ' + message);
process.exit(1);
}
process.stdout.write(JSON.stringify({
childProcessStarts,
durationMs: performance.now() - startedAt,
@@ -153,11 +152,18 @@ process.stdout.write(JSON.stringify({
}));
`;
const childNodePath = [
path.join(root, 'node_modules', '.bun', 'node_modules'),
process.env.NODE_PATH,
].filter(candidate => candidate && existsSync(candidate)).join(path.delimiter);
const samples = [];
for (let index = 0; index < 7; index += 1) {
const result = spawnSync(process.execPath, ['-e', childScript, mainPath], {
cwd: root,
encoding: 'utf8',
env: childNodePath
? { ...process.env, NODE_PATH: childNodePath }
: process.env,
});
if (result.status !== 0) {
throw new Error(`Module evaluation harness failed: ${result.stderr || result.stdout}`);
+52 -5
View File
@@ -1,4 +1,5 @@
const { readFileSync } = require('node:fs');
const { readFileSync, readdirSync } = require('node:fs');
const path = require('node:path');
const {
brotliCompressSync,
constants: zlibConstants,
@@ -6,6 +7,8 @@ const {
const localeFilter = /[\\/]src[\\/]i18n[\\/]locales[\\/][^\\/]+\.json$/;
const sqlWasmFilter = /[\\/]node_modules[\\/]sql\.js[\\/]dist[\\/]sql-wasm\.wasm$/;
const localeCatalogSpecifier = 'claudian:compressed-locale-catalog';
const localeCatalogNamespace = 'compressed-locale-catalog';
function compress(contents, mode) {
return brotliCompressSync(contents, {
@@ -20,10 +23,47 @@ function decodeExpression(base64) {
return `brotliDecompressSync(Buffer.from(${JSON.stringify(base64)}, "base64"))`;
}
function createCompressedStaticAssetsPlugin() {
function createCompressedStaticAssetsPlugin({ root = process.cwd() } = {}) {
const localeDirectory = path.join(root, 'src', 'i18n', 'locales');
return {
name: 'compressed-static-assets',
setup(build) {
build.onResolve({ filter: /^claudian:compressed-locale-catalog$/ }, () => ({
namespace: localeCatalogNamespace,
path: 'non-english',
}));
build.onLoad({ filter: /.*/, namespace: localeCatalogNamespace }, () => {
const catalog = Object.fromEntries(
readdirSync(localeDirectory)
.filter(fileName => fileName.endsWith('.json') && fileName !== 'en.json')
.sort()
.map(fileName => [
path.basename(fileName, '.json'),
JSON.parse(readFileSync(path.join(localeDirectory, fileName), 'utf8')),
]),
);
const base64 = compress(
Buffer.from(JSON.stringify(catalog)),
zlibConstants.BROTLI_MODE_TEXT,
);
return {
contents: [
'import { brotliDecompressSync } from "node:zlib";',
`const compressedCatalog = ${JSON.stringify(base64)};`,
'export function loadCompressedLocale(locale) {',
' const bytes = brotliDecompressSync(Buffer.from(compressedCatalog, "base64"));',
' const catalog = JSON.parse(bytes.toString("utf8"));',
' const dictionary = catalog[locale];',
' if (!dictionary) throw new Error(`Unsupported compressed locale: ${locale}`);',
' return dictionary;',
'}',
].join('\n'),
loader: 'js',
};
});
build.onLoad({ filter: sqlWasmFilter }, (args) => {
const base64 = compress(
readFileSync(args.path),
@@ -46,11 +86,18 @@ function createCompressedStaticAssetsPlugin() {
if (!exportNames.every(name => /^[$A-Z_a-z][$\w]*$/.test(name))) {
throw new Error(`Locale ${args.path} has a top-level key that cannot be exported`);
}
const base64 = compress(raw, zlibConstants.BROTLI_MODE_TEXT);
const locale = path.basename(args.path, '.json');
const dictionaryExpression = locale === 'en'
? `JSON.parse(${decodeExpression(
compress(raw, zlibConstants.BROTLI_MODE_TEXT),
)}.toString("utf8"))`
: `loadCompressedLocale(${JSON.stringify(locale)})`;
return {
contents: [
'import { brotliDecompressSync } from "node:zlib";',
`const dictionary = JSON.parse(${decodeExpression(base64)}.toString("utf8"));`,
locale === 'en'
? 'import { brotliDecompressSync } from "node:zlib";'
: `import { loadCompressedLocale } from ${JSON.stringify(localeCatalogSpecifier)};`,
`const dictionary = ${dictionaryExpression};`,
...exportNames.map(name => `const ${name} = dictionary.${name};`),
`export { ${exportNames.join(', ')} };`,
'export default dictionary;',
+15
View File
@@ -0,0 +1,15 @@
const path = require('node:path');
function createSourcePackageAliases({ root = process.cwd() } = {}) {
return Object.freeze({
'@claudian/collab-protocol': path.join(
root,
'packages',
'collab-protocol',
'src',
'index.ts',
),
});
}
module.exports = { createSourcePackageAliases };
+49
View File
@@ -0,0 +1,49 @@
const { promises: fs } = require('node:fs');
const path = require('node:path');
const { minify } = require('terser');
const preservedComment = /^!|@preserve|@license|@cc_on/i;
async function minifyProductionBundle(source) {
const result = await minify(source, {
compress: {
passes: 3,
toplevel: true,
},
ecma: 2022,
format: {
comments: preservedComment,
},
mangle: {
toplevel: true,
},
module: false,
});
if (typeof result.code !== 'string') {
throw new Error('Terser did not produce a production bundle');
}
return result.code;
}
function createTerserProductionBundlePlugin(outputPaths) {
return {
name: 'terser-production-bundle',
setup(build) {
build.onEnd(async (result) => {
if (result.errors.length > 0) return;
const workingDirectory = build.initialOptions.absWorkingDir ?? process.cwd();
for (const outputPath of outputPaths) {
const absolutePath = path.resolve(workingDirectory, outputPath);
const source = await fs.readFile(absolutePath, 'utf8');
const minified = await minifyProductionBundle(source);
await fs.writeFile(absolutePath, `${minified}\n`, 'utf8');
}
});
},
};
}
module.exports = {
createTerserProductionBundlePlugin,
minifyProductionBundle,
};
+19 -4
View File
@@ -9,8 +9,10 @@ import {
import { lstat, open, readFile, unlink } from 'node:fs/promises';
import { isIP } from 'node:net';
import forgePki from 'node-forge/lib/pki';
import forgeAsn1 from 'node-forge/lib/asn1';
import forgePem from 'node-forge/lib/pem';
import forgeSha256 from 'node-forge/lib/sha256';
import forgePki from 'node-forge/lib/x509';
import {
ensureCollabContainerGuard,
@@ -90,6 +92,19 @@ function normalizePem(pem: string): string {
return `${pem.replace(/\r\n?/g, '\n').trim()}\n`;
}
function privateKeyFromPem(pem: string): ReturnType<typeof forgePki.privateKeyFromAsn1> {
const message = forgePem.decode(pem)[0];
const procType = message?.procType as { readonly type?: unknown } | null | undefined;
if (
!message
|| (message.type !== 'PRIVATE KEY' && message.type !== 'RSA PRIVATE KEY')
|| procType?.type === 'ENCRYPTED'
) {
throw new Error('Unsupported RSA private key PEM');
}
return forgePki.privateKeyFromAsn1(forgeAsn1.fromDer(message.body));
}
function certificateSerial(): string {
const bytes = randomBytes(16);
bytes[0] &= 0x7f;
@@ -193,7 +208,7 @@ export class LanTlsIdentity {
}
const hostCa = await this.loadOrCreate();
const caCertificate = forgePki.certificateFromPem(hostCa.caCertificatePem);
const caPrivateKey = forgePki.privateKeyFromPem(hostCa.caPrivateKeyPem);
const caPrivateKey = privateKeyFromPem(hostCa.caPrivateKeyPem);
const keyPairPem = await generateRsaKeyPair();
const certificate = forgePki.createCertificate();
const issuedAt = options.now ?? this.now();
@@ -305,7 +320,7 @@ export class LanTlsIdentity {
private async createHostCa(): Promise<LanTlsHostCa> {
const keyPairPem = await generateRsaKeyPair();
const privateKey = forgePki.privateKeyFromPem(keyPairPem.privateKeyPem);
const privateKey = privateKeyFromPem(keyPairPem.privateKeyPem);
const certificate = forgePki.createCertificate();
const now = this.now();
certificate.publicKey = forgePki.publicKeyFromPem(keyPairPem.publicKeyPem);
@@ -351,7 +366,7 @@ export class LanTlsIdentity {
) {
throw new Error('Host CA validation failed');
}
forgePki.privateKeyFromPem(normalizedPrivateKey);
privateKeyFromPem(normalizedPrivateKey);
return Object.freeze({
caCertificatePem: normalizedCertificate,
caFingerprint: fingerprintCertificatePem(normalizedCertificate),
@@ -130,7 +130,7 @@ let sharedPierreModulePromise: Promise<PierreDiffModule> | null = null;
export function preloadCollabDiffRenderer(): Promise<PierreDiffModule> {
sharedPierreModulePromise ??= (
import('@pierre/diffs') as unknown as Promise<PierreDiffModule>
import('./CollabPierreDiffModule') as unknown as Promise<PierreDiffModule>
).catch((error: unknown) => {
sharedPierreModulePromise = null;
throw error;
@@ -0,0 +1,3 @@
import { FileDiff as PierreFileDiff } from '@pierre/diffs';
export const FileDiff = PierreFileDiff;
+21 -7
View File
@@ -1,13 +1,27 @@
declare module 'node-forge/lib/pki' {
import type forge from 'node-forge';
const pki: typeof forge.pki;
export default pki;
}
declare module 'node-forge/lib/sha256' {
import type forge from 'node-forge';
const sha256: typeof forge.md.sha256;
export default sha256;
}
declare module 'node-forge/lib/asn1' {
import type forge from 'node-forge';
const asn1: typeof forge.asn1;
export default asn1;
}
declare module 'node-forge/lib/pem' {
import type forge from 'node-forge';
const pem: typeof forge.pem;
export default pem;
}
declare module 'node-forge/lib/x509' {
import type forge from 'node-forge';
const pki: typeof forge.pki;
export default pki;
}
@@ -14,8 +14,10 @@ import { build, stop } from 'esbuild';
import * as compressedStaticAssetsHelpers from '../../../scripts/compressedStaticAssets.js';
import * as desktopRuntimeAliasHelpers from '../../../scripts/desktopRuntimeAliases.js';
import * as pierreShikiBundleHelpers from '../../../scripts/pierreShikiBundle.js';
import * as sourcePackageAliasHelpers from '../../../scripts/sourcePackageAliases.js';
const { createDesktopRuntimeAliases } = desktopRuntimeAliasHelpers;
const { createSourcePackageAliases } = sourcePackageAliasHelpers;
const { createCompressedStaticAssetsPlugin } = compressedStaticAssetsHelpers;
const {
createPierreShikiBundlePlugin,
@@ -30,12 +32,16 @@ const performanceScriptPath = path.join(root, 'scripts/check-startup-performance
describe('Collab dependency envelope', () => {
const tempDirectory = mkdtempSync(path.join(tmpdir(), 'claudian-collab-build-'));
const bundlePath = path.join(tempDirectory, 'dependency-envelope.cjs');
let bundleContributors: string[] = [];
let bundleInputs: string[] = [];
beforeAll(async () => {
const result = await build({
absWorkingDir: root,
alias: createDesktopRuntimeAliases(),
alias: {
...createDesktopRuntimeAliases(),
...createSourcePackageAliases({ root }),
},
bundle: true,
external: [
...builtinModules,
@@ -54,11 +60,18 @@ describe('Collab dependency envelope', () => {
stdin: {
contents: `
import { WebSocket, WebSocketServer } from 'ws';
import { parser as markdownParser } from '@lezer/markdown';
import { scanCollabTicketReferences } from '@claudian/collab-protocol';
import initSqlJs from 'sql.js';
import sqlWasmBinary from 'sql.js/dist/sql-wasm.wasm';
import * as english from './src/i18n/locales/en.json';
import * as german from './src/i18n/locales/de.json';
import { pierreThemes, shikiThemes } from '@pierre/theming/themes';
import { CollabDiffRenderer } from './src/features/collab/detail/review/CollabDiffRenderer';
import { LanTlsIdentity } from './src/app/collab/lan/LanTlsIdentity';
import {
CollabDiffRenderer,
preloadCollabDiffRenderer,
} from './src/features/collab/detail/review/CollabDiffRenderer';
export function probeWebSocket() {
return [typeof WebSocket, typeof WebSocketServer];
@@ -73,17 +86,31 @@ describe('Collab dependency envelope', () => {
}
export async function probeDiffs() {
const diffs = await import('@pierre/diffs');
const diffs = await preloadCollabDiffRenderer();
return typeof diffs.FileDiff;
}
export function probeLocale() {
return english.collab.commands.createProject;
return [
english.collab.commands.createProject,
german.common.save,
];
}
export function probeMarkdownDependencies() {
return [
markdownParser.parse('# heading').length,
scanCollabTicketReferences('References #12').length,
];
}
export function probeThemes() {
return [pierreThemes.getThemeNames(), shikiThemes.getThemeNames()];
}
export function probeTlsIdentity() {
return typeof LanTlsIdentity;
}
export async function renderCollabTextDiff(container) {
const renderer = new CollabDiffRenderer({
themeSource: {
@@ -105,8 +132,12 @@ describe('Collab dependency envelope', () => {
sourcefile: 'collab-dependency-envelope.ts',
},
target: 'node24',
treeShaking: true,
});
bundleInputs = Object.keys(result.metafile.inputs);
bundleContributors = Object.entries(Object.values(result.metafile.outputs)[0].inputs)
.filter(([, contribution]) => contribution.bytesInOutput > 0)
.map(([input]) => input);
}, 60_000);
afterAll(() => {
@@ -166,12 +197,60 @@ describe('Collab dependency envelope', () => {
expect(inlinedOnigurumaInputs).toEqual([]);
});
it('retains only the Pierre component surface used by Collab', () => {
const normalizedInputs = bundleContributors.map(input => input.replaceAll('\\\\', '/'));
const unusedComponentInputs = normalizedInputs.filter(input => (
input.endsWith('/@pierre/diffs/dist/components/CodeView.js')
|| input.endsWith('/@pierre/diffs/dist/components/FileStream.js')
|| input.endsWith('/@pierre/diffs/dist/components/UnresolvedFile.js')
));
expect(unusedComponentInputs).toEqual([]);
});
it('bundles one shared Markdown parser implementation', () => {
const markdownParserContributors = bundleContributors
.map(input => input.replaceAll('\\\\', '/'))
.filter(input => input.includes('/@lezer/markdown/dist/'));
expect(markdownParserContributors).toHaveLength(1);
expect(markdownParserContributors[0]).toMatch(
/(?:^|\/)node_modules\/@lezer\/markdown\/dist\/index\.js$/,
);
});
it('excludes unused Forge PKCS and password-encryption modules', () => {
const normalizedContributors = bundleContributors.map(input => (
input.replaceAll('\\\\', '/')
));
const unusedForgeInputs = normalizedContributors.filter(input => (
input.endsWith('/node-forge/lib/pbe.js')
|| input.endsWith('/node-forge/lib/pbkdf2.js')
|| input.endsWith('/node-forge/lib/pkcs12.js')
|| input.endsWith('/node-forge/lib/pkcs7asn1.js')
|| input.endsWith('/node-forge/lib/rc2.js')
));
expect(unusedForgeInputs).toEqual([]);
});
it('forces the Node WebSocket implementation inside the browser-oriented bundle', () => {
const config = readFileSync(esbuildConfigPath, 'utf8');
const aliases = createDesktopRuntimeAliases();
const aliases = {
...createDesktopRuntimeAliases(),
...createSourcePackageAliases({ root }),
};
expect(path.basename(aliases.ws)).toBe('index.js');
expect(config).toContain('alias: createDesktopRuntimeAliases()');
expect(aliases['@claudian/collab-protocol']).toBe(path.join(
root,
'packages',
'collab-protocol',
'src',
'index.ts',
));
expect(config).toContain('...createDesktopRuntimeAliases()');
expect(config).toContain('...createSourcePackageAliases()');
expect(readFileSync(bundlePath, 'utf8')).not.toContain('ws does not work in the browser');
expect(runBundle(`
const dependencyEnvelope = require(process.argv[1]);
@@ -179,20 +258,24 @@ describe('Collab dependency envelope', () => {
`)).toBe('["function","function"]');
});
it('treats 5 MB as historical guidance and 20 MB as the review gate', () => {
it('enforces a 5 MB main bundle budget', () => {
const script = readFileSync(performanceScriptPath, 'utf8');
expect(script).toContain('preCollabReferenceMainBytes = 3_739_584');
expect(script).toContain('historicalMainWarningBytes = 5_000_000');
expect(script).toContain('mainReviewThresholdBytes = 20_000_000');
expect(script).toContain('mainBudgetBytes = 5_000_000');
expect(script).toContain('evaluationReviewThresholdMs = 150');
expect(script).toContain('pre-Collab reference delta');
expect(script).not.toContain('mainBudgetBytes');
expect(script).toContain('artifact.budgetExceeded');
expect(script).not.toContain('historicalMainWarningBytes');
expect(script).not.toContain('mainReviewThresholdBytes');
});
it('guards ordinary evaluation from deferred runtime initialization', () => {
const script = readFileSync(performanceScriptPath, 'utf8');
expect(script).toContain('Module evaluation failed:');
expect(script).toContain("path.join(root, 'node_modules', '.bun', 'node_modules')");
expect(script).toContain('NODE_PATH: childNodePath');
expect(script).toContain('childProcessStarts !== 0');
expect(script).toContain('networkListens !== 0');
expect(script).toContain('wasmInitializations !== 0');
@@ -219,8 +302,10 @@ describe('Collab dependency envelope', () => {
exports: [
'probeDiffs',
'probeLocale',
'probeMarkdownDependencies',
'probeSql',
'probeThemes',
'probeTlsIdentity',
'probeWebSocket',
'renderCollabTextDiff',
],
@@ -244,12 +329,25 @@ describe('Collab dependency envelope', () => {
const bundle = readFileSync(bundlePath, 'utf8');
const localeResult = runBundle(`
const dependencyEnvelope = require(process.argv[1]);
process.stdout.write(dependencyEnvelope.probeLocale());
process.stdout.write(JSON.stringify(dependencyEnvelope.probeLocale()));
`);
expect(bundle).toContain('brotliDecompressSync');
expect(bundle).not.toContain('Create Collab project');
expect(localeResult).toBe('Create Collab project');
expect(JSON.parse(localeResult)).toEqual([
'Create Collab project',
'Speichern',
]);
});
it('shares one compressed catalog across non-English locales', () => {
const compressedCatalogContributors = bundleContributors.filter(input => (
input.includes('compressed-locale-catalog')
));
expect(compressedCatalogContributors).toEqual([
'compressed-locale-catalog:non-english',
]);
});
it('mounts Collab review through the styled Pierre custom element', () => {
@@ -0,0 +1,25 @@
import * as terserProductionBundleHelpers from '../../../scripts/terserProductionBundle.js';
const { minifyProductionBundle } = terserProductionBundleHelpers;
describe('production bundle minification', () => {
it('preserves CommonJS behavior and license comments while reducing output', async () => {
const source = `
/*! Example dependency license */
function computeVisibleResult(firstValue, secondValue) {
const unusedIntermediateName = firstValue * 100;
if (unusedIntermediateName < 0) throw new Error('unreachable');
return firstValue + secondValue;
}
module.exports = { computeVisibleResult };
`;
const output = await minifyProductionBundle(source);
const module = { exports: {} as { computeVisibleResult?: (left: number, right: number) => number } };
Function('module', 'exports', output)(module, module.exports);
expect(output.length).toBeLessThan(source.length);
expect(output).toContain('Example dependency license');
expect(module.exports.computeVisibleResult?.(20, 22)).toBe(42);
});
});
@@ -88,7 +88,7 @@ describe('OpencodeConversationHistoryService', () => {
userMessageId: 'msg-user',
},
]);
});
}, 15_000);
it('recovers the last OpenCode model from native message metadata', async () => {
const dbPath = path.join(tmpRoot, 'model-history.db');