Files
ECC/scripts/lib/missing-dependency.js
T
wakqasahmedandhaelyra ce11e8f690 fix(install): ship ajv/sql.js with the plugin install bundle (#2822)
install-plan.js and install-apply.js both require ./lib/install/config at
load time, and that module required ajv unconditionally at the top of the
file even though ajv is only actually used when validating an
ecc-install.json. When ECC is installed via the Claude Code plugin
marketplace, the marketplace directory is a bare git clone with no
node_modules, so requiring ajv crashes commands like --list-profiles that
never touch install-config validation at all.

Same root cause in scripts/lib/control-pane/state.js: sql.js and
@iarna/toml were required at module scope even though they are only used
inside openSqlDatabase() and readTomlConfig(), so control-pane.js --help
crashed too.

Make both requires lazy so they only load when the feature that actually
needs them runs. For the case where ajv/sql.js/js-yaml/@iarna-toml is
genuinely needed and still missing, add a small helper that turns the raw
MODULE_NOT_FOUND into an actionable message naming the package and the
install command, instead of a stack trace (install-apply.js) or, worse, an
unhandled crash with a usage banner tacked on that reads like a bad
argument (install-plan.js, control-pane.js). Applied the same helper to
memory-mcp.mjs, where ajv is genuinely load-bearing (it compiles every MCP
tool's JSON schema up front) so it can't be made lazy the same way.

Added a regression test that copies just scripts/, schemas/, and
manifests/ into a directory with no node_modules anywhere above it in the
filesystem, which reproduces the plugin-marketplace install exactly, and
asserts install-plan.js and control-pane.js still work.
2026-09-07 16:26:10 -04:00

39 lines
1.2 KiB
JavaScript

'use strict';
// Production dependencies declared in package.json's "dependencies" field.
// `npm install` never runs when ECC is installed via the Claude Code plugin
// marketplace (a plain git clone), so these can be missing at runtime even
// though the code that needs them is fine.
const RUNTIME_DEPENDENCY_VERSIONS = {
ajv: '8.20.0',
'sql.js': '1.14.2',
'js-yaml': '4.3.1',
'@iarna/toml': '2.2.5',
};
function describeMissingDependencyError(error) {
if (!error || error.code !== 'MODULE_NOT_FOUND') {
return null;
}
const match = /Cannot find module '([^']+)'/.exec(error.message || '');
const moduleName = match && match[1];
const pinnedVersion = moduleName && RUNTIME_DEPENDENCY_VERSIONS[moduleName];
if (!pinnedVersion) {
return null;
}
return (
`Missing dependency '${moduleName}'. ECC's production dependencies aren't installed ` +
'(this happens when ECC was installed via the Claude Code plugin marketplace, which ' +
'clones the repo but never runs npm install). Run "npm install" from the ECC repo ' +
`root, or install just this package with "npm install --no-save ${moduleName}@${pinnedVersion}".`
);
}
module.exports = {
RUNTIME_DEPENDENCY_VERSIONS,
describeMissingDependencyError,
};