mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-04-05 16:53:29 +08:00
fix: harden install planning and sync tracked catalogs
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const { planInstallTargetScaffold } = require('./install-targets/registry');
|
||||
const { getInstallTargetAdapter, planInstallTargetScaffold } = require('./install-targets/registry');
|
||||
|
||||
const DEFAULT_REPO_ROOT = path.join(__dirname, '../..');
|
||||
const SUPPORTED_INSTALL_TARGETS = ['claude', 'cursor', 'antigravity', 'codex', 'gemini', 'opencode', 'codebuddy'];
|
||||
@@ -76,6 +76,48 @@ function dedupeStrings(values) {
|
||||
return [...new Set((Array.isArray(values) ? values : []).map(value => String(value).trim()).filter(Boolean))];
|
||||
}
|
||||
|
||||
function readOptionalStringOption(options, key) {
|
||||
if (
|
||||
!Object.prototype.hasOwnProperty.call(options, key)
|
||||
|| options[key] === null
|
||||
|| options[key] === undefined
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (typeof options[key] !== 'string' || options[key].trim() === '') {
|
||||
throw new Error(`${key} must be a non-empty string when provided`);
|
||||
}
|
||||
|
||||
return options[key];
|
||||
}
|
||||
|
||||
function readModuleTargetsOrThrow(module) {
|
||||
const moduleId = module && module.id ? module.id : '<unknown>';
|
||||
const targets = module && module.targets;
|
||||
|
||||
if (!Array.isArray(targets)) {
|
||||
throw new Error(`Install module ${moduleId} has invalid targets; expected an array of supported target ids`);
|
||||
}
|
||||
|
||||
const normalizedTargets = targets.map(target => (
|
||||
typeof target === 'string' ? target.trim() : ''
|
||||
));
|
||||
|
||||
if (normalizedTargets.some(target => target.length === 0)) {
|
||||
throw new Error(`Install module ${moduleId} has invalid targets; expected an array of supported target ids`);
|
||||
}
|
||||
|
||||
const unsupportedTargets = normalizedTargets.filter(target => !SUPPORTED_INSTALL_TARGETS.includes(target));
|
||||
if (unsupportedTargets.length > 0) {
|
||||
throw new Error(
|
||||
`Install module ${moduleId} has unsupported targets: ${unsupportedTargets.join(', ')}`
|
||||
);
|
||||
}
|
||||
|
||||
return normalizedTargets;
|
||||
}
|
||||
|
||||
function assertKnownModuleIds(moduleIds, manifests) {
|
||||
const unknownModuleIds = dedupeStrings(moduleIds)
|
||||
.filter(moduleId => !manifests.modulesById.has(moduleId));
|
||||
@@ -125,6 +167,11 @@ function loadInstallManifests(options = {}) {
|
||||
? profilesData.profiles
|
||||
: {};
|
||||
const components = Array.isArray(componentsData.components) ? componentsData.components : [];
|
||||
|
||||
for (const module of modules) {
|
||||
readModuleTargetsOrThrow(module);
|
||||
}
|
||||
|
||||
const modulesById = new Map(modules.map(module => [module.id, module]));
|
||||
const componentsById = new Map(components.map(component => [component.id, component]));
|
||||
|
||||
@@ -361,6 +408,16 @@ function resolveInstallPlan(options = {}) {
|
||||
`Unknown install target: ${target}. Expected one of ${SUPPORTED_INSTALL_TARGETS.join(', ')}`
|
||||
);
|
||||
}
|
||||
const validatedProjectRoot = readOptionalStringOption(options, 'projectRoot');
|
||||
const validatedHomeDir = readOptionalStringOption(options, 'homeDir');
|
||||
const targetPlanningInput = target
|
||||
? {
|
||||
repoRoot: manifests.repoRoot,
|
||||
projectRoot: validatedProjectRoot || manifests.repoRoot,
|
||||
homeDir: validatedHomeDir || os.homedir(),
|
||||
}
|
||||
: null;
|
||||
const targetAdapter = target ? getInstallTargetAdapter(target) : null;
|
||||
|
||||
const effectiveRequestedIds = dedupeStrings(
|
||||
requestedModuleIds.filter(moduleId => !excludedModuleOwners.has(moduleId))
|
||||
@@ -396,7 +453,13 @@ function resolveInstallPlan(options = {}) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (target && !module.targets.includes(target)) {
|
||||
const supportsTarget = !target
|
||||
|| (
|
||||
readModuleTargetsOrThrow(module).includes(target)
|
||||
&& (!targetAdapter || targetAdapter.supportsModule(module, targetPlanningInput))
|
||||
);
|
||||
|
||||
if (!supportsTarget) {
|
||||
if (dependencyOf) {
|
||||
skippedTargetIds.add(rootRequesterId || dependencyOf);
|
||||
return false;
|
||||
@@ -444,9 +507,9 @@ function resolveInstallPlan(options = {}) {
|
||||
const scaffoldPlan = target
|
||||
? planInstallTargetScaffold({
|
||||
target,
|
||||
repoRoot: manifests.repoRoot,
|
||||
projectRoot: options.projectRoot || manifests.repoRoot,
|
||||
homeDir: options.homeDir || os.homedir(),
|
||||
repoRoot: targetPlanningInput.repoRoot,
|
||||
projectRoot: targetPlanningInput.projectRoot,
|
||||
homeDir: targetPlanningInput.homeDir,
|
||||
modules: selectedModules,
|
||||
})
|
||||
: null;
|
||||
|
||||
Reference in New Issue
Block a user