@dsh-workbench/shared 0.3.11 → 1.0.0-beta.1

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 (403) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +97 -0
  3. package/dist/api/blocker-table.d.ts +3 -3
  4. package/dist/api/blocker-table.js +47 -23
  5. package/dist/api/dsh.d.ts +1 -1
  6. package/dist/api/workbench-client.js +2 -1
  7. package/dist/components/Activity.css +0 -1
  8. package/dist/components/ApprovalDetail.css +1 -2
  9. package/dist/components/ApprovalDetail.d.ts +1 -1
  10. package/dist/components/ApprovalPlan.css +0 -1
  11. package/dist/components/Card.css +0 -1
  12. package/dist/components/Card.d.ts +1 -1
  13. package/dist/components/CardBoundary.d.ts +1 -1
  14. package/dist/components/CardHead.css +0 -1
  15. package/dist/components/CardHead.d.ts +1 -1
  16. package/dist/components/ChoiceGroup.css +1 -2
  17. package/dist/components/ConfirmBar.d.ts +1 -1
  18. package/dist/components/ConfirmBar.js +1 -1
  19. package/dist/components/Form.css +1 -1
  20. package/dist/components/FormActions.js +1 -1
  21. package/dist/components/FormNodes.js +5 -1
  22. package/dist/components/FormRows.css +1 -0
  23. package/dist/components/FormRows.d.ts +4 -2
  24. package/dist/components/FormRows.js +5 -4
  25. package/dist/components/LongTaskRow.css +1 -2
  26. package/dist/components/LongTaskRow.d.ts +1 -1
  27. package/dist/components/LongTaskRow.js +1 -1
  28. package/dist/components/Note.css +0 -1
  29. package/dist/components/ResourceStates.css +0 -1
  30. package/dist/components/SettingsSection.css +0 -1
  31. package/dist/components/Spinner.css +0 -1
  32. package/dist/components/Stack.css +0 -1
  33. package/dist/components/StateBlock.css +0 -1
  34. package/dist/components/board-module.d.ts +3 -3
  35. package/dist/components/icons.d.ts +1 -1
  36. package/dist/components/icons.js +11 -4
  37. package/dist/config/constants.d.ts +2 -4
  38. package/dist/config/constants.js +2 -7
  39. package/dist/contract/adapters.d.ts +10 -0
  40. package/dist/contract/cli.d.ts +3 -0
  41. package/dist/contract/command.d.ts +22 -0
  42. package/dist/contract/data.d.ts +127 -0
  43. package/dist/contract/extension.d.ts +14 -0
  44. package/dist/contract/extension.js +1 -0
  45. package/dist/{api → contract}/facts.d.ts +12 -3
  46. package/dist/{api → contract}/facts.js +19 -1
  47. package/dist/contract/git.d.ts +38 -0
  48. package/dist/contract/git.js +1 -0
  49. package/dist/contract/lib.d.ts +4 -0
  50. package/dist/contract/lib.js +1 -0
  51. package/dist/contract/needs.d.ts +132 -0
  52. package/dist/contract/needs.js +232 -0
  53. package/dist/contract/plugin-source.d.ts +1 -0
  54. package/dist/contract/plugin-source.js +1 -0
  55. package/dist/contract/protocol/bundle-install.d.ts +136 -0
  56. package/dist/contract/protocol/bundle-install.js +12 -0
  57. package/dist/contract/protocol/config-sync.d.ts +55 -0
  58. package/dist/contract/protocol/config-sync.js +2 -0
  59. package/dist/contract/protocol/diy.d.ts +4 -0
  60. package/dist/contract/protocol/diy.js +4 -0
  61. package/dist/contract/protocol/dsh-plugins.d.ts +11 -0
  62. package/dist/contract/protocol/dsh-plugins.js +1 -0
  63. package/dist/contract/protocol/long-tasks.d.ts +13 -0
  64. package/dist/contract/protocol/long-tasks.js +1 -0
  65. package/dist/contract/protocol/market-index.d.ts +195 -0
  66. package/dist/contract/protocol/market-index.js +7 -0
  67. package/dist/contract/protocol/platform.d.ts +44 -0
  68. package/dist/contract/protocol/platform.js +1 -0
  69. package/dist/contract/protocol/preflight-wake.d.ts +7 -0
  70. package/dist/contract/protocol/preflight-wake.js +1 -0
  71. package/dist/contract/protocol/profile-create.d.ts +30 -0
  72. package/dist/contract/protocol/profile-create.js +2 -0
  73. package/dist/contract/protocol/sidebar-edition.d.ts +14 -0
  74. package/dist/contract/protocol/sidebar-edition.js +2 -0
  75. package/dist/contract/protocol/unit-manifests.d.ts +6 -0
  76. package/dist/contract/protocol/unit-manifests.js +1 -0
  77. package/dist/contract/unit-board.js +1 -0
  78. package/dist/contract/unit-capability.d.ts +34 -0
  79. package/dist/contract/unit-capability.js +1 -0
  80. package/dist/{host → contract}/unit-declaration.d.ts +7 -5
  81. package/dist/{api → contract}/unit-declaration.js +19 -13
  82. package/dist/contract/unit.d.ts +57 -0
  83. package/dist/contract/unit.js +24 -0
  84. package/dist/contract/workbench-contract.d.ts +15 -0
  85. package/dist/contract/workbench-contract.js +1 -0
  86. package/dist/host/adapter-set.d.ts +26 -0
  87. package/dist/host/adapter-set.js +244 -0
  88. package/dist/host/adapter-types.d.ts +79 -0
  89. package/dist/host/adapter-types.js +23 -0
  90. package/dist/host/adapters.d.ts +28 -0
  91. package/dist/host/adapters.js +9 -0
  92. package/dist/host/browser.d.ts +3 -0
  93. package/dist/host/browser.js +3 -0
  94. package/dist/host/changelog.d.ts +21 -0
  95. package/dist/host/changelog.js +188 -0
  96. package/dist/host/channel-plugin.d.ts +15 -0
  97. package/dist/host/channel-plugin.js +42 -0
  98. package/dist/host/cli.d.ts +4 -0
  99. package/dist/host/cli.js +7 -0
  100. package/dist/host/command-name.d.ts +1 -0
  101. package/dist/host/command-name.js +14 -0
  102. package/dist/host/data-error.d.ts +13 -0
  103. package/dist/host/data-error.js +20 -0
  104. package/dist/host/data-root.js +3 -0
  105. package/dist/host/diy-debug.js +2 -1
  106. package/dist/host/diy-record.js +2 -1
  107. package/dist/host/extension.d.ts +7 -0
  108. package/dist/host/extension.js +39 -0
  109. package/dist/host/facts.d.ts +1 -1
  110. package/dist/host/facts.js +3 -2
  111. package/dist/host/git.d.ts +2 -33
  112. package/dist/host/git.js +2 -2
  113. package/dist/host/http.js +2 -2
  114. package/dist/host/lib-capabilities.d.ts +22 -0
  115. package/dist/host/lib-capabilities.js +37 -0
  116. package/dist/host/lib-install.d.ts +9 -0
  117. package/dist/host/lib-install.js +10 -0
  118. package/dist/host/long-task.d.ts +1 -1
  119. package/dist/host/long-task.js +4 -3
  120. package/dist/host/market-index.d.ts +22 -0
  121. package/dist/host/market-index.js +379 -0
  122. package/dist/host/needs.d.ts +4 -0
  123. package/dist/host/needs.js +2 -0
  124. package/dist/host/patch.d.ts +9 -0
  125. package/dist/host/patch.js +78 -0
  126. package/dist/host/paths.d.ts +12 -0
  127. package/dist/host/paths.js +28 -0
  128. package/dist/host/platform.d.ts +14 -0
  129. package/dist/host/platform.js +40 -0
  130. package/dist/host/plugin-source.d.ts +8 -6
  131. package/dist/host/plugin-source.js +43 -33
  132. package/dist/host/plugin.d.ts +4 -0
  133. package/dist/host/plugin.js +39 -0
  134. package/dist/host/port-types.d.ts +192 -0
  135. package/dist/host/port-types.js +1 -0
  136. package/dist/host/preflight.d.ts +28 -0
  137. package/dist/host/preflight.js +1 -0
  138. package/dist/host/profile-port.d.ts +4 -0
  139. package/dist/host/profile-port.js +4 -0
  140. package/dist/host/provision.d.ts +2 -2
  141. package/dist/host/provision.js +5 -3
  142. package/dist/host/recipe-rules.d.ts +5 -0
  143. package/dist/host/recipe-rules.js +382 -0
  144. package/dist/host/recipe.d.ts +14 -0
  145. package/dist/host/recipe.js +283 -0
  146. package/dist/host/release-packages.generated.d.ts +1 -0
  147. package/dist/host/release-packages.generated.js +10 -0
  148. package/dist/host/shell-text.d.ts +9 -2
  149. package/dist/host/shell-text.js +15 -3
  150. package/dist/host/shell.d.ts +2 -0
  151. package/dist/host/shell.js +7 -0
  152. package/dist/host/spec.d.ts +8 -0
  153. package/dist/host/spec.js +24 -0
  154. package/dist/host/supply-index.d.ts +34 -0
  155. package/dist/host/supply-index.js +202 -0
  156. package/dist/host/supply-port.d.ts +5 -0
  157. package/dist/host/supply-port.js +39 -0
  158. package/dist/host/time.d.ts +12 -0
  159. package/dist/host/time.js +19 -0
  160. package/dist/host/tokens.d.ts +26 -0
  161. package/dist/host/tokens.js +154 -0
  162. package/dist/host/tool-kit.d.ts +0 -6
  163. package/dist/host/tool-kit.js +0 -22
  164. package/dist/host/unit-face.d.ts +12 -4
  165. package/dist/host/version-range.d.ts +2 -0
  166. package/dist/host/version-range.js +13 -0
  167. package/dist/host/version.d.ts +4 -0
  168. package/dist/host/version.js +27 -0
  169. package/dist/host.d.ts +53 -16
  170. package/dist/host.js +53 -16
  171. package/dist/i18n/en.js +225 -71
  172. package/dist/i18n/index.d.ts +299 -73
  173. package/dist/i18n/merge.js +1 -1
  174. package/dist/i18n/need-text.d.ts +26 -0
  175. package/dist/i18n/need-text.js +26 -0
  176. package/dist/i18n/settings.d.ts +70 -0
  177. package/dist/i18n/settings.js +136 -0
  178. package/dist/i18n/zh.d.ts +298 -72
  179. package/dist/i18n/zh.js +227 -73
  180. package/dist/index.d.ts +27 -7
  181. package/dist/index.js +27 -7
  182. package/dist/{api → lib}/dsh-client.d.ts +11 -1
  183. package/dist/lib/dsh-client.js +1 -0
  184. package/dist/lib/market-index.d.ts +7 -0
  185. package/dist/lib/market-index.js +25 -0
  186. package/dist/lib/react.d.ts +0 -40
  187. package/dist/lib/react.js +0 -36
  188. package/dist/lib/ui.js +3 -9
  189. package/dist/lib/version.d.ts +4 -0
  190. package/dist/lib/version.js +21 -0
  191. package/dist/testing/data.d.ts +13 -0
  192. package/dist/testing/data.js +46 -0
  193. package/dist/testing/declaration.d.ts +1 -1
  194. package/dist/testing/declaration.js +1 -1
  195. package/dist/testing/host-fakes.d.ts +0 -13
  196. package/dist/testing/host-fakes.js +0 -24
  197. package/dist/testing/needs.d.ts +16 -0
  198. package/dist/testing/needs.js +46 -0
  199. package/dist/testing.d.ts +2 -0
  200. package/dist/testing.js +2 -0
  201. package/package.json +22 -4
  202. package/src/api/__tests__/blocker-table.test.ts +135 -86
  203. package/src/api/blocker-table.ts +52 -26
  204. package/src/api/dsh.ts +1 -1
  205. package/src/api/host-write.ts +0 -1
  206. package/src/api/workbench-client.test.ts +2 -2
  207. package/src/api/workbench-client.ts +2 -1
  208. package/src/components/Activity.css +0 -1
  209. package/src/components/ApprovalDetail.css +1 -2
  210. package/src/components/ApprovalDetail.tsx +1 -1
  211. package/src/components/ApprovalPlan.css +0 -1
  212. package/src/components/Card.css +0 -1
  213. package/src/components/Card.tsx +1 -1
  214. package/src/components/CardAnchor.test.tsx +1 -1
  215. package/src/components/CardBoundary.tsx +1 -1
  216. package/src/components/CardHead.css +0 -1
  217. package/src/components/CardHead.tsx +1 -1
  218. package/src/components/ChoiceGroup.css +1 -2
  219. package/src/components/ConfirmBar.tsx +1 -1
  220. package/src/components/Form.css +1 -1
  221. package/src/components/Form.test.tsx +6 -0
  222. package/src/components/Form.tsx +1 -1
  223. package/src/components/FormActions.tsx +1 -1
  224. package/src/components/FormNodes.tsx +6 -1
  225. package/src/components/FormRows.css +1 -0
  226. package/src/components/FormRows.test.tsx +30 -0
  227. package/src/components/FormRows.tsx +9 -5
  228. package/src/components/LongTaskRow.css +1 -2
  229. package/src/components/LongTaskRow.tsx +1 -1
  230. package/src/components/Note.css +0 -1
  231. package/src/components/ResourceStates.css +0 -1
  232. package/src/components/SelectFieldNodes.tsx +0 -1
  233. package/src/components/SettingsSection.css +0 -1
  234. package/src/components/Spinner.css +0 -1
  235. package/src/components/Stack.css +0 -1
  236. package/src/components/StateBlock.css +0 -1
  237. package/src/components/__tests__/long-task-row.test.ts +1 -1
  238. package/src/components/board-module.ts +3 -3
  239. package/src/components/icons.tsx +16 -8
  240. package/src/config/constants.ts +2 -8
  241. package/src/{api → contract}/__tests__/facts.test.ts +73 -25
  242. package/src/{api → contract}/__tests__/long-task.test.ts +3 -3
  243. package/src/contract/__tests__/needs.test.ts +74 -0
  244. package/src/{host → contract}/__tests__/unit-declaration.test.ts +1 -1
  245. package/src/contract/__tests__/unit.test.ts +43 -0
  246. package/src/contract/adapters.ts +9 -0
  247. package/src/contract/cli.ts +3 -0
  248. package/src/contract/command.ts +25 -0
  249. package/src/contract/data.ts +146 -0
  250. package/src/contract/extension.ts +20 -0
  251. package/src/{api → contract}/facts.ts +34 -4
  252. package/src/contract/git.ts +20 -0
  253. package/src/contract/lib.ts +5 -0
  254. package/src/contract/needs.ts +331 -0
  255. package/src/contract/plugin-source.ts +1 -0
  256. package/src/contract/protocol/bundle-install.ts +198 -0
  257. package/src/contract/protocol/config-sync.ts +65 -0
  258. package/src/contract/protocol/diy.ts +4 -0
  259. package/src/contract/protocol/dsh-plugins.ts +13 -0
  260. package/src/contract/protocol/long-tasks.ts +16 -0
  261. package/src/contract/protocol/market-index.ts +246 -0
  262. package/src/contract/protocol/platform.ts +47 -0
  263. package/src/contract/protocol/preflight-wake.ts +17 -0
  264. package/src/contract/protocol/profile-create.ts +36 -0
  265. package/src/contract/protocol/sidebar-edition.ts +19 -0
  266. package/src/contract/protocol/unit-manifests.ts +8 -0
  267. package/src/{api → contract}/unit-board.ts +0 -1
  268. package/src/contract/unit-capability.ts +37 -0
  269. package/src/{host → contract}/unit-declaration.ts +22 -18
  270. package/src/contract/unit.ts +76 -0
  271. package/src/contract/workbench-contract.ts +30 -0
  272. package/src/host/__tests__/adapter-set.test.ts +228 -0
  273. package/src/host/__tests__/adapters.test.ts +27 -0
  274. package/src/host/__tests__/changelog.test.ts +102 -0
  275. package/src/host/__tests__/command-name.test.ts +16 -0
  276. package/src/host/__tests__/diy-record.test.ts +3 -3
  277. package/src/host/__tests__/facts.test.ts +5 -5
  278. package/src/host/__tests__/long-task.test.ts +1 -1
  279. package/src/host/__tests__/market-index.test.ts +179 -0
  280. package/src/host/__tests__/plugin-ledger.test.ts +10 -10
  281. package/src/host/__tests__/provision.test.ts +7 -6
  282. package/src/host/__tests__/shell-text.test.ts +16 -1
  283. package/src/host/__tests__/supply-index.test.ts +137 -0
  284. package/src/host/__tests__/tokens.test.ts +110 -0
  285. package/src/host/__tests__/version-range.test.ts +21 -0
  286. package/src/host/adapter-set.ts +299 -0
  287. package/src/host/adapter-types.ts +105 -0
  288. package/src/host/adapters.ts +50 -0
  289. package/src/host/browser.ts +3 -0
  290. package/src/host/changelog.ts +212 -0
  291. package/src/host/channel-plugin.ts +55 -0
  292. package/src/host/cli.ts +11 -0
  293. package/src/host/command-name.ts +15 -0
  294. package/src/host/data-error.ts +21 -0
  295. package/src/host/data-root.ts +2 -0
  296. package/src/host/diy-debug.ts +2 -1
  297. package/src/host/diy-record.ts +2 -1
  298. package/src/host/extension.test.ts +55 -0
  299. package/src/host/extension.ts +57 -0
  300. package/src/host/facts.ts +4 -3
  301. package/src/host/git.ts +8 -16
  302. package/src/host/http.ts +2 -2
  303. package/src/host/lib-capabilities.ts +52 -0
  304. package/src/host/lib-install.ts +18 -0
  305. package/src/host/long-task.ts +4 -3
  306. package/src/host/market-index.ts +383 -0
  307. package/src/host/needs.ts +6 -0
  308. package/src/host/patch.ts +93 -0
  309. package/src/host/paths.ts +37 -0
  310. package/src/host/platform.ts +48 -0
  311. package/src/host/plugin-source.ts +48 -56
  312. package/src/host/plugin.ts +39 -0
  313. package/src/host/port-types.ts +223 -0
  314. package/src/host/preflight.ts +31 -0
  315. package/src/host/profile-port.ts +9 -0
  316. package/src/host/provision.ts +7 -4
  317. package/src/host/recipe-rules.ts +330 -0
  318. package/src/host/recipe.test.ts +334 -0
  319. package/src/host/recipe.ts +323 -0
  320. package/src/host/release-packages.generated.ts +10 -0
  321. package/src/host/shell-text.ts +15 -3
  322. package/src/host/shell.ts +9 -0
  323. package/src/host/spec.ts +32 -0
  324. package/src/host/supply-index.ts +256 -0
  325. package/src/host/supply-port.ts +45 -0
  326. package/src/host/time.ts +22 -0
  327. package/src/host/tokens.ts +186 -0
  328. package/src/host/tool-kit.ts +0 -35
  329. package/src/host/unit-face.ts +12 -4
  330. package/src/host/version-range.ts +13 -0
  331. package/src/host/version.ts +30 -0
  332. package/src/host.ts +53 -16
  333. package/src/i18n/en.ts +225 -71
  334. package/src/i18n/merge.test.ts +6 -6
  335. package/src/i18n/merge.ts +1 -1
  336. package/src/i18n/need-text.ts +27 -0
  337. package/src/i18n/settings.ts +141 -0
  338. package/src/i18n/zh.ts +228 -73
  339. package/src/index.ts +27 -7
  340. package/src/lib/blocker-action.ts +0 -1
  341. package/src/{api → lib}/dsh-client.ts +12 -1
  342. package/src/lib/market-index.ts +36 -0
  343. package/src/lib/react.ts +0 -40
  344. package/src/lib/text.test.ts +2 -2
  345. package/src/lib/ui.test.ts +6 -5
  346. package/src/lib/ui.ts +3 -9
  347. package/src/testing/__tests__/declaration.test.ts +1 -1
  348. package/src/testing/data.ts +66 -0
  349. package/src/testing/declaration.ts +2 -2
  350. package/src/testing/host-fakes.ts +0 -38
  351. package/src/testing/needs.ts +80 -0
  352. package/src/testing.ts +2 -0
  353. package/dist/api/unit-declaration.d.ts +0 -65
  354. package/dist/api/unit.d.ts +0 -85
  355. package/dist/api/unit.js +0 -8
  356. package/dist/api/workbench-contract.d.ts +0 -44
  357. package/dist/components/MockStrip.css +0 -39
  358. package/dist/components/MockStrip.d.ts +0 -15
  359. package/dist/components/MockStrip.js +0 -8
  360. package/dist/components/SaveBar.css +0 -7
  361. package/dist/host/browser-find.d.ts +0 -38
  362. package/dist/host/browser-find.js +0 -242
  363. package/dist/host/browser-read.d.ts +0 -28
  364. package/dist/host/browser-read.js +0 -243
  365. package/dist/host/opencli-runtime.d.ts +0 -25
  366. package/dist/host/opencli-runtime.js +0 -56
  367. package/dist/host/opencli-window.d.ts +0 -2
  368. package/dist/host/opencli-window.js +0 -8
  369. package/dist/host/opencli.d.ts +0 -37
  370. package/dist/host/opencli.js +0 -155
  371. package/dist/host/unit-declaration.js +0 -213
  372. package/dist/host/unit-libs.d.ts +0 -37
  373. package/dist/lib/diy-debug.d.ts +0 -80
  374. package/dist/lib/diy-debug.js +0 -88
  375. package/dist/lib/diy-record.d.ts +0 -135
  376. package/dist/lib/diy-record.js +0 -162
  377. package/dist/lib/lint-probe.d.ts +0 -1
  378. package/dist/lib/lint-probe.js +0 -6
  379. package/dist/lib/panel-state.d.ts +0 -120
  380. package/dist/lib/panel-state.js +0 -176
  381. package/src/api/__tests__/unit.test.ts +0 -38
  382. package/src/api/unit.ts +0 -93
  383. package/src/api/workbench-contract.ts +0 -59
  384. package/src/host/__tests__/browser-find.test.ts +0 -330
  385. package/src/host/__tests__/browser-read.test.ts +0 -228
  386. package/src/host/__tests__/opencli-runtime.test.ts +0 -46
  387. package/src/host/browser-find.ts +0 -311
  388. package/src/host/browser-read.ts +0 -311
  389. package/src/host/opencli-runtime.ts +0 -79
  390. package/src/host/opencli-window.ts +0 -11
  391. package/src/host/opencli.ts +0 -213
  392. package/src/host/unit-libs.ts +0 -41
  393. /package/dist/{api/blocker.js → contract/adapters.js} +0 -0
  394. /package/dist/{api → contract}/blocker.d.ts +0 -0
  395. /package/dist/{api/dsh-client.js → contract/blocker.js} +0 -0
  396. /package/dist/{api/unit-board.js → contract/cli.js} +0 -0
  397. /package/dist/{api/workbench-contract.js → contract/command.js} +0 -0
  398. /package/dist/{host/unit-libs.js → contract/data.js} +0 -0
  399. /package/dist/{api → contract}/long-task.d.ts +0 -0
  400. /package/dist/{api → contract}/long-task.js +0 -0
  401. /package/dist/{api → contract}/unit-board.d.ts +0 -0
  402. /package/src/{api → contract}/blocker.ts +0 -0
  403. /package/src/{api → contract}/long-task.ts +0 -0
@@ -0,0 +1,22 @@
1
+ export interface CommandFile {
2
+ readonly content: string;
3
+ readonly suffix?: string | undefined;
4
+ }
5
+ export interface CommandRequest {
6
+ readonly argv: readonly string[];
7
+ readonly timeoutMs?: number | undefined;
8
+ readonly cwd?: string | undefined;
9
+ readonly files?: readonly CommandFile[] | undefined;
10
+ readonly appendFileArgs?: string | undefined;
11
+ }
12
+ export interface CommandResult {
13
+ readonly stdout: string;
14
+ readonly stderr: string;
15
+ readonly exitCode: number;
16
+ readonly timedOut: boolean;
17
+ readonly filePaths: readonly string[];
18
+ readonly error?: string | undefined;
19
+ }
20
+ export interface CommandReader {
21
+ run(request: CommandRequest): Promise<CommandResult>;
22
+ }
@@ -0,0 +1,127 @@
1
+ export interface DataRequestBase {
2
+ readonly timeoutMs?: number;
3
+ }
4
+ export interface HttpDataRequest extends DataRequestBase {
5
+ readonly kind: 'http';
6
+ readonly url: string;
7
+ readonly headers?: Readonly<Record<string, string>>;
8
+ }
9
+ export interface BrowserDataRequest extends DataRequestBase {
10
+ readonly kind: 'browser';
11
+ readonly script: string;
12
+ readonly url?: string;
13
+ readonly loginUrl?: string;
14
+ readonly session?: string;
15
+ readonly open?: boolean;
16
+ }
17
+ export interface CommandDataRequest extends DataRequestBase {
18
+ readonly kind: 'command';
19
+ readonly adapter: string;
20
+ readonly argv: readonly string[];
21
+ }
22
+ export type DataRequest = HttpDataRequest | BrowserDataRequest | CommandDataRequest;
23
+ export type DataErrorCode = 'invalid-request' | 'http' | 'auth' | 'timeout' | 'parse' | 'command' | 'browser';
24
+ export interface DataError {
25
+ readonly code: DataErrorCode;
26
+ readonly message: string;
27
+ readonly status?: number;
28
+ readonly detail?: string;
29
+ readonly hint?: string;
30
+ readonly helpUrl?: string;
31
+ readonly pageCode?: string;
32
+ }
33
+ export interface DataSuccess<T = unknown> {
34
+ readonly ok: true;
35
+ readonly data: T;
36
+ }
37
+ export interface DataFailure {
38
+ readonly ok: false;
39
+ readonly error: DataError;
40
+ }
41
+ export type DataResult<T = unknown> = DataSuccess<T> | DataFailure;
42
+ export interface CredentialSourceCookie {
43
+ readonly kind: 'cookie';
44
+ }
45
+ export interface CredentialSourceCookieValue {
46
+ readonly kind: 'cookieValue';
47
+ readonly name: string;
48
+ }
49
+ export interface CredentialSourceEndpoint {
50
+ readonly kind: 'endpoint';
51
+ readonly url: string;
52
+ readonly method?: 'GET' | 'POST';
53
+ readonly body?: unknown;
54
+ readonly path: string;
55
+ }
56
+ export interface CredentialSourceMeta {
57
+ readonly kind: 'meta';
58
+ readonly name: string;
59
+ }
60
+ export interface CredentialSourceGlobal {
61
+ readonly kind: 'global';
62
+ readonly path: string;
63
+ }
64
+ export interface CredentialSourceStorage {
65
+ readonly kind: 'storage';
66
+ readonly area: 'local' | 'session';
67
+ readonly key: string;
68
+ readonly path?: string;
69
+ }
70
+ export type CredentialSource = CredentialSourceCookie | CredentialSourceCookieValue | CredentialSourceEndpoint | CredentialSourceMeta | CredentialSourceGlobal | CredentialSourceStorage;
71
+ export type CredentialPlace = {
72
+ readonly in: 'cookie';
73
+ } | {
74
+ readonly in: 'header';
75
+ readonly name: string;
76
+ readonly prefix?: string;
77
+ } | {
78
+ readonly in: 'query';
79
+ readonly name: string;
80
+ } | {
81
+ readonly in: 'body';
82
+ readonly field: string;
83
+ };
84
+ export type RecipeAuth = {
85
+ readonly kind: 'none';
86
+ } | {
87
+ readonly kind?: undefined;
88
+ readonly source: CredentialSource;
89
+ readonly place: CredentialPlace;
90
+ };
91
+ export interface RecipeRequest {
92
+ readonly method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
93
+ readonly path: string;
94
+ readonly query?: Readonly<Record<string, string | number | boolean>>;
95
+ readonly headers?: Readonly<Record<string, string>>;
96
+ readonly body?: unknown;
97
+ readonly contentType?: 'json' | 'form';
98
+ }
99
+ export interface RecipeResponse {
100
+ readonly kind: 'json' | 'text';
101
+ readonly path?: string;
102
+ readonly maxBytes?: number;
103
+ }
104
+ export interface RequestRecipe {
105
+ readonly origin: string;
106
+ readonly loginUrl?: string;
107
+ readonly session?: string;
108
+ readonly timeoutMs?: number;
109
+ readonly auth?: RecipeAuth;
110
+ readonly request: RecipeRequest;
111
+ readonly response?: RecipeResponse;
112
+ }
113
+ export interface CallOverrides {
114
+ readonly path?: string;
115
+ readonly query?: Readonly<Record<string, string | number | boolean>>;
116
+ readonly headers?: Readonly<Record<string, string>>;
117
+ readonly body?: unknown;
118
+ readonly response?: Partial<RecipeResponse>;
119
+ }
120
+ export type RecipeCalls = Readonly<Record<string, CallOverrides>>;
121
+ export type RecipeResults<T = unknown> = Readonly<Record<string, DataResult<T>>>;
122
+ export interface DataReader {
123
+ read<T = unknown>(request: DataRequest): Promise<DataResult<T>>;
124
+ request<T = unknown>(recipe: RequestRecipe, overrides?: CallOverrides): Promise<DataResult<T>>;
125
+ requestMany<T = unknown>(recipe: RequestRecipe, calls: RecipeCalls): Promise<RecipeResults<T>>;
126
+ submit<T = unknown>(recipe: RequestRecipe, overrides?: CallOverrides): Promise<DataResult<T>>;
127
+ }
@@ -0,0 +1,14 @@
1
+ export type ExtensionSession = 'persistent' | 'ephemeral' | 'none';
2
+ export interface ExtensionCallOptions {
3
+ readonly key?: string;
4
+ readonly workdir?: string;
5
+ readonly session?: ExtensionSession;
6
+ readonly timeoutMs?: number;
7
+ }
8
+ export interface ExtensionValue<T = unknown> {
9
+ readonly value: T;
10
+ readonly at: number;
11
+ }
12
+ export interface ExtensionCaller {
13
+ json(args: readonly string[], options?: ExtensionCallOptions): Promise<ExtensionValue>;
14
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -7,7 +7,7 @@ export interface FactFrame {
7
7
  readonly facts: readonly string[];
8
8
  }
9
9
  /**
10
- * 范围查法的后缀:cmdb/* 这类名字表示「这个前缀下的一族」,不是一条事实。
10
+ * 范围查法的后缀:inventory/* 这类名字表示「这个前缀下的一族」,不是一条事实。
11
11
  */
12
12
  export declare const FACT_SCOPE_SUFFIX = "*";
13
13
  /**
@@ -23,16 +23,23 @@ export declare function isFactScope(name: string): boolean;
23
23
  */
24
24
  export declare function scopePrefixOf(name: string): string;
25
25
  /**
26
- * 事实的来路:start 建连并按帧回调,cursor 报已收到的宿主 rev(断线重连时交给宿主)。
26
+ * 事实传输层的来路:SSE 直连,或降级成轮询。
27
+ */
28
+ export type FactTransportMode = 'sse' | 'polling';
29
+ /**
30
+ * 事实的来路:start 建连并按帧回调,cursor 报已收到的宿主 rev(断线重连时交给宿主),
31
+ * onMode 报这一层现在是哪种传输。
27
32
  */
28
33
  export interface FactTransport {
29
34
  start(handlers: {
30
35
  readonly onFrame: (frame: FactFrame) => void;
31
36
  readonly cursor: () => number;
37
+ readonly onMode?: ((mode: FactTransportMode) => void) | undefined;
32
38
  }): () => void;
33
39
  }
34
40
  /**
35
- * 浏览器侧的事实通道:订阅、读版本、手动刷新,帧到了由它分发给订阅者。
41
+ * 浏览器侧的事实通道:订阅、读版本、手动刷新,帧到了由它分发给订阅者;
42
+ * mode 是传输层现在走的来路(还没建连就是 null),subscribeMode 听它换档。
36
43
  */
37
44
  export interface FactChannel {
38
45
  subscribe(fact: string, listener: () => void): () => void;
@@ -40,6 +47,8 @@ export interface FactChannel {
40
47
  refresh(fact?: string): void;
41
48
  applyFrame(frame: FactFrame): void;
42
49
  subscriberCount(): number;
50
+ mode(): FactTransportMode | null;
51
+ subscribeMode(listener: () => void): () => void;
43
52
  }
44
53
  /**
45
54
  * 造一条事实通道:第一次订阅时才连传输层,最后一个订阅者走掉就断开。
@@ -1,5 +1,5 @@
1
1
  /**
2
- * 范围查法的后缀:cmdb/* 这类名字表示「这个前缀下的一族」,不是一条事实。
2
+ * 范围查法的后缀:inventory/* 这类名字表示「这个前缀下的一族」,不是一条事实。
3
3
  */
4
4
  export const FACT_SCOPE_SUFFIX = '*';
5
5
  /**
@@ -25,10 +25,19 @@ export function scopePrefixOf(name) {
25
25
  */
26
26
  export function createFactChannel(options) {
27
27
  const entries = new Map();
28
+ const modeListeners = new Set();
28
29
  let epoch = null;
29
30
  let stopTransport = null;
30
31
  let hostRev = 0;
31
32
  let generation = 0;
33
+ let mode = null;
34
+ const setMode = (next) => {
35
+ if (mode === next)
36
+ return;
37
+ mode = next;
38
+ for (const listener of [...modeListeners])
39
+ listener();
40
+ };
32
41
  const entryOf = (fact) => {
33
42
  const existing = entries.get(fact);
34
43
  if (existing !== undefined)
@@ -72,6 +81,7 @@ export function createFactChannel(options) {
72
81
  stopTransport = options.transport.start({
73
82
  onFrame: (frame) => channel.applyFrame(frame),
74
83
  cursor: () => hostRev,
84
+ onMode: (next) => setMode(next),
75
85
  });
76
86
  };
77
87
  const releaseTransport = () => {
@@ -79,6 +89,7 @@ export function createFactChannel(options) {
79
89
  return;
80
90
  stopTransport();
81
91
  stopTransport = null;
92
+ setMode(null);
82
93
  };
83
94
  const channel = {
84
95
  revisionOf: (fact) => entries.get(fact)?.rev ?? 0,
@@ -98,6 +109,13 @@ export function createFactChannel(options) {
98
109
  count += entry.listeners.size;
99
110
  return count;
100
111
  },
112
+ mode: () => mode,
113
+ subscribeMode(listener) {
114
+ modeListeners.add(listener);
115
+ return () => {
116
+ modeListeners.delete(listener);
117
+ };
118
+ },
101
119
  refresh(fact) {
102
120
  generation += 1;
103
121
  if (fact === undefined) {
@@ -0,0 +1,38 @@
1
+ export type OriginRead = {
2
+ readonly kind: 'ok';
3
+ readonly remote: string;
4
+ } | {
5
+ readonly kind: 'no-origin';
6
+ readonly detail?: string;
7
+ } | {
8
+ readonly kind: 'unknown';
9
+ readonly reason: string;
10
+ readonly detail?: string;
11
+ };
12
+ export type BranchRead = {
13
+ readonly kind: 'ok';
14
+ readonly branch: string;
15
+ } | {
16
+ readonly kind: 'no-branch';
17
+ readonly detail?: string | undefined;
18
+ } | {
19
+ readonly kind: 'unknown';
20
+ readonly reason: string;
21
+ readonly detail?: string | undefined;
22
+ };
23
+ export type HeadRead = {
24
+ readonly kind: 'ok';
25
+ readonly commit: string;
26
+ } | {
27
+ readonly kind: 'no-head';
28
+ readonly detail?: string;
29
+ } | {
30
+ readonly kind: 'unknown';
31
+ readonly reason: string;
32
+ readonly detail?: string;
33
+ };
34
+ export interface GitReader {
35
+ origin(path: string): Promise<OriginRead>;
36
+ branch(path: string): Promise<BranchRead>;
37
+ head(path: string): Promise<HeadRead>;
38
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ import type { LibNeed } from './needs.js';
2
+ export interface LibReader {
3
+ load<T = unknown>(need: LibNeed, entry: string): Promise<T>;
4
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,132 @@
1
+ /**
2
+ * 模块要的一样东西的类别;v2 只认这四种,加种类在注册表里加,不改这份形状。
3
+ */
4
+ export declare const NEED_KINDS: readonly ["bin", "extension", "lib", "env"];
5
+ /**
6
+ * need 的类别。
7
+ */
8
+ export type NeedKind = (typeof NEED_KINDS)[number];
9
+ /**
10
+ * 一种外部来源;每一种都只说「去哪拿」,装不装、怎么装由宿主决定。
11
+ */
12
+ export type SupplySource = {
13
+ readonly kind: 'npm';
14
+ readonly package?: string;
15
+ readonly registryEnv?: string;
16
+ readonly registryDefault?: string;
17
+ } | {
18
+ readonly kind: 'git';
19
+ readonly url: string;
20
+ readonly ref?: string;
21
+ } | {
22
+ readonly kind: 'local';
23
+ readonly path?: string;
24
+ readonly env?: string;
25
+ };
26
+ /**
27
+ * 协议认得的外部来源种类。
28
+ */
29
+ export declare const SUPPLY_SOURCE_KINDS: readonly ["npm", "git", "local"];
30
+ /**
31
+ * 外部来源的类别。
32
+ */
33
+ export type SupplySourceKind = (typeof SUPPLY_SOURCE_KINDS)[number];
34
+ /**
35
+ * 每条 need 都有的字段:为什么需要它、缺了算不算问题。
36
+ */
37
+ export interface NeedCommon {
38
+ readonly kind: NeedKind;
39
+ readonly purpose: string;
40
+ readonly required?: boolean;
41
+ readonly id?: string;
42
+ }
43
+ /**
44
+ * 机器上要有一个可执行文件;探法是 `command -v` / `where`。
45
+ */
46
+ export interface BinNeed extends NeedCommon {
47
+ readonly kind: 'bin';
48
+ readonly name: string;
49
+ }
50
+ /**
51
+ * 某个运行时上要有一个扩展(opencli 的插件就是这种),并且要提供这些命令。
52
+ */
53
+ export interface ExtensionNeed extends NeedCommon {
54
+ readonly kind: 'extension';
55
+ readonly runtime: string;
56
+ readonly name: string;
57
+ readonly commands?: readonly string[];
58
+ readonly version?: string;
59
+ readonly sources?: readonly SupplySource[];
60
+ }
61
+ /**
62
+ * 要在隔离运行时里有一个共用依赖包。
63
+ */
64
+ export interface LibNeed extends NeedCommon {
65
+ readonly kind: 'lib';
66
+ readonly name: string;
67
+ readonly version?: string;
68
+ readonly sources?: readonly SupplySource[];
69
+ }
70
+ /**
71
+ * 跑起来时要有这个环境变量;`secret` 为真时任何地方都不回显它的值。
72
+ */
73
+ export interface EnvNeed extends NeedCommon {
74
+ readonly kind: 'env';
75
+ readonly name: string;
76
+ readonly secret?: boolean;
77
+ }
78
+ /**
79
+ * 模块声明的一条需要。
80
+ */
81
+ export type Need = BinNeed | ExtensionNeed | LibNeed | EnvNeed;
82
+ /**
83
+ * 一份 needs 校验结果:错误拒收,警告只提醒(未知可选字段就是警告)。
84
+ */
85
+ export interface NeedsProblems {
86
+ readonly errors: readonly string[];
87
+ readonly warnings: readonly string[];
88
+ }
89
+ /**
90
+ * 协议认得的 need 字段;`x-` 前缀的字段留给第三方扩展,直接忽略。
91
+ */
92
+ export declare const NEED_KEYS: readonly string[];
93
+ /**
94
+ * 注册表把「怎么校验、怎么探、能不能代装」收在一处;加一种 kind 只在这里加一行。
95
+ */
96
+ export interface NeedKindSpec {
97
+ readonly kind: NeedKind;
98
+ readonly probe: 'bin' | 'extension' | 'package' | 'env';
99
+ readonly sources: readonly SupplySourceKind[];
100
+ readonly validate: (raw: Readonly<Record<string, unknown>>, at: string) => readonly string[];
101
+ }
102
+ /**
103
+ * 这个字符串是不是协议认得的 need 类别。
104
+ * @param value 待判的值。
105
+ * @returns 是就收窄成 NeedKind。
106
+ */
107
+ export declare function isKnownNeedKind(value: unknown): value is NeedKind;
108
+ /**
109
+ * 一条 need 的稳定标识:作者写 `id` 就用它,否则 `kind:name`。
110
+ * @param need 一条 need。
111
+ * @returns 标识串。
112
+ */
113
+ export declare function needIdOf(need: Need): string;
114
+ /**
115
+ * 一张表说了算:每种 kind 的探法、可用来源与校验。
116
+ */
117
+ export declare const NEED_KIND_SPECS: Readonly<Record<NeedKind, NeedKindSpec>>;
118
+ /**
119
+ * 校验一条 need;未知类别是错误,未知字段是警告。
120
+ * @param label 报错时用的主语(模块包名)。
121
+ * @param raw 这一条 need 的原始值。
122
+ * @param index 它在 needs 里的下标。
123
+ * @returns 错误与警告。
124
+ */
125
+ export declare function needProblemsOf(label: string, raw: unknown, index: number): NeedsProblems;
126
+ /**
127
+ * 校验整张 needs 表(没写就是空表)。
128
+ * @param label 报错时用的主语。
129
+ * @param raw 声明里的 needs 原始值。
130
+ * @returns 错误与警告。
131
+ */
132
+ export declare function needsProblemsOf(label: string, raw: unknown): NeedsProblems;
@@ -0,0 +1,232 @@
1
+ /**
2
+ * 模块要的一样东西的类别;v2 只认这四种,加种类在注册表里加,不改这份形状。
3
+ */
4
+ export const NEED_KINDS = ['bin', 'extension', 'lib', 'env'];
5
+ /**
6
+ * 协议认得的外部来源种类。
7
+ */
8
+ export const SUPPLY_SOURCE_KINDS = ['npm', 'git', 'local'];
9
+ /**
10
+ * 协议认得的 need 字段;`x-` 前缀的字段留给第三方扩展,直接忽略。
11
+ */
12
+ export const NEED_KEYS = [
13
+ 'kind',
14
+ 'purpose',
15
+ 'required',
16
+ 'id',
17
+ 'name',
18
+ 'runtime',
19
+ 'commands',
20
+ 'version',
21
+ 'sources',
22
+ 'secret',
23
+ ];
24
+ const SOURCE_KEYS = ['kind', 'package', 'registryEnv', 'registryDefault', 'url', 'ref', 'path', 'env'];
25
+ const REGISTRY_PATTERN = /^(?:https?|file):\/\//;
26
+ function text(value) {
27
+ return typeof value === 'string' ? value.trim() : '';
28
+ }
29
+ function isRecord(value) {
30
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
31
+ }
32
+ /**
33
+ * 这个字符串是不是协议认得的 need 类别。
34
+ * @param value 待判的值。
35
+ * @returns 是就收窄成 NeedKind。
36
+ */
37
+ export function isKnownNeedKind(value) {
38
+ return typeof value === 'string' && NEED_KINDS.includes(value);
39
+ }
40
+ /**
41
+ * 一条 need 的稳定标识:作者写 `id` 就用它,否则 `kind:name`。
42
+ * @param need 一条 need。
43
+ * @returns 标识串。
44
+ */
45
+ export function needIdOf(need) {
46
+ return need.id === undefined || need.id.trim() === '' ? `${need.kind}:${need.name}` : need.id;
47
+ }
48
+ function sourceProblemsOf(raw, at) {
49
+ if (!isRecord(raw))
50
+ return [`${at} 要是对象`];
51
+ const kind = text(raw['kind']);
52
+ if (!SUPPLY_SOURCE_KINDS.includes(kind)) {
53
+ return [`${at}.kind 不认识 —— ${JSON.stringify(raw['kind'])}(只有 ${SUPPLY_SOURCE_KINDS.join(' / ')})`];
54
+ }
55
+ const errors = [];
56
+ for (const key of Object.keys(raw)) {
57
+ if (SOURCE_KEYS.includes(key) || key.startsWith('x-'))
58
+ continue;
59
+ errors.push(`${at} 有不认识的字段 ${key}`);
60
+ }
61
+ if (kind === 'npm') {
62
+ if (raw['package'] !== undefined && text(raw['package']) === '')
63
+ errors.push(`${at}.package 是空串`);
64
+ if (raw['registryEnv'] !== undefined && text(raw['registryEnv']) === '') {
65
+ errors.push(`${at}.registryEnv 是空串`);
66
+ }
67
+ if (raw['registryDefault'] !== undefined && !REGISTRY_PATTERN.test(text(raw['registryDefault']))) {
68
+ errors.push(`${at}.registryDefault 要是 http(s):// 或 file:// 的源地址`);
69
+ }
70
+ return errors;
71
+ }
72
+ if (kind === 'git') {
73
+ if (text(raw['url']) === '')
74
+ errors.push(`${at}.url 没写`);
75
+ return errors;
76
+ }
77
+ if (text(raw['path']) === '' && text(raw['env']) === '') {
78
+ errors.push(`${at} 是 local,但 path 与 env 都没写`);
79
+ }
80
+ return errors;
81
+ }
82
+ function sourcesProblemsOf(raw, at, allowed) {
83
+ if (raw === undefined)
84
+ return [];
85
+ if (!Array.isArray(raw))
86
+ return [`${at}.sources 要是数组`];
87
+ if (raw.length === 0)
88
+ return [`${at}.sources 是空数组 —— 不代装就整条删掉`];
89
+ if (allowed.length === 0) {
90
+ return [`${at} 这种需要不支持 sources —— 它没有「从哪装」这回事`];
91
+ }
92
+ const errors = [];
93
+ raw.forEach((source, index) => {
94
+ const one = sourceProblemsOf(source, `${at}.sources[${index}]`);
95
+ errors.push(...one);
96
+ if (one.length === 0 && isRecord(source)) {
97
+ const kind = text(source['kind']);
98
+ if (!allowed.includes(kind)) {
99
+ errors.push(`${at}.sources[${index}].kind 是 ${kind},这种需要只支持 ${allowed.join(' / ')}`);
100
+ }
101
+ }
102
+ });
103
+ return errors;
104
+ }
105
+ function commonProblemsOf(raw, at) {
106
+ const errors = [];
107
+ if (text(raw['purpose']) === '')
108
+ errors.push(`${at}.purpose 没写 —— 「为什么要它」是缺失文案的那半句`);
109
+ if (raw['required'] !== undefined && typeof raw['required'] !== 'boolean') {
110
+ errors.push(`${at}.required 要是布尔`);
111
+ }
112
+ if (raw['id'] !== undefined && text(raw['id']) === '')
113
+ errors.push(`${at}.id 是空串`);
114
+ return errors;
115
+ }
116
+ function perKindProblemsOf(kind, raw, at) {
117
+ const errors = [];
118
+ if (kind === 'bin' || kind === 'lib' || kind === 'env') {
119
+ if (text(raw['name']) === '')
120
+ errors.push(`${at}.name 没写`);
121
+ }
122
+ if (kind === 'extension') {
123
+ if (text(raw['runtime']) === '')
124
+ errors.push(`${at}.runtime 没写 —— 扩展属于哪个运行时(如 opencli)`);
125
+ if (text(raw['name']) === '')
126
+ errors.push(`${at}.name 没写`);
127
+ if (raw['commands'] !== undefined) {
128
+ if (!Array.isArray(raw['commands']))
129
+ errors.push(`${at}.commands 要是数组`);
130
+ else if (raw['commands'].some((one) => text(one) === ''))
131
+ errors.push(`${at}.commands 里有空字符串`);
132
+ }
133
+ }
134
+ if (kind === 'env' && raw['secret'] !== undefined && typeof raw['secret'] !== 'boolean') {
135
+ errors.push(`${at}.secret 要是布尔`);
136
+ }
137
+ return errors;
138
+ }
139
+ function validateKind(kind) {
140
+ return (raw, at) => perKindProblemsOf(kind, raw, at);
141
+ }
142
+ /**
143
+ * 一张表说了算:每种 kind 的探法、可用来源与校验。
144
+ */
145
+ export const NEED_KIND_SPECS = Object.freeze({
146
+ bin: Object.freeze({
147
+ kind: 'bin',
148
+ probe: 'bin',
149
+ sources: Object.freeze([]),
150
+ validate: validateKind('bin'),
151
+ }),
152
+ extension: Object.freeze({
153
+ kind: 'extension',
154
+ probe: 'extension',
155
+ sources: Object.freeze(['npm', 'git', 'local']),
156
+ validate: validateKind('extension'),
157
+ }),
158
+ lib: Object.freeze({
159
+ kind: 'lib',
160
+ probe: 'package',
161
+ sources: Object.freeze(['npm']),
162
+ validate: validateKind('lib'),
163
+ }),
164
+ env: Object.freeze({
165
+ kind: 'env',
166
+ probe: 'env',
167
+ sources: Object.freeze([]),
168
+ validate: validateKind('env'),
169
+ }),
170
+ });
171
+ /**
172
+ * 校验一条 need;未知类别是错误,未知字段是警告。
173
+ * @param label 报错时用的主语(模块包名)。
174
+ * @param raw 这一条 need 的原始值。
175
+ * @param index 它在 needs 里的下标。
176
+ * @returns 错误与警告。
177
+ */
178
+ export function needProblemsOf(label, raw, index) {
179
+ const at = `${label}.needs[${index}]`;
180
+ if (!isRecord(raw))
181
+ return { errors: [`${at} 要是对象`], warnings: [] };
182
+ const kind = text(raw['kind']);
183
+ if (!isKnownNeedKind(kind)) {
184
+ return {
185
+ errors: [
186
+ `${at}.kind 不认识 —— ${JSON.stringify(raw['kind'])}(v2 只认 ${NEED_KINDS.join(' / ')};` +
187
+ '要是模块用了更新的工作台才有的种类,升级工作台)',
188
+ ],
189
+ warnings: [],
190
+ };
191
+ }
192
+ const warnings = [];
193
+ for (const key of Object.keys(raw)) {
194
+ if (NEED_KEYS.includes(key) || key.startsWith('x-'))
195
+ continue;
196
+ warnings.push(`${at} 有不认识的字段 ${key}(宿主会忽略它)`);
197
+ }
198
+ const errors = [
199
+ ...commonProblemsOf(raw, at),
200
+ ...perKindProblemsOf(kind, raw, at),
201
+ ...sourcesProblemsOf(raw['sources'], at, NEED_KIND_SPECS[kind].sources),
202
+ ];
203
+ return { errors, warnings };
204
+ }
205
+ /**
206
+ * 校验整张 needs 表(没写就是空表)。
207
+ * @param label 报错时用的主语。
208
+ * @param raw 声明里的 needs 原始值。
209
+ * @returns 错误与警告。
210
+ */
211
+ export function needsProblemsOf(label, raw) {
212
+ if (raw === undefined)
213
+ return { errors: [], warnings: [] };
214
+ if (!Array.isArray(raw))
215
+ return { errors: [`${label}.needs 要是数组`], warnings: [] };
216
+ const errors = [];
217
+ const warnings = [];
218
+ const seen = new Set();
219
+ raw.forEach((one, index) => {
220
+ const found = needProblemsOf(label, one, index);
221
+ errors.push(...found.errors);
222
+ warnings.push(...found.warnings);
223
+ if (found.errors.length > 0 || !isRecord(one))
224
+ return;
225
+ const kind = text(one['kind']);
226
+ const id = text(one['id']) === '' ? `${kind}:${text(one['name'])}` : text(one['id']);
227
+ if (seen.has(id))
228
+ errors.push(`${label}.needs 里 ${id} 重复了 —— 每条 need 的 id 要唯一`);
229
+ seen.add(id);
230
+ });
231
+ return { errors, warnings };
232
+ }
@@ -0,0 +1 @@
1
+ export type ProvisionProblem = 'not-declared' | 'env-missing' | 'malformed';
@@ -0,0 +1 @@
1
+ export {};