Deep Dive | src/utils/plugins/marketplaceManager.ts 2643 行 — 插件市场管理¶
重要性:⭐⭐⭐(plugin 分发生态——marketplace 加载、缓存、刷新、自动更新) 真实位置:
src/utils/plugins/marketplaceManager.ts(2643 行) 角色:管理所有已注册的 plugin marketplace(git / URL / seed),缓存 marketplace manifest,支持手动 / 自动刷新 关联:topics/deep-dive-plugin-loader.md(plugin 加载)、topics/deep-dive-manage-plugins.md(管理 UI)
1. 文件全景¶
marketplaceManager.ts (2643 行)
│
├── 行 1-200 :imports + 2 个 type + 5 个 helper
│ ├── LoadedPluginMarketplace type (行 93)
│ ├── getKnownMarketplacesFile / getMarketplacesCacheDir (行 102, 110)
│ ├── clearMarketplacesCache (行 122)
│ ├── KnownMarketplacesConfig type (行 129)
│ ├── DeclaredMarketplace type (行 138)
│ ├── getDeclaredMarketplaces (行 161)
│ └── getMarketplaceDeclaringSource (行 200)
│
├── 行 220-380 :settings 持久化
│ ├── saveMarketplaceToSettings (行 226)
│ ├── loadKnownMarketplacesConfig (行 264)
│ ├── loadKnownMarketplacesConfigSafe (行 309)
│ └── saveKnownMarketplacesConfig (行 327)
│
├── 行 380-510 :seed marketplace
│ ├── registerSeedMarketplaces (行 380, ~55 行)
│ ├── readSeedKnownMarketplaces (行 436)
│ ├── findSeedMarketplaceLocation (行 473)
│ └── seedDirFor (行 496)
│
├── 行 510-800 :git 操作
│ ├── GIT_NO_PROMPT_ENV (行 510)
│ ├── DEFAULT_PLUGIN_GIT_TIMEOUT_MS (120s, 行 515)
│ ├── getPluginGitTimeoutMs (行 517)
│ ├── gitPull (行 528, ~80 行)
│ ├── gitSubmoduleUpdate (行 609, ~40 行)
│ ├── enhanceGitPullErrorMessages (行 649, ~75 行)
│ ├── isGitHubSshLikelyConfigured (行 723, ~45 行)
│ ├── isAuthenticationError (行 767, ~15 行)
│ ├── extractSshHost (行 781, ~22 行)
│ └── gitClone (行 803, ~195 行)
│
├── 行 998-1080:进度回调
│ ├── MarketplaceProgressCallback type (行 998)
│ ├── safeCallProgress (行 1007)
│ └── reconcileSparseCheckout (行 1034, ~50 行)
│
├── 行 1084-1370:cache
│ ├── cacheMarketplaceFromGit (行 1084, ~100 行)
│ ├── redactHeaders (行 1186)
│ ├── redactUrlCredentials (行 1213, ~42 行)
│ ├── cacheMarketplaceFromUrl (行 1256, ~100 行)
│ └── getCachePathForSource (行 1355)
│
├── 行 1372-1780:parseFileWithSchema (行 1372, ~60 行) + loadAndCacheMarketplace (行 1433, ~350 行)
│
├── 行 1782-2058:增删
│ ├── addMarketplaceSource (行 1782, ~155 行)
│ └── removeMarketplaceSource (行 1937, ~120 行)
│
├── 行 2058-2238:读
│ ├── readCachedMarketplace (行 2058)
│ ├── getMarketplaceCacheOnly (行 2081, ~40 行)
│ ├── getMarketplace (memoize, 行 2122, ~65 行)
│ ├── getPluginByIdCacheOnly (行 2188, ~50 行)
│ └── getPluginById (行 2238, ~58 行)
│
├── 行 2296-2640:刷新
│ ├── refreshAllMarketplaces (行 2296, ~70 行)
│ ├── refreshMarketplace (行 2365, ~220 行)
│ └── setMarketplaceAutoUpdate (行 2587, ~55 行)
│
└── 行 2641-2643:_test (export for testing)
2. 2 个核心 Type¶
type LoadedPluginMarketplace = { ... } // 加载后的 marketplace
type DeclaredMarketplace = { ... } // 用户声明的 marketplace
3. 5 个核心 Helper¶
function getKnownMarketplacesFile(): string { ... } // 配置路径
export function getMarketplacesCacheDir(): string { ... } // 缓存目录
export function clearMarketplacesCache(): void { ... } // 清缓存
export function getDeclaredMarketplaces(): Record<string, DeclaredMarketplace> { ... }
export function getMarketplaceDeclaringSource(name: string): ... { ... }
5 个 helper——获取配置、缓存、来源。
4. Settings 持久化(4 个函数)¶
saveMarketplaceToSettings(name, marketplace) // 写到 user/project
loadKnownMarketplacesConfig() // 从多源读
loadKnownMarketplacesConfigSafe() // safe 版本(不抛)
saveKnownMarketplacesConfig() // 保存
4 个函数——配置增删改查。
5. Seed Marketplace(4 个函数)¶
registerSeedMarketplaces() // 注册内置 seed
readSeedKnownMarketplaces() // 读 seed 配置
findSeedMarketplaceLocation() // 找 seed 路径
seedDirFor() // seed 目录
4 个函数——Anthropic 预装的 marketplace(类似 npm 的官方源)。
6. Git 操作(9 个函数)¶
6.1 gitPull — 80 行(行 528)¶
export async function gitPull(repoDir: string, ...): Promise<...> {
// 1. 检查 git 可用
// 2. 设置 env (no prompt)
// 3. git pull
// 4. 处理错误
// 5. 增强错误信息
}
6.2 gitClone — 195 行(行 803)¶
export async function gitClone(url, dest, ...): Promise<...> {
// 1. 选 transport (HTTPS/SSH)
// 2. 处理 SSH config
// 3. 设置 timeout
// 4. git clone
// 5. 处理错误
}
195 行反映 git clone 的复杂(auth/SSH/HTTPS/proxy)。
6.3 enhanceGitPullErrorMessages — 75 行(行 649)¶
错误信息美化——给用户可读的错误提示。
6.4 isGitHubSshLikelyConfigured — 45 行(行 723)¶
GitHub SSH 检测——避免 ssh auth 失败时给出无意义错误。
6.5 extractSshHost + isAuthenticationError¶
2 个 helper——解析 SSH host、识别 auth 错误。
6.6 gitSubmoduleUpdate — 40 行¶
submodule 支持——marketplace 可能用 git submodule。
7. reconcileSparseCheckout — 50 行(行 1034)¶
Sparse checkout——只 checkout marketplace 需要的目录。
8. Cache(4 个函数)¶
cacheMarketplaceFromGit() // 从 git 缓存 (~100 行)
redactHeaders() // 移除敏感 header
redactUrlCredentials() // URL 去凭证
cacheMarketplaceFromUrl() // 从 URL 缓存 (~100 行)
getCachePathForSource() // cache 路径
4 个 cache 函数——marketplace manifest 缓存到本地。
8.1 redactUrlCredentials — 42 行(行 1213)¶
function redactUrlCredentials(urlString: string): string {
// https://user:pass@github.com → https://***:***@github.com
}
凭证脱敏——错误信息中不暴露用户密码。
9. loadAndCacheMarketplace — 350 行(行 1433)¶
async function loadAndCacheMarketplace(source: MarketplaceSource, ...): Promise<LoadedPluginMarketplace> {
// 1. 选择 source 类型 (git/url)
// 2. cache
// 3. 解析 manifest
// 4. 校验
}
350 行——加载并缓存 marketplace。
10. 增删(2 个函数)¶
10.1 addMarketplaceSource — 155 行(行 1782)¶
export async function addMarketplaceSource(name: string, source: MarketplaceSource): Promise<...> {
// 1. 校验 name
// 2. clone / fetch
// 3. 解析 manifest
// 4. 写到 settings
}
10.2 removeMarketplaceSource — 120 行(行 1937)¶
export async function removeMarketplaceSource(name: string): Promise<void> {
// 1. 从 settings 删除
// 2. 清理 cache
}
11. 读(5 个函数)¶
readCachedMarketplace() // 读 cache
getMarketplaceCacheOnly() // 只读 cache
getMarketplace (memoize) // cache 优先,miss 时拉
getPluginByIdCacheOnly() // 找单 plugin (cache only)
getPluginById() // 找单 plugin
5 个读 API——cache-only 和 full 分离。
12. 刷新(2 个函数)¶
12.1 refreshAllMarketplaces — 70 行(行 2296)¶
export async function refreshAllMarketplaces(): Promise<void> {
// 1. 遍历所有 marketplaces
// 2. 并行 refresh
// 3. 错误聚合
}
12.2 refreshMarketplace — 220 行(行 2365)¶
export async function refreshMarketplace(name: string, ...): Promise<...> {
// 1. git pull
// 2. 重新解析
// 3. 写 cache
}
220 行——单 marketplace 完整刷新。
13. setMarketplaceAutoUpdate — 55 行(行 2587)¶
export async function setMarketplaceAutoUpdate(name: string, enabled: boolean): Promise<void> {
// 开关自动更新
}
auto update 开关——某些 marketplace 支持 auto-refresh。
14. _test 导出¶
测试导出——单元测试可访问内部。
15. 关键设计模式¶
15.1 多源 Marketplace¶
- Seed(内置)
- Git(git URL)
- HTTPS URL(任意 URL)
- Local(本地路径)
4 种源 统一抽象。
15.2 缓存分层¶
readCachedMarketplace—— 读 cachegetMarketplaceCacheOnly—— 只 cachegetMarketplace(memoize) —— cache 优先,miss 拉
3 层。
15.3 凭证脱敏¶
redactUrlCredentials —— 错误信息不暴露密码。
15.4 SSH 智能检测¶
isGitHubSshLikelyConfigured —— 提前发现 SSH 配置问题。
15.5 错误信息增强¶
enhanceGitPullErrorMessages —— 把"fatal: could not read"变成"check your SSH keys"。
15.6 Sparse checkout 优化¶
reconcileSparseCheckout —— monorepo 只 checkout 需要的部分。
15.7 安全 git 操作¶
GIT_NO_PROMPT_ENV —— git 不提示输入(避免挂起)。
DEFAULT_PLUGIN_GIT_TIMEOUT_MS = 120s —— 超时兜底。
16. 复杂度分析¶
| 维度 | 数字 |
|---|---|
| 总行数 | 2643 |
| 类型 | 2 |
| 公开函数 | 15+ |
| Git 函数 | 9 |
| Cache 函数 | 4 |
| 读 API | 5 |
17. 性能特征¶
17.1 加载¶
- 缓存命中:< 50ms
- Git pull:~500ms-2s(取决于网络)
- HTTPS URL:~200ms-2s
- 全 marketplace 刷新(10 个):~3-10s(并行)
17.2 内存¶
每个 LoadedPluginMarketplace ~10-100KB。
18. 与其他文件的关系¶
marketplaceManager.ts
├──→ git subprocess
├──→ HTTP fetch
├──→ settings.json
├──→ pluginLoader.ts (消费)
└──→ ManagePlugins.tsx (UI)
19. 关键洞察¶
19.1 Git 操作的复杂度¶
gitClone 195 行 —— 真实工程中 git 集成非常复杂(auth/SSH/HTTPS/proxy/sparse/timeout)。
19.2 凭证脱敏是"安全细节"¶
redactUrlCredentials —— 错误信息保护用户密码。
19.3 错误信息增强 = "UX 细节"¶
enhanceGitPullErrorMessages —— 把"fatal error"变成可读建议。
19.4 3 层 cache 设计¶
- readCached
- getCacheOnly
- getMarketplace (memoize)
层层 fallback。
19.5 SSH 检测避免"试错"¶
isGitHubSshLikelyConfigured —— 提前告诉用户"先配 SSH"。
19.6 120s git timeout¶
DEFAULT_PLUGIN_GIT_TIMEOUT_MS = 120s —— 防止挂死。
19.7 _test 导出¶
明确暴露内部 API 给测试 —— 测试友好。
20. 阅读建议¶
- 看 2 个 type(行 93, 138)—— 数据模型
- 看 4 个 settings 函数(行 220-380)—— 持久化
- 看 gitPull + gitClone(行 528, 803)—— git 核心
- 看 cache 函数(行 1084-1370)—— 缓存
- 看 addMarketplaceSource(行 1782)—— 添加流程
- 看 refreshMarketplace(行 2365)—— 刷新流程
21. 与其他深度拆解的关系¶
| 文件 | 关系 |
|---|---|
pluginLoader.ts |
消费 marketplace |
ManagePlugins.tsx |
UI |
settings.json |
持久化 |
22. 阅读清单¶
- ✅ 看 2 个 type(行 93, 138)
- ✅ 看 4 个 settings 函数(行 220-380)
- ✅ 看 gitPull + gitClone(行 528, 803)
- ✅ 看 addMarketplaceSource(行 1782)
- ✅ 看 refreshMarketplace(行 2365)
- 📌 对照 topics/deep-dive-plugin-loader.md
- 📌 对照 topics/deep-dive-manage-plugins.md
23. 练习任务¶
- 数 git 函数(grep)—— 9 个
- 数 cache 函数(grep)—— 4 个
- 画 marketplace 加载流程 —— source → cache → loadAndCache → LoadedPluginMarketplace
- 手写迷你 git pull(~30 行)—— 用 simple-git
- 思考:marketplace 系统的"安全"应该在哪一层做?