@logictan/dsh-config-manager 0.1.60

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 (429) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +105 -0
  3. package/cordis.patch.yml +21 -0
  4. package/lib/adapters/agent-instructions.d.ts +13 -0
  5. package/lib/adapters/agent-instructions.js +46 -0
  6. package/lib/adapters/agent-presets.d.ts +13 -0
  7. package/lib/adapters/agent-presets.js +14 -0
  8. package/lib/adapters/credentials.d.ts +37 -0
  9. package/lib/adapters/credentials.js +122 -0
  10. package/lib/adapters/file-collection.d.ts +15 -0
  11. package/lib/adapters/file-collection.js +127 -0
  12. package/lib/adapters/index.d.ts +57 -0
  13. package/lib/adapters/index.js +55 -0
  14. package/lib/adapters/link-report.d.ts +16 -0
  15. package/lib/adapters/link-report.js +47 -0
  16. package/lib/adapters/mcp.d.ts +28 -0
  17. package/lib/adapters/mcp.js +178 -0
  18. package/lib/adapters/plugin-files.d.ts +18 -0
  19. package/lib/adapters/plugin-files.js +142 -0
  20. package/lib/adapters/plugins.d.ts +41 -0
  21. package/lib/adapters/plugins.js +603 -0
  22. package/lib/adapters/pnpm-workspace.d.ts +26 -0
  23. package/lib/adapters/pnpm-workspace.js +147 -0
  24. package/lib/adapters/prompts.d.ts +30 -0
  25. package/lib/adapters/prompts.js +231 -0
  26. package/lib/adapters/providers.d.ts +34 -0
  27. package/lib/adapters/providers.js +155 -0
  28. package/lib/adapters/self.d.ts +17 -0
  29. package/lib/adapters/self.js +71 -0
  30. package/lib/adapters/sessions.d.ts +14 -0
  31. package/lib/adapters/sessions.js +15 -0
  32. package/lib/adapters/settings.d.ts +28 -0
  33. package/lib/adapters/settings.js +165 -0
  34. package/lib/adapters/skills.d.ts +13 -0
  35. package/lib/adapters/skills.js +14 -0
  36. package/lib/adapters/test-helpers.d.ts +125 -0
  37. package/lib/adapters/test-helpers.js +236 -0
  38. package/lib/adapters/ui.d.ts +27 -0
  39. package/lib/adapters/ui.js +89 -0
  40. package/lib/adapters/workspaces.d.ts +13 -0
  41. package/lib/adapters/workspaces.js +106 -0
  42. package/lib/client.d.ts +1026 -0
  43. package/lib/client.js +10047 -0
  44. package/lib/core/analyzer.d.ts +99 -0
  45. package/lib/core/analyzer.js +934 -0
  46. package/lib/core/backup.d.ts +138 -0
  47. package/lib/core/backup.js +513 -0
  48. package/lib/core/boot-rescue.d.ts +146 -0
  49. package/lib/core/boot-rescue.js +618 -0
  50. package/lib/core/cache-cleaner.d.ts +31 -0
  51. package/lib/core/cache-cleaner.js +95 -0
  52. package/lib/core/config-lifecycle.d.ts +180 -0
  53. package/lib/core/config-lifecycle.js +481 -0
  54. package/lib/core/config-snapshot.d.ts +135 -0
  55. package/lib/core/config-snapshot.js +424 -0
  56. package/lib/core/config-state.d.ts +70 -0
  57. package/lib/core/config-state.js +177 -0
  58. package/lib/core/consult-source.d.ts +58 -0
  59. package/lib/core/consult-source.js +260 -0
  60. package/lib/core/crash-report.d.ts +84 -0
  61. package/lib/core/crash-report.js +317 -0
  62. package/lib/core/exporter.d.ts +68 -0
  63. package/lib/core/exporter.js +375 -0
  64. package/lib/core/ghost-sweep.d.ts +19 -0
  65. package/lib/core/ghost-sweep.js +52 -0
  66. package/lib/core/importer.d.ts +60 -0
  67. package/lib/core/importer.js +29 -0
  68. package/lib/core/index.d.ts +14 -0
  69. package/lib/core/index.js +14 -0
  70. package/lib/core/journal.d.ts +197 -0
  71. package/lib/core/journal.js +418 -0
  72. package/lib/core/local-plugin-host.d.ts +35 -0
  73. package/lib/core/local-plugin-host.js +120 -0
  74. package/lib/core/local-plugin-pack.d.ts +135 -0
  75. package/lib/core/local-plugin-pack.js +278 -0
  76. package/lib/core/messages.d.ts +310 -0
  77. package/lib/core/messages.js +621 -0
  78. package/lib/core/migration-consult.d.ts +117 -0
  79. package/lib/core/migration-consult.js +363 -0
  80. package/lib/core/migration-history.d.ts +153 -0
  81. package/lib/core/migration-history.js +411 -0
  82. package/lib/core/model-tools.d.ts +50 -0
  83. package/lib/core/model-tools.js +148 -0
  84. package/lib/core/msg-types.d.ts +8 -0
  85. package/lib/core/msg-types.js +6 -0
  86. package/lib/core/phase3-child-crash.d.ts +1 -0
  87. package/lib/core/phase3-child-crash.js +87 -0
  88. package/lib/core/phase3-host.d.ts +138 -0
  89. package/lib/core/phase3-host.js +359 -0
  90. package/lib/core/phase3-prod-child.d.ts +1 -0
  91. package/lib/core/phase3-prod-child.js +35 -0
  92. package/lib/core/phase4-crash-child.d.ts +1 -0
  93. package/lib/core/phase4-crash-child.js +103 -0
  94. package/lib/core/plugin-cli.d.ts +150 -0
  95. package/lib/core/plugin-cli.js +497 -0
  96. package/lib/core/reconcile.d.ts +120 -0
  97. package/lib/core/reconcile.js +389 -0
  98. package/lib/core/recovery-orchestrator.d.ts +94 -0
  99. package/lib/core/recovery-orchestrator.js +327 -0
  100. package/lib/core/restore.d.ts +162 -0
  101. package/lib/core/restore.js +703 -0
  102. package/lib/core/rollback.d.ts +12 -0
  103. package/lib/core/rollback.js +145 -0
  104. package/lib/core/run-registry.d.ts +85 -0
  105. package/lib/core/run-registry.js +157 -0
  106. package/lib/core/startup-barrier.d.ts +53 -0
  107. package/lib/core/startup-barrier.js +77 -0
  108. package/lib/core/types.d.ts +515 -0
  109. package/lib/core/types.js +27 -0
  110. package/lib/core/undo.d.ts +73 -0
  111. package/lib/core/undo.js +87 -0
  112. package/lib/core/validator.d.ts +18 -0
  113. package/lib/core/validator.js +77 -0
  114. package/lib/core/verify-recovery.d.ts +21 -0
  115. package/lib/core/verify-recovery.js +256 -0
  116. package/lib/core/watcher.d.ts +101 -0
  117. package/lib/core/watcher.js +219 -0
  118. package/lib/index.d.ts +238 -0
  119. package/lib/index.js +2764 -0
  120. package/lib/migrations/index.d.ts +29 -0
  121. package/lib/migrations/index.js +56 -0
  122. package/lib/migrations/v1-to-v2.d.ts +9 -0
  123. package/lib/migrations/v1-to-v2.js +10 -0
  124. package/lib/profiles/index.d.ts +4 -0
  125. package/lib/profiles/index.js +5 -0
  126. package/lib/profiles/profile-manager.d.ts +106 -0
  127. package/lib/profiles/profile-manager.js +543 -0
  128. package/lib/schema/config.d.ts +28 -0
  129. package/lib/schema/config.js +165 -0
  130. package/lib/schema/index.d.ts +24 -0
  131. package/lib/schema/index.js +26 -0
  132. package/lib/schema/manifest.d.ts +28 -0
  133. package/lib/schema/manifest.js +109 -0
  134. package/lib/schema/tombstones.d.ts +46 -0
  135. package/lib/schema/tombstones.js +64 -0
  136. package/lib/schema/types.d.ts +232 -0
  137. package/lib/schema/types.js +8 -0
  138. package/lib/schema/versions.d.ts +27 -0
  139. package/lib/schema/versions.js +50 -0
  140. package/lib/security/encryption.d.ts +85 -0
  141. package/lib/security/encryption.js +279 -0
  142. package/lib/security/index.d.ts +16 -0
  143. package/lib/security/index.js +17 -0
  144. package/lib/security/integrity.d.ts +30 -0
  145. package/lib/security/integrity.js +78 -0
  146. package/lib/security/redaction.d.ts +26 -0
  147. package/lib/security/redaction.js +95 -0
  148. package/lib/security/secret-scanner.d.ts +86 -0
  149. package/lib/security/secret-scanner.js +404 -0
  150. package/lib/security/vault.d.ts +59 -0
  151. package/lib/security/vault.js +151 -0
  152. package/lib/security/zip-security.d.ts +27 -0
  153. package/lib/security/zip-security.js +154 -0
  154. package/lib/sync/autosync-config.d.ts +39 -0
  155. package/lib/sync/autosync-config.js +151 -0
  156. package/lib/sync/autosync-scheduler.d.ts +139 -0
  157. package/lib/sync/autosync-scheduler.js +564 -0
  158. package/lib/sync/fs.d.ts +18 -0
  159. package/lib/sync/fs.js +49 -0
  160. package/lib/sync/git/git-transport.d.ts +100 -0
  161. package/lib/sync/git/git-transport.js +437 -0
  162. package/lib/sync/github-auth.d.ts +131 -0
  163. package/lib/sync/github-auth.js +264 -0
  164. package/lib/sync/layout.d.ts +43 -0
  165. package/lib/sync/layout.js +203 -0
  166. package/lib/sync/snapshot-json.d.ts +9 -0
  167. package/lib/sync/snapshot-json.js +107 -0
  168. package/lib/sync/sync-config.d.ts +81 -0
  169. package/lib/sync/sync-config.js +281 -0
  170. package/lib/sync/sync-engine.d.ts +269 -0
  171. package/lib/sync/sync-engine.js +591 -0
  172. package/lib/sync/sync-history.d.ts +42 -0
  173. package/lib/sync/sync-history.js +78 -0
  174. package/lib/sync/sync-selection.d.ts +29 -0
  175. package/lib/sync/sync-selection.js +127 -0
  176. package/lib/sync/sync-session.d.ts +40 -0
  177. package/lib/sync/sync-session.js +54 -0
  178. package/lib/sync/sync-state.d.ts +37 -0
  179. package/lib/sync/sync-state.js +108 -0
  180. package/lib/sync/transport.d.ts +75 -0
  181. package/lib/sync/transport.js +55 -0
  182. package/lib/sync/ui-prefs.d.ts +34 -0
  183. package/lib/sync/ui-prefs.js +109 -0
  184. package/lib/sync/webdav/webdav-transport.d.ts +77 -0
  185. package/lib/sync/webdav/webdav-transport.js +451 -0
  186. package/lib/ui/errors.d.ts +19 -0
  187. package/lib/ui/errors.js +81 -0
  188. package/lib/ui/export-flow.d.ts +82 -0
  189. package/lib/ui/export-flow.js +98 -0
  190. package/lib/ui/i18n.d.ts +289 -0
  191. package/lib/ui/i18n.js +581 -0
  192. package/lib/ui/migration-consult-view.d.ts +91 -0
  193. package/lib/ui/migration-consult-view.js +115 -0
  194. package/lib/ui/progress.d.ts +38 -0
  195. package/lib/ui/progress.js +87 -0
  196. package/lib/ui/report.d.ts +23 -0
  197. package/lib/ui/report.js +153 -0
  198. package/lib/ui/test-helpers.d.ts +69 -0
  199. package/lib/ui/test-helpers.js +154 -0
  200. package/lib/ui/types.d.ts +257 -0
  201. package/lib/ui/types.js +21 -0
  202. package/lib/utils/atomic-write.d.ts +88 -0
  203. package/lib/utils/atomic-write.js +399 -0
  204. package/lib/utils/env-lock.d.ts +393 -0
  205. package/lib/utils/env-lock.js +930 -0
  206. package/lib/utils/hashing.d.ts +17 -0
  207. package/lib/utils/hashing.js +41 -0
  208. package/lib/utils/json.d.ts +24 -0
  209. package/lib/utils/json.js +76 -0
  210. package/lib/utils/logger.d.ts +39 -0
  211. package/lib/utils/logger.js +82 -0
  212. package/lib/utils/paths.d.ts +42 -0
  213. package/lib/utils/paths.js +189 -0
  214. package/lib/utils/proxy.d.ts +69 -0
  215. package/lib/utils/proxy.js +455 -0
  216. package/lib/utils/recursive-walk.d.ts +24 -0
  217. package/lib/utils/recursive-walk.js +134 -0
  218. package/lib/utils/zip.d.ts +54 -0
  219. package/lib/utils/zip.js +285 -0
  220. package/package.json +188 -0
  221. package/src/adapters/agent-instructions.ts +48 -0
  222. package/src/adapters/agent-presets.ts +14 -0
  223. package/src/adapters/credentials.test.ts +90 -0
  224. package/src/adapters/credentials.ts +143 -0
  225. package/src/adapters/file-collection.ts +137 -0
  226. package/src/adapters/files.test.ts +353 -0
  227. package/src/adapters/index.ts +94 -0
  228. package/src/adapters/link-report.test.ts +65 -0
  229. package/src/adapters/link-report.ts +61 -0
  230. package/src/adapters/mcp.test.ts +96 -0
  231. package/src/adapters/mcp.ts +185 -0
  232. package/src/adapters/plugin-files.ts +146 -0
  233. package/src/adapters/plugins.test.ts +326 -0
  234. package/src/adapters/plugins.ts +615 -0
  235. package/src/adapters/pnpm-workspace.test.ts +87 -0
  236. package/src/adapters/pnpm-workspace.ts +150 -0
  237. package/src/adapters/prompts.test.ts +110 -0
  238. package/src/adapters/prompts.ts +230 -0
  239. package/src/adapters/providers.test.ts +126 -0
  240. package/src/adapters/providers.ts +173 -0
  241. package/src/adapters/roundtrip.test.ts +190 -0
  242. package/src/adapters/self.test.ts +92 -0
  243. package/src/adapters/self.ts +75 -0
  244. package/src/adapters/sessions.ts +15 -0
  245. package/src/adapters/settings.test.ts +100 -0
  246. package/src/adapters/settings.ts +187 -0
  247. package/src/adapters/skills.ts +14 -0
  248. package/src/adapters/test-helpers.ts +248 -0
  249. package/src/adapters/ui.test.ts +57 -0
  250. package/src/adapters/ui.ts +108 -0
  251. package/src/adapters/workspaces.test.ts +106 -0
  252. package/src/adapters/workspaces.ts +109 -0
  253. package/src/client/ConfigManagerSection.tsx +90 -0
  254. package/src/client/api.ts +66 -0
  255. package/src/client/client-types.ts +18 -0
  256. package/src/client/common/ErrorBanner.tsx +73 -0
  257. package/src/client/common/Icon.tsx +129 -0
  258. package/src/client/common/Modal.tsx +173 -0
  259. package/src/client/common/ToastViewport.tsx +73 -0
  260. package/src/client/common/toast-store.test.ts +192 -0
  261. package/src/client/common/toast-store.ts +181 -0
  262. package/src/client/common/toast-types.ts +7 -0
  263. package/src/client/common/ui.tsx +342 -0
  264. package/src/client/config-manager.module.css +2971 -0
  265. package/src/client/css-modules.d.ts +8 -0
  266. package/src/client/index.ts +65 -0
  267. package/src/client/locales.ts +56 -0
  268. package/src/client/lucide-icons.d.ts +38 -0
  269. package/src/client/run-store.test.ts +223 -0
  270. package/src/client/run-store.ts +372 -0
  271. package/src/client/sync/SyncConfirmView.tsx +379 -0
  272. package/src/client/sync/SyncHistoryView.test.ts +40 -0
  273. package/src/client/sync/SyncHistoryView.tsx +220 -0
  274. package/src/client/sync/SyncSettingsView.tsx +1535 -0
  275. package/src/client/sync/history-model.test.ts +194 -0
  276. package/src/client/sync/history-model.ts +195 -0
  277. package/src/client/sync/sync-api.test.ts +585 -0
  278. package/src/client/sync/sync-api.ts +543 -0
  279. package/src/client/sync/sync-locales.ts +416 -0
  280. package/src/client/sync/sync-push-preview.test.ts +52 -0
  281. package/src/client/sync/sync-view-v2.test.ts +213 -0
  282. package/src/client/sync/sync-view.test.ts +487 -0
  283. package/src/client/sync/sync-view.ts +759 -0
  284. package/src/core/analyzer.ts +1068 -0
  285. package/src/core/backup.ts +605 -0
  286. package/src/core/boot-rescue.test.ts +847 -0
  287. package/src/core/boot-rescue.ts +737 -0
  288. package/src/core/cache-cleaner.test.ts +169 -0
  289. package/src/core/cache-cleaner.ts +121 -0
  290. package/src/core/config-lifecycle.test.ts +727 -0
  291. package/src/core/config-lifecycle.ts +573 -0
  292. package/src/core/config-snapshot.test.ts +369 -0
  293. package/src/core/config-snapshot.ts +522 -0
  294. package/src/core/config-state.test.ts +381 -0
  295. package/src/core/config-state.ts +207 -0
  296. package/src/core/consult-source.test.ts +199 -0
  297. package/src/core/consult-source.ts +293 -0
  298. package/src/core/crash-report.test.ts +380 -0
  299. package/src/core/crash-report.ts +369 -0
  300. package/src/core/exporter.ts +417 -0
  301. package/src/core/ghost-sweep.test.ts +94 -0
  302. package/src/core/ghost-sweep.ts +67 -0
  303. package/src/core/importer.ts +83 -0
  304. package/src/core/index.ts +56 -0
  305. package/src/core/journal.test.ts +257 -0
  306. package/src/core/journal.ts +518 -0
  307. package/src/core/local-plugin-host.ts +152 -0
  308. package/src/core/local-plugin-pack.test.ts +359 -0
  309. package/src/core/local-plugin-pack.ts +363 -0
  310. package/src/core/messages.test.ts +54 -0
  311. package/src/core/messages.ts +664 -0
  312. package/src/core/migration-consult.test.ts +315 -0
  313. package/src/core/migration-consult.ts +494 -0
  314. package/src/core/migration-history.test.ts +319 -0
  315. package/src/core/migration-history.ts +484 -0
  316. package/src/core/model-tools.test.ts +190 -0
  317. package/src/core/model-tools.ts +208 -0
  318. package/src/core/msg-types.ts +10 -0
  319. package/src/core/phase3-child-crash.ts +95 -0
  320. package/src/core/phase3-host.ts +411 -0
  321. package/src/core/phase3-p1.test.ts +212 -0
  322. package/src/core/phase3-p2b-fingerprint.test.ts +189 -0
  323. package/src/core/phase3-prod-child.ts +36 -0
  324. package/src/core/phase3-production-integration.test.ts +286 -0
  325. package/src/core/phase4-crash-child.ts +101 -0
  326. package/src/core/phase4-crash-injection.test.ts +166 -0
  327. package/src/core/plugin-cli.fs.test.ts +184 -0
  328. package/src/core/plugin-cli.test.ts +137 -0
  329. package/src/core/plugin-cli.ts +563 -0
  330. package/src/core/reconcile.test.ts +392 -0
  331. package/src/core/reconcile.ts +498 -0
  332. package/src/core/recovery-orchestrator.test.ts +145 -0
  333. package/src/core/recovery-orchestrator.ts +366 -0
  334. package/src/core/restore-manage.test.ts +94 -0
  335. package/src/core/restore.ts +849 -0
  336. package/src/core/rollback.ts +151 -0
  337. package/src/core/run-progress.test.ts +237 -0
  338. package/src/core/run-registry.test.ts +232 -0
  339. package/src/core/run-registry.ts +209 -0
  340. package/src/core/smoke.test.ts +842 -0
  341. package/src/core/startup-barrier.ts +99 -0
  342. package/src/core/types.ts +542 -0
  343. package/src/core/undo.ts +116 -0
  344. package/src/core/validator.ts +84 -0
  345. package/src/core/verify-recovery.ts +265 -0
  346. package/src/core/watcher.test.ts +326 -0
  347. package/src/core/watcher.ts +263 -0
  348. package/src/index.facade.test.ts +265 -0
  349. package/src/index.sync.test.ts +217 -0
  350. package/src/index.ts +2975 -0
  351. package/src/migrations/index.ts +71 -0
  352. package/src/migrations/v1-to-v2.ts +17 -0
  353. package/src/profiles/index.ts +8 -0
  354. package/src/profiles/profile-manager.test.ts +282 -0
  355. package/src/profiles/profile-manager.ts +630 -0
  356. package/src/schema/config.ts +165 -0
  357. package/src/schema/index.ts +71 -0
  358. package/src/schema/manifest-schema.test.ts +519 -0
  359. package/src/schema/manifest.ts +124 -0
  360. package/src/schema/tombstones.test.ts +131 -0
  361. package/src/schema/tombstones.ts +89 -0
  362. package/src/schema/types.ts +245 -0
  363. package/src/schema/versions.ts +55 -0
  364. package/src/security/encryption.ts +335 -0
  365. package/src/security/index.ts +16 -0
  366. package/src/security/integrity.ts +102 -0
  367. package/src/security/redaction.ts +101 -0
  368. package/src/security/secret-scanner.ts +445 -0
  369. package/src/security/security.test.ts +1215 -0
  370. package/src/security/vault.test.ts +164 -0
  371. package/src/security/vault.ts +198 -0
  372. package/src/security/zip-security.ts +180 -0
  373. package/src/sync/autosync-config.test.ts +147 -0
  374. package/src/sync/autosync-config.ts +179 -0
  375. package/src/sync/autosync-scheduler.test.ts +490 -0
  376. package/src/sync/autosync-scheduler.ts +646 -0
  377. package/src/sync/fs.ts +48 -0
  378. package/src/sync/git/git-transport.test.ts +673 -0
  379. package/src/sync/git/git-transport.ts +491 -0
  380. package/src/sync/github-auth.test.ts +280 -0
  381. package/src/sync/github-auth.ts +356 -0
  382. package/src/sync/layout.test.ts +270 -0
  383. package/src/sync/layout.ts +222 -0
  384. package/src/sync/snapshot-json.test.ts +119 -0
  385. package/src/sync/snapshot-json.ts +128 -0
  386. package/src/sync/sync-config.test.ts +310 -0
  387. package/src/sync/sync-config.ts +299 -0
  388. package/src/sync/sync-engine.test.ts +1074 -0
  389. package/src/sync/sync-engine.ts +754 -0
  390. package/src/sync/sync-history.test.ts +116 -0
  391. package/src/sync/sync-history.ts +120 -0
  392. package/src/sync/sync-selection.test.ts +186 -0
  393. package/src/sync/sync-selection.ts +143 -0
  394. package/src/sync/sync-session.test.ts +143 -0
  395. package/src/sync/sync-session.ts +77 -0
  396. package/src/sync/sync-state.test.ts +164 -0
  397. package/src/sync/sync-state.ts +131 -0
  398. package/src/sync/transport.test.ts +111 -0
  399. package/src/sync/transport.ts +118 -0
  400. package/src/sync/ui-prefs.test.ts +152 -0
  401. package/src/sync/ui-prefs.ts +135 -0
  402. package/src/sync/webdav/webdav-transport.test.ts +871 -0
  403. package/src/sync/webdav/webdav-transport.ts +535 -0
  404. package/src/ui/errors.test.ts +47 -0
  405. package/src/ui/errors.ts +100 -0
  406. package/src/ui/export-flow.test.ts +87 -0
  407. package/src/ui/export-flow.ts +156 -0
  408. package/src/ui/i18n.ts +590 -0
  409. package/src/ui/migration-consult-view.test.ts +151 -0
  410. package/src/ui/migration-consult-view.ts +178 -0
  411. package/src/ui/progress.test.ts +47 -0
  412. package/src/ui/progress.ts +102 -0
  413. package/src/ui/report.test.ts +101 -0
  414. package/src/ui/report.ts +146 -0
  415. package/src/ui/test-helpers.ts +184 -0
  416. package/src/ui/types.ts +325 -0
  417. package/src/utils/atomic-write.test.ts +312 -0
  418. package/src/utils/atomic-write.ts +422 -0
  419. package/src/utils/env-lock.test.ts +999 -0
  420. package/src/utils/env-lock.ts +1086 -0
  421. package/src/utils/hashing.ts +53 -0
  422. package/src/utils/json.ts +77 -0
  423. package/src/utils/logger.ts +114 -0
  424. package/src/utils/paths.ts +176 -0
  425. package/src/utils/proxy.test.ts +465 -0
  426. package/src/utils/proxy.ts +493 -0
  427. package/src/utils/recursive-walk.test.ts +148 -0
  428. package/src/utils/recursive-walk.ts +145 -0
  429. package/src/utils/zip.ts +332 -0
@@ -0,0 +1,17 @@
1
+ export declare function sha256Hex(data: Uint8Array | string): string;
2
+ export declare function hashFile(filePath: string): Promise<string>;
3
+ /** 生成一组 ZIP 相对路径 → SHA-256 的校验表(路径必须为 ZIP 内正斜杠相对路径) */
4
+ export declare function buildChecksums(entries: {
5
+ name: string;
6
+ data: Uint8Array;
7
+ }[]): Record<string, string>;
8
+ export interface ChecksumVerifyResult {
9
+ ok: boolean;
10
+ mismatches: string[];
11
+ missing: string[];
12
+ }
13
+ /**
14
+ * 校验:checksums 表内每个相对路径必须在 entries 中存在且 SHA-256 一致。
15
+ * entries 中多余的文件(如 manifest.json / checksums.json 自身)不参与校验。
16
+ */
17
+ export declare function verifyChecksums(entries: ReadonlyMap<string, Uint8Array>, checksums: Record<string, string>): ChecksumVerifyResult;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * SHA-256 完整性工具(integrity/checksums.json 的生成与校验)。
3
+ * m4 的 security/integrity.ts 可在此之上强化(本模块已实现规范 §18 全部语义)。
4
+ */
5
+ import crypto from 'node:crypto';
6
+ import fs from 'node:fs/promises';
7
+ export function sha256Hex(data) {
8
+ return crypto.createHash('sha256').update(data).digest('hex');
9
+ }
10
+ export async function hashFile(filePath) {
11
+ const data = await fs.readFile(filePath);
12
+ return sha256Hex(data);
13
+ }
14
+ /** 生成一组 ZIP 相对路径 → SHA-256 的校验表(路径必须为 ZIP 内正斜杠相对路径) */
15
+ export function buildChecksums(entries) {
16
+ const checksums = {};
17
+ for (const e of entries) {
18
+ checksums[e.name] = sha256Hex(e.data);
19
+ }
20
+ return checksums;
21
+ }
22
+ /**
23
+ * 校验:checksums 表内每个相对路径必须在 entries 中存在且 SHA-256 一致。
24
+ * entries 中多余的文件(如 manifest.json / checksums.json 自身)不参与校验。
25
+ */
26
+ export function verifyChecksums(entries, checksums) {
27
+ const mismatches = [];
28
+ const missing = [];
29
+ for (const [relPath, expected] of Object.entries(checksums)) {
30
+ const data = entries.get(relPath);
31
+ if (data === undefined) {
32
+ missing.push(relPath);
33
+ continue;
34
+ }
35
+ if (sha256Hex(data) !== expected) {
36
+ mismatches.push(relPath);
37
+ }
38
+ }
39
+ return { ok: mismatches.length === 0 && missing.length === 0, mismatches, missing };
40
+ }
41
+ //# sourceMappingURL=hashing.js.map
@@ -0,0 +1,24 @@
1
+ /**
2
+ * JSON 深度保护:解析/序列化/克隆带嵌套深度上限(防 JSON 深度攻击,规范 §19.5)。
3
+ * 解析分两段:JSON.parse 可能因引擎栈限制抛 RangeError(捕获并归一),
4
+ * 再对结果做显式栈 walk 检查深度(避免 walk 自身递归爆栈)。
5
+ */
6
+ export declare const DEFAULT_MAX_JSON_DEPTH = 64;
7
+ export declare const DEFAULT_MAX_JSON_BYTES: number;
8
+ export declare class JsonDepthError extends Error {
9
+ constructor(message?: string);
10
+ }
11
+ /** 测量对象/数组的嵌套深度(迭代式显式栈,不会递归爆栈;二进制视为叶子) */
12
+ export declare function measureDepth(value: unknown): number;
13
+ /** 深度保护解析:超限抛 JsonDepthError,非法 JSON 抛 SyntaxError */
14
+ export declare function parseJsonSafe(text: string, opts?: {
15
+ maxDepth?: number;
16
+ maxBytes?: number;
17
+ }): unknown;
18
+ /** 深度保护序列化:先测深度再 stringify(默认不缩进) */
19
+ export declare function stringifyJsonSafe(value: unknown, opts?: {
20
+ maxDepth?: number;
21
+ space?: number;
22
+ }): string;
23
+ /** 深度保护深拷贝(迭代式,安全) */
24
+ export declare function deepClone<T>(value: T, maxDepth?: number): T;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * JSON 深度保护:解析/序列化/克隆带嵌套深度上限(防 JSON 深度攻击,规范 §19.5)。
3
+ * 解析分两段:JSON.parse 可能因引擎栈限制抛 RangeError(捕获并归一),
4
+ * 再对结果做显式栈 walk 检查深度(避免 walk 自身递归爆栈)。
5
+ */
6
+ export const DEFAULT_MAX_JSON_DEPTH = 64;
7
+ export const DEFAULT_MAX_JSON_BYTES = 64 * 1024 * 1024;
8
+ export class JsonDepthError extends Error {
9
+ constructor(message = `JSON 嵌套深度超过上限 ${DEFAULT_MAX_JSON_DEPTH}`) {
10
+ super(message);
11
+ this.name = 'JsonDepthError';
12
+ }
13
+ }
14
+ /** 测量对象/数组的嵌套深度(迭代式显式栈,不会递归爆栈;二进制视为叶子) */
15
+ export function measureDepth(value) {
16
+ let max = 0;
17
+ // 栈元素:[value, depth]
18
+ const stack = [[value, 1]];
19
+ while (stack.length > 0) {
20
+ const [current, depth] = stack.pop();
21
+ if (depth > max)
22
+ max = depth;
23
+ if (current !== null && typeof current === 'object' && !(current instanceof Uint8Array)) {
24
+ const next = depth + 1;
25
+ if (Array.isArray(current)) {
26
+ for (const item of current)
27
+ stack.push([item, next]);
28
+ }
29
+ else {
30
+ for (const key of Object.keys(current)) {
31
+ stack.push([current[key], next]);
32
+ }
33
+ }
34
+ }
35
+ }
36
+ return max;
37
+ }
38
+ /** 深度保护解析:超限抛 JsonDepthError,非法 JSON 抛 SyntaxError */
39
+ export function parseJsonSafe(text, opts = {}) {
40
+ const maxDepth = opts.maxDepth ?? DEFAULT_MAX_JSON_DEPTH;
41
+ const maxBytes = opts.maxBytes ?? DEFAULT_MAX_JSON_BYTES;
42
+ if (text.length > maxBytes) {
43
+ throw new JsonDepthError(`JSON 体积超过上限 ${maxBytes} 字节`);
44
+ }
45
+ let parsed;
46
+ try {
47
+ parsed = JSON.parse(text);
48
+ }
49
+ catch (err) {
50
+ // 引擎栈限制导致的深层嵌套也会以 RangeError 出现 → 归一为 JsonDepthError
51
+ if (err instanceof RangeError)
52
+ throw new JsonDepthError(`JSON 解析失败(可能是嵌套过深): ${String(err.message)}`);
53
+ throw err;
54
+ }
55
+ const depth = measureDepth(parsed);
56
+ if (depth > maxDepth) {
57
+ throw new JsonDepthError(`JSON 嵌套深度 ${depth} 超过上限 ${maxDepth}`);
58
+ }
59
+ return parsed;
60
+ }
61
+ /** 深度保护序列化:先测深度再 stringify(默认不缩进) */
62
+ export function stringifyJsonSafe(value, opts = {}) {
63
+ const maxDepth = opts.maxDepth ?? DEFAULT_MAX_JSON_DEPTH;
64
+ const depth = measureDepth(value);
65
+ if (depth > maxDepth)
66
+ throw new JsonDepthError(`JSON 嵌套深度 ${depth} 超过上限 ${maxDepth}`);
67
+ return JSON.stringify(value, null, opts.space);
68
+ }
69
+ /** 深度保护深拷贝(迭代式,安全) */
70
+ export function deepClone(value, maxDepth = DEFAULT_MAX_JSON_DEPTH) {
71
+ const depth = measureDepth(value);
72
+ if (depth > maxDepth)
73
+ throw new JsonDepthError();
74
+ return JSON.parse(JSON.stringify(value));
75
+ }
76
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1,39 @@
1
+ /**
2
+ * 结构化日志(规范 §24):LEVEL / 消息 / 可选元数据,带 redact 钩子。
3
+ * Secret 值永不入日志:sink 前对 msg 做文本级掩码、对 meta 做字段名级掩码。
4
+ */
5
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
6
+ /** 敏感字段名黑名单(大小写不敏感;命中即掩码值,规范 §6 清单) */
7
+ export declare const SENSITIVE_FIELD_BLACKLIST: string[];
8
+ /** 字段名是否命中敏感黑名单(大小写不敏感,子串匹配) */
9
+ export declare function isSensitiveField(field: string): boolean;
10
+ /** 对象级掩码:字段名命中黑名单 → 值替换(返回新对象,不改原对象) */
11
+ export declare function redactValue(value: unknown, blacklist?: string[]): unknown;
12
+ /** 文本级掩码:JSON 片段 `"field": "value"`、`field=value`、`field: value` 形态 */
13
+ export declare function redact(text: string, blacklist?: string[]): string;
14
+ export interface LogMeta {
15
+ [key: string]: unknown;
16
+ }
17
+ export interface LogSink {
18
+ (level: LogLevel, message: string, meta?: LogMeta): void;
19
+ }
20
+ export interface Logger {
21
+ level: LogLevel;
22
+ debug(message: string, meta?: LogMeta): void;
23
+ info(message: string, meta?: LogMeta): void;
24
+ warn(message: string, meta?: LogMeta): void;
25
+ error(message: string, meta?: LogMeta): void;
26
+ }
27
+ export interface LoggerOptions {
28
+ level?: LogLevel;
29
+ /** 输出目标;缺省写 console(单行 JSON)。测试可注入内存 sink。 */
30
+ sink?: LogSink;
31
+ /** 额外敏感字段黑名单 */
32
+ extraBlacklist?: string[];
33
+ /** 是否带时间戳前缀 */
34
+ timestamp?: boolean;
35
+ }
36
+ /** 创建结构化日志器(默认 console JSON 行,全部输出过 redact) */
37
+ export declare function createLogger(opts?: LoggerOptions): Logger;
38
+ /** 静默日志器(测试用) */
39
+ export declare function nullLogger(): Logger;
@@ -0,0 +1,82 @@
1
+ /** 敏感字段名黑名单(大小写不敏感;命中即掩码值,规范 §6 清单) */
2
+ export const SENSITIVE_FIELD_BLACKLIST = [
3
+ 'password', 'passwd', 'token', 'accesstoken', 'refreshtoken', 'apikey',
4
+ 'secret', 'credential', 'authorization', 'cookie', 'privatekey', 'clientsecret',
5
+ 'sessionkey', 'authtoken', 'bearer',
6
+ ];
7
+ const REDACTED = '***REDACTED***';
8
+ /** 字段名是否命中敏感黑名单(大小写不敏感,子串匹配) */
9
+ export function isSensitiveField(field) {
10
+ const lower = field.toLowerCase().replace(/[^a-z0-9]/g, '');
11
+ return SENSITIVE_FIELD_BLACKLIST.some((f) => lower.includes(f));
12
+ }
13
+ /** 对象级掩码:字段名命中黑名单 → 值替换(返回新对象,不改原对象) */
14
+ export function redactValue(value, blacklist = SENSITIVE_FIELD_BLACKLIST) {
15
+ if (value === null || typeof value !== 'object')
16
+ return value;
17
+ if (Array.isArray(value))
18
+ return value.map((v) => redactValue(v, blacklist));
19
+ const out = {};
20
+ for (const [k, v] of Object.entries(value)) {
21
+ const lower = k.toLowerCase();
22
+ const hit = blacklist.some((f) => lower.includes(f));
23
+ out[k] = hit ? REDACTED : redactValue(v, blacklist);
24
+ }
25
+ return out;
26
+ }
27
+ /** 文本级掩码:JSON 片段 `"field": "value"`、`field=value`、`field: value` 形态 */
28
+ export function redact(text, blacklist = SENSITIVE_FIELD_BLACKLIST) {
29
+ let out = text;
30
+ for (const field of blacklist) {
31
+ // "field": "anything"
32
+ out = out.replace(new RegExp(`("${field}"\\s*:\\s*")[^"]*(")`, 'gi'), `$1${REDACTED}$2`);
33
+ // field=value / field: value(不含 JSON 引号形态)
34
+ out = out.replace(new RegExp(`(\\b${field}\\s*=\\s*)[^\\s,;]+`, 'gi'), `$1${REDACTED}`);
35
+ out = out.replace(new RegExp(`(\\b${field}\\s*:\\s*)[^\\s,;}]+`, 'gi'), `$1${REDACTED}`);
36
+ }
37
+ return out;
38
+ }
39
+ const LEVEL_ORDER = { debug: 0, info: 1, warn: 2, error: 3 };
40
+ /** 创建结构化日志器(默认 console JSON 行,全部输出过 redact) */
41
+ export function createLogger(opts = {}) {
42
+ const level = opts.level ?? 'info';
43
+ const blacklist = [...SENSITIVE_FIELD_BLACKLIST, ...(opts.extraBlacklist ?? [])];
44
+ const sink = opts.sink ?? ((lvl, message, meta) => {
45
+ const line = JSON.stringify({
46
+ ts: new Date().toISOString(),
47
+ level: lvl,
48
+ msg: redact(message, blacklist),
49
+ ...(meta ? { meta: redactValue(meta, blacklist) } : {}),
50
+ });
51
+ // eslint-disable-next-line no-console
52
+ (lvl === 'error' ? console.error : lvl === 'warn' ? console.warn : console.log)(line);
53
+ });
54
+ const emit = (lvl, message, meta) => {
55
+ if (LEVEL_ORDER[lvl] < LEVEL_ORDER[level])
56
+ return;
57
+ try {
58
+ sink(lvl, message, meta);
59
+ }
60
+ catch {
61
+ // 日志器自身永不抛错
62
+ }
63
+ };
64
+ return {
65
+ level,
66
+ debug: (m, meta) => emit('debug', m, meta),
67
+ info: (m, meta) => emit('info', m, meta),
68
+ warn: (m, meta) => emit('warn', m, meta),
69
+ error: (m, meta) => emit('error', m, meta),
70
+ };
71
+ }
72
+ /** 静默日志器(测试用) */
73
+ export function nullLogger() {
74
+ return {
75
+ level: 'error',
76
+ debug: () => { },
77
+ info: () => { },
78
+ warn: () => { },
79
+ error: () => { },
80
+ };
81
+ }
82
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1,42 @@
1
+ import type { PathMapping } from '../core/types.ts';
2
+ /** 归一化内部表示:统一 `/` 分隔、去尾部斜杠(空串保持) */
3
+ export declare function normalizePath(p: string): string;
4
+ /** 转当前平台原生路径 */
5
+ export declare function toNativePath(p: string): string;
6
+ /** 跨平台绝对路径识别(POSIX `/x` 与 Windows `C:\x`、UNC `\\server\share`) */
7
+ export declare function isAbsolutePath(p: string): boolean;
8
+ /** 路径是否为 home 目录(~ 或用户主目录开头) */
9
+ export declare function isHomePath(p: string, homeDir: string): boolean;
10
+ /** 目标平台与当前平台是否一致 */
11
+ export declare function isSamePlatform(a: string, b: string): boolean;
12
+ /** ZIP 条目名安全检查(Zip Slip / 绝对路径 / 盘符 / NUL,规范 §19.1-2)。
13
+ * 规则与 node:path 解耦:纯分段校验,跨平台无歧义。 */
14
+ export declare function isPathSafe(entryName: string): boolean;
15
+ /** 候选目录是否位于父目录之内(含等于父目录) */
16
+ export declare function isSameOrChild(p: string, parent: string): boolean;
17
+ /**
18
+ * 归一化并折叠 `.` / `..` 路径段(Reviewer B P0 修复)。
19
+ * 宿主 fs 经 `resolve(join(homeDir, rel))` 会折叠 `..`,因此「看似不在保留命名空间、实际经 `..` 落到保留区」
20
+ * 的路径(如 `dsh-config-manager/../dsh-config-manager/snapshots/...`)必须在此折叠后再判,否则 F23 被绕过。
21
+ * 纯字符串、跨平台(只用 `/`)语义与 node:path normalize 一致;`..` 超根时按根截断(不越到 home 外)。
22
+ */
23
+ export declare function normalizePathCollapsed(p: string): string;
24
+ /** 判断相对 homeDir 的路径是否落在内部 control-plane namespace(F23 投毒防护)。
25
+ * 大小写不敏感(Windows 文件系统大小写不敏感,防 `DSh-Config-Manager/...` 绕过);
26
+ * 先折叠 `..`/`.` 段(宿主 fs 会折叠,此处必须同样折叠以免被路径穿越绕过)。 */
27
+ export declare function isReservedInternalRel(relPath: string): boolean;
28
+ /**
29
+ * 前缀批量映射(规范 §12):把对象内所有字符串值中匹配 oldPrefix 的路径
30
+ * 替换为 newPrefix(路径感知:必须落在段边界)。返回新对象(不改原对象)。
31
+ */
32
+ export declare function applyPrefixMappings(value: unknown, mappings: PathMapping[]): unknown;
33
+ /** 对对象内所有字符串叶节点做变换(迭代式,保留非字符串原样;二进制 Uint8Array 视为叶子) */
34
+ export declare function mapStrings(value: unknown, fn: (s: string) => string): unknown;
35
+ /**
36
+ * 收集对象中所有绝对路径叶值(供 analyzer 做跨设备路径检测)。
37
+ * 返回 (value, jsonPath) 对;jsonPath 形如 "workspaces[0].path"。
38
+ */
39
+ export declare function collectAbsolutePaths(value: unknown, prefix?: string): {
40
+ value: string;
41
+ path: string;
42
+ }[];
@@ -0,0 +1,189 @@
1
+ /**
2
+ * 路径处理唯一出口(node:path 不直接散落业务代码):
3
+ * 规范化、平台判定、绝对路径识别、前缀批量映射、ZIP 条目名安全校验。
4
+ */
5
+ import path from 'node:path';
6
+ /** 归一化内部表示:统一 `/` 分隔、去尾部斜杠(空串保持) */
7
+ export function normalizePath(p) {
8
+ if (p === '')
9
+ return '';
10
+ const norm = p.replaceAll('\\', '/');
11
+ return norm.length > 1 ? norm.replace(/\/+$/, '') : norm;
12
+ }
13
+ /** 转当前平台原生路径 */
14
+ export function toNativePath(p) {
15
+ const norm = normalizePath(p);
16
+ if (process.platform === 'win32')
17
+ return norm.replaceAll('/', '\\');
18
+ return norm;
19
+ }
20
+ /** 跨平台绝对路径识别(POSIX `/x` 与 Windows `C:\x`、UNC `\\server\share`) */
21
+ export function isAbsolutePath(p) {
22
+ if (p === '')
23
+ return false;
24
+ if (p.startsWith('/'))
25
+ return true;
26
+ if (/^[a-zA-Z]:[\\/]/.test(p))
27
+ return true; // 盘符
28
+ if (p.startsWith('\\\\') || p.startsWith('//'))
29
+ return true; // UNC
30
+ return false;
31
+ }
32
+ /** 路径是否为 home 目录(~ 或用户主目录开头) */
33
+ export function isHomePath(p, homeDir) {
34
+ const norm = normalizePath(p);
35
+ const home = normalizePath(homeDir);
36
+ return norm === '~' || norm === home || norm.startsWith(home + '/') || norm.startsWith('~/');
37
+ }
38
+ /** 目标平台与当前平台是否一致 */
39
+ export function isSamePlatform(a, b) {
40
+ return a === b;
41
+ }
42
+ /** ZIP 条目名安全检查(Zip Slip / 绝对路径 / 盘符 / NUL,规范 §19.1-2)。
43
+ * 规则与 node:path 解耦:纯分段校验,跨平台无歧义。 */
44
+ export function isPathSafe(entryName) {
45
+ if (entryName === '')
46
+ return false;
47
+ if (entryName.includes('\0'))
48
+ return false;
49
+ if (entryName.startsWith('/') || entryName.startsWith('\\'))
50
+ return false; // 绝对路径
51
+ if (/^[a-zA-Z]:[\\/]/.test(entryName))
52
+ return false; // 盘符
53
+ if (/^\\\\/.test(entryName))
54
+ return false; // UNC
55
+ const segments = entryName.split(/[\\/]+/);
56
+ if (segments.some((s) => s === '..'))
57
+ return false; // 目录穿越
58
+ return true;
59
+ }
60
+ /** 候选目录是否位于父目录之内(含等于父目录) */
61
+ export function isSameOrChild(p, parent) {
62
+ const rel = path.relative(parent, p);
63
+ return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));
64
+ }
65
+ /**
66
+ * 内部 control-plane namespace(F23 修复):不可信 import(pluginFiles/self/file adapters)
67
+ * 不得把普通 config/file item 映射到这些 recovery storage 目录。
68
+ * 相对 homeDir 的路径(正斜杠归一)命中任一前缀 → 拒绝。
69
+ */
70
+ const RESERVED_INTERNAL_PREFIXES = [
71
+ 'dsh-config-manager/snapshots/',
72
+ 'dsh-config-manager/transactions/',
73
+ 'dsh-config-manager/locks/',
74
+ 'dsh-config-manager/safe-mode',
75
+ 'dsh-config-manager/recovery-history/',
76
+ 'dsh-config-manager/environment-fingerprint.token',
77
+ // Phase 6:迁移历史审计目录(统一历史引擎;防 F23 投毒链——不可信导入不得映射到该目录)。
78
+ 'dsh-config-manager/migration-history/',
79
+ // 注意:不得整段保留 dsh-config-manager/sync/ —— self 分区合法持有 sync/*.json 白名单配置
80
+ //(sync-config / sync-selection / ui-prefs / backup-schedule),会误伤。
81
+ 'dsh-config-manager/sync/snapshots/',
82
+ 'dsh-config-manager/sync/work/',
83
+ ];
84
+ /**
85
+ * 归一化并折叠 `.` / `..` 路径段(Reviewer B P0 修复)。
86
+ * 宿主 fs 经 `resolve(join(homeDir, rel))` 会折叠 `..`,因此「看似不在保留命名空间、实际经 `..` 落到保留区」
87
+ * 的路径(如 `dsh-config-manager/../dsh-config-manager/snapshots/...`)必须在此折叠后再判,否则 F23 被绕过。
88
+ * 纯字符串、跨平台(只用 `/`)语义与 node:path normalize 一致;`..` 超根时按根截断(不越到 home 外)。
89
+ */
90
+ export function normalizePathCollapsed(p) {
91
+ const norm = normalizePath(p);
92
+ if (norm === '')
93
+ return '';
94
+ if (norm === '.')
95
+ return '';
96
+ const out = [];
97
+ for (const seg of norm.split('/')) {
98
+ if (seg === '' || seg === '.')
99
+ continue;
100
+ if (seg === '..') {
101
+ if (out.length > 0)
102
+ out.pop();
103
+ continue; // 超根 `..` 直接丢弃(home 相对路径不可能越出 homeDir)
104
+ }
105
+ out.push(seg);
106
+ }
107
+ return out.join('/');
108
+ }
109
+ /** 判断相对 homeDir 的路径是否落在内部 control-plane namespace(F23 投毒防护)。
110
+ * 大小写不敏感(Windows 文件系统大小写不敏感,防 `DSh-Config-Manager/...` 绕过);
111
+ * 先折叠 `..`/`.` 段(宿主 fs 会折叠,此处必须同样折叠以免被路径穿越绕过)。 */
112
+ export function isReservedInternalRel(relPath) {
113
+ const norm = normalizePathCollapsed(relPath).toLowerCase();
114
+ if (norm === '')
115
+ return false;
116
+ for (const prefix of RESERVED_INTERNAL_PREFIXES) {
117
+ if (norm === prefix || norm.startsWith(prefix))
118
+ return true;
119
+ }
120
+ return false;
121
+ }
122
+ /**
123
+ * 前缀批量映射(规范 §12):把对象内所有字符串值中匹配 oldPrefix 的路径
124
+ * 替换为 newPrefix(路径感知:必须落在段边界)。返回新对象(不改原对象)。
125
+ */
126
+ export function applyPrefixMappings(value, mappings) {
127
+ if (mappings.length === 0)
128
+ return value;
129
+ return mapStrings(value, (s) => {
130
+ let out = s;
131
+ for (const m of mappings) {
132
+ const oldNorm = normalizePath(m.oldPrefix);
133
+ if (oldNorm === '')
134
+ continue;
135
+ const candidate = normalizePath(out);
136
+ if (candidate === oldNorm) {
137
+ out = normalizePath(m.newPrefix);
138
+ continue;
139
+ }
140
+ if (candidate.startsWith(oldNorm + '/')) {
141
+ const rest = candidate.slice(oldNorm.length); // 含前导 /
142
+ out = normalizePath(normalizePath(m.newPrefix) + rest);
143
+ }
144
+ }
145
+ return out;
146
+ });
147
+ }
148
+ /** 对对象内所有字符串叶节点做变换(迭代式,保留非字符串原样;二进制 Uint8Array 视为叶子) */
149
+ export function mapStrings(value, fn) {
150
+ if (typeof value === 'string')
151
+ return fn(value);
152
+ if (value === null || typeof value !== 'object')
153
+ return value;
154
+ if (value instanceof Uint8Array)
155
+ return value; // 二进制不按字段展开
156
+ if (Array.isArray(value))
157
+ return value.map((v) => mapStrings(v, fn));
158
+ const out = {};
159
+ for (const [k, v] of Object.entries(value)) {
160
+ out[k] = mapStrings(v, fn);
161
+ }
162
+ return out;
163
+ }
164
+ /**
165
+ * 收集对象中所有绝对路径叶值(供 analyzer 做跨设备路径检测)。
166
+ * 返回 (value, jsonPath) 对;jsonPath 形如 "workspaces[0].path"。
167
+ */
168
+ export function collectAbsolutePaths(value, prefix = '') {
169
+ const hits = [];
170
+ const visit = (v, p) => {
171
+ if (typeof v === 'string') {
172
+ if (isAbsolutePath(v))
173
+ hits.push({ value: v, path: p });
174
+ return;
175
+ }
176
+ if (v === null || typeof v !== 'object')
177
+ return;
178
+ if (Array.isArray(v)) {
179
+ v.forEach((item, i) => visit(item, `${p}[${i}]`));
180
+ return;
181
+ }
182
+ for (const [k, val] of Object.entries(v)) {
183
+ visit(val, p === '' ? k : `${p}.${k}`);
184
+ }
185
+ };
186
+ visit(value, prefix);
187
+ return hits;
188
+ }
189
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1,69 @@
1
+ /** 代理相关环境变量(大小写兼容后的归一形态) */
2
+ export interface ProxyEnv {
3
+ /** http 目标使用的代理(`HTTP_PROXY` / `http_proxy`) */
4
+ httpProxy: string | null;
5
+ /** https 目标使用的代理(`HTTPS_PROXY` / `https_proxy`) */
6
+ httpsProxy: string | null;
7
+ /** 直连白名单(`NO_PROXY` / `no_proxy`) */
8
+ noProxy: string | null;
9
+ }
10
+ /** 读代理环境变量(纯函数,便于测试注​入任意 env) */
11
+ export declare function readProxyEnv(env?: Record<string, string | undefined>): ProxyEnv;
12
+ /** 是否配置了任何代理(用于启动日志与「是否需要走代理链路」的判定) */
13
+ export declare function isProxyConfigured(env?: ProxyEnv): boolean;
14
+ /**
15
+ * 目标是否命中 `NO_PROXY`。
16
+ * 支持:`*`(全直连)、精确主机、`.example.com` 与 `example.com`(含子域)、可选 `:port` 限定。
17
+ */
18
+ export declare function matchesNoProxy(host: string, port: string, noProxy: string | null): boolean;
19
+ /**
20
+ * 该目标应使用的代理 URL;无需代理(未配置 / 命中 NO_PROXY / 非法)→ null。
21
+ *
22
+ * 选择规则(对齐 undici `EnvHttpProxyAgent` 的直觉语义):
23
+ * - `https:` 目标 → `HTTPS_PROXY`,缺省回退 `HTTP_PROXY`;
24
+ * - `http:` 目标 → `HTTP_PROXY`,缺省回退 `HTTPS_PROXY`。
25
+ */
26
+ export declare function proxyUrlFor(target: string | URL, env?: ProxyEnv): string | null;
27
+ /** 代理的**脱敏**描述(供日志/报错提示;凭据一律剥离,绝不外泄) */
28
+ export declare function describeProxy(proxyUrl: string): string;
29
+ /** 单次请求的输入 */
30
+ export interface RawRequestOptions {
31
+ method?: string;
32
+ url: string;
33
+ headers?: Record<string, string>;
34
+ body?: Buffer | string | undefined;
35
+ timeoutMs?: number;
36
+ signal?: AbortSignal;
37
+ env?: ProxyEnv;
38
+ }
39
+ /** 单次请求的响应(始终缓冲完整响应体;插件用到的响应体都是小 JSON/文本) */
40
+ export interface RawResponse {
41
+ status: number;
42
+ statusText: string;
43
+ headers: Headers;
44
+ body: Buffer;
45
+ }
46
+ /**
47
+ * 发起一次 HTTP/1.1 请求(自动:直连 / 经代理 absolute-form / 经代理 CONNECT 隧道)。
48
+ * 不跟随重定向(跟随策略由调用方决定:WebDAV 保方法语义,fetch 按浏览器语义)。
49
+ */
50
+ export declare function requestOnce(options: RawRequestOptions): Promise<RawResponse>;
51
+ /**
52
+ * 代理感知的 fetch 兼容实现(仅插件自身使用;替代 `globalThis.fetch` 的默认值)。
53
+ *
54
+ * 与浏览器 fetch 的关键语义对齐:自动跟随 301/302/303/307/308(上限 5 跳);303 且非 GET/HEAD
55
+ * 降级为 GET 并丢弃请求体;**跨源跳转剥离 `authorization`**(token 不转发给第三方域名);
56
+ * 无响应体状态(204/304 等)不构造 body。
57
+ */
58
+ export declare function createProxyAwareFetch(env?: ProxyEnv): typeof fetch;
59
+ /**
60
+ * 默认出站 fetcher:**未配置代理时原样返回全局 `fetch`**(保持既有行为零变化);
61
+ * 配置了代理才切到代理感知实现。
62
+ */
63
+ export declare function defaultFetcher(env?: ProxyEnv): typeof fetch;
64
+ /** 启动日志用:当前生效的代理描述(已脱敏),未启用 → null */
65
+ export declare function activeProxySummary(env?: ProxyEnv): {
66
+ http: string | null;
67
+ https: string | null;
68
+ noProxyEntries: number;
69
+ } | null;