dsh-config-manager 0.1.39 → 0.1.41

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.
Files changed (50) hide show
  1. package/lib/client.d.ts +90 -8
  2. package/lib/client.js +1904 -1086
  3. package/lib/client.js.map +1 -1
  4. package/lib/core/cache-cleaner.d.ts +39 -0
  5. package/lib/core/cache-cleaner.js +164 -0
  6. package/lib/core/cache-cleaner.js.map +1 -0
  7. package/lib/index.js +172 -3
  8. package/lib/index.js.map +1 -1
  9. package/lib/market/github-repos.d.ts +19 -8
  10. package/lib/market/github-repos.js +62 -33
  11. package/lib/market/github-repos.js.map +1 -1
  12. package/lib/market/my-repo.d.ts +111 -3
  13. package/lib/market/my-repo.js +309 -26
  14. package/lib/market/my-repo.js.map +1 -1
  15. package/lib/market/prepare.js +3 -2
  16. package/lib/market/prepare.js.map +1 -1
  17. package/lib/market/types.d.ts +2 -0
  18. package/lib/security/secret-scanner.d.ts +18 -3
  19. package/lib/security/secret-scanner.js +144 -20
  20. package/lib/security/secret-scanner.js.map +1 -1
  21. package/package.json +1 -1
  22. package/src/client/common/ConfirmDialog.tsx +135 -0
  23. package/src/client/config-manager.module.css +101 -0
  24. package/src/client/market/MarketPanel.tsx +138 -45
  25. package/src/client/market/MyConfigsView.tsx +515 -132
  26. package/src/client/market/disclaimer.test.ts +57 -0
  27. package/src/client/market/disclaimer.ts +43 -0
  28. package/src/client/market/market-api.test.ts +3 -0
  29. package/src/client/market/market-locales.ts +37 -13
  30. package/src/client/market/my-configs-api.ts +20 -2
  31. package/src/client/market/my-configs-view.test.ts +137 -2
  32. package/src/client/market/my-configs-view.ts +174 -2
  33. package/src/client/run-store.test.ts +40 -2
  34. package/src/client/run-store.ts +70 -10
  35. package/src/client/sync/SyncConfirmView.tsx +28 -22
  36. package/src/client/sync/SyncSettingsView.tsx +175 -65
  37. package/src/client/sync/sync-api.ts +19 -0
  38. package/src/client/sync/sync-locales.ts +14 -2
  39. package/src/core/cache-cleaner.test.ts +333 -0
  40. package/src/core/cache-cleaner.ts +196 -0
  41. package/src/index.ts +165 -5
  42. package/src/market/github-repos.test.ts +99 -8
  43. package/src/market/github-repos.ts +67 -35
  44. package/src/market/my-repo.test.ts +218 -27
  45. package/src/market/my-repo.ts +403 -30
  46. package/src/market/prepare.test.ts +71 -1
  47. package/src/market/prepare.ts +3 -2
  48. package/src/market/types.ts +2 -0
  49. package/src/security/secret-scanner.ts +139 -22
  50. package/src/security/security.test.ts +111 -2
package/lib/client.d.ts CHANGED
@@ -962,6 +962,17 @@ interface GithubPollResponse {
962
962
  /** success 时恒 true(凭据已配置);便于 UI 直接刷新状态 */
963
963
  credentialConfigured?: boolean;
964
964
  }
965
+ /** POST /sync/github/validate 响应:token 是否已配置 + 是否有效(GET /user;
966
+ * 401 → 无效)。只回布尔 + 登录名(非敏感),token 值永不回传浏览器。 */
967
+ interface GithubValidateResponse {
968
+ ok: boolean;
969
+ /** token 是否存在于 DSH credentials */
970
+ configured: boolean;
971
+ /** token 是否有效(GitHub GET /user 成功;configured=false 时恒 false) */
972
+ valid: boolean;
973
+ /** GitHub 登录名(valid=true 时;非敏感展示位) */
974
+ login?: string;
975
+ }
965
976
  /** 远程同步浏览器半数据入口(备份与迁移页第 4 个 tab 的注入业务面) */
966
977
  declare class SyncApi {
967
978
  readonly t: UiT;
@@ -980,6 +991,9 @@ declare class SyncApi {
980
991
  githubCancel(flowId: string): Promise<{
981
992
  ok: boolean;
982
993
  }>;
994
+ /** GitHub token 有效性校验(判定「是否已登录」:token 存在且 GitHub API 接受;
995
+ * 401 → valid:false 引导重新登录;非 401 错误向上抛,UI 兜底不误判登出) */
996
+ githubValidate(): Promise<GithubValidateResponse>;
983
997
  /** 同步历史:列出本地祖先快照 + 自动同步执行记录(按 createdAt 倒序合并)。 */
984
998
  history(): Promise<SyncHistoryResponse>;
985
999
  /** 远端历史快照列表(供「选择历史快照」下拉)。 */
@@ -1110,6 +1124,8 @@ interface MarketStatusResponse {
1110
1124
  /** 是否已添加过至少一个市场 */
1111
1125
  configured: boolean;
1112
1126
  markets: MarketSummary[];
1127
+ /** 本次 dsh 启动后市场是否已刷新过(首次打开市场页自动更新一次的依据;进程内存,dsh 重启后重置) */
1128
+ bootAutoRefreshed?: boolean;
1113
1129
  }
1114
1130
  /** POST /market/refresh 响应:{ ok, items, market } */
1115
1131
  interface MarketRefreshResponse {
@@ -1184,10 +1200,21 @@ type MyItemStatus = 'not-listed' | 'pr-pending' | 'listed';
1184
1200
  interface MyRepoForm {
1185
1201
  /** 配置名(预填 zip 文件名,可改);id 由其派生稳定 slug */
1186
1202
  name: string;
1203
+ /** 显式目标条目 id(**仅 update 模式**用:由列表「更新」按钮预填,避免靠 name→slug 猜测匹配;
1204
+ * 上传(新条目)时省略;后端校验存在性,缺省回退 name slug 匹配(向后兼容) */
1205
+ id?: string;
1187
1206
  description?: string;
1188
1207
  categories?: string[];
1189
1208
  }
1190
- /** upload / update 返回(ok=false 时携带已脱敏 error + errorCode) */
1209
+ /** 收录流程状态:pending=已提交、后台处理中;done=已提交收录(PR 已开/复用);failed=收录失败可重试 */
1210
+ type ListingState = 'pending' | 'done' | 'failed';
1211
+ /**
1212
+ * upload / update 返回(ok=false 时携带已脱敏 error + errorCode)。
1213
+ * 流程拆分(2026-08-20 优化):upload/update 只同步执行「推用户仓库」并立即返回
1214
+ * (listing='pending'),「收录流程」(fork + 官方 index + PR)在后台异步执行,
1215
+ * 避免 GitHub fork 排队时整个上传请求长时间挂起;收录结果经 listingStatus /
1216
+ * /me/items 状态徽章查询。
1217
+ */
1191
1218
  interface UploadResult {
1192
1219
  ok: boolean;
1193
1220
  itemId: string;
@@ -1196,14 +1223,47 @@ interface UploadResult {
1196
1223
  sections: SectionId[];
1197
1224
  /** 用户公开仓库 URL(https://github.com/<login>/dsh-configs) */
1198
1225
  repoUrl: string;
1226
+ /** 收录 PR 编号(异步模式下收起完成前为 null;完成经 listingStatus 查询) */
1199
1227
  prNumber: number | null;
1228
+ /** 收录 PR 链接(同上) */
1200
1229
  prUrl: string | null;
1201
1230
  warnings: string[];
1231
+ /** 收录流程状态:ok=true 且上传成功后为 'pending'(后台进行中);失败无收录流程时 'done' 无意义 */
1232
+ listing: ListingState;
1233
+ /** listing='failed' 时:收录失败原因(已脱敏,含重试指引) */
1234
+ listingError?: string;
1202
1235
  /** ok=false 时:可展示错误(已脱敏,无 token 形态) */
1203
1236
  error?: string;
1204
1237
  /** ok=false 时:错误分类码(unauthorized/prepare_failed/...;无则 'internal') */
1205
1238
  errorCode?: string;
1206
1239
  }
1240
+ /** POST /me/listing 响应:收录任务状态(结果卡轮询用,比拉全列表更轻) */
1241
+ interface ListingStatusResponse {
1242
+ itemId: string;
1243
+ listing: ListingState;
1244
+ /** listing='done' 时:PR 编号 */
1245
+ prNumber: number | null;
1246
+ /** listing='done' 时:PR 链接 */
1247
+ prUrl: string | null;
1248
+ /** listing='failed' 时:失败原因(已脱敏) */
1249
+ error?: string;
1250
+ }
1251
+ /** POST /me/delete 响应:删除条目结果 */
1252
+ interface DeleteResult {
1253
+ ok: boolean;
1254
+ itemId: string;
1255
+ /** 是否已异步提交「下架 PR」(条目此前已收录进官方市场时 true) */
1256
+ delisted: boolean;
1257
+ /** 被关闭的收录 PR(条目处于待审核、有 open PR 时关闭它) */
1258
+ prNumber: number | null;
1259
+ /** 被关闭 PR 的链接(同上) */
1260
+ prUrl: string | null;
1261
+ warnings: string[];
1262
+ /** ok=false 时:可展示错误(已脱敏) */
1263
+ error?: string;
1264
+ /** ok=false 时:错误分类码(item_not_found/unauthorized/...) */
1265
+ errorCode?: string;
1266
+ }
1207
1267
  /** listItems 条目:用户仓库 index.json 条目 + 收录状态 */
1208
1268
  interface MyItemEntry {
1209
1269
  id: string;
@@ -1273,6 +1333,12 @@ declare class MyConfigsApi {
1273
1333
  zipPath: string;
1274
1334
  form: MyConfigsFormPayload;
1275
1335
  }): Promise<MyUploadResult>;
1336
+ /** 查询收录/下架任务状态(结果卡轮询;任务表未命中时 Host 回退 GitHub 实况推导;无任务无实况 → null) */
1337
+ meListing(itemId: string): Promise<ListingStatusResponse | null>;
1338
+ /** 重新提交收录(失败/重启丢失后重试;幂等复用已存在 fork/open PR) */
1339
+ meRelist(itemId: string): Promise<ListingStatusResponse>;
1340
+ /** 删除条目(同步删本地索引+文件;已收录自动后台提下架 PR;待审核自动关闭收录 PR) */
1341
+ meDelete(itemId: string): Promise<DeleteResult>;
1276
1342
  }
1277
1343
  //#endregion
1278
1344
  //#region src/client/client-types.d.ts
@@ -1461,10 +1527,14 @@ declare const zh$1: {
1461
1527
  readonly 'config.saving': "保存中…";
1462
1528
  readonly 'config.saveHint': "表单改动会自动保存(密码/token 安全写入 DSH credentials,不会写入同步文件或日志);也可点击按钮立即保存。";
1463
1529
  readonly 'channel.title': "同步通道";
1464
- readonly 'channel.hint': "选择远程同步通道:Git 私有仓库或 WebDAV 服务器。";
1465
1530
  readonly 'channel.git': "Git 私有仓库";
1466
1531
  readonly 'channel.webdav': "WebDAV 服务器";
1467
1532
  readonly 'channel.perChannelHint': "GitHub 与 WebDAV 通道的自动同步、同步模式、加密与远端快照各自独立配置。";
1533
+ readonly 'channel.open': "配置同步通道";
1534
+ readonly 'channel.openHint': "远程同步通过「同步通道」进行:Git 私有仓库或 WebDAV 服务器。点击按钮在弹窗中配置或修改。";
1535
+ readonly 'channel.configured': "已配置";
1536
+ readonly 'channel.notConfigured': "未配置";
1537
+ readonly 'channel.currentUrl': "当前地址";
1468
1538
  readonly 'webdav.title': "WebDAV 配置";
1469
1539
  readonly 'webdav.url': "服务器地址";
1470
1540
  readonly 'webdav.urlHint': "WebDAV 服务器根地址(https://…)。同步快照与索引存放于该地址的 snapshots/ 子目录下。请勿在地址中包含用户名/密码。";
@@ -1480,6 +1550,7 @@ declare const zh$1: {
1480
1550
  readonly 'github.login': "使用 GitHub 登录";
1481
1551
  readonly 'github.retry': "重新登录";
1482
1552
  readonly 'github.cancel': "取消";
1553
+ readonly 'github.tokenInvalid': "GitHub 登录已失效,请重新登录。";
1483
1554
  readonly 'github.userCode': "一次性授权代码";
1484
1555
  readonly 'github.openAuth': "打开 GitHub 授权页面";
1485
1556
  readonly 'github.clientIdHint': "需要插件配置 githubClientId(GitHub OAuth App 的 client_id)才能使用 GitHub 登录。";
@@ -1628,14 +1699,8 @@ declare const zh: {
1628
1699
  readonly 'section.label': "配置市场";
1629
1700
  readonly 'section.description': "浏览并下载社区共享的配置(公开 Git 仓库;下载内容一律视为不可信,导入前必经校验与确认)";
1630
1701
  readonly 'config.title': "市场仓库";
1631
- readonly 'config.builtinHint': "内置官方市场,只读、不可编辑(由创建者维护的公开 Git 仓库)。";
1632
- readonly 'config.official': "内置官方市场";
1633
- readonly 'config.custom': "自定义市场地址";
1634
- readonly 'config.repoUrlHint': "内置公开 Git 仓库地址。市场只读拉取(绝不推送)。";
1635
1702
  readonly 'config.refresh': "拉取最新";
1636
1703
  readonly 'config.refreshing': "拉取中…";
1637
- readonly 'config.addedAt': "更新于:{time}";
1638
- readonly 'config.itemCount': "{count} 个条目";
1639
1704
  readonly 'list.empty': "内置市场尚未加载。请先「拉取最新」。";
1640
1705
  readonly 'list.browse': "浏览";
1641
1706
  readonly 'list.loading': "正在读取市场…";
@@ -1702,6 +1767,8 @@ declare const zh: {
1702
1767
  readonly 'myconfigs.update.hint': "版本将自动 +1,已预填原条目信息(名称可改)。";
1703
1768
  readonly 'myconfigs.update.run': "一键更新";
1704
1769
  readonly 'myconfigs.update.running': "更新中…";
1770
+ readonly 'myconfigs.update.zipHint': "更新需要新的配置包:选择新 zip 后自动校验,通过后即可一键更新。";
1771
+ readonly 'myconfigs.update.selectZip': "选择新 ZIP…";
1705
1772
  readonly 'myconfigs.result.title': "上传/更新完成";
1706
1773
  readonly 'myconfigs.result.version': "版本 {version}";
1707
1774
  readonly 'myconfigs.result.sha256': "SHA-256:{hash}";
@@ -1710,6 +1777,9 @@ declare const zh: {
1710
1777
  readonly 'myconfigs.result.openRepo': "打开仓库";
1711
1778
  readonly 'myconfigs.result.pr': "收录 PR #{number}";
1712
1779
  readonly 'myconfigs.result.openPr': "查看 PR";
1780
+ readonly 'myconfigs.result.listingPending': "已上传 ✓ 正在后台提交收录(fork + 收录 PR),稍后列表状态自动更新";
1781
+ readonly 'myconfigs.result.listingFailed': "收录失败";
1782
+ readonly 'myconfigs.result.relist': "重新提交收录";
1713
1783
  readonly 'myconfigs.list.title': "已上传";
1714
1784
  readonly 'myconfigs.list.empty': "尚未上传任何配置";
1715
1785
  readonly 'myconfigs.list.loading': "正在读取…";
@@ -1719,6 +1789,18 @@ declare const zh: {
1719
1789
  readonly 'myconfigs.item.update': "更新";
1720
1790
  readonly 'myconfigs.item.install': "装回本地";
1721
1791
  readonly 'myconfigs.item.openPr': "查看收录 PR";
1792
+ readonly 'myconfigs.delete.run': "删除";
1793
+ readonly 'myconfigs.delete.confirm': "确认删除";
1794
+ readonly 'myconfigs.delete.confirmTitle': "删除条目";
1795
+ readonly 'myconfigs.delete.confirmText': "确认删除?该操作会从配置仓库永久删除该条目的索引与文件(不可恢复)";
1796
+ readonly 'myconfigs.delete.delistStarted': "已删除本地条目,并自动提交「下架 PR」(官方市场移除需人工合并,期间市场可能仍显示该条目)";
1797
+ readonly 'myconfigs.delete.prClosed': "已删除本地条目,并关闭该条目的待审核收录 PR";
1798
+ readonly 'disclaimer.title': "免责声明";
1799
+ readonly 'disclaimer.upload.text': "你即将把配置上传到你的公开仓库(<login>/dsh-configs)并提交官方市场收录申请。\n\n上传后内容将对所有人公开可见,且需经过人工审核才能进入官方市场。请确保:\n· 内容不包含任何真实密钥 / 凭据(环境变量引用如 $VAR 是安全的);\n· 内容不包含个人隐私或本地环境信息;\n· 你有权分享这些配置。";
1800
+ readonly 'disclaimer.download.text': "你即将从公共网络市场下载配置并导入本地。\n\n下载内容属于不可信输入:未经官方审核、可能包含风险(安装插件 / 写入文件 / 修改设置)。\n· 导入前会逐项展示并校验,高风险分区默认不导入、需逐项批准;\n· 导入会先自动创建快照,失败可回滚;\n· 请核对来源与内容后再确认导入。";
1801
+ readonly 'disclaimer.install.text': "你即将把配置从你的公开仓库装回本地。\n\n该内容属于你此前上传的配置,但同样会经过安全校验与逐分区批准:\n· 高风险分区默认不导入、需逐项批准;\n· 导入前自动创建快照,失败可回滚。";
1802
+ readonly 'disclaimer.confirm': "我已了解,继续";
1803
+ readonly 'disclaimer.dontAsk': "不再提示(该操作以后不再显示免责声明)";
1722
1804
  readonly 'myconfigs.error.loadStatus': "登录状态读取失败";
1723
1805
  readonly 'myconfigs.error.loadItems': "已上传列表读取失败";
1724
1806
  readonly 'common.cancel': "取消";