diff --git a/libs/langchain-scripts/bin/build.js b/libs/langchain-scripts/bin/build.js index 172d1fa8fc67..40b80ac0d611 100755 --- a/libs/langchain-scripts/bin/build.js +++ b/libs/langchain-scripts/bin/build.js @@ -225,16 +225,15 @@ async function listExternals( export async function checkTreeShaking(options) { const externals = await listExternals(options?.extraInternals ?? []); const entrypoints = await listEntrypoints(); - const consoleLog = console.log; - /** @type {Map} */ + const consoleInfo = console.info; const reportMap = new Map(); for (const entrypoint of entrypoints) { let sideEffects = ""; - console.log = function (...args) { + console.info = function (...args) { const line = args.length ? args.join(" ") : ""; - if (line.trim().startsWith("First side effect in")) { + if (line.includes("First side effect in")) { sideEffects += `${line}\n`; } }; @@ -245,17 +244,26 @@ export async function checkTreeShaking(options) { experimentalLogSideEffects: true, }); + let hasUnexpectedSideEffects = sideEffects.length > 0; + if (hasUnexpectedSideEffects) { + const entrypointContent = await fs.promises.readFile(`./dist/${entrypoint.replace(/^\.\//, "")}`); + // Allow escaping side effects strictly within code directly + // within an entrypoint + hasUnexpectedSideEffects = !entrypointContent + .toString() + .includes("/* __LC_ALLOW_ENTRYPOINT_SIDE_EFFECTS__ */"); + } reportMap.set(entrypoint, { log: sideEffects, - hasSideEffects: sideEffects.length > 0, + hasUnexpectedSideEffects, }); } - console.log = consoleLog; + console.info = consoleInfo; let failed = false; for (const [entrypoint, report] of reportMap) { - if (report.hasSideEffects) { + if (report.hasUnexpectedSideEffects) { failed = true; console.log("---------------------------------"); console.log(`Tree shaking failed for ${entrypoint}`); @@ -264,7 +272,7 @@ export async function checkTreeShaking(options) { } if (failed) { - process.exit(1); + throw new Error("Tree shaking checks failed."); } else { console.log("Tree shaking checks passed!"); } diff --git a/libs/langchain-scripts/package.json b/libs/langchain-scripts/package.json index efcba3c1f946..ffa7187fece6 100644 --- a/libs/langchain-scripts/package.json +++ b/libs/langchain-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@langchain/scripts", - "version": "0.0.15", + "version": "0.0.18", "description": "Shared scripts for LangChain.js", "type": "module", "engines": { diff --git a/libs/langchain-scripts/src/build_v2.ts b/libs/langchain-scripts/src/build_v2.ts index e8764f6b48e5..a07ae6ec9074 100644 --- a/libs/langchain-scripts/src/build_v2.ts +++ b/libs/langchain-scripts/src/build_v2.ts @@ -441,16 +441,16 @@ async function checkTreeShaking(config: LangChainConfig) { ); const externals = listExternals(packageJson, config?.internals ?? []); const entrypoints = listEntrypoints(packageJson); - const consoleLog = console.log; - /** @type {Map} */ + const consoleInfo = console.info; + /** @type {Map} */ const reportMap = new Map(); for (const entrypoint of entrypoints) { let sideEffects = ""; - console.log = function (...args) { + console.info = function (...args) { const line = args.length ? args.join(" ") : ""; - if (line.trim().startsWith("First side effect in")) { + if (line.includes("First side effect in")) { sideEffects += `${line}\n`; } }; @@ -461,17 +461,28 @@ async function checkTreeShaking(config: LangChainConfig) { experimentalLogSideEffects: true, }); + let hasUnexpectedSideEffects = sideEffects.length > 0; + if (hasUnexpectedSideEffects) { + const entrypointContent = await fs.promises.readFile( + `./dist/${entrypoint.replace(/^\.\//, "")}` + ); + // Allow escaping side effects strictly within code directly + // within an entrypoint + hasUnexpectedSideEffects = !entrypointContent + .toString() + .includes("/* __LC_ALLOW_ENTRYPOINT_SIDE_EFFECTS__ */"); + } reportMap.set(entrypoint, { log: sideEffects, - hasSideEffects: sideEffects.length > 0, + hasUnexpectedSideEffects, }); } - console.log = consoleLog; + console.info = consoleInfo; let failed = false; for (const [entrypoint, report] of reportMap) { - if (report.hasSideEffects) { + if (report.hasUnexpectedSideEffects) { failed = true; console.log("---------------------------------"); console.log(`Tree shaking failed for ${entrypoint}`); @@ -480,7 +491,8 @@ async function checkTreeShaking(config: LangChainConfig) { } if (failed) { - process.exit(1); + // TODO: Throw a hard error here + console.log("Tree shaking checks failed."); } else { console.log("Tree shaking checks passed!"); } diff --git a/libs/langchain-scripts/src/check-tree-shaking.ts b/libs/langchain-scripts/src/check-tree-shaking.ts index d5f724607948..cabec3b60200 100644 --- a/libs/langchain-scripts/src/check-tree-shaking.ts +++ b/libs/langchain-scripts/src/check-tree-shaking.ts @@ -60,21 +60,21 @@ async function listExternals( export async function checkTreeShaking(options?: TreeShakingArgs) { const externals = await listExternals(options?.extraInternals ?? []); const entrypoints = await listEntrypoints(); - const consoleLog = console.log; + const consoleInfo = console.info; const reportMap: Map< string, { log: string; - hasSideEffects: boolean; + hasUnexpectedSideEffects: boolean; } > = new Map(); for (const entrypoint of entrypoints) { let sideEffects = ""; - console.log = function (...args) { + console.info = function (...args) { const line = args.length ? args.join(" ") : ""; - if (line.trim().startsWith("First side effect in")) { + if (line.includes("First side effect in")) { sideEffects += `${line}\n`; } }; @@ -85,17 +85,28 @@ export async function checkTreeShaking(options?: TreeShakingArgs) { experimentalLogSideEffects: true, }); + let hasUnexpectedSideEffects = sideEffects.length > 0; + if (hasUnexpectedSideEffects) { + const entrypointContent = await fs.readFile( + `./dist/${entrypoint.replace(/^\.\//, "")}` + ); + // Allow escaping side effects strictly within code directly + // within an entrypoint + hasUnexpectedSideEffects = !entrypointContent + .toString() + .includes("/* __LC_ALLOW_ENTRYPOINT_SIDE_EFFECTS__ */"); + } reportMap.set(entrypoint, { log: sideEffects, - hasSideEffects: sideEffects.length > 0, + hasUnexpectedSideEffects, }); } - console.log = consoleLog; + console.info = consoleInfo; let failed = false; for (const [entrypoint, report] of reportMap) { - if (report.hasSideEffects) { + if (report.hasUnexpectedSideEffects) { failed = true; console.log("---------------------------------"); console.log(`Tree shaking failed for ${entrypoint}`); @@ -104,7 +115,7 @@ export async function checkTreeShaking(options?: TreeShakingArgs) { } if (failed) { - process.exit(1); + throw new Error("Tree shaking checks failed."); } else { console.log("Tree shaking checks passed!"); }