diff --git a/scripts/auto-update.js b/scripts/auto-update.js index 52ae9d25..284e532c 100644 --- a/scripts/auto-update.js +++ b/scripts/auto-update.js @@ -25,7 +25,7 @@ function parseArgs(argv) { repoRoot: null, dryRun: false, json: false, - help: false, + help: false }; for (let index = 0; index < args.length; index += 1) { @@ -63,9 +63,7 @@ function deriveRepoRootFromState(state) { continue; } - const relativeParts = operation.sourceRelativePath - .split(/[\\/]+/) - .filter(Boolean); + const relativeParts = operation.sourceRelativePath.split(/[\\/]+/).filter(Boolean); if (relativeParts.length === 0) { continue; @@ -149,9 +147,7 @@ function validateRepoRoot(repoRoot) { throw new Error(`Invalid ECC repo root: unreadable package.json at ${packageJsonPath}`); } if (!ECC_PACKAGE_NAMES.has(pkgName)) { - throw new Error( - `Refusing to run install from untrusted repo root ${normalized}: package.json name '${pkgName}' is not an official ECC package.` - ); + throw new Error(`Refusing to run install from untrusted repo root ${normalized}: package.json name '${pkgName}' is not an official ECC package.`); } return normalized; @@ -162,7 +158,7 @@ function runExternalCommand(command, args, options = {}) { cwd: options.cwd, env: options.env || process.env, encoding: 'utf8', - maxBuffer: 10 * 1024 * 1024, + maxBuffer: 10 * 1024 * 1024 }); if (result.error) { @@ -186,7 +182,7 @@ function runAutoUpdate(options = {}, dependencies = {}) { const records = discover({ homeDir, projectRoot, - targets: options.targets, + targets: options.targets }).filter(record => record.exists); const results = []; @@ -198,8 +194,8 @@ function runAutoUpdate(options = {}, dependencies = {}) { summary: { checkedCount: 0, updatedCount: 0, - errorCount: 0, - }, + errorCount: 0 + } }; } @@ -211,7 +207,7 @@ function runAutoUpdate(options = {}, dependencies = {}) { adapter: record.adapter, installStatePath: record.installStatePath, status: 'error', - error: record.error || 'No valid install-state available', + error: record.error || 'No valid install-state available' }); continue; } @@ -220,7 +216,7 @@ function runAutoUpdate(options = {}, dependencies = {}) { inferredRepoRoots.push(recordRepoRoot); validRecords.push({ record, - repoRoot: recordRepoRoot, + repoRoot: recordRepoRoot }); } @@ -240,15 +236,15 @@ function runAutoUpdate(options = {}, dependencies = {}) { summary: { checkedCount: results.length, updatedCount: 0, - errorCount: results.length, - }, + errorCount: results.length + } }; } const env = { ...process.env, HOME: homeDir, - USERPROFILE: homeDir, + USERPROFILE: homeDir }; if (!options.dryRun) { @@ -258,11 +254,7 @@ function runAutoUpdate(options = {}, dependencies = {}) { for (const entry of validRecords) { const installArgs = buildInstallApplyArgs(entry.record); - const args = [ - path.join(repoRoot, 'scripts', 'install-apply.js'), - ...installArgs, - '--json', - ]; + const args = [path.join(repoRoot, 'scripts', 'install-apply.js'), ...installArgs, '--json']; if (options.dryRun) { args.push('--dry-run'); @@ -271,7 +263,7 @@ function runAutoUpdate(options = {}, dependencies = {}) { try { const commandResult = execute(process.execPath, args, { cwd: determineInstallCwd(entry.record, repoRoot), - env, + env }); let payload = null; @@ -286,7 +278,7 @@ function runAutoUpdate(options = {}, dependencies = {}) { cwd: determineInstallCwd(entry.record, repoRoot), installArgs, status: options.dryRun ? 'planned' : 'updated', - payload, + payload }); } catch (error) { results.push({ @@ -295,7 +287,7 @@ function runAutoUpdate(options = {}, dependencies = {}) { repoRoot, installArgs, status: 'error', - error: error.message, + error: error.message }); } } @@ -307,8 +299,8 @@ function runAutoUpdate(options = {}, dependencies = {}) { summary: { checkedCount: results.length, updatedCount: results.filter(result => result.status === 'updated' || result.status === 'planned').length, - errorCount: results.filter(result => result.status === 'error').length, - }, + errorCount: results.filter(result => result.status === 'error').length + } }; } @@ -350,7 +342,7 @@ function main() { projectRoot: process.cwd(), targets: options.targets, repoRoot: options.repoRoot, - dryRun: options.dryRun, + dryRun: options.dryRun }); if (options.json) { @@ -375,5 +367,5 @@ module.exports = { deriveRepoRootFromState, buildInstallApplyArgs, determineInstallCwd, - runAutoUpdate, + runAutoUpdate }; diff --git a/scripts/lib/install-lifecycle.js b/scripts/lib/install-lifecycle.js index 53df1e3c..b35764c6 100644 --- a/scripts/lib/install-lifecycle.js +++ b/scripts/lib/install-lifecycle.js @@ -5,13 +5,8 @@ const path = require('path'); const { resolveInstallPlan, loadInstallManifests } = require('./install-manifests'); const { readInstallState, writeInstallState } = require('./install-state'); const { assertWithinTrustedRoot } = require('./path-safety'); -const { - createManifestInstallPlan, -} = require('./install-executor'); -const { - getInstallTargetAdapter, - listInstallTargetAdapters, -} = require('./install-targets/registry'); +const { createManifestInstallPlan } = require('./install-executor'); +const { getInstallTargetAdapter, listInstallTargetAdapters } = require('./install-targets/registry'); const DEFAULT_REPO_ROOT = path.join(__dirname, '../..'); @@ -52,9 +47,7 @@ function compareStringArrays(left, right) { } function getManagedOperations(state) { - return Array.isArray(state && state.operations) - ? state.operations.filter(operation => operation.ownership === 'managed') - : []; + return Array.isArray(state && state.operations) ? state.operations.filter(operation => operation.ownership === 'managed') : []; } function resolveOperationSourcePath(repoRoot, operation) { @@ -116,13 +109,7 @@ function parseJsonLikeValue(value, label) { } function getOperationTextContent(operation) { - const candidateKeys = [ - 'renderedContent', - 'content', - 'managedContent', - 'expectedContent', - 'templateOutput', - ]; + const candidateKeys = ['renderedContent', 'content', 'managedContent', 'expectedContent', 'templateOutput']; for (const key of candidateKeys) { if (typeof operation[key] === 'string') { @@ -134,13 +121,7 @@ function getOperationTextContent(operation) { } function getOperationJsonPayload(operation) { - const candidateKeys = [ - 'mergePayload', - 'managedPayload', - 'payload', - 'value', - 'expectedValue', - ]; + const candidateKeys = ['mergePayload', 'managedPayload', 'payload', 'value', 'expectedValue']; for (const key of candidateKeys) { if (operation[key] !== undefined) { @@ -152,11 +133,7 @@ function getOperationJsonPayload(operation) { } function getOperationPreviousContent(operation) { - const candidateKeys = [ - 'previousContent', - 'originalContent', - 'backupContent', - ]; + const candidateKeys = ['previousContent', 'originalContent', 'backupContent']; for (const key of candidateKeys) { if (typeof operation[key] === 'string') { @@ -168,11 +145,7 @@ function getOperationPreviousContent(operation) { } function getOperationPreviousJson(operation) { - const candidateKeys = [ - 'previousValue', - 'previousJson', - 'originalValue', - ]; + const candidateKeys = ['previousValue', 'previousJson', 'originalValue']; for (const key of candidateKeys) { if (operation[key] !== undefined) { @@ -217,10 +190,7 @@ function jsonContainsSubset(actualValue, expectedValue) { return false; } - return Object.entries(expectedValue).every(([key, value]) => ( - Object.prototype.hasOwnProperty.call(actualValue, key) - && jsonContainsSubset(actualValue[key], value) - )); + return Object.entries(expectedValue).every(([key, value]) => Object.prototype.hasOwnProperty.call(actualValue, key) && jsonContainsSubset(actualValue[key], value)); } if (Array.isArray(expectedValue)) { @@ -288,7 +258,7 @@ function hydrateRecordedOperations(repoRoot, operations) { return { ...operation, - sourcePath: resolveOperationSourcePath(repoRoot, operation), + sourcePath: resolveOperationSourcePath(repoRoot, operation) }; }); } @@ -300,9 +270,9 @@ function buildRecordedStatePreview(state, context, operations) { source: { ...state.source, repoVersion: context.packageVersion, - manifestVersion: context.manifestVersion, + manifestVersion: context.manifestVersion }, - lastValidatedAt: new Date().toISOString(), + lastValidatedAt: new Date().toISOString() }; } @@ -344,9 +314,7 @@ function executeRepairOperation(repoRoot, operation, trustedRoot) { throw new Error(`Missing merge payload for repair: ${operation.destinationPath}`); } - const currentValue = fs.existsSync(operation.destinationPath) - ? readJsonFile(operation.destinationPath) - : {}; + const currentValue = fs.existsSync(operation.destinationPath) ? readJsonFile(operation.destinationPath) : {}; const mergedValue = deepMergeJson(currentValue, payload); ensureParentDir(operation.destinationPath); @@ -374,14 +342,14 @@ function executeUninstallOperation(operation, trustedRoot) { if (!fs.existsSync(operation.destinationPath)) { return { removedPaths: [], - cleanupTargets: [], + cleanupTargets: [] }; } fs.rmSync(operation.destinationPath, { force: true }); return { removedPaths: [operation.destinationPath], - cleanupTargets: [operation.destinationPath], + cleanupTargets: [operation.destinationPath] }; } @@ -392,7 +360,7 @@ function executeUninstallOperation(operation, trustedRoot) { fs.writeFileSync(operation.destinationPath, previousContent); return { removedPaths: [], - cleanupTargets: [], + cleanupTargets: [] }; } @@ -402,21 +370,21 @@ function executeUninstallOperation(operation, trustedRoot) { fs.writeFileSync(operation.destinationPath, formatJson(previousJson)); return { removedPaths: [], - cleanupTargets: [], + cleanupTargets: [] }; } if (!fs.existsSync(operation.destinationPath)) { return { removedPaths: [], - cleanupTargets: [], + cleanupTargets: [] }; } fs.rmSync(operation.destinationPath, { force: true }); return { removedPaths: [operation.destinationPath], - cleanupTargets: [operation.destinationPath], + cleanupTargets: [operation.destinationPath] }; } @@ -427,7 +395,7 @@ function executeUninstallOperation(operation, trustedRoot) { fs.writeFileSync(operation.destinationPath, previousContent); return { removedPaths: [], - cleanupTargets: [], + cleanupTargets: [] }; } @@ -437,14 +405,14 @@ function executeUninstallOperation(operation, trustedRoot) { fs.writeFileSync(operation.destinationPath, formatJson(previousJson)); return { removedPaths: [], - cleanupTargets: [], + cleanupTargets: [] }; } if (!fs.existsSync(operation.destinationPath)) { return { removedPaths: [], - cleanupTargets: [], + cleanupTargets: [] }; } @@ -459,7 +427,7 @@ function executeUninstallOperation(operation, trustedRoot) { fs.rmSync(operation.destinationPath, { force: true }); return { removedPaths: [operation.destinationPath], - cleanupTargets: [operation.destinationPath], + cleanupTargets: [operation.destinationPath] }; } @@ -467,7 +435,7 @@ function executeUninstallOperation(operation, trustedRoot) { fs.writeFileSync(operation.destinationPath, formatJson(nextValue)); return { removedPaths: [], - cleanupTargets: [], + cleanupTargets: [] }; } @@ -478,7 +446,7 @@ function executeUninstallOperation(operation, trustedRoot) { fs.writeFileSync(operation.destinationPath, previousContent); return { removedPaths: [], - cleanupTargets: [], + cleanupTargets: [] }; } @@ -488,13 +456,13 @@ function executeUninstallOperation(operation, trustedRoot) { fs.writeFileSync(operation.destinationPath, formatJson(previousJson)); return { removedPaths: [], - cleanupTargets: [], + cleanupTargets: [] }; } return { removedPaths: [], - cleanupTargets: [], + cleanupTargets: [] }; } @@ -506,7 +474,7 @@ function inspectManagedOperation(repoRoot, operation) { if (!destinationPath) { return { status: 'invalid-destination', - operation, + operation }; } @@ -515,14 +483,14 @@ function inspectManagedOperation(repoRoot, operation) { return { status: 'drifted', operation, - destinationPath, + destinationPath }; } return { status: 'ok', operation, - destinationPath, + destinationPath }; } @@ -530,7 +498,7 @@ function inspectManagedOperation(repoRoot, operation) { return { status: 'missing', operation, - destinationPath, + destinationPath }; } @@ -541,7 +509,7 @@ function inspectManagedOperation(repoRoot, operation) { status: 'missing-source', operation, destinationPath, - sourcePath, + sourcePath }; } @@ -550,7 +518,7 @@ function inspectManagedOperation(repoRoot, operation) { status: 'drifted', operation, destinationPath, - sourcePath, + sourcePath }; } @@ -558,7 +526,7 @@ function inspectManagedOperation(repoRoot, operation) { status: 'ok', operation, destinationPath, - sourcePath, + sourcePath }; } @@ -568,7 +536,7 @@ function inspectManagedOperation(repoRoot, operation) { return { status: 'unverified', operation, - destinationPath, + destinationPath }; } @@ -576,14 +544,14 @@ function inspectManagedOperation(repoRoot, operation) { return { status: 'drifted', operation, - destinationPath, + destinationPath }; } return { status: 'ok', operation, - destinationPath, + destinationPath }; } @@ -593,7 +561,7 @@ function inspectManagedOperation(repoRoot, operation) { return { status: 'unverified', operation, - destinationPath, + destinationPath }; } @@ -603,57 +571,60 @@ function inspectManagedOperation(repoRoot, operation) { return { status: 'drifted', operation, - destinationPath, + destinationPath }; } } catch (_error) { return { status: 'drifted', operation, - destinationPath, + destinationPath }; } return { status: 'ok', operation, - destinationPath, + destinationPath }; } return { status: 'unverified', operation, - destinationPath, + destinationPath }; } function summarizeManagedOperationHealth(repoRoot, operations) { - return operations.reduce((summary, operation) => { - const inspection = inspectManagedOperation(repoRoot, operation); - if (inspection.status === 'missing') { - summary.missing.push(inspection); - } else if (inspection.status === 'drifted') { - summary.drifted.push(inspection); - } else if (inspection.status === 'missing-source') { - summary.missingSource.push(inspection); - } else if (inspection.status === 'unverified' || inspection.status === 'invalid-destination') { - summary.unverified.push(inspection); + return operations.reduce( + (summary, operation) => { + const inspection = inspectManagedOperation(repoRoot, operation); + if (inspection.status === 'missing') { + summary.missing.push(inspection); + } else if (inspection.status === 'drifted') { + summary.drifted.push(inspection); + } else if (inspection.status === 'missing-source') { + summary.missingSource.push(inspection); + } else if (inspection.status === 'unverified' || inspection.status === 'invalid-destination') { + summary.unverified.push(inspection); + } + return summary; + }, + { + missing: [], + drifted: [], + missingSource: [], + unverified: [] } - return summary; - }, { - missing: [], - drifted: [], - missingSource: [], - unverified: [], - }); + ); } function buildDiscoveryRecord(adapter, context) { const installTargetInput = { homeDir: context.homeDir, projectRoot: context.projectRoot, - repoRoot: context.projectRoot, + repoRoot: context.projectRoot }; const targetRoot = adapter.resolveRoot(installTargetInput); const installStatePath = adapter.getInstallStatePath(installTargetInput); @@ -664,13 +635,13 @@ function buildDiscoveryRecord(adapter, context) { adapter: { id: adapter.id, target: adapter.target, - kind: adapter.kind, + kind: adapter.kind }, targetRoot, installStatePath, exists: false, state: null, - error: null, + error: null }; } @@ -680,26 +651,26 @@ function buildDiscoveryRecord(adapter, context) { adapter: { id: adapter.id, target: adapter.target, - kind: adapter.kind, + kind: adapter.kind }, targetRoot, installStatePath, exists: true, state, - error: null, + error: null }; } catch (error) { return { adapter: { id: adapter.id, target: adapter.target, - kind: adapter.kind, + kind: adapter.kind }, targetRoot, installStatePath, exists: true, state: null, - error: error.message, + error: error.message }; } } @@ -707,7 +678,7 @@ function buildDiscoveryRecord(adapter, context) { function discoverInstalledStates(options = {}) { const context = { homeDir: options.homeDir || process.env.HOME || os.homedir(), - projectRoot: options.projectRoot || process.cwd(), + projectRoot: options.projectRoot || process.cwd() }; const targets = normalizeTargets(options.targets); @@ -722,7 +693,7 @@ function buildIssue(severity, code, message, extra = {}) { severity, code, message, - ...extra, + ...extra }; } @@ -746,7 +717,7 @@ function analyzeRecord(record, context) { return { ...record, status: determineStatus(issues), - issues, + issues }; } @@ -755,40 +726,30 @@ function analyzeRecord(record, context) { return { ...record, status: 'missing', - issues, + issues }; } if (!fs.existsSync(state.target.root)) { - issues.push(buildIssue( - 'error', - 'missing-target-root', - `Target root does not exist: ${state.target.root}` - )); + issues.push(buildIssue('error', 'missing-target-root', `Target root does not exist: ${state.target.root}`)); } if (state.target.root !== record.targetRoot) { - issues.push(buildIssue( - 'warning', - 'target-root-mismatch', - `Recorded target root differs from current target root (${record.targetRoot})`, - { + issues.push( + buildIssue('warning', 'target-root-mismatch', `Recorded target root differs from current target root (${record.targetRoot})`, { recordedTargetRoot: state.target.root, - currentTargetRoot: record.targetRoot, - } - )); + currentTargetRoot: record.targetRoot + }) + ); } if (state.target.installStatePath !== record.installStatePath) { - issues.push(buildIssue( - 'warning', - 'install-state-path-mismatch', - `Recorded install-state path differs from current path (${record.installStatePath})`, - { + issues.push( + buildIssue('warning', 'install-state-path-mismatch', `Recorded install-state path differs from current path (${record.installStatePath})`, { recordedInstallStatePath: state.target.installStatePath, - currentInstallStatePath: record.installStatePath, - } - )); + currentInstallStatePath: record.installStatePath + }) + ); } const managedOperations = getManagedOperations(state); @@ -796,67 +757,43 @@ function analyzeRecord(record, context) { const missingManagedOperations = operationHealth.missing; if (missingManagedOperations.length > 0) { - issues.push(buildIssue( - 'error', - 'missing-managed-files', - `${missingManagedOperations.length} managed file(s) are missing`, - { - paths: missingManagedOperations.map(entry => entry.destinationPath), - } - )); + issues.push( + buildIssue('error', 'missing-managed-files', `${missingManagedOperations.length} managed file(s) are missing`, { + paths: missingManagedOperations.map(entry => entry.destinationPath) + }) + ); } if (operationHealth.drifted.length > 0) { - issues.push(buildIssue( - 'warning', - 'drifted-managed-files', - `${operationHealth.drifted.length} managed file(s) differ from the source repo`, - { - paths: operationHealth.drifted.map(entry => entry.destinationPath), - } - )); + issues.push( + buildIssue('warning', 'drifted-managed-files', `${operationHealth.drifted.length} managed file(s) differ from the source repo`, { + paths: operationHealth.drifted.map(entry => entry.destinationPath) + }) + ); } if (operationHealth.missingSource.length > 0) { - issues.push(buildIssue( - 'error', - 'missing-source-files', - `${operationHealth.missingSource.length} source file(s) referenced by install-state are missing`, - { - paths: operationHealth.missingSource.map(entry => entry.sourcePath).filter(Boolean), - } - )); + issues.push( + buildIssue('error', 'missing-source-files', `${operationHealth.missingSource.length} source file(s) referenced by install-state are missing`, { + paths: operationHealth.missingSource.map(entry => entry.sourcePath).filter(Boolean) + }) + ); } if (operationHealth.unverified.length > 0) { - issues.push(buildIssue( - 'warning', - 'unverified-managed-operations', - `${operationHealth.unverified.length} managed operation(s) could not be content-verified`, - { - paths: operationHealth.unverified.map(entry => entry.destinationPath).filter(Boolean), - } - )); + issues.push( + buildIssue('warning', 'unverified-managed-operations', `${operationHealth.unverified.length} managed operation(s) could not be content-verified`, { + paths: operationHealth.unverified.map(entry => entry.destinationPath).filter(Boolean) + }) + ); } if (state.source.manifestVersion !== context.manifestVersion) { - issues.push(buildIssue( - 'warning', - 'manifest-version-mismatch', - `Recorded manifest version ${state.source.manifestVersion} differs from current manifest version ${context.manifestVersion}` - )); + issues.push(buildIssue('warning', 'manifest-version-mismatch', `Recorded manifest version ${state.source.manifestVersion} differs from current manifest version ${context.manifestVersion}`)); } - if ( - context.packageVersion - && state.source.repoVersion - && state.source.repoVersion !== context.packageVersion - ) { - issues.push(buildIssue( - 'warning', - 'repo-version-mismatch', - `Recorded repo version ${state.source.repoVersion} differs from current repo version ${context.packageVersion}` - )); + if (context.packageVersion && state.source.repoVersion && state.source.repoVersion !== context.packageVersion) { + issues.push(buildIssue('warning', 'repo-version-mismatch', `Recorded repo version ${state.source.repoVersion} differs from current repo version ${context.packageVersion}`)); } if (!state.request.legacyMode) { @@ -869,38 +806,28 @@ function analyzeRecord(record, context) { profileId: state.request.profile || null, moduleIds: state.request.modules || [], includeComponentIds: state.request.includeComponents || [], - excludeComponentIds: state.request.excludeComponents || [], + excludeComponentIds: state.request.excludeComponents || [] }); - if ( - !compareStringArrays(desiredPlan.selectedModuleIds, state.resolution.selectedModules) - || !compareStringArrays(desiredPlan.skippedModuleIds, state.resolution.skippedModules) - ) { - issues.push(buildIssue( - 'warning', - 'resolution-drift', - 'Current manifest resolution differs from recorded install-state', - { + if (!compareStringArrays(desiredPlan.selectedModuleIds, state.resolution.selectedModules) || !compareStringArrays(desiredPlan.skippedModuleIds, state.resolution.skippedModules)) { + issues.push( + buildIssue('warning', 'resolution-drift', 'Current manifest resolution differs from recorded install-state', { expectedSelectedModules: desiredPlan.selectedModuleIds, recordedSelectedModules: state.resolution.selectedModules, expectedSkippedModules: desiredPlan.skippedModuleIds, - recordedSkippedModules: state.resolution.skippedModules, - } - )); + recordedSkippedModules: state.resolution.skippedModules + }) + ); } } catch (error) { - issues.push(buildIssue( - 'error', - 'resolution-unavailable', - error.message - )); + issues.push(buildIssue('error', 'resolution-unavailable', error.message)); } } return { ...record, status: determineStatus(issues), - issues, + issues }; } @@ -910,39 +837,42 @@ function buildDoctorReport(options = {}) { const records = discoverInstalledStates({ homeDir: options.homeDir, projectRoot: options.projectRoot, - targets: options.targets, + targets: options.targets }).filter(record => record.exists); const context = { repoRoot, homeDir: options.homeDir || process.env.HOME || os.homedir(), projectRoot: options.projectRoot || process.cwd(), manifestVersion: manifests.modulesVersion, - packageVersion: readPackageVersion(repoRoot), + packageVersion: readPackageVersion(repoRoot) }; const results = records.map(record => analyzeRecord(record, context)); - const summary = results.reduce((accumulator, result) => { - const errorCount = result.issues.filter(issue => issue.severity === 'error').length; - const warningCount = result.issues.filter(issue => issue.severity === 'warning').length; + const summary = results.reduce( + (accumulator, result) => { + const errorCount = result.issues.filter(issue => issue.severity === 'error').length; + const warningCount = result.issues.filter(issue => issue.severity === 'warning').length; - return { - checkedCount: accumulator.checkedCount + 1, - okCount: accumulator.okCount + (result.status === 'ok' ? 1 : 0), - errorCount: accumulator.errorCount + errorCount, - warningCount: accumulator.warningCount + warningCount, - }; - }, { - checkedCount: 0, - okCount: 0, - errorCount: 0, - warningCount: 0, - }); + return { + checkedCount: accumulator.checkedCount + 1, + okCount: accumulator.okCount + (result.status === 'ok' ? 1 : 0), + errorCount: accumulator.errorCount + errorCount, + warningCount: accumulator.warningCount + warningCount + }; + }, + { + checkedCount: 0, + okCount: 0, + errorCount: 0, + warningCount: 0 + } + ); return { generatedAt: new Date().toISOString(), packageVersion: context.packageVersion, manifestVersion: context.manifestVersion, results, - summary, + summary }; } @@ -964,11 +894,9 @@ function createRepairPlanFromRecord(record, context) { installRoot: state.target.root, installStatePath: state.target.installStatePath, warnings: [], - languages: Array.isArray(state.request.legacyLanguages) - ? [...state.request.legacyLanguages] - : [], + languages: Array.isArray(state.request.legacyLanguages) ? [...state.request.legacyLanguages] : [], operations, - statePreview, + statePreview }; } @@ -980,7 +908,7 @@ function createRepairPlanFromRecord(record, context) { includeComponentIds: state.request.includeComponents || [], excludeComponentIds: state.request.excludeComponents || [], projectRoot: context.projectRoot, - homeDir: context.homeDir, + homeDir: context.homeDir }); return { @@ -988,8 +916,8 @@ function createRepairPlanFromRecord(record, context) { statePreview: { ...desiredPlan.statePreview, installedAt: state.installedAt, - lastValidatedAt: new Date().toISOString(), - }, + lastValidatedAt: new Date().toISOString() + } }; } @@ -1001,12 +929,12 @@ function repairInstalledStates(options = {}) { homeDir: options.homeDir || process.env.HOME || os.homedir(), projectRoot: options.projectRoot || process.cwd(), manifestVersion: manifests.modulesVersion, - packageVersion: readPackageVersion(repoRoot), + packageVersion: readPackageVersion(repoRoot) }; const records = discoverInstalledStates({ homeDir: context.homeDir, projectRoot: context.projectRoot, - targets: options.targets, + targets: options.targets }).filter(record => record.exists); const results = records.map(record => { @@ -1017,7 +945,7 @@ function repairInstalledStates(options = {}) { installStatePath: record.installStatePath, repairedPaths: [], plannedRepairs: [], - error: record.error, + error: record.error }; } @@ -1032,14 +960,11 @@ function repairInstalledStates(options = {}) { installStatePath: record.installStatePath, repairedPaths: [], plannedRepairs: [], - error: `Missing source file(s): ${operationHealth.missingSource.map(entry => entry.sourcePath).join(', ')}`, + error: `Missing source file(s): ${operationHealth.missingSource.map(entry => entry.sourcePath).join(', ')}` }; } - const repairOperations = [ - ...operationHealth.missing.map(entry => ({ ...entry.operation })), - ...operationHealth.drifted.map(entry => ({ ...entry.operation })), - ]; + const repairOperations = [...operationHealth.missing.map(entry => ({ ...entry.operation })), ...operationHealth.drifted.map(entry => ({ ...entry.operation }))]; const plannedRepairs = repairOperations.map(operation => operation.destinationPath); if (options.dryRun) { @@ -1050,7 +975,7 @@ function repairInstalledStates(options = {}) { repairedPaths: [], plannedRepairs, stateRefreshed: plannedRepairs.length === 0, - error: null, + error: null }; } @@ -1070,7 +995,7 @@ function repairInstalledStates(options = {}) { repairedPaths: plannedRepairs, plannedRepairs: [], stateRefreshed: true, - error: null, + error: null }; } catch (error) { return { @@ -1079,28 +1004,31 @@ function repairInstalledStates(options = {}) { installStatePath: record.installStatePath, repairedPaths: [], plannedRepairs: [], - error: error.message, + error: error.message }; } }); - const summary = results.reduce((accumulator, result) => ({ - checkedCount: accumulator.checkedCount + 1, - repairedCount: accumulator.repairedCount + (result.status === 'repaired' ? 1 : 0), - plannedRepairCount: accumulator.plannedRepairCount + (result.status === 'planned' ? 1 : 0), - errorCount: accumulator.errorCount + (result.status === 'error' ? 1 : 0), - }), { - checkedCount: 0, - repairedCount: 0, - plannedRepairCount: 0, - errorCount: 0, - }); + const summary = results.reduce( + (accumulator, result) => ({ + checkedCount: accumulator.checkedCount + 1, + repairedCount: accumulator.repairedCount + (result.status === 'repaired' ? 1 : 0), + plannedRepairCount: accumulator.plannedRepairCount + (result.status === 'planned' ? 1 : 0), + errorCount: accumulator.errorCount + (result.status === 'error' ? 1 : 0) + }), + { + checkedCount: 0, + repairedCount: 0, + plannedRepairCount: 0, + errorCount: 0 + } + ); return { dryRun: Boolean(options.dryRun), generatedAt: new Date().toISOString(), results, - summary, + summary }; } @@ -1108,11 +1036,7 @@ function cleanupEmptyParentDirs(filePath, stopAt) { let currentPath = path.dirname(filePath); const normalizedStopAt = path.resolve(stopAt); - while ( - currentPath - && path.resolve(currentPath).startsWith(normalizedStopAt) - && path.resolve(currentPath) !== normalizedStopAt - ) { + while (currentPath && path.resolve(currentPath).startsWith(normalizedStopAt) && path.resolve(currentPath) !== normalizedStopAt) { if (!fs.existsSync(currentPath)) { currentPath = path.dirname(currentPath); continue; @@ -1132,7 +1056,7 @@ function uninstallInstalledStates(options = {}) { const records = discoverInstalledStates({ homeDir: options.homeDir, projectRoot: options.projectRoot, - targets: options.targets, + targets: options.targets }).filter(record => record.exists); const results = records.map(record => { @@ -1143,15 +1067,12 @@ function uninstallInstalledStates(options = {}) { installStatePath: record.installStatePath, removedPaths: [], plannedRemovals: [], - error: record.error || 'No valid install-state available', + error: record.error || 'No valid install-state available' }; } const state = record.state; - const plannedRemovals = Array.from(new Set([ - ...getManagedOperations(state).map(operation => operation.destinationPath), - state.target.installStatePath, - ])); + const plannedRemovals = Array.from(new Set([...getManagedOperations(state).map(operation => operation.destinationPath), state.target.installStatePath])); if (options.dryRun) { return { @@ -1160,7 +1081,7 @@ function uninstallInstalledStates(options = {}) { installStatePath: record.installStatePath, removedPaths: [], plannedRemovals, - error: null, + error: null }; } @@ -1192,7 +1113,7 @@ function uninstallInstalledStates(options = {}) { installStatePath: record.installStatePath, removedPaths, plannedRemovals: [], - error: null, + error: null }; } catch (error) { return { @@ -1201,28 +1122,31 @@ function uninstallInstalledStates(options = {}) { installStatePath: record.installStatePath, removedPaths: [], plannedRemovals, - error: error.message, + error: error.message }; } }); - const summary = results.reduce((accumulator, result) => ({ - checkedCount: accumulator.checkedCount + 1, - uninstalledCount: accumulator.uninstalledCount + (result.status === 'uninstalled' ? 1 : 0), - plannedRemovalCount: accumulator.plannedRemovalCount + (result.status === 'planned' ? 1 : 0), - errorCount: accumulator.errorCount + (result.status === 'error' ? 1 : 0), - }), { - checkedCount: 0, - uninstalledCount: 0, - plannedRemovalCount: 0, - errorCount: 0, - }); + const summary = results.reduce( + (accumulator, result) => ({ + checkedCount: accumulator.checkedCount + 1, + uninstalledCount: accumulator.uninstalledCount + (result.status === 'uninstalled' ? 1 : 0), + plannedRemovalCount: accumulator.plannedRemovalCount + (result.status === 'planned' ? 1 : 0), + errorCount: accumulator.errorCount + (result.status === 'error' ? 1 : 0) + }), + { + checkedCount: 0, + uninstalledCount: 0, + plannedRemovalCount: 0, + errorCount: 0 + } + ); return { dryRun: Boolean(options.dryRun), generatedAt: new Date().toISOString(), results, - summary, + summary }; } @@ -1232,5 +1156,5 @@ module.exports = { discoverInstalledStates, normalizeTargets, repairInstalledStates, - uninstallInstalledStates, + uninstallInstalledStates }; diff --git a/scripts/lib/path-safety.js b/scripts/lib/path-safety.js index e1ad3dd1..1a2a47d9 100644 --- a/scripts/lib/path-safety.js +++ b/scripts/lib/path-safety.js @@ -70,9 +70,7 @@ function assertWithinTrustedRoot(target, root, action = 'write') { throw new Error(`Refusing to ${action} '${target}': no trusted install root resolved.`); } if (!isWithinRoot(target, root)) { - throw new Error( - `Refusing to ${action} outside the install root: '${target}' is not within '${root}'.` - ); + throw new Error(`Refusing to ${action} outside the install root: '${target}' is not within '${root}'.`); } return realpathNearestExisting(target); } @@ -80,5 +78,5 @@ function assertWithinTrustedRoot(target, root, action = 'write') { module.exports = { realpathNearestExisting, isWithinRoot, - assertWithinTrustedRoot, + assertWithinTrustedRoot };