autosnippet 3.2.21 → 3.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dashboard/dist/assets/icons-BJ2mUBi8.js +1 -0
- package/dashboard/dist/assets/index-B659K9t5.js +128 -0
- package/dashboard/dist/assets/index-NCm40PMD.css +1 -0
- package/dashboard/dist/index.html +3 -3
- package/dist/bin/cli.d.ts +1 -1
- package/dist/bin/cli.js +244 -261
- package/dist/lib/agent/context/ExplorationTracker.d.ts +2 -0
- package/dist/lib/agent/context/ExplorationTracker.js +21 -3
- package/dist/lib/agent/core/ToolExecutionPipeline.d.ts +3 -1
- package/dist/lib/agent/core/ToolExecutionPipeline.js +8 -1
- package/dist/lib/agent/forge/DynamicComposer.d.ts +58 -0
- package/dist/lib/agent/forge/DynamicComposer.js +99 -0
- package/dist/lib/agent/forge/SandboxRunner.d.ts +60 -0
- package/dist/lib/agent/forge/SandboxRunner.js +251 -0
- package/dist/lib/agent/forge/TemporaryToolRegistry.d.ts +76 -0
- package/dist/lib/agent/forge/TemporaryToolRegistry.js +154 -0
- package/dist/lib/agent/forge/ToolForge.d.ts +92 -0
- package/dist/lib/agent/forge/ToolForge.js +239 -0
- package/dist/lib/agent/forge/ToolRequirementAnalyzer.d.ts +44 -0
- package/dist/lib/agent/forge/ToolRequirementAnalyzer.js +119 -0
- package/dist/lib/agent/tools/ToolRegistry.d.ts +2 -0
- package/dist/lib/agent/tools/ToolRegistry.js +4 -0
- package/dist/lib/agent/tools/composite.js +0 -1
- package/dist/lib/agent/tools/index.d.ts +2 -50
- package/dist/lib/agent/tools/index.js +2 -3
- package/dist/lib/agent/tools/lifecycle.d.ts +1 -58
- package/dist/lib/agent/tools/lifecycle.js +2 -75
- package/dist/lib/cli/SetupService.d.ts +46 -2
- package/dist/lib/cli/SetupService.js +2 -27
- package/dist/lib/cli/deploy/FileManifest.d.ts +0 -21
- package/dist/lib/cli/deploy/FileManifest.js +0 -11
- package/dist/lib/{platform/ios/spm → core/discovery}/SpmDiscoverer.d.ts +2 -5
- package/dist/lib/{platform/ios/spm → core/discovery}/SpmDiscoverer.js +159 -44
- package/dist/lib/core/discovery/index.d.ts +1 -1
- package/dist/lib/core/discovery/index.js +2 -2
- package/dist/lib/domain/knowledge/KnowledgeEntry.d.ts +10 -0
- package/dist/lib/domain/knowledge/KnowledgeEntry.js +2 -0
- package/dist/lib/domain/knowledge/Lifecycle.d.ts +19 -2
- package/dist/lib/domain/knowledge/Lifecycle.js +32 -6
- package/dist/lib/domain/knowledge/UnifiedValidator.d.ts +1 -5
- package/dist/lib/domain/knowledge/UnifiedValidator.js +7 -44
- package/dist/lib/domain/knowledge/values/Stats.d.ts +29 -0
- package/dist/lib/domain/knowledge/values/Stats.js +41 -0
- package/dist/lib/external/mcp/McpServer.d.ts +19 -38
- package/dist/lib/external/mcp/McpServer.js +145 -117
- package/dist/lib/external/mcp/autoApproveInjector.js +0 -2
- package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.d.ts +26 -1
- package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.js +41 -0
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +49 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.d.ts +3 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +27 -0
- package/dist/lib/external/mcp/handlers/bootstrap/skills.js +1 -1
- package/dist/lib/external/mcp/handlers/bootstrap-external.js +1 -0
- package/dist/lib/external/mcp/handlers/bootstrap-internal.js +2 -0
- package/dist/lib/external/mcp/handlers/consolidated.d.ts +116 -6
- package/dist/lib/external/mcp/handlers/consolidated.js +251 -71
- package/dist/lib/external/mcp/handlers/guard.d.ts +150 -0
- package/dist/lib/external/mcp/handlers/guard.js +245 -8
- package/dist/lib/external/mcp/handlers/knowledge.d.ts +0 -29
- package/dist/lib/external/mcp/handlers/knowledge.js +1 -76
- package/dist/lib/external/mcp/handlers/panorama.d.ts +36 -0
- package/dist/lib/external/mcp/handlers/panorama.js +156 -0
- package/dist/lib/external/mcp/handlers/system.d.ts +2 -54
- package/dist/lib/external/mcp/handlers/system.js +3 -113
- package/dist/lib/external/mcp/handlers/task.d.ts +13 -24
- package/dist/lib/external/mcp/handlers/task.js +217 -557
- package/dist/lib/external/mcp/handlers/types.d.ts +91 -8
- package/dist/lib/external/mcp/handlers/types.js +18 -1
- package/dist/lib/external/mcp/handlers/wiki-external.d.ts +18 -1
- package/dist/lib/external/mcp/handlers/wiki-external.js +16 -1
- package/dist/lib/external/mcp/tools.d.ts +14 -20
- package/dist/lib/external/mcp/tools.js +62 -91
- package/dist/lib/http/HttpServer.js +52 -6
- package/dist/lib/http/routes/{snippets.d.ts → audit.d.ts} +4 -2
- package/dist/lib/http/routes/audit.js +51 -0
- package/dist/lib/http/routes/commands.d.ts +1 -1
- package/dist/lib/http/routes/commands.js +1 -66
- package/dist/lib/http/routes/guardReport.d.ts +10 -0
- package/dist/lib/http/routes/guardReport.js +143 -0
- package/dist/lib/http/routes/knowledge.js +32 -1
- package/dist/lib/http/routes/panorama.d.ts +11 -0
- package/dist/lib/http/routes/panorama.js +322 -0
- package/dist/lib/http/routes/remote.js +0 -5
- package/dist/lib/http/routes/signals.d.ts +10 -0
- package/dist/lib/http/routes/signals.js +104 -0
- package/dist/lib/http/routes/task.d.ts +2 -3
- package/dist/lib/http/routes/task.js +17 -347
- package/dist/lib/http/routes/violations.js +1 -1
- package/dist/lib/infrastructure/audit/AuditLogger.d.ts +6 -1
- package/dist/lib/infrastructure/audit/AuditLogger.js +14 -1
- package/dist/lib/infrastructure/database/drizzle/schema.d.ts +181 -583
- package/dist/lib/infrastructure/database/drizzle/schema.js +28 -69
- package/dist/lib/infrastructure/database/migrations/004_evolution_proposals.d.ts +8 -0
- package/dist/lib/infrastructure/database/migrations/004_evolution_proposals.js +43 -0
- package/dist/lib/infrastructure/logging/Logger.d.ts +2 -0
- package/dist/lib/infrastructure/logging/Logger.js +34 -7
- package/dist/lib/infrastructure/monitoring/ErrorTracker.js +3 -1
- package/dist/lib/infrastructure/monitoring/PerformanceMonitor.d.ts +2 -2
- package/dist/lib/infrastructure/monitoring/PerformanceMonitor.js +12 -10
- package/dist/lib/infrastructure/notification/LarkNotifier.d.ts +24 -0
- package/dist/lib/infrastructure/notification/LarkNotifier.js +97 -0
- package/dist/lib/infrastructure/report/ReportStore.d.ts +45 -0
- package/dist/lib/infrastructure/report/ReportStore.js +133 -0
- package/dist/lib/infrastructure/signal/SignalAggregator.d.ts +18 -0
- package/dist/lib/infrastructure/signal/SignalAggregator.js +84 -0
- package/dist/lib/infrastructure/signal/SignalBridge.d.ts +13 -0
- package/dist/lib/infrastructure/signal/SignalBridge.js +20 -0
- package/dist/lib/infrastructure/signal/SignalBus.d.ts +63 -0
- package/dist/lib/infrastructure/signal/SignalBus.js +106 -0
- package/dist/lib/infrastructure/signal/SignalTraceWriter.d.ts +36 -0
- package/dist/lib/infrastructure/signal/SignalTraceWriter.js +130 -0
- package/dist/lib/injection/ServiceContainer.js +6 -0
- package/dist/lib/injection/ServiceMap.d.ts +16 -19
- package/dist/lib/injection/modules/AgentModule.d.ts +1 -1
- package/dist/lib/injection/modules/AgentModule.js +7 -1
- package/dist/lib/injection/modules/AppModule.d.ts +3 -4
- package/dist/lib/injection/modules/AppModule.js +7 -43
- package/dist/lib/injection/modules/GuardModule.js +59 -2
- package/dist/lib/injection/modules/InfraModule.d.ts +0 -1
- package/dist/lib/injection/modules/InfraModule.js +9 -7
- package/dist/lib/injection/modules/KnowledgeModule.js +51 -0
- package/dist/lib/injection/modules/PanoramaModule.d.ts +18 -0
- package/dist/lib/injection/modules/PanoramaModule.js +76 -0
- package/dist/lib/injection/modules/SignalModule.d.ts +10 -0
- package/dist/lib/injection/modules/SignalModule.js +84 -0
- package/dist/lib/repository/knowledge/KnowledgeRepository.impl.d.ts +1 -0
- package/dist/lib/repository/knowledge/KnowledgeRepository.impl.js +6 -0
- package/dist/lib/service/bootstrap/BootstrapTaskManager.d.ts +3 -1
- package/dist/lib/service/bootstrap/BootstrapTaskManager.js +20 -1
- package/dist/lib/service/delivery/AgentInstructionsGenerator.js +4 -5
- package/dist/lib/service/delivery/CursorDeliveryPipeline.d.ts +3 -1
- package/dist/lib/service/delivery/CursorDeliveryPipeline.js +13 -10
- package/dist/lib/service/delivery/RulesGenerator.js +3 -2
- package/dist/lib/service/evolution/ConsolidationAdvisor.d.ts +114 -0
- package/dist/lib/service/evolution/ConsolidationAdvisor.js +542 -0
- package/dist/lib/service/evolution/ContradictionDetector.d.ts +54 -0
- package/dist/lib/service/evolution/ContradictionDetector.js +253 -0
- package/dist/lib/service/evolution/DecayDetector.d.ts +71 -0
- package/dist/lib/service/evolution/DecayDetector.js +244 -0
- package/dist/lib/service/evolution/EnhancementSuggester.d.ts +38 -0
- package/dist/lib/service/evolution/EnhancementSuggester.js +220 -0
- package/dist/lib/service/evolution/KnowledgeMetabolism.d.ts +82 -0
- package/dist/lib/service/evolution/KnowledgeMetabolism.js +167 -0
- package/dist/lib/service/evolution/RedundancyAnalyzer.d.ts +53 -0
- package/dist/lib/service/evolution/RedundancyAnalyzer.js +210 -0
- package/dist/lib/service/evolution/StagingManager.d.ts +57 -0
- package/dist/lib/service/evolution/StagingManager.js +201 -0
- package/dist/lib/service/guard/ComplianceReporter.d.ts +42 -2
- package/dist/lib/service/guard/ComplianceReporter.js +43 -5
- package/dist/lib/service/guard/CoverageAnalyzer.d.ts +54 -0
- package/dist/lib/service/guard/CoverageAnalyzer.js +149 -0
- package/dist/lib/service/guard/GuardCheckEngine.d.ts +55 -1
- package/dist/lib/service/guard/GuardCheckEngine.js +508 -15
- package/dist/lib/service/guard/GuardFeedbackLoop.d.ts +3 -0
- package/dist/lib/service/guard/GuardFeedbackLoop.js +9 -0
- package/dist/lib/service/guard/ReverseGuard.d.ts +73 -0
- package/dist/lib/service/guard/ReverseGuard.js +256 -0
- package/dist/lib/service/guard/RuleLearner.d.ts +12 -0
- package/dist/lib/service/guard/RuleLearner.js +38 -0
- package/dist/lib/service/guard/UncertaintyCollector.d.ts +83 -0
- package/dist/lib/service/guard/UncertaintyCollector.js +149 -0
- package/dist/lib/service/guard/ViolationsStore.d.ts +1 -0
- package/dist/lib/service/guard/ViolationsStore.js +33 -3
- package/dist/lib/service/knowledge/ConfidenceRouter.d.ts +13 -0
- package/dist/lib/service/knowledge/ConfidenceRouter.js +14 -0
- package/dist/lib/service/knowledge/KnowledgeService.js +22 -4
- package/dist/lib/service/module/ModuleService.js +3 -13
- package/dist/lib/service/panorama/CouplingAnalyzer.d.ts +27 -0
- package/dist/lib/service/panorama/CouplingAnalyzer.js +192 -0
- package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +28 -0
- package/dist/lib/service/panorama/DimensionAnalyzer.js +320 -0
- package/dist/lib/service/panorama/LayerInferrer.d.ts +19 -0
- package/dist/lib/service/panorama/LayerInferrer.js +182 -0
- package/dist/lib/service/panorama/ModuleDiscoverer.d.ts +24 -0
- package/dist/lib/service/panorama/ModuleDiscoverer.js +185 -0
- package/dist/lib/service/panorama/PanoramaAggregator.d.ts +29 -0
- package/dist/lib/service/panorama/PanoramaAggregator.js +228 -0
- package/dist/lib/service/panorama/PanoramaScanner.d.ts +52 -0
- package/dist/lib/service/panorama/PanoramaScanner.js +188 -0
- package/dist/lib/service/panorama/PanoramaService.d.ts +108 -0
- package/dist/lib/service/panorama/PanoramaService.js +220 -0
- package/dist/lib/service/panorama/PanoramaTypes.d.ts +134 -0
- package/dist/lib/service/panorama/PanoramaTypes.js +6 -0
- package/dist/lib/service/panorama/RoleRefiner.d.ts +48 -0
- package/dist/lib/service/panorama/RoleRefiner.js +535 -0
- package/dist/lib/service/search/MultiSignalRanker.d.ts +1 -0
- package/dist/lib/service/search/MultiSignalRanker.js +16 -0
- package/dist/lib/service/search/SearchEngine.d.ts +1 -0
- package/dist/lib/service/search/SearchEngine.js +9 -1
- package/dist/lib/service/search/SearchTypes.d.ts +2 -0
- package/dist/lib/service/signal/HitRecorder.d.ts +68 -0
- package/dist/lib/service/signal/HitRecorder.js +173 -0
- package/dist/lib/service/skills/SignalCollector.d.ts +3 -1
- package/dist/lib/service/skills/SignalCollector.js +31 -1
- package/dist/lib/service/task/IntentExtractor.d.ts +58 -0
- package/dist/lib/service/task/IntentExtractor.js +142 -0
- package/dist/lib/service/task/PrimeSearchPipeline.d.ts +54 -0
- package/dist/lib/service/task/PrimeSearchPipeline.js +98 -0
- package/dist/lib/shared/constants.d.ts +0 -15
- package/dist/lib/shared/constants.js +0 -10
- package/dist/lib/shared/schemas/config.d.ts +4 -1
- package/dist/lib/shared/schemas/config.js +8 -1
- package/dist/lib/shared/schemas/mcp-tools.d.ts +41 -96
- package/dist/lib/shared/schemas/mcp-tools.js +59 -119
- package/dist/scripts/analyze-signals.d.ts +20 -0
- package/dist/scripts/analyze-signals.js +155 -0
- package/dist/scripts/diagnose-mcp.js +1 -1
- package/dist/scripts/release.js +2 -10
- package/package.json +4 -19
- package/skills/autosnippet-devdocs/SKILL.md +11 -8
- package/templates/claude-code/hooks/autosnippet-session.sh +10 -15
- package/templates/cursor-hooks/hooks/session-start.sh +1 -1
- package/templates/instructions/agent-static.md +2 -1
- package/templates/instructions/conventions.md +5 -6
- package/templates/recipes-setup/README.md +1 -2
- package/dashboard/dist/assets/icons-C1dUryS-.js +0 -1
- package/dashboard/dist/assets/index-D0whuycy.css +0 -1
- package/dashboard/dist/assets/index-DdvZE4Yd.js +0 -128
- package/dist/lib/domain/task/Task.d.ts +0 -140
- package/dist/lib/domain/task/Task.js +0 -254
- package/dist/lib/domain/task/TaskDependency.d.ts +0 -23
- package/dist/lib/domain/task/TaskDependency.js +0 -34
- package/dist/lib/domain/task/TaskIdGenerator.d.ts +0 -40
- package/dist/lib/domain/task/TaskIdGenerator.js +0 -75
- package/dist/lib/domain/task/index.d.ts +0 -4
- package/dist/lib/domain/task/index.js +0 -4
- package/dist/lib/http/routes/snippets.js +0 -49
- package/dist/lib/infrastructure/database/migrations/002_add_tasks.d.ts +0 -11
- package/dist/lib/infrastructure/database/migrations/002_add_tasks.js +0 -86
- package/dist/lib/platform/ClipboardManager.d.ts +0 -24
- package/dist/lib/platform/ClipboardManager.js +0 -142
- package/dist/lib/platform/NativeUi.d.ts +0 -53
- package/dist/lib/platform/NativeUi.js +0 -284
- package/dist/lib/platform/ios/index.d.ts +0 -38
- package/dist/lib/platform/ios/index.js +0 -42
- package/dist/lib/platform/ios/routes/spm.d.ts +0 -9
- package/dist/lib/platform/ios/routes/spm.js +0 -371
- package/dist/lib/platform/ios/snippet/PlaceholderConverter.d.ts +0 -21
- package/dist/lib/platform/ios/snippet/PlaceholderConverter.js +0 -48
- package/dist/lib/platform/ios/snippet/XcodeCodec.d.ts +0 -23
- package/dist/lib/platform/ios/snippet/XcodeCodec.js +0 -96
- package/dist/lib/platform/ios/spm/DependencyGraph.d.ts +0 -56
- package/dist/lib/platform/ios/spm/DependencyGraph.js +0 -195
- package/dist/lib/platform/ios/spm/PackageSwiftParser.d.ts +0 -69
- package/dist/lib/platform/ios/spm/PackageSwiftParser.js +0 -231
- package/dist/lib/platform/ios/spm/PathFinder.d.ts +0 -28
- package/dist/lib/platform/ios/spm/PathFinder.js +0 -117
- package/dist/lib/platform/ios/spm/PolicyEngine.d.ts +0 -44
- package/dist/lib/platform/ios/spm/PolicyEngine.js +0 -79
- package/dist/lib/platform/ios/spm/SpmHelper.d.ts +0 -102
- package/dist/lib/platform/ios/spm/SpmHelper.js +0 -464
- package/dist/lib/platform/ios/xcode/HeaderResolver.d.ts +0 -33
- package/dist/lib/platform/ios/xcode/HeaderResolver.js +0 -90
- package/dist/lib/platform/ios/xcode/SaveEventFilter.d.ts +0 -66
- package/dist/lib/platform/ios/xcode/SaveEventFilter.js +0 -142
- package/dist/lib/platform/ios/xcode/XcodeAutomation.d.ts +0 -71
- package/dist/lib/platform/ios/xcode/XcodeAutomation.js +0 -327
- package/dist/lib/platform/ios/xcode/XcodeImportResolver.d.ts +0 -130
- package/dist/lib/platform/ios/xcode/XcodeImportResolver.js +0 -404
- package/dist/lib/platform/ios/xcode/XcodeIntegration.d.ts +0 -89
- package/dist/lib/platform/ios/xcode/XcodeIntegration.js +0 -588
- package/dist/lib/platform/ios/xcode/XcodeWriteUtils.d.ts +0 -99
- package/dist/lib/platform/ios/xcode/XcodeWriteUtils.js +0 -190
- package/dist/lib/repository/task/TaskRepository.impl.d.ts +0 -171
- package/dist/lib/repository/task/TaskRepository.impl.js +0 -347
- package/dist/lib/service/automation/ActionPipeline.d.ts +0 -34
- package/dist/lib/service/automation/ActionPipeline.js +0 -53
- package/dist/lib/service/automation/AutomationOrchestrator.d.ts +0 -86
- package/dist/lib/service/automation/AutomationOrchestrator.js +0 -57
- package/dist/lib/service/automation/ContextCollector.d.ts +0 -24
- package/dist/lib/service/automation/ContextCollector.js +0 -35
- package/dist/lib/service/automation/DirectiveDetector.d.ts +0 -51
- package/dist/lib/service/automation/DirectiveDetector.js +0 -112
- package/dist/lib/service/automation/FileWatcher.d.ts +0 -51
- package/dist/lib/service/automation/FileWatcher.js +0 -366
- package/dist/lib/service/automation/TriggerResolver.d.ts +0 -36
- package/dist/lib/service/automation/TriggerResolver.js +0 -62
- package/dist/lib/service/automation/handlers/AlinkHandler.d.ts +0 -7
- package/dist/lib/service/automation/handlers/AlinkHandler.js +0 -80
- package/dist/lib/service/automation/handlers/CreateHandler.d.ts +0 -11
- package/dist/lib/service/automation/handlers/CreateHandler.js +0 -170
- package/dist/lib/service/automation/handlers/GuardHandler.d.ts +0 -17
- package/dist/lib/service/automation/handlers/GuardHandler.js +0 -218
- package/dist/lib/service/automation/handlers/HeaderHandler.d.ts +0 -2
- package/dist/lib/service/automation/handlers/HeaderHandler.js +0 -32
- package/dist/lib/service/automation/handlers/SearchHandler.d.ts +0 -11
- package/dist/lib/service/automation/handlers/SearchHandler.js +0 -278
- package/dist/lib/service/snippet/SnippetFactory.d.ts +0 -101
- package/dist/lib/service/snippet/SnippetFactory.js +0 -145
- package/dist/lib/service/snippet/SnippetInstaller.d.ts +0 -91
- package/dist/lib/service/snippet/SnippetInstaller.js +0 -276
- package/dist/lib/service/snippet/codecs/SnippetCodec.d.ts +0 -44
- package/dist/lib/service/snippet/codecs/SnippetCodec.js +0 -35
- package/dist/lib/service/snippet/codecs/VSCodeCodec.d.ts +0 -27
- package/dist/lib/service/snippet/codecs/VSCodeCodec.js +0 -82
- package/dist/lib/service/task/TaskGraphService.d.ts +0 -222
- package/dist/lib/service/task/TaskGraphService.js +0 -597
- package/dist/lib/service/task/TaskKnowledgeBridge.d.ts +0 -95
- package/dist/lib/service/task/TaskKnowledgeBridge.js +0 -298
- package/dist/lib/service/task/TaskReadyEngine.d.ts +0 -84
- package/dist/lib/service/task/TaskReadyEngine.js +0 -115
- package/dist/scripts/build-native-ui.d.ts +0 -3
- package/dist/scripts/build-native-ui.js +0 -62
- package/dist/scripts/init-snippets.d.ts +0 -30
- package/dist/scripts/init-snippets.js +0 -298
- package/dist/scripts/install-full.d.ts +0 -7
- package/dist/scripts/install-full.js +0 -38
- package/resources/native-ui/README.md +0 -29
- package/resources/native-ui/combined-window.swift +0 -494
- package/resources/native-ui/main.swift +0 -598
- package/scripts/postinstall-safe.mjs +0 -89
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PolicyEngine — SPM 依赖策略引擎
|
|
3
|
-
* 检查循环依赖、反向依赖 (违反分层架构原则)、方针约束
|
|
4
|
-
*/
|
|
5
|
-
export class PolicyEngine {
|
|
6
|
-
/**
|
|
7
|
-
* 全面策略检查
|
|
8
|
-
* @param config - layerOrder 定义分层顺序,低层不应依赖高层
|
|
9
|
-
* @returns }
|
|
10
|
-
*/
|
|
11
|
-
check(graph, config = {}) {
|
|
12
|
-
const violations = [];
|
|
13
|
-
// 1. 检查循环依赖
|
|
14
|
-
const cycles = graph.detectCycles();
|
|
15
|
-
for (const cycle of cycles) {
|
|
16
|
-
violations.push({
|
|
17
|
-
type: 'circular-dependency',
|
|
18
|
-
severity: 'error',
|
|
19
|
-
message: `循环依赖: ${cycle.join(' → ')}`,
|
|
20
|
-
nodes: cycle,
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
// 2. 检查反向依赖 (低层依赖高层)
|
|
24
|
-
if (config.layerOrder && config.layerOrder.length > 0) {
|
|
25
|
-
const layerIndex = new Map();
|
|
26
|
-
config.layerOrder.forEach((layer, idx) => {
|
|
27
|
-
layerIndex.set(layer, idx);
|
|
28
|
-
});
|
|
29
|
-
for (const node of graph.getNodes()) {
|
|
30
|
-
const nodeLayer = this.#findLayer(node, layerIndex);
|
|
31
|
-
if (nodeLayer === -1) {
|
|
32
|
-
continue;
|
|
33
|
-
}
|
|
34
|
-
for (const dep of graph.getDependencies(node)) {
|
|
35
|
-
const depLayer = this.#findLayer(dep, layerIndex);
|
|
36
|
-
if (depLayer === -1) {
|
|
37
|
-
continue;
|
|
38
|
-
}
|
|
39
|
-
if (depLayer > nodeLayer) {
|
|
40
|
-
violations.push({
|
|
41
|
-
type: 'downward-dependency',
|
|
42
|
-
severity: 'warning',
|
|
43
|
-
message: `反向依赖: ${node} (L${nodeLayer}) → ${dep} (L${depLayer}),违反分层原则`,
|
|
44
|
-
from: node,
|
|
45
|
-
to: dep,
|
|
46
|
-
fromLayer: nodeLayer,
|
|
47
|
-
toLayer: depLayer,
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return {
|
|
54
|
-
passed: violations.length === 0,
|
|
55
|
-
violations,
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* 单独检查能否添加新依赖
|
|
60
|
-
* @returns }
|
|
61
|
-
*/
|
|
62
|
-
canAddDependency(graph, from, to) {
|
|
63
|
-
// 检查是否会导致循环
|
|
64
|
-
if (graph.isReachable(to, from)) {
|
|
65
|
-
return { allowed: false, reason: `添加 ${from} → ${to} 会导致循环依赖` };
|
|
66
|
-
}
|
|
67
|
-
return { allowed: true };
|
|
68
|
-
}
|
|
69
|
-
// ─── 私有 ─────────────────────────────────────────────
|
|
70
|
-
#findLayer(nodeName, layerIndex) {
|
|
71
|
-
// 尝试精确匹配或前缀匹配
|
|
72
|
-
for (const [layer, idx] of layerIndex) {
|
|
73
|
-
if (nodeName === layer || nodeName.startsWith(layer)) {
|
|
74
|
-
return idx;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return -1;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SpmHelper — SPM 依赖检查与修复工具
|
|
3
|
-
* 整合 PackageSwiftParser + DependencyGraph + PolicyEngine
|
|
4
|
-
* 专注于 Xcode 工作流的 SPM 依赖管理(ensureDependency / addDependency / resolveCurrentTarget)
|
|
5
|
-
* 模块列表、文件遍历等 Dashboard 能力由 SpmDiscoverer + ModuleService 提供
|
|
6
|
-
*/
|
|
7
|
-
import { DependencyGraph } from './DependencyGraph.js';
|
|
8
|
-
import { PackageSwiftParser } from './PackageSwiftParser.js';
|
|
9
|
-
import { PolicyEngine } from './PolicyEngine.js';
|
|
10
|
-
export declare class SpmHelper {
|
|
11
|
-
#private;
|
|
12
|
-
constructor(projectRoot: string, options?: {
|
|
13
|
-
parser?: PackageSwiftParser;
|
|
14
|
-
graph?: DependencyGraph;
|
|
15
|
-
policy?: PolicyEngine;
|
|
16
|
-
});
|
|
17
|
-
/**
|
|
18
|
-
* 加载并解析 Package.swift,构建依赖图
|
|
19
|
-
* 支持多 Package 项目
|
|
20
|
-
* 优先从磁盘缓存加载(Package.swift contentHash 匹配即命中)
|
|
21
|
-
*/
|
|
22
|
-
load(): Promise<any>;
|
|
23
|
-
/**
|
|
24
|
-
* BFS 检查包级可达性(V1 _canReachPackage 等价)
|
|
25
|
-
* @param fromPkgPath 起始包的 Package.swift 路径
|
|
26
|
-
* @param toPkgPath 目标包的 Package.swift 路径
|
|
27
|
-
*/
|
|
28
|
-
_canReachPackage(fromPkgPath: string, toPkgPath: string): boolean;
|
|
29
|
-
/**
|
|
30
|
-
* 获取 target 所属包信息(V1 spmmap 等价)
|
|
31
|
-
* @returns | null}
|
|
32
|
-
*/
|
|
33
|
-
getPackageForTarget(targetName: string): any;
|
|
34
|
-
/**
|
|
35
|
-
* 获取 Fix Mode 配置 (V1 allowActions 等价)
|
|
36
|
-
* 环境变量: ASD_FIX_SPM_DEPS_MODE = off | suggest | fix
|
|
37
|
-
* - off: 不检查、不提示
|
|
38
|
-
* - suggest: 仅提示(直接插入、提示操作插入按钮,无自动修复)
|
|
39
|
-
* - fix: 完整4按钮(直接插入、提示操作插入、自动修复依赖、取消操作)
|
|
40
|
-
*/
|
|
41
|
-
getFixMode(): "suggest" | "off" | "fix";
|
|
42
|
-
/**
|
|
43
|
-
* 确保依赖存在: 如果不存在则评估是否可以添加
|
|
44
|
-
* 支持跨包循环检测:如果 from 和 to 在不同包内,额外检查包级依赖图
|
|
45
|
-
* @param from 源 target
|
|
46
|
-
* @param to 目标 target
|
|
47
|
-
* @returns }
|
|
48
|
-
*/
|
|
49
|
-
ensureDependency(from: string, to: string): {
|
|
50
|
-
exists: boolean;
|
|
51
|
-
canAdd: boolean;
|
|
52
|
-
reason?: undefined;
|
|
53
|
-
crossPackage?: undefined;
|
|
54
|
-
} | {
|
|
55
|
-
exists: boolean;
|
|
56
|
-
canAdd: boolean;
|
|
57
|
-
reason: string | undefined;
|
|
58
|
-
crossPackage?: undefined;
|
|
59
|
-
} | {
|
|
60
|
-
exists: boolean;
|
|
61
|
-
canAdd: boolean;
|
|
62
|
-
crossPackage: boolean;
|
|
63
|
-
reason: string;
|
|
64
|
-
} | {
|
|
65
|
-
exists: boolean;
|
|
66
|
-
canAdd: boolean;
|
|
67
|
-
crossPackage: boolean;
|
|
68
|
-
reason?: undefined;
|
|
69
|
-
};
|
|
70
|
-
/**
|
|
71
|
-
* 自动修复依赖:向 Package.swift 中添加 target 级依赖(V1 DepFixer 逻辑)
|
|
72
|
-
*
|
|
73
|
-
* 同包 target → 添加 "TargetName" 到 dependencies
|
|
74
|
-
* 跨包 target → 添加 .product(name: "X", package: "Y") + 确保 .package(path: "...") 声明
|
|
75
|
-
*
|
|
76
|
-
* @param from 源 target
|
|
77
|
-
* @param to 目标 target
|
|
78
|
-
* @returns }
|
|
79
|
-
*/
|
|
80
|
-
addDependency(from: string, to: string): {
|
|
81
|
-
ok: boolean;
|
|
82
|
-
changed: boolean;
|
|
83
|
-
error: string;
|
|
84
|
-
file?: undefined;
|
|
85
|
-
crossPackage?: undefined;
|
|
86
|
-
} | {
|
|
87
|
-
ok: boolean;
|
|
88
|
-
changed: boolean;
|
|
89
|
-
file: any;
|
|
90
|
-
crossPackage: any;
|
|
91
|
-
error?: undefined;
|
|
92
|
-
};
|
|
93
|
-
/**
|
|
94
|
-
* 推断文件所属 target(源自 V1 ModuleResolverV2.determineCurrentModule)
|
|
95
|
-
*
|
|
96
|
-
* 从文件到 Package.swift 所在目录的相对路径中,反向匹配已知 target 名。
|
|
97
|
-
* 如果文件不在任何 SPM target 的源码目录中(如 Xcode 主 App target),返回 null。
|
|
98
|
-
* @param filePath 源文件绝对路径
|
|
99
|
-
* @returns target 名称,未匹配返回 null
|
|
100
|
-
*/
|
|
101
|
-
resolveCurrentTarget(filePath: string): string | null;
|
|
102
|
-
}
|
|
@@ -1,464 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SpmHelper — SPM 依赖检查与修复工具
|
|
3
|
-
* 整合 PackageSwiftParser + DependencyGraph + PolicyEngine
|
|
4
|
-
* 专注于 Xcode 工作流的 SPM 依赖管理(ensureDependency / addDependency / resolveCurrentTarget)
|
|
5
|
-
* 模块列表、文件遍历等 Dashboard 能力由 SpmDiscoverer + ModuleService 提供
|
|
6
|
-
*/
|
|
7
|
-
import { readFileSync, writeFileSync } from 'node:fs';
|
|
8
|
-
import { dirname, resolve as pathResolve, relative, sep } from 'node:path';
|
|
9
|
-
import { GraphCache } from '#infra/cache/GraphCache.js';
|
|
10
|
-
import Logger from '#infra/logging/Logger.js';
|
|
11
|
-
import { DependencyGraph } from './DependencyGraph.js';
|
|
12
|
-
import { PackageSwiftParser } from './PackageSwiftParser.js';
|
|
13
|
-
import { PolicyEngine } from './PolicyEngine.js';
|
|
14
|
-
export class SpmHelper {
|
|
15
|
-
#parser;
|
|
16
|
-
#graph;
|
|
17
|
-
#policy;
|
|
18
|
-
#logger;
|
|
19
|
-
#projectRoot;
|
|
20
|
-
/** target → { packageName, packagePath } 映射(V1 spmmap 等价) */
|
|
21
|
-
#targetPackageMap;
|
|
22
|
-
/** 包级依赖图:packagePath → Set<packagePath>(用于跨包循环检测) */
|
|
23
|
-
#packageDepGraph;
|
|
24
|
-
/** 磁盘缓存层 */
|
|
25
|
-
#graphCache;
|
|
26
|
-
constructor(projectRoot, options = {}) {
|
|
27
|
-
this.#projectRoot = projectRoot;
|
|
28
|
-
this.#parser = options.parser || new PackageSwiftParser(projectRoot);
|
|
29
|
-
this.#graph = options.graph || new DependencyGraph();
|
|
30
|
-
this.#policy = options.policy || new PolicyEngine();
|
|
31
|
-
this.#logger = Logger.getInstance();
|
|
32
|
-
this.#targetPackageMap = new Map();
|
|
33
|
-
this.#packageDepGraph = new Map();
|
|
34
|
-
this.#graphCache = new GraphCache(projectRoot);
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* 加载并解析 Package.swift,构建依赖图
|
|
38
|
-
* 支持多 Package 项目
|
|
39
|
-
* 优先从磁盘缓存加载(Package.swift contentHash 匹配即命中)
|
|
40
|
-
*/
|
|
41
|
-
async load() {
|
|
42
|
-
this.#targetPackageMap.clear();
|
|
43
|
-
this.#packageDepGraph.clear();
|
|
44
|
-
// ── 收集所有 Package.swift 路径 + 联合 hash ──
|
|
45
|
-
const packagePath = this.#parser.findPackageSwift(this.#projectRoot);
|
|
46
|
-
// 判断是否需要多包模式:
|
|
47
|
-
// 1. 根目录没有 Package.swift → findAllPackageSwifts
|
|
48
|
-
// 2. 根目录有 Package.swift 但 targets 为空且有 local path dependencies → 聚合根 + 子包
|
|
49
|
-
let allPaths;
|
|
50
|
-
if (packagePath) {
|
|
51
|
-
const rootParsed = this.#parser.parse(packagePath);
|
|
52
|
-
const hasNoTargets = !rootParsed?.targets || rootParsed.targets.length === 0;
|
|
53
|
-
const hasLocalDeps = (rootParsed?.dependencies || []).some((d) => d.type === 'local' || d.path);
|
|
54
|
-
if (hasNoTargets && hasLocalDeps) {
|
|
55
|
-
// 聚合根模式:根 Package.swift 仅声明 local path 依赖,target 在子包里
|
|
56
|
-
allPaths = this.#parser.findAllPackageSwifts(this.#projectRoot);
|
|
57
|
-
this.#logger.info(`[SpmHelper] 聚合根检测: 根无 target 但有 ${rootParsed.dependencies.length} 个 local dep,切换多包模式`);
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
allPaths = [packagePath];
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
allPaths = this.#parser.findAllPackageSwifts(this.#projectRoot);
|
|
65
|
-
}
|
|
66
|
-
if (allPaths.length === 0) {
|
|
67
|
-
this.#logger.warn('[SpmHelper] Package.swift 未找到');
|
|
68
|
-
return null;
|
|
69
|
-
}
|
|
70
|
-
const combinedHash = allPaths.map((p) => this.#graphCache.computeFileHash(p)).join(':');
|
|
71
|
-
// ── 尝试命中缓存 ──
|
|
72
|
-
const cached = this.#graphCache.load('spm-graph');
|
|
73
|
-
if (cached && cached.contentHash === combinedHash) {
|
|
74
|
-
this.#restoreFromCache(cached.data);
|
|
75
|
-
this.#logger.info(`[SpmHelper] ⚡ 缓存命中 (${this.#graph.getNodes().length} targets, hash=${combinedHash.substring(0, 8)})`);
|
|
76
|
-
return cached.data.parsedResult;
|
|
77
|
-
}
|
|
78
|
-
// ── 缓存未命中,走完整解析 ──
|
|
79
|
-
const startTime = Date.now();
|
|
80
|
-
let parsedResult;
|
|
81
|
-
if (packagePath && allPaths.length === 1) {
|
|
82
|
-
// 单包模式(根有 target)
|
|
83
|
-
const parsed = this.#parser.parse(packagePath);
|
|
84
|
-
this.#graph.buildFromParsed(parsed);
|
|
85
|
-
for (const t of parsed.targets || []) {
|
|
86
|
-
this.#targetPackageMap.set(t.name, { packageName: parsed.name, packagePath });
|
|
87
|
-
}
|
|
88
|
-
this.#buildPackageDepGraph([{ path: packagePath, parsed }]);
|
|
89
|
-
this.#logger.info(`[SpmHelper] 加载完成: ${parsed.name} (${parsed.targets.length} targets)`);
|
|
90
|
-
parsedResult = parsed;
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
// 多包模式
|
|
94
|
-
parsedResult = this.#loadMultiPackage(allPaths);
|
|
95
|
-
}
|
|
96
|
-
// ── 写入缓存 ──
|
|
97
|
-
if (parsedResult) {
|
|
98
|
-
this.#saveToCache(combinedHash, parsedResult);
|
|
99
|
-
this.#logger.info(`[SpmHelper] 缓存已写入 (${Date.now() - startTime}ms 解析)`);
|
|
100
|
-
}
|
|
101
|
-
return parsedResult;
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* 多包加载(从 load() 拆出)
|
|
105
|
-
* @param allPaths Package.swift 路径数组
|
|
106
|
-
*/
|
|
107
|
-
#loadMultiPackage(allPaths) {
|
|
108
|
-
this.#logger.info(`[SpmHelper] 发现 ${allPaths.length} 个 Package.swift,逐一解析...`);
|
|
109
|
-
const mergedTargets = [];
|
|
110
|
-
let lastName = 'multi-package';
|
|
111
|
-
const allParsed = [];
|
|
112
|
-
this.#graph.clear();
|
|
113
|
-
for (const pkgPath of allPaths) {
|
|
114
|
-
try {
|
|
115
|
-
const parsed = this.#parser.parse(pkgPath);
|
|
116
|
-
if (parsed) {
|
|
117
|
-
allParsed.push({ path: pkgPath, parsed });
|
|
118
|
-
for (const t of parsed.targets || []) {
|
|
119
|
-
this.#graph.addNode(t.name);
|
|
120
|
-
for (const dep of t.dependencies || []) {
|
|
121
|
-
this.#graph.addEdge(t.name, dep);
|
|
122
|
-
}
|
|
123
|
-
this.#targetPackageMap.set(t.name, { packageName: parsed.name, packagePath: pkgPath });
|
|
124
|
-
}
|
|
125
|
-
for (const t of parsed.targets) {
|
|
126
|
-
mergedTargets.push({
|
|
127
|
-
...t,
|
|
128
|
-
packageName: parsed.name,
|
|
129
|
-
packagePath: pkgPath,
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
lastName = parsed.name;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
catch (e) {
|
|
136
|
-
this.#logger.warn(`[SpmHelper] 解析失败: ${pkgPath} - ${e instanceof Error ? e.message : String(e)}`);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
this.#buildPackageDepGraph(allParsed);
|
|
140
|
-
this.#logger.info(`[SpmHelper] 多包加载完成: ${mergedTargets.length} targets from ${allPaths.length} packages`);
|
|
141
|
-
return {
|
|
142
|
-
name: lastName,
|
|
143
|
-
targets: mergedTargets,
|
|
144
|
-
path: this.#projectRoot,
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
/** 将当前内存状态序列化到缓存 */
|
|
148
|
-
#saveToCache(contentHash, parsedResult) {
|
|
149
|
-
const graphJSON = this.#graph.toJSON();
|
|
150
|
-
const targetPackageEntries = [...this.#targetPackageMap.entries()];
|
|
151
|
-
const packageDepEntries = [...this.#packageDepGraph.entries()].map(([k, v]) => [k, [...v]]);
|
|
152
|
-
this.#graphCache.save('spm-graph', {
|
|
153
|
-
parsedResult,
|
|
154
|
-
graphNodes: graphJSON.nodes,
|
|
155
|
-
graphEdges: graphJSON.edges,
|
|
156
|
-
targetPackageMap: targetPackageEntries,
|
|
157
|
-
packageDepGraph: packageDepEntries,
|
|
158
|
-
}, { contentHash });
|
|
159
|
-
}
|
|
160
|
-
/** 从缓存数据恢复内存状态 */
|
|
161
|
-
#restoreFromCache(data) {
|
|
162
|
-
// 恢复 DependencyGraph
|
|
163
|
-
this.#graph.clear();
|
|
164
|
-
for (const node of data.graphNodes || []) {
|
|
165
|
-
this.#graph.addNode(node);
|
|
166
|
-
}
|
|
167
|
-
for (const edge of data.graphEdges || []) {
|
|
168
|
-
this.#graph.addEdge(edge.from, edge.to);
|
|
169
|
-
}
|
|
170
|
-
// 恢复 targetPackageMap
|
|
171
|
-
this.#targetPackageMap.clear();
|
|
172
|
-
for (const [name, info] of data.targetPackageMap || []) {
|
|
173
|
-
this.#targetPackageMap.set(name, info);
|
|
174
|
-
}
|
|
175
|
-
// 恢复 packageDepGraph
|
|
176
|
-
this.#packageDepGraph.clear();
|
|
177
|
-
for (const [pkgPath, deps] of data.packageDepGraph || []) {
|
|
178
|
-
this.#packageDepGraph.set(pkgPath, new Set(deps));
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
// ─────────────── 包级依赖图构建 ───────────────
|
|
182
|
-
/**
|
|
183
|
-
* 解析所有 Package.swift 中的 .package(path: "...") 声明,构建包级依赖图
|
|
184
|
-
* @param allParsed
|
|
185
|
-
*/
|
|
186
|
-
#buildPackageDepGraph(allParsed) {
|
|
187
|
-
this.#packageDepGraph.clear();
|
|
188
|
-
// 初始化所有包节点
|
|
189
|
-
for (const { path: pkgPath } of allParsed) {
|
|
190
|
-
if (!this.#packageDepGraph.has(pkgPath)) {
|
|
191
|
-
this.#packageDepGraph.set(pkgPath, new Set());
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
// 建立 dirname → pkgPath 索引(避免 O(n²) 线性扫描)
|
|
195
|
-
const dirToPkgPath = new Map();
|
|
196
|
-
for (const { path: pkgPath } of allParsed) {
|
|
197
|
-
dirToPkgPath.set(dirname(pkgPath), pkgPath);
|
|
198
|
-
}
|
|
199
|
-
// 解析 .package(path: "...") 引用,建立包级边
|
|
200
|
-
for (const { path: pkgPath, parsed } of allParsed) {
|
|
201
|
-
const pkgDir = dirname(pkgPath);
|
|
202
|
-
const packageDeps = parsed.packageDependencies ??
|
|
203
|
-
parsed.dependencies ??
|
|
204
|
-
[];
|
|
205
|
-
for (const dep of packageDeps) {
|
|
206
|
-
if ('path' in dep && dep.path) {
|
|
207
|
-
const depAbsDir = pathResolve(pkgDir, dep.path);
|
|
208
|
-
const otherPkgPath = dirToPkgPath.get(depAbsDir);
|
|
209
|
-
if (otherPkgPath) {
|
|
210
|
-
this.#packageDepGraph.get(pkgPath)?.add(otherPkgPath);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
this.#logger.debug(`[SpmHelper] 包级依赖图: ${this.#packageDepGraph.size} packages`);
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* BFS 检查包级可达性(V1 _canReachPackage 等价)
|
|
219
|
-
* @param fromPkgPath 起始包的 Package.swift 路径
|
|
220
|
-
* @param toPkgPath 目标包的 Package.swift 路径
|
|
221
|
-
*/
|
|
222
|
-
_canReachPackage(fromPkgPath, toPkgPath) {
|
|
223
|
-
if (fromPkgPath === toPkgPath) {
|
|
224
|
-
return true;
|
|
225
|
-
}
|
|
226
|
-
const visited = new Set();
|
|
227
|
-
const queue = [fromPkgPath];
|
|
228
|
-
while (queue.length > 0) {
|
|
229
|
-
const current = queue.shift();
|
|
230
|
-
if (current === toPkgPath) {
|
|
231
|
-
return true;
|
|
232
|
-
}
|
|
233
|
-
if (visited.has(current)) {
|
|
234
|
-
continue;
|
|
235
|
-
}
|
|
236
|
-
visited.add(current);
|
|
237
|
-
const neighbors = this.#packageDepGraph.get(current);
|
|
238
|
-
if (neighbors) {
|
|
239
|
-
for (const n of neighbors) {
|
|
240
|
-
queue.push(n);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
return false;
|
|
245
|
-
}
|
|
246
|
-
// ─────────────── 公共查询 API ───────────────
|
|
247
|
-
/**
|
|
248
|
-
* 获取 target 所属包信息(V1 spmmap 等价)
|
|
249
|
-
* @returns | null}
|
|
250
|
-
*/
|
|
251
|
-
getPackageForTarget(targetName) {
|
|
252
|
-
return this.#targetPackageMap.get(targetName) || null;
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
* 获取 Fix Mode 配置 (V1 allowActions 等价)
|
|
256
|
-
* 环境变量: ASD_FIX_SPM_DEPS_MODE = off | suggest | fix
|
|
257
|
-
* - off: 不检查、不提示
|
|
258
|
-
* - suggest: 仅提示(直接插入、提示操作插入按钮,无自动修复)
|
|
259
|
-
* - fix: 完整4按钮(直接插入、提示操作插入、自动修复依赖、取消操作)
|
|
260
|
-
*/
|
|
261
|
-
getFixMode() {
|
|
262
|
-
const env = (process.env.ASD_FIX_SPM_DEPS_MODE || '').toLowerCase().trim();
|
|
263
|
-
if (env === 'off' || env === 'suggest' || env === 'fix') {
|
|
264
|
-
return env;
|
|
265
|
-
}
|
|
266
|
-
return 'suggest'; // 默认仅提示模式
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* 确保依赖存在: 如果不存在则评估是否可以添加
|
|
270
|
-
* 支持跨包循环检测:如果 from 和 to 在不同包内,额外检查包级依赖图
|
|
271
|
-
* @param from 源 target
|
|
272
|
-
* @param to 目标 target
|
|
273
|
-
* @returns }
|
|
274
|
-
*/
|
|
275
|
-
ensureDependency(from, to) {
|
|
276
|
-
if (this.#graph.isReachable(from, to)) {
|
|
277
|
-
return { exists: true, canAdd: true };
|
|
278
|
-
}
|
|
279
|
-
// target 级策略检查
|
|
280
|
-
const check = this.#policy.canAddDependency(this.#graph, from, to);
|
|
281
|
-
if (!check.allowed) {
|
|
282
|
-
return { exists: false, canAdd: false, reason: check.reason };
|
|
283
|
-
}
|
|
284
|
-
// 跨包循环检测
|
|
285
|
-
const fromPkg = this.#targetPackageMap.get(from);
|
|
286
|
-
const toPkg = this.#targetPackageMap.get(to);
|
|
287
|
-
if (fromPkg && toPkg && fromPkg.packagePath !== toPkg.packagePath) {
|
|
288
|
-
// 检查反向:如果 toPkg 已经能到达 fromPkg,添加 from→to 会形成包级循环
|
|
289
|
-
if (this._canReachPackage(toPkg.packagePath, fromPkg.packagePath)) {
|
|
290
|
-
return {
|
|
291
|
-
exists: false,
|
|
292
|
-
canAdd: false,
|
|
293
|
-
crossPackage: true,
|
|
294
|
-
reason: `跨包循环依赖: ${fromPkg.packageName} ↔ ${toPkg.packageName}`,
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
return { exists: false, canAdd: true, crossPackage: true };
|
|
298
|
-
}
|
|
299
|
-
return {
|
|
300
|
-
exists: false,
|
|
301
|
-
canAdd: check.allowed,
|
|
302
|
-
reason: check.reason,
|
|
303
|
-
};
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* 自动修复依赖:向 Package.swift 中添加 target 级依赖(V1 DepFixer 逻辑)
|
|
307
|
-
*
|
|
308
|
-
* 同包 target → 添加 "TargetName" 到 dependencies
|
|
309
|
-
* 跨包 target → 添加 .product(name: "X", package: "Y") + 确保 .package(path: "...") 声明
|
|
310
|
-
*
|
|
311
|
-
* @param from 源 target
|
|
312
|
-
* @param to 目标 target
|
|
313
|
-
* @returns }
|
|
314
|
-
*/
|
|
315
|
-
addDependency(from, to) {
|
|
316
|
-
// 安全检查
|
|
317
|
-
const check = this.#policy.canAddDependency(this.#graph, from, to);
|
|
318
|
-
if (!check.allowed) {
|
|
319
|
-
return { ok: false, changed: false, error: check.reason || 'policy-blocked' };
|
|
320
|
-
}
|
|
321
|
-
// 判断同包 vs 跨包
|
|
322
|
-
const fromPkg = this.#targetPackageMap.get(from);
|
|
323
|
-
const toPkg = this.#targetPackageMap.get(to);
|
|
324
|
-
const isCrossPackage = fromPkg && toPkg && fromPkg.packagePath !== toPkg.packagePath;
|
|
325
|
-
try {
|
|
326
|
-
// 确定要修改的 Package.swift(from 所在的包)
|
|
327
|
-
const packagePath = fromPkg?.packagePath || this.#parser.findPackageSwift(this.#projectRoot);
|
|
328
|
-
if (!packagePath) {
|
|
329
|
-
return { ok: false, changed: false, error: 'Package.swift not found' };
|
|
330
|
-
}
|
|
331
|
-
const content = readFileSync(packagePath, 'utf8');
|
|
332
|
-
// ── 1. 构建依赖 token ──
|
|
333
|
-
let depToken;
|
|
334
|
-
if (isCrossPackage) {
|
|
335
|
-
// 跨包: .product(name: "TargetName", package: "PackageName")
|
|
336
|
-
depToken = `.product(name: "${to}", package: "${toPkg.packageName}")`;
|
|
337
|
-
}
|
|
338
|
-
else {
|
|
339
|
-
// 同包: "TargetName"
|
|
340
|
-
depToken = `"${to}"`;
|
|
341
|
-
}
|
|
342
|
-
// ── 2. 向 from target 的 dependencies 添加 token ──
|
|
343
|
-
const escaped = from.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
344
|
-
const targetRe = new RegExp(`(\\.(?:target|testTarget|executableTarget)\\s*\\(\\s*name\\s*:\\s*"${escaped}"[\\s\\S]*?)\\)`, 'm');
|
|
345
|
-
const targetMatch = content.match(targetRe);
|
|
346
|
-
if (!targetMatch) {
|
|
347
|
-
return { ok: false, changed: false, error: `Target "${from}" not found in Package.swift` };
|
|
348
|
-
}
|
|
349
|
-
const targetBlock = targetMatch[1];
|
|
350
|
-
let patched;
|
|
351
|
-
const depsRe = /dependencies\s*:\s*\[([^\]]*)\]/s;
|
|
352
|
-
const depsMatch = targetBlock.match(depsRe);
|
|
353
|
-
if (depsMatch) {
|
|
354
|
-
const existingDeps = depsMatch[1].trim();
|
|
355
|
-
const separator = existingDeps.length > 0 ? ',\n ' : '\n ';
|
|
356
|
-
const newDeps = `dependencies: [${existingDeps}${separator}${depToken}\n ]`;
|
|
357
|
-
const newBlock = targetBlock.replace(depsRe, newDeps);
|
|
358
|
-
patched = content.replace(targetBlock, newBlock);
|
|
359
|
-
}
|
|
360
|
-
else {
|
|
361
|
-
const nameRe = /name\s*:\s*"[^"]+"/;
|
|
362
|
-
const nameMatch = targetBlock.match(nameRe);
|
|
363
|
-
if (!nameMatch) {
|
|
364
|
-
return { ok: false, changed: false, error: `Cannot parse target "${from}" structure` };
|
|
365
|
-
}
|
|
366
|
-
const newBlock = targetBlock.replace(nameMatch[0], `${nameMatch[0]},\n dependencies: [${depToken}]`);
|
|
367
|
-
patched = content.replace(targetBlock, newBlock);
|
|
368
|
-
}
|
|
369
|
-
if (patched === content) {
|
|
370
|
-
return { ok: false, changed: false, error: 'Patch produced no changes' };
|
|
371
|
-
}
|
|
372
|
-
// ── 3. 跨包: 确保 .package(path: "...") 声明存在 ──
|
|
373
|
-
if (isCrossPackage) {
|
|
374
|
-
const ensureResult = this.#ensurePackageDependency(patched, packagePath, toPkg);
|
|
375
|
-
if (ensureResult.changed) {
|
|
376
|
-
patched = ensureResult.content;
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
writeFileSync(packagePath, patched, 'utf8');
|
|
380
|
-
// 更新内存中的图
|
|
381
|
-
this.#graph.addEdge(from, to);
|
|
382
|
-
this.#parser.clearCache();
|
|
383
|
-
this.#logger.info(`[SpmHelper] 已自动补齐依赖: ${from} -> ${to}${isCrossPackage ? ' (跨包)' : ''} (${packagePath})`);
|
|
384
|
-
return { ok: true, changed: true, file: packagePath, crossPackage: isCrossPackage };
|
|
385
|
-
}
|
|
386
|
-
catch (err) {
|
|
387
|
-
this.#logger.error(`[SpmHelper] addDependency failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
388
|
-
return { ok: false, changed: false, error: err instanceof Error ? err.message : String(err) };
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
/**
|
|
392
|
-
* 确保 Package.swift 中有对目标包的 .package(path: "...") 声明
|
|
393
|
-
* @param content Package.swift 内容
|
|
394
|
-
* @param fromPkgPath 当前包的 Package.swift 路径
|
|
395
|
-
* @param toPkg 目标包信息
|
|
396
|
-
* @returns }
|
|
397
|
-
*/
|
|
398
|
-
#ensurePackageDependency(content, fromPkgPath, toPkg) {
|
|
399
|
-
const fromDir = dirname(fromPkgPath);
|
|
400
|
-
const toDir = dirname(toPkg.packagePath);
|
|
401
|
-
const relPath = relative(fromDir, toDir).split(sep).join('/');
|
|
402
|
-
// 检查是否已有对该路径的 .package 声明
|
|
403
|
-
const escapedPath = relPath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
404
|
-
const existsRe = new RegExp(`\\.package\\s*\\(\\s*(?:name\\s*:[^,]*,\\s*)?path\\s*:\\s*"${escapedPath}"`, 'm');
|
|
405
|
-
if (existsRe.test(content)) {
|
|
406
|
-
return { changed: false, content };
|
|
407
|
-
}
|
|
408
|
-
// 也检查包名
|
|
409
|
-
const escapedName = toPkg.packageName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
410
|
-
const nameExistsRe = new RegExp(`\\.package\\s*\\(\\s*name\\s*:\\s*"${escapedName}"`, 'm');
|
|
411
|
-
if (nameExistsRe.test(content)) {
|
|
412
|
-
return { changed: false, content };
|
|
413
|
-
}
|
|
414
|
-
// 在 dependencies: [...] (包级)中追加
|
|
415
|
-
const pkgDepsRe = /(dependencies\s*:\s*\[)([\s\S]*?)(\][\s\S]*?targets\s*:)/m;
|
|
416
|
-
const pkgDepsMatch = content.match(pkgDepsRe);
|
|
417
|
-
if (pkgDepsMatch) {
|
|
418
|
-
const existing = pkgDepsMatch[2].trimEnd();
|
|
419
|
-
const separator = existing.length > 0 ? ',\n ' : '\n ';
|
|
420
|
-
const newDep = `.package(path: "${relPath}")`;
|
|
421
|
-
const patched = content.replace(pkgDepsRe, `${pkgDepsMatch[1]}${existing}${separator}${newDep}\n ${pkgDepsMatch[3]}`);
|
|
422
|
-
this.#logger.info(`[SpmHelper] 已添加包级依赖: .package(path: "${relPath}")`);
|
|
423
|
-
return { changed: true, content: patched };
|
|
424
|
-
}
|
|
425
|
-
this.#logger.warn(`[SpmHelper] 未能找到包级 dependencies 数组,跳过 .package(path:) 插入`);
|
|
426
|
-
return { changed: false, content };
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* 推断文件所属 target(源自 V1 ModuleResolverV2.determineCurrentModule)
|
|
430
|
-
*
|
|
431
|
-
* 从文件到 Package.swift 所在目录的相对路径中,反向匹配已知 target 名。
|
|
432
|
-
* 如果文件不在任何 SPM target 的源码目录中(如 Xcode 主 App target),返回 null。
|
|
433
|
-
* @param filePath 源文件绝对路径
|
|
434
|
-
* @returns target 名称,未匹配返回 null
|
|
435
|
-
*/
|
|
436
|
-
resolveCurrentTarget(filePath) {
|
|
437
|
-
try {
|
|
438
|
-
const packagePath = this.#parser.findPackageSwift(dirname(filePath));
|
|
439
|
-
if (!packagePath) {
|
|
440
|
-
return null;
|
|
441
|
-
}
|
|
442
|
-
const nodes = this.#graph.getNodes();
|
|
443
|
-
if (nodes.length === 0) {
|
|
444
|
-
return null;
|
|
445
|
-
}
|
|
446
|
-
const packageDir = dirname(packagePath);
|
|
447
|
-
const rel = relative(packageDir, filePath);
|
|
448
|
-
const segments = rel.split(sep);
|
|
449
|
-
// 从路径段反向查找第一个匹配的 target(V1 原始逻辑)
|
|
450
|
-
const nodeSet = new Set(nodes);
|
|
451
|
-
for (let i = segments.length - 1; i >= 0; i--) {
|
|
452
|
-
if (nodeSet.has(segments[i])) {
|
|
453
|
-
return segments[i];
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
// 文件不属于任何 SPM target(如 Xcode 主 App target 下的文件)
|
|
457
|
-
// 不做错误的 fallback,返回 null 让调用方跳过依赖检查
|
|
458
|
-
return null;
|
|
459
|
-
}
|
|
460
|
-
catch {
|
|
461
|
-
return null;
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HeaderResolver — ObjC/Swift #import 头文件路径解析
|
|
3
|
-
* 解析 import 语句,定位头文件相对路径
|
|
4
|
-
*/
|
|
5
|
-
/** 解析单行 import 语句 */
|
|
6
|
-
export declare function parseImportLine(headerStr: string): {
|
|
7
|
-
moduleName: string;
|
|
8
|
-
headerName: string;
|
|
9
|
-
} | {
|
|
10
|
-
moduleName: null;
|
|
11
|
-
headerName: string;
|
|
12
|
-
} | null;
|
|
13
|
-
/** 解析单个 import 的相对路径 */
|
|
14
|
-
export declare function resolveHeaderRelativePath(headerStr: string, targetRootDir: string): Promise<string | undefined>;
|
|
15
|
-
/** 从文件路径和 Package 信息推断模块名 */
|
|
16
|
-
export declare function determineModuleNameFromPath(filePath: string, packageInfo: {
|
|
17
|
-
path: string;
|
|
18
|
-
targets?: string[];
|
|
19
|
-
name?: string;
|
|
20
|
-
}): string | null;
|
|
21
|
-
/** 综合解析:从路径+文本提取 headers、headerPaths、moduleName */
|
|
22
|
-
export declare function resolveHeadersForText(projectRoot: string, relativePath: string, text: string): Promise<{
|
|
23
|
-
headers: string[];
|
|
24
|
-
headerPaths: (string | undefined)[];
|
|
25
|
-
moduleName: string | null;
|
|
26
|
-
}>;
|
|
27
|
-
declare const _default: {
|
|
28
|
-
resolveHeadersForText: typeof resolveHeadersForText;
|
|
29
|
-
parseImportLine: typeof parseImportLine;
|
|
30
|
-
resolveHeaderRelativePath: typeof resolveHeaderRelativePath;
|
|
31
|
-
determineModuleNameFromPath: typeof determineModuleNameFromPath;
|
|
32
|
-
};
|
|
33
|
-
export default _default;
|