chore: Fix hot reload for nodes-langchain package (no-changelog) (#17111)

This commit is contained in:
oleg
2025-07-09 13:13:07 +02:00
committed by GitHub
parent d1ac292709
commit d08f306c83
4 changed files with 64 additions and 17 deletions

View File

@@ -14,7 +14,7 @@
"format:check": "biome ci .",
"lint": "eslint nodes credentials utils --quiet",
"lintfix": "eslint nodes credentials utils --fix",
"watch": "tsup --watch --tsconfig tsconfig.build.json --onSuccess \"pnpm copy-nodes-json && tsc-alias -p tsconfig.build.json && pnpm n8n-generate-metadata\"",
"watch": "tsup --watch nodes --watch credentials --watch utils --watch types --tsconfig tsconfig.build.json --onSuccess \"node ./scripts/post-build.js\"",
"test": "jest",
"test:dev": "jest --watch"
},

View File

@@ -0,0 +1,23 @@
/**
* Post-build script
*
* This is a separate script instead of inline npm commands because using "&&"" to chain commands in --onSuccess can cause the watch mode to hang
*/
const { execSync } = require('child_process');
function runCommand(command) {
try {
execSync(command, { stdio: 'inherit' });
} catch (error) {
console.error(`Command failed: ${command}`);
process.exit(1);
}
}
// Run all post-build tasks
runCommand('npx tsc-alias -p tsconfig.build.json');
runCommand('node scripts/copy-tokenizer-json.js .');
runCommand('node ../../nodes-base/scripts/copy-nodes-json.js .');
runCommand('pnpm n8n-copy-static-files');
runCommand('pnpm n8n-generate-metadata');

View File

@@ -10,7 +10,7 @@
"build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && pnpm run build:data",
"build:data": "node scripts/build.mjs",
"buildAndDev": "pnpm run build && pnpm run dev",
"dev": "concurrently -k -n \"TypeScript,Node\" -c \"yellow.bold,cyan.bold\" \"npm run watch\" \"nodemon\"",
"dev": "concurrently -k -n \"TypeScript,Node\" -c \"yellow.bold,cyan.bold\" \"npm run watch\" \"nodemon --delay 1\"",
"dev:worker": "concurrently -k -n \"TypeScript,Node\" -c \"yellow.bold,cyan.bold\" \"npm run watch\" \"nodemon worker\"",
"dev:webhook": "concurrently -k -n \"TypeScript,Node\" -c \"yellow.bold,cyan.bold\" \"npm run watch\" \"nodemon webhook\"",
"format": "biome format --write .",

View File

@@ -26,6 +26,7 @@ import type {
LoadedNodesAndCredentials,
} from 'n8n-workflow';
import { deepCopy, NodeConnectionTypes, UnexpectedError, UserError } from 'n8n-workflow';
import { type Stats } from 'node:fs';
import path from 'path';
import picocolors from 'picocolors';
@@ -532,24 +533,47 @@ export class LoadNodesAndCredentials {
}
const reloader = debounce(async () => {
loader.reset();
await loader.loadAll();
await this.postProcessLoaders();
push.broadcast({ type: 'nodeDescriptionUpdated', data: {} });
this.logger.info(`Hot reload triggered for ${loader.packageName}`);
try {
loader.reset();
await loader.loadAll();
await this.postProcessLoaders();
push.broadcast({ type: 'nodeDescriptionUpdated', data: {} });
} catch (error) {
this.logger.error(`Hot reload failed for ${loader.packageName}`);
}
}, 100);
const toWatch = loader.isLazyLoaded
? ['**/nodes.json', '**/credentials.json']
: ['**/*.js', '**/*.json'];
const files = await glob(toWatch, {
cwd: directory,
ignore: ['node_modules/**'],
});
const watcher = watch(files, {
cwd: directory,
// For lazy loaded packages, we need to watch the dist directory
const watchPath = loader.isLazyLoaded ? path.join(directory, 'dist') : directory;
// Watch options for chokidar v4
const watchOptions = {
ignoreInitial: true,
});
watcher.on('add', reloader).on('change', reloader).on('unlink', reloader);
cwd: directory,
// Filter which files to watch based on loader type
ignored: (filePath: string, stats?: Stats) => {
if (!stats) return false;
if (stats.isDirectory()) return false;
if (filePath.includes('node_modules')) return true;
if (loader.isLazyLoaded) {
// Only watch nodes.json and credentials.json files
const basename = path.basename(filePath);
return basename !== 'nodes.json' && basename !== 'credentials.json';
}
// Watch all .js and .json files
return !filePath.endsWith('.js') && !filePath.endsWith('.json');
},
};
const watcher = watch(watchPath, watchOptions);
// Watch for file changes and additions
// Not watching removals to prevent issues during build processes
watcher.on('change', reloader);
watcher.on('add', reloader);
});
}
}