diff --git a/libs/langchain-scripts/package.json b/libs/langchain-scripts/package.json index 258423db68b8..13e9167a436b 100644 --- a/libs/langchain-scripts/package.json +++ b/libs/langchain-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@langchain/scripts", - "version": "0.1.1", + "version": "0.1.2", "description": "Shared scripts for LangChain.js", "type": "module", "engines": { diff --git a/libs/langchain-scripts/src/build/index.ts b/libs/langchain-scripts/src/build/index.ts index 5a02a2e9ff45..f224d3678383 100644 --- a/libs/langchain-scripts/src/build/index.ts +++ b/libs/langchain-scripts/src/build/index.ts @@ -28,47 +28,25 @@ async function asyncSpawn(command: string, args: string[]) { }); } -const deleteFolderRecursive = async function (inputPath: string) { +const fsRmRfSafe = async (inputPath: string) => { try { - // Verify the path exists - if ( - await fs.promises - .access(inputPath) - .then(() => true) - .catch(() => false) - ) { - const pathStat = await fs.promises.lstat(inputPath); - // If it's a file, delete it and return - if (pathStat.isFile()) { - await fs.promises.unlink(inputPath); - } else if (pathStat.isDirectory()) { - // List contents of directory - const directoryContents = await fs.promises.readdir(inputPath); - if (directoryContents.length) { - for await (const item of directoryContents) { - const itemStat = await fs.promises.lstat( - path.join(inputPath, item) - ); - if (itemStat.isFile()) { - // Delete file - await fs.promises.unlink(path.join(inputPath, item)); - } else if (itemStat.isDirectory()) { - await deleteFolderRecursive(path.join(inputPath, item)); - } - } - } else if (directoryContents.length === 0) { - // If the directory is empty, delete it - await fs.promises.rmdir(inputPath); - } - } - } + await fs.promises.rm(inputPath, { recursive: true, force: true }); // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error: any) { - if (error.code !== "ENOENT") { - // If the error is not "file or directory doesn't exist", rethrow it - throw error; - } - // Otherwise, ignore the error (file or directory already doesn't exist) + console.log( + `Error deleting directory via fs.promises.rm: ${error.code}. Path: ${inputPath}` + ); + } +}; + +const fsUnlinkSafe = async (filePath: string) => { + try { + await fs.promises.unlink(filePath); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (error: any) { + console.log( + `Error deleting file via fs.promises.unlink: ${error.code}. Path: ${filePath}` + ); } }; @@ -611,15 +589,11 @@ function processOptions(): { async function cleanGeneratedFiles(config: LangChainConfig) { const allFileNames = Object.keys(config.entrypoints) - .map((key) => [`${key}.cjs`, `${key}.js`, `${key}.d.ts`, `${key}.d.dts`]) + .map((key) => [`${key}.cjs`, `${key}.js`, `${key}.d.ts`]) .flat(); return Promise.all( allFileNames.map(async (fileName) => { - try { - await fs.promises.unlink(fileName); - } catch { - // no-op - } + await fsUnlinkSafe(fileName); }) ); } @@ -637,8 +611,9 @@ export async function moveAndRename({ return; } + let renamedDestination = ""; try { - for (const file of await fs.promises.readdir(abs(source), { + for await (const file of await fs.promises.readdir(abs(source), { withFileTypes: true, })) { if (file.isDirectory()) { @@ -667,17 +642,23 @@ export async function moveAndRename({ // Rename the file to .cjs const renamed = path.format({ name: parsed.name, ext: ".cjs" }); - - await fs.promises.writeFile( - abs(`${dest}/${renamed}`), - rewritten, - "utf8" + renamedDestination = abs(`${dest}/${renamed}`); + await fs.promises.writeFile(renamedDestination, rewritten, "utf8"); + } + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (error: any) { + console.error("Error during moveAndRename"); + if (error.code === "ENOENT") { + // Check if file already exists in destination + if (fs.existsSync(renamedDestination)) { + console.error( + `File already exists in destination: ${renamedDestination}` ); + } else { + console.error(`File not found: ${error.path}`); } } - } catch (err) { - console.error(err); - process.exit(1); } } @@ -702,14 +683,10 @@ export async function buildWithTSup() { // Clean & generate build files if (pre && shouldGenMaps) { await Promise.all([ - deleteFolderRecursive("dist").catch((e) => { + fsRmRfSafe("dist").catch((e) => { console.error("Error removing dist (pre && shouldGenMaps)"); throw e; }), - deleteFolderRecursive(".turbo").catch((e) => { - console.error("Error removing .turbo (pre && shouldGenMaps)"); - throw e; - }), cleanGeneratedFiles(config), createImportMapFile(config), generateImportConstants(config), @@ -717,14 +694,10 @@ export async function buildWithTSup() { ]); } else if (pre && !shouldGenMaps) { await Promise.all([ - deleteFolderRecursive("dist").catch((e) => { + fsRmRfSafe("dist").catch((e) => { console.error("Error removing dist (pre && !shouldGenMaps)"); throw e; }), - deleteFolderRecursive(".turbo").catch((e) => { - console.error("Error deleting with deleteFolderRecursive"); - throw e; - }), cleanGeneratedFiles(config), ]); } @@ -742,11 +715,11 @@ export async function buildWithTSup() { // move CJS to dist await Promise.all([ updatePackageJson(config), - deleteFolderRecursive("dist-cjs").catch((e) => { + fsRmRfSafe("dist-cjs").catch((e) => { console.error("Error removing dist-cjs"); throw e; }), - deleteFolderRecursive("dist/tests").catch((e) => { + fsRmRfSafe("dist/tests").catch((e) => { console.error("Error removing dist/tests"); throw e; }), @@ -754,9 +727,7 @@ export async function buildWithTSup() { // Required for cross-platform compatibility. // Windows does not manage globs the same as Max/Linux when deleting directories. const testFolders = await glob("dist/**/tests"); - await Promise.all( - testFolders.map((folder) => deleteFolderRecursive(folder)) - ); + await Promise.all(testFolders.map((folder) => fsRmRfSafe(folder))); })().catch((e) => { console.error("Error removing dist/**/tests"); throw e;