@dsh-workbench/shared 0.3.11 → 1.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +97 -0
- package/dist/api/blocker-table.d.ts +3 -3
- package/dist/api/blocker-table.js +47 -23
- package/dist/api/dsh.d.ts +1 -1
- package/dist/api/workbench-client.js +2 -1
- package/dist/components/Activity.css +0 -1
- package/dist/components/ApprovalDetail.css +1 -2
- package/dist/components/ApprovalDetail.d.ts +1 -1
- package/dist/components/ApprovalPlan.css +0 -1
- package/dist/components/Card.css +0 -1
- package/dist/components/Card.d.ts +1 -1
- package/dist/components/CardBoundary.d.ts +1 -1
- package/dist/components/CardHead.css +0 -1
- package/dist/components/CardHead.d.ts +1 -1
- package/dist/components/ChoiceGroup.css +1 -2
- package/dist/components/ConfirmBar.d.ts +1 -1
- package/dist/components/ConfirmBar.js +1 -1
- package/dist/components/Form.css +1 -1
- package/dist/components/FormActions.js +1 -1
- package/dist/components/LongTaskRow.css +1 -2
- package/dist/components/LongTaskRow.d.ts +1 -1
- package/dist/components/LongTaskRow.js +1 -1
- package/dist/components/Note.css +0 -1
- package/dist/components/ResourceStates.css +0 -1
- package/dist/components/SettingsSection.css +0 -1
- package/dist/components/Spinner.css +0 -1
- package/dist/components/Stack.css +0 -1
- package/dist/components/StateBlock.css +0 -1
- package/dist/components/board-module.d.ts +3 -3
- package/dist/components/icons.d.ts +1 -1
- package/dist/components/icons.js +11 -4
- package/dist/config/constants.d.ts +2 -2
- package/dist/config/constants.js +2 -2
- package/dist/contract/adapters.d.ts +10 -0
- package/dist/contract/cli.d.ts +3 -0
- package/dist/contract/data.d.ts +126 -0
- package/dist/{api → contract}/facts.d.ts +12 -3
- package/dist/{api → contract}/facts.js +19 -1
- package/dist/contract/needs.d.ts +132 -0
- package/dist/contract/needs.js +232 -0
- package/dist/contract/plugin-source.d.ts +1 -0
- package/dist/contract/protocol/bundle-install.d.ts +136 -0
- package/dist/contract/protocol/bundle-install.js +12 -0
- package/dist/contract/protocol/config-sync.d.ts +55 -0
- package/dist/contract/protocol/config-sync.js +2 -0
- package/dist/contract/protocol/diy.d.ts +4 -0
- package/dist/contract/protocol/diy.js +4 -0
- package/dist/contract/protocol/dsh-plugins.d.ts +11 -0
- package/dist/contract/protocol/dsh-plugins.js +1 -0
- package/dist/contract/protocol/long-tasks.d.ts +13 -0
- package/dist/contract/protocol/long-tasks.js +1 -0
- package/dist/contract/protocol/market-index.d.ts +195 -0
- package/dist/contract/protocol/market-index.js +7 -0
- package/dist/contract/protocol/platform.d.ts +44 -0
- package/dist/contract/protocol/platform.js +1 -0
- package/dist/contract/protocol/preflight-wake.d.ts +7 -0
- package/dist/contract/protocol/preflight-wake.js +1 -0
- package/dist/contract/protocol/profile-create.d.ts +30 -0
- package/dist/contract/protocol/profile-create.js +2 -0
- package/dist/contract/protocol/sidebar-edition.d.ts +14 -0
- package/dist/contract/protocol/sidebar-edition.js +2 -0
- package/dist/contract/protocol/unit-manifests.d.ts +6 -0
- package/dist/contract/protocol/unit-manifests.js +1 -0
- package/dist/contract/unit-board.js +1 -0
- package/dist/contract/unit-capability.d.ts +34 -0
- package/dist/contract/unit-capability.js +1 -0
- package/dist/{host → contract}/unit-declaration.d.ts +7 -5
- package/dist/{api → contract}/unit-declaration.js +19 -13
- package/dist/contract/unit.d.ts +57 -0
- package/dist/contract/unit.js +24 -0
- package/dist/contract/workbench-contract.d.ts +15 -0
- package/dist/contract/workbench-contract.js +1 -0
- package/dist/host/adapter-set.d.ts +26 -0
- package/dist/host/adapter-set.js +243 -0
- package/dist/host/adapter-types.d.ts +79 -0
- package/dist/host/adapter-types.js +23 -0
- package/dist/host/adapters.d.ts +22 -0
- package/dist/host/adapters.js +9 -0
- package/dist/host/browser.d.ts +3 -0
- package/dist/host/browser.js +3 -0
- package/dist/host/changelog.d.ts +21 -0
- package/dist/host/changelog.js +188 -0
- package/dist/host/channel-plugin.d.ts +15 -0
- package/dist/host/channel-plugin.js +42 -0
- package/dist/host/cli.d.ts +4 -0
- package/dist/host/cli.js +7 -0
- package/dist/host/command-name.d.ts +1 -0
- package/dist/host/command-name.js +14 -0
- package/dist/host/data-error.d.ts +13 -0
- package/dist/host/data-error.js +20 -0
- package/dist/host/data-root.js +3 -0
- package/dist/host/diy-debug.js +2 -1
- package/dist/host/diy-record.js +2 -1
- package/dist/host/facts.d.ts +1 -1
- package/dist/host/facts.js +3 -2
- package/dist/host/git.js +2 -2
- package/dist/host/http.js +1 -1
- package/dist/host/lib-capabilities.d.ts +22 -0
- package/dist/host/lib-capabilities.js +37 -0
- package/dist/host/lib-install.d.ts +9 -0
- package/dist/host/lib-install.js +10 -0
- package/dist/host/long-task.d.ts +1 -1
- package/dist/host/long-task.js +4 -3
- package/dist/host/market-index.d.ts +22 -0
- package/dist/host/market-index.js +420 -0
- package/dist/host/needs.d.ts +4 -0
- package/dist/host/needs.js +2 -0
- package/dist/host/patch.d.ts +9 -0
- package/dist/host/patch.js +78 -0
- package/dist/host/paths.d.ts +12 -0
- package/dist/host/paths.js +28 -0
- package/dist/host/platform.d.ts +14 -0
- package/dist/host/platform.js +40 -0
- package/dist/host/plugin-source.d.ts +8 -6
- package/dist/host/plugin-source.js +43 -33
- package/dist/host/plugin.d.ts +4 -0
- package/dist/host/plugin.js +39 -0
- package/dist/host/port-types.d.ts +191 -0
- package/dist/host/port-types.js +1 -0
- package/dist/host/preflight.d.ts +28 -0
- package/dist/host/preflight.js +1 -0
- package/dist/host/profile-port.d.ts +4 -0
- package/dist/host/profile-port.js +4 -0
- package/dist/host/provision.d.ts +2 -2
- package/dist/host/provision.js +5 -3
- package/dist/host/recipe-rules.d.ts +5 -0
- package/dist/host/recipe-rules.js +382 -0
- package/dist/host/recipe.d.ts +14 -0
- package/dist/host/recipe.js +283 -0
- package/dist/host/shell-text.d.ts +9 -2
- package/dist/host/shell-text.js +15 -3
- package/dist/host/shell.d.ts +2 -0
- package/dist/host/shell.js +7 -0
- package/dist/host/spec.d.ts +8 -0
- package/dist/host/spec.js +24 -0
- package/dist/host/supply-index.d.ts +34 -0
- package/dist/host/supply-index.js +202 -0
- package/dist/host/supply-port.d.ts +5 -0
- package/dist/host/supply-port.js +39 -0
- package/dist/host/time.d.ts +12 -0
- package/dist/host/time.js +19 -0
- package/dist/host/tokens.d.ts +26 -0
- package/dist/host/tokens.js +154 -0
- package/dist/host/tool-kit.js +1 -1
- package/dist/host/unit-face.d.ts +5 -4
- package/dist/host/version-range.d.ts +2 -0
- package/dist/host/version-range.js +73 -0
- package/dist/host/version.d.ts +3 -0
- package/dist/host/version.js +29 -0
- package/dist/host.d.ts +47 -16
- package/dist/host.js +47 -16
- package/dist/i18n/en.js +224 -71
- package/dist/i18n/index.d.ts +298 -73
- package/dist/i18n/merge.js +1 -1
- package/dist/i18n/need-text.d.ts +26 -0
- package/dist/i18n/need-text.js +26 -0
- package/dist/i18n/settings.d.ts +70 -0
- package/dist/i18n/settings.js +136 -0
- package/dist/i18n/zh.d.ts +297 -72
- package/dist/i18n/zh.js +226 -73
- package/dist/index.d.ts +23 -7
- package/dist/index.js +23 -7
- package/dist/{api → lib}/dsh-client.d.ts +11 -1
- package/dist/lib/dsh-client.js +1 -0
- package/dist/lib/market-index.d.ts +7 -0
- package/dist/lib/market-index.js +25 -0
- package/dist/lib/react.d.ts +0 -40
- package/dist/lib/react.js +0 -36
- package/dist/lib/ui.js +3 -9
- package/dist/testing/data.d.ts +13 -0
- package/dist/testing/data.js +46 -0
- package/dist/testing/declaration.d.ts +1 -1
- package/dist/testing/declaration.js +1 -1
- package/dist/testing/host-fakes.d.ts +0 -13
- package/dist/testing/host-fakes.js +0 -24
- package/dist/testing/needs.d.ts +16 -0
- package/dist/testing/needs.js +46 -0
- package/dist/testing.d.ts +2 -0
- package/dist/testing.js +2 -0
- package/package.json +18 -2
- package/src/api/__tests__/blocker-table.test.ts +135 -86
- package/src/api/blocker-table.ts +52 -26
- package/src/api/dsh.ts +1 -1
- package/src/api/host-write.ts +0 -1
- package/src/api/workbench-client.test.ts +2 -2
- package/src/api/workbench-client.ts +2 -1
- package/src/components/Activity.css +0 -1
- package/src/components/ApprovalDetail.css +1 -2
- package/src/components/ApprovalDetail.tsx +1 -1
- package/src/components/ApprovalPlan.css +0 -1
- package/src/components/Card.css +0 -1
- package/src/components/Card.tsx +1 -1
- package/src/components/CardAnchor.test.tsx +1 -1
- package/src/components/CardBoundary.tsx +1 -1
- package/src/components/CardHead.css +0 -1
- package/src/components/CardHead.tsx +1 -1
- package/src/components/ChoiceGroup.css +1 -2
- package/src/components/ConfirmBar.tsx +1 -1
- package/src/components/Form.css +1 -1
- package/src/components/Form.tsx +1 -1
- package/src/components/FormActions.tsx +1 -1
- package/src/components/LongTaskRow.css +1 -2
- package/src/components/LongTaskRow.tsx +1 -1
- package/src/components/Note.css +0 -1
- package/src/components/ResourceStates.css +0 -1
- package/src/components/SelectFieldNodes.tsx +0 -1
- package/src/components/SettingsSection.css +0 -1
- package/src/components/Spinner.css +0 -1
- package/src/components/Stack.css +0 -1
- package/src/components/StateBlock.css +0 -1
- package/src/components/__tests__/long-task-row.test.ts +1 -1
- package/src/components/board-module.ts +3 -3
- package/src/components/icons.tsx +16 -8
- package/src/config/constants.ts +2 -2
- package/src/{api → contract}/__tests__/facts.test.ts +73 -25
- package/src/{api → contract}/__tests__/long-task.test.ts +3 -3
- package/src/contract/__tests__/needs.test.ts +74 -0
- package/src/{host → contract}/__tests__/unit-declaration.test.ts +1 -1
- package/src/contract/__tests__/unit.test.ts +43 -0
- package/src/contract/adapters.ts +9 -0
- package/src/contract/cli.ts +3 -0
- package/src/contract/data.ts +145 -0
- package/src/{api → contract}/facts.ts +34 -4
- package/src/contract/needs.ts +331 -0
- package/src/contract/plugin-source.ts +1 -0
- package/src/contract/protocol/bundle-install.ts +198 -0
- package/src/contract/protocol/config-sync.ts +65 -0
- package/src/contract/protocol/diy.ts +4 -0
- package/src/contract/protocol/dsh-plugins.ts +13 -0
- package/src/contract/protocol/long-tasks.ts +16 -0
- package/src/contract/protocol/market-index.ts +246 -0
- package/src/contract/protocol/platform.ts +47 -0
- package/src/contract/protocol/preflight-wake.ts +17 -0
- package/src/contract/protocol/profile-create.ts +36 -0
- package/src/contract/protocol/sidebar-edition.ts +19 -0
- package/src/contract/protocol/unit-manifests.ts +8 -0
- package/src/{api → contract}/unit-board.ts +0 -1
- package/src/contract/unit-capability.ts +37 -0
- package/src/{host → contract}/unit-declaration.ts +22 -18
- package/src/contract/unit.ts +76 -0
- package/src/contract/workbench-contract.ts +30 -0
- package/src/host/__tests__/adapter-set.test.ts +228 -0
- package/src/host/__tests__/adapters.test.ts +27 -0
- package/src/host/__tests__/changelog.test.ts +102 -0
- package/src/host/__tests__/command-name.test.ts +16 -0
- package/src/host/__tests__/diy-record.test.ts +3 -3
- package/src/host/__tests__/facts.test.ts +5 -5
- package/src/host/__tests__/long-task.test.ts +1 -1
- package/src/host/__tests__/market-index.test.ts +179 -0
- package/src/host/__tests__/plugin-ledger.test.ts +10 -10
- package/src/host/__tests__/provision.test.ts +7 -6
- package/src/host/__tests__/shell-text.test.ts +16 -1
- package/src/host/__tests__/supply-index.test.ts +137 -0
- package/src/host/__tests__/tokens.test.ts +110 -0
- package/src/host/__tests__/version-range.test.ts +21 -0
- package/src/host/adapter-set.ts +298 -0
- package/src/host/adapter-types.ts +105 -0
- package/src/host/adapters.ts +44 -0
- package/src/host/browser.ts +3 -0
- package/src/host/changelog.ts +212 -0
- package/src/host/channel-plugin.ts +55 -0
- package/src/host/cli.ts +11 -0
- package/src/host/command-name.ts +15 -0
- package/src/host/data-error.ts +21 -0
- package/src/host/data-root.ts +2 -0
- package/src/host/diy-debug.ts +2 -1
- package/src/host/diy-record.ts +2 -1
- package/src/host/facts.ts +4 -3
- package/src/host/git.ts +2 -2
- package/src/host/http.ts +1 -1
- package/src/host/lib-capabilities.ts +52 -0
- package/src/host/lib-install.ts +18 -0
- package/src/host/long-task.ts +4 -3
- package/src/host/market-index.ts +413 -0
- package/src/host/needs.ts +6 -0
- package/src/host/patch.ts +93 -0
- package/src/host/paths.ts +37 -0
- package/src/host/platform.ts +48 -0
- package/src/host/plugin-source.ts +48 -56
- package/src/host/plugin.ts +39 -0
- package/src/host/port-types.ts +222 -0
- package/src/host/preflight.ts +31 -0
- package/src/host/profile-port.ts +9 -0
- package/src/host/provision.ts +7 -4
- package/src/host/recipe-rules.ts +330 -0
- package/src/host/recipe.test.ts +334 -0
- package/src/host/recipe.ts +323 -0
- package/src/host/shell-text.ts +15 -3
- package/src/host/shell.ts +9 -0
- package/src/host/spec.ts +32 -0
- package/src/host/supply-index.ts +256 -0
- package/src/host/supply-port.ts +45 -0
- package/src/host/time.ts +22 -0
- package/src/host/tokens.ts +186 -0
- package/src/host/tool-kit.ts +1 -1
- package/src/host/unit-face.ts +5 -4
- package/src/host/version-range.ts +71 -0
- package/src/host/version.ts +30 -0
- package/src/host.ts +47 -16
- package/src/i18n/en.ts +224 -71
- package/src/i18n/merge.test.ts +6 -6
- package/src/i18n/merge.ts +1 -1
- package/src/i18n/need-text.ts +27 -0
- package/src/i18n/settings.ts +141 -0
- package/src/i18n/zh.ts +227 -73
- package/src/index.ts +23 -7
- package/src/lib/blocker-action.ts +0 -1
- package/src/{api → lib}/dsh-client.ts +12 -1
- package/src/lib/market-index.ts +36 -0
- package/src/lib/react.ts +0 -40
- package/src/lib/text.test.ts +2 -2
- package/src/lib/ui.test.ts +6 -5
- package/src/lib/ui.ts +3 -9
- package/src/testing/__tests__/declaration.test.ts +1 -1
- package/src/testing/data.ts +66 -0
- package/src/testing/declaration.ts +2 -2
- package/src/testing/host-fakes.ts +0 -38
- package/src/testing/needs.ts +80 -0
- package/src/testing.ts +2 -0
- package/dist/api/unit-declaration.d.ts +0 -65
- package/dist/api/unit.d.ts +0 -85
- package/dist/api/unit.js +0 -8
- package/dist/api/workbench-contract.d.ts +0 -44
- package/dist/components/MockStrip.css +0 -39
- package/dist/components/MockStrip.d.ts +0 -15
- package/dist/components/MockStrip.js +0 -8
- package/dist/components/SaveBar.css +0 -7
- package/dist/host/browser-find.d.ts +0 -38
- package/dist/host/browser-find.js +0 -242
- package/dist/host/browser-read.d.ts +0 -28
- package/dist/host/browser-read.js +0 -243
- package/dist/host/opencli-runtime.d.ts +0 -25
- package/dist/host/opencli-runtime.js +0 -56
- package/dist/host/opencli-window.d.ts +0 -2
- package/dist/host/opencli-window.js +0 -8
- package/dist/host/opencli.d.ts +0 -37
- package/dist/host/opencli.js +0 -155
- package/dist/host/unit-declaration.js +0 -213
- package/dist/host/unit-libs.d.ts +0 -37
- package/dist/lib/diy-debug.d.ts +0 -80
- package/dist/lib/diy-debug.js +0 -88
- package/dist/lib/diy-record.d.ts +0 -135
- package/dist/lib/diy-record.js +0 -162
- package/dist/lib/lint-probe.d.ts +0 -1
- package/dist/lib/lint-probe.js +0 -6
- package/dist/lib/panel-state.d.ts +0 -120
- package/dist/lib/panel-state.js +0 -176
- package/src/api/__tests__/unit.test.ts +0 -38
- package/src/api/unit.ts +0 -93
- package/src/api/workbench-contract.ts +0 -59
- package/src/host/__tests__/browser-find.test.ts +0 -330
- package/src/host/__tests__/browser-read.test.ts +0 -228
- package/src/host/__tests__/opencli-runtime.test.ts +0 -46
- package/src/host/browser-find.ts +0 -311
- package/src/host/browser-read.ts +0 -311
- package/src/host/opencli-runtime.ts +0 -79
- package/src/host/opencli-window.ts +0 -11
- package/src/host/opencli.ts +0 -213
- package/src/host/unit-libs.ts +0 -41
- /package/dist/{api/blocker.js → contract/adapters.js} +0 -0
- /package/dist/{api → contract}/blocker.d.ts +0 -0
- /package/dist/{api/dsh-client.js → contract/blocker.js} +0 -0
- /package/dist/{api/unit-board.js → contract/cli.js} +0 -0
- /package/dist/{api/workbench-contract.js → contract/data.js} +0 -0
- /package/dist/{api → contract}/long-task.d.ts +0 -0
- /package/dist/{api → contract}/long-task.js +0 -0
- /package/dist/{host/unit-libs.js → contract/plugin-source.js} +0 -0
- /package/dist/{api → contract}/unit-board.d.ts +0 -0
- /package/src/{api → contract}/blocker.ts +0 -0
- /package/src/{api → contract}/long-task.ts +0 -0
package/src/components/Note.css
CHANGED
package/src/components/Stack.css
CHANGED
|
@@ -43,7 +43,7 @@ describe('两按停止钮:接线(这仓的组件测试是 node 环境,读
|
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
it('★★ 上膛后 3 秒自己落膛:用 LONG_TASK_STOP_ARM_MS,卸载 / 落膛都清掉计时器', () => {
|
|
46
|
-
expect(ROW).toContain("from '../
|
|
46
|
+
expect(ROW).toContain("from '../contract/long-task.js'");
|
|
47
47
|
expect(ROW).toContain('setTimeout(() => setArmed(false), LONG_TASK_STOP_ARM_MS)');
|
|
48
48
|
expect(ROW).toContain('clearTimeout(timer)');
|
|
49
49
|
expect(ROW).toContain('}, [armed]);');
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type { SessionsSnapshot, Translate, WorkspaceSnapshot, WorkspaceView } from '../
|
|
3
|
-
import type { UnitManifest } from '../
|
|
4
|
-
import type { CapabilityPayload } from '../
|
|
2
|
+
import type { SessionsSnapshot, Translate, WorkspaceSnapshot, WorkspaceView } from '../lib/dsh-client.js';
|
|
3
|
+
import type { UnitManifest } from '../contract/unit.js';
|
|
4
|
+
import type { CapabilityPayload } from '../contract/workbench-contract.js';
|
|
5
5
|
import type { Dictionaries } from '../i18n/index.js';
|
|
6
6
|
|
|
7
7
|
/**
|
package/src/components/icons.tsx
CHANGED
|
@@ -51,20 +51,28 @@ export function IconConversation({ size = 16 }: IconProps) {
|
|
|
51
51
|
);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
const BRAND_FRAME = 'M10 6H54A5 5 0 0 1 59 11V43A5 5 0 0 1 54 48H10A5 5 0 0 1 5 43V11A5 5 0 0 1 10 6Z M12 10H52A3 3 0 0 1 55 13V41A3 3 0 0 1 52 44H12A3 3 0 0 1 9 41V13A3 3 0 0 1 12 10Z';
|
|
55
|
+
|
|
56
|
+
const BRAND_TAIL =
|
|
57
|
+
'M8.844 13.742C8.967 12.328 8.45 10.4 8.45 9.65C8.45 8.94 8.88 8.43 9.6 8.43C11.285 8.43 12.106 8.281 12.685 8.104C13.71 7.791 14.585 6.768 15.055 5.945C15.137 5.803 14.99 5.641 14.829 5.671C13.829 5.86 12.828 5.376 11.827 4.978C10.659 4.514 9.491 4.707 8.935 4.876C8.805 4.915 8.658 4.819 8.636 4.686C8.468 3.643 7.405 2.615 5.498 2.238C4.54 2.048 3.748 1.574 3.347 1.202C3.252 1.113 3.088 1.125 3.03 1.242C2.628 2.059 2.168 3.82 5.248 6.115C5.82 6.494 6.31 6.785 6.574 7.637C6.72 8.104 6.157 9.168 6.061 9.368C5.157 11.27 5.089 12.19 4.926 13.742Z';
|
|
58
|
+
|
|
59
|
+
const BRAND_TAIL_TRANSFORM = 'translate(14.6263 10.5853) scale(1.95)';
|
|
60
|
+
|
|
54
61
|
/**
|
|
55
|
-
*
|
|
62
|
+
* 品牌标:一台显示器里放着 dsh 的鲸鱼尾巴;默认 24px(它是品牌物,别拿它当通用图标)。
|
|
56
63
|
* @param props.size - 边长像素,同时给 `width` 与 `height`。
|
|
57
64
|
* @returns 一枚 `aria-hidden` 的 svg。
|
|
58
65
|
*/
|
|
59
66
|
export function IconBrandMark({ size = 24 }: IconProps) {
|
|
60
67
|
return (
|
|
61
|
-
<Shell size={size}
|
|
62
|
-
<
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
<Shell size={size} viewBox="0 0 64 64">
|
|
69
|
+
<path d={BRAND_FRAME} fill="currentColor" fillRule="evenodd" />
|
|
70
|
+
<rect x={27.5} y={48} width={9} height={4.75} fill="currentColor" />
|
|
71
|
+
<rect x={19} y={52.75} width={26} height={4.75} rx={2.375} fill="currentColor" />
|
|
72
|
+
<g transform={BRAND_TAIL_TRANSFORM}>
|
|
73
|
+
<path d={BRAND_TAIL} fill="currentColor" />
|
|
74
|
+
<circle cx={6.885} cy={13.742} r={1.95} fill="currentColor" />
|
|
75
|
+
</g>
|
|
68
76
|
</Shell>
|
|
69
77
|
);
|
|
70
78
|
}
|
package/src/config/constants.ts
CHANGED
|
@@ -40,8 +40,8 @@ export const PANEL_STATE_PREFIX = `${API_PREFIX}/${PANEL_STATE_PATH}`;
|
|
|
40
40
|
/** 钉住的 opencli 插件版本:`opencli-runtime` 按它校验、取那一份。 */
|
|
41
41
|
export const OPENCLI_PIN = "1.8.8";
|
|
42
42
|
|
|
43
|
-
/** 缺陷看板套件的 dsh 服务名(`
|
|
44
|
-
export const
|
|
43
|
+
/** 缺陷看板套件的 dsh 服务名(`workbenchIssues`):套件照它登记自己那份服务。 */
|
|
44
|
+
export const ISSUES_SERVICE = "workbenchIssues";
|
|
45
45
|
|
|
46
46
|
/** 面板套件的 dsh 服务名(`workbenchPanels`):宿主经它取套件公布的清单与订阅。 */
|
|
47
47
|
export const PANELS_SERVICE = "workbenchPanels";
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
parseFactFrame,
|
|
6
6
|
type FactFrame,
|
|
7
7
|
type FactTransport,
|
|
8
|
+
type FactTransportMode,
|
|
8
9
|
} from '../facts.js';
|
|
9
10
|
|
|
10
11
|
function fakeTransport(): {
|
|
@@ -52,17 +53,17 @@ describe('createFactChannel', () => {
|
|
|
52
53
|
it('★ 之后的帧只惊动它点名的事实(别的读者不该白跑一次)', () => {
|
|
53
54
|
const wire = fakeTransport();
|
|
54
55
|
const channel = createFactChannel({ transport: wire.transport });
|
|
55
|
-
const
|
|
56
|
+
const inventory = vi.fn();
|
|
56
57
|
const issues = vi.fn();
|
|
57
|
-
channel.subscribe('
|
|
58
|
+
channel.subscribe('inventory/summary', inventory);
|
|
58
59
|
channel.subscribe('issues', issues);
|
|
59
60
|
channel.applyFrame({ epoch: 'e1', rev: 1, facts: [] });
|
|
60
61
|
|
|
61
|
-
channel.applyFrame({ epoch: 'e1', rev: 2, facts: ['
|
|
62
|
+
channel.applyFrame({ epoch: 'e1', rev: 2, facts: ['inventory/summary'] });
|
|
62
63
|
|
|
63
|
-
expect(
|
|
64
|
+
expect(inventory).toHaveBeenCalledTimes(1);
|
|
64
65
|
expect(issues).not.toHaveBeenCalled();
|
|
65
|
-
expect(channel.revisionOf('
|
|
66
|
+
expect(channel.revisionOf('inventory/summary')).toBe(2);
|
|
66
67
|
expect(channel.revisionOf('issues')).toBe(0);
|
|
67
68
|
});
|
|
68
69
|
|
|
@@ -132,33 +133,33 @@ describe('createFactChannel', () => {
|
|
|
132
133
|
const summary = vi.fn();
|
|
133
134
|
const builds = vi.fn();
|
|
134
135
|
const issues = vi.fn();
|
|
135
|
-
channel.subscribe('
|
|
136
|
-
channel.subscribe('
|
|
137
|
-
channel.subscribe('
|
|
136
|
+
channel.subscribe('inventory/summary', summary);
|
|
137
|
+
channel.subscribe('inventory/builds?env=innettest', builds);
|
|
138
|
+
channel.subscribe('issues/list', issues);
|
|
138
139
|
channel.applyFrame({ epoch: 'e1', rev: 1, facts: [] });
|
|
139
140
|
|
|
140
|
-
channel.applyFrame({ epoch: 'e1', rev: 2, facts: ['capability', 'panels', '
|
|
141
|
+
channel.applyFrame({ epoch: 'e1', rev: 2, facts: ['capability', 'panels', 'inventory*'] });
|
|
141
142
|
|
|
142
143
|
expect(summary).toHaveBeenCalledTimes(1);
|
|
143
144
|
expect(builds).toHaveBeenCalledTimes(1);
|
|
144
145
|
expect(issues).not.toHaveBeenCalled();
|
|
145
|
-
expect(channel.revisionOf('
|
|
146
|
+
expect(channel.revisionOf('inventory/summary')).toBeGreaterThan(1);
|
|
146
147
|
});
|
|
147
148
|
|
|
148
149
|
it('命名空间不许凭空造出订阅(订阅表只由读者写),也不许越界到别的模块', () => {
|
|
149
150
|
const wire = fakeTransport();
|
|
150
151
|
const channel = createFactChannel({ transport: wire.transport });
|
|
151
|
-
const
|
|
152
|
+
const demoAnalysis = vi.fn();
|
|
152
153
|
const lookalike = vi.fn();
|
|
153
|
-
channel.subscribe('
|
|
154
|
-
channel.subscribe('
|
|
154
|
+
channel.subscribe('analysis/summary', demoAnalysis);
|
|
155
|
+
channel.subscribe('inventory-extra/summary', lookalike);
|
|
155
156
|
channel.applyFrame({ epoch: 'e1', rev: 1, facts: [] });
|
|
156
157
|
|
|
157
|
-
channel.applyFrame({ epoch: 'e1', rev: 2, facts: ['
|
|
158
|
+
channel.applyFrame({ epoch: 'e1', rev: 2, facts: ['inventory*'] });
|
|
158
159
|
|
|
159
|
-
expect(
|
|
160
|
+
expect(demoAnalysis).not.toHaveBeenCalled();
|
|
160
161
|
expect(lookalike).not.toHaveBeenCalled();
|
|
161
|
-
expect(channel.revisionOf('
|
|
162
|
+
expect(channel.revisionOf('inventory/never-subscribed')).toBe(0);
|
|
162
163
|
expect(channel.subscriberCount()).toBe(2);
|
|
163
164
|
});
|
|
164
165
|
|
|
@@ -166,26 +167,26 @@ describe('createFactChannel', () => {
|
|
|
166
167
|
const wire = fakeTransport();
|
|
167
168
|
const channel = createFactChannel({ transport: wire.transport });
|
|
168
169
|
const listener = vi.fn();
|
|
169
|
-
channel.subscribe('
|
|
170
|
+
channel.subscribe('inventory/builds?env=innettest', listener);
|
|
170
171
|
|
|
171
|
-
channel.applyFrame({ epoch: 'e1', rev: 4, facts: ['
|
|
172
|
+
channel.applyFrame({ epoch: 'e1', rev: 4, facts: ['inventory*'] });
|
|
172
173
|
|
|
173
174
|
expect(listener).not.toHaveBeenCalled();
|
|
174
|
-
expect(channel.revisionOf('
|
|
175
|
+
expect(channel.revisionOf('inventory/builds?env=innettest')).toBeGreaterThan(0);
|
|
175
176
|
});
|
|
176
177
|
|
|
177
178
|
it('refresh(命名空间) 只惊动它下面的事实(本地失效也按模块点名,不是一律全量)', () => {
|
|
178
179
|
const wire = fakeTransport();
|
|
179
180
|
const channel = createFactChannel({ transport: wire.transport });
|
|
180
|
-
const
|
|
181
|
+
const inventory = vi.fn();
|
|
181
182
|
const issues = vi.fn();
|
|
182
|
-
channel.subscribe('
|
|
183
|
-
channel.subscribe('
|
|
183
|
+
channel.subscribe('inventory/summary', inventory);
|
|
184
|
+
channel.subscribe('issues/list', issues);
|
|
184
185
|
channel.applyFrame({ epoch: 'e1', rev: 1, facts: [] });
|
|
185
186
|
|
|
186
|
-
channel.refresh('
|
|
187
|
+
channel.refresh('inventory*');
|
|
187
188
|
|
|
188
|
-
expect(
|
|
189
|
+
expect(inventory).toHaveBeenCalledTimes(1);
|
|
189
190
|
expect(issues).not.toHaveBeenCalled();
|
|
190
191
|
});
|
|
191
192
|
|
|
@@ -204,6 +205,53 @@ describe('createFactChannel', () => {
|
|
|
204
205
|
|
|
205
206
|
expect(seen).toEqual([4]);
|
|
206
207
|
});
|
|
208
|
+
|
|
209
|
+
it('★ 传输来路:没建连是 null,报上来就换档,同一档不重复惊动', () => {
|
|
210
|
+
const wire: { report: ((mode: FactTransportMode) => void) | null } = { report: null };
|
|
211
|
+
const channel = createFactChannel({
|
|
212
|
+
transport: {
|
|
213
|
+
start(handlers) {
|
|
214
|
+
wire.report = handlers.onMode ?? null;
|
|
215
|
+
return () => {};
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
});
|
|
219
|
+
const listener = vi.fn();
|
|
220
|
+
expect(channel.mode()).toBeNull();
|
|
221
|
+
channel.subscribeMode(listener);
|
|
222
|
+
channel.subscribe('panels', vi.fn());
|
|
223
|
+
|
|
224
|
+
wire.report?.('polling');
|
|
225
|
+
expect(channel.mode()).toBe('polling');
|
|
226
|
+
wire.report?.('polling');
|
|
227
|
+
expect(listener).toHaveBeenCalledTimes(1);
|
|
228
|
+
|
|
229
|
+
wire.report?.('sse');
|
|
230
|
+
expect(channel.mode()).toBe('sse');
|
|
231
|
+
expect(listener).toHaveBeenCalledTimes(2);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it('★ 最后一个订阅走掉、传输停了,来路回到没建连', () => {
|
|
235
|
+
const wire: { report: ((mode: FactTransportMode) => void) | null } = { report: null };
|
|
236
|
+
const channel = createFactChannel({
|
|
237
|
+
transport: {
|
|
238
|
+
start(handlers) {
|
|
239
|
+
wire.report = handlers.onMode ?? null;
|
|
240
|
+
return () => {};
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
const listener = vi.fn();
|
|
245
|
+
channel.subscribeMode(listener);
|
|
246
|
+
const off = channel.subscribe('panels', vi.fn());
|
|
247
|
+
wire.report?.('sse');
|
|
248
|
+
listener.mockClear();
|
|
249
|
+
|
|
250
|
+
off();
|
|
251
|
+
|
|
252
|
+
expect(channel.mode()).toBeNull();
|
|
253
|
+
expect(listener).toHaveBeenCalledTimes(1);
|
|
254
|
+
});
|
|
207
255
|
});
|
|
208
256
|
|
|
209
257
|
describe('parseFactFrame', () => {
|
|
@@ -255,7 +303,7 @@ describe('parseFactFrame', () => {
|
|
|
255
303
|
|
|
256
304
|
describe('factOfRoute', () => {
|
|
257
305
|
it('事实名就是路由名(不另起一套词汇,读与订阅不可能各说各话)', () => {
|
|
258
|
-
expect(factOfRoute('
|
|
306
|
+
expect(factOfRoute('inventory/summary')).toBe('inventory/summary');
|
|
259
307
|
expect(factOfRoute('capability')).toBe('capability');
|
|
260
308
|
});
|
|
261
309
|
});
|
|
@@ -13,16 +13,16 @@ import {
|
|
|
13
13
|
|
|
14
14
|
describe('runsRouteOf', () => {
|
|
15
15
|
it('★ 事实名 = 路由名(三处同一个来源,改一处不可能漏另一处)', () => {
|
|
16
|
-
expect(runsRouteOf('
|
|
16
|
+
expect(runsRouteOf('inventory')).toBe('inventory/runs');
|
|
17
17
|
expect(runsRouteOf('issues')).toBe('issues/runs');
|
|
18
18
|
});
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
describe('stopRouteOf(停止那条写路由)', () => {
|
|
22
22
|
it('★ 就是读路由 + `/stop`(读口与写口同一个单元名,不另造一套命名)', () => {
|
|
23
|
-
expect(stopRouteOf('
|
|
23
|
+
expect(stopRouteOf('inventory')).toBe('inventory/runs/stop');
|
|
24
24
|
expect(stopRouteOf('issues')).toBe('issues/runs/stop');
|
|
25
|
-
expect(stopRouteOf('
|
|
25
|
+
expect(stopRouteOf('inventory')).toBe(`${runsRouteOf('inventory')}/stop`);
|
|
26
26
|
});
|
|
27
27
|
});
|
|
28
28
|
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
NEED_KINDS,
|
|
4
|
+
NEED_KIND_SPECS,
|
|
5
|
+
SUPPLY_SOURCE_KINDS,
|
|
6
|
+
needProblemsOf,
|
|
7
|
+
needsProblemsOf,
|
|
8
|
+
} from '../needs.js';
|
|
9
|
+
|
|
10
|
+
const npm = { kind: 'npm', package: '@acme/plugin-demo', registryDefault: 'https://registry.test/' };
|
|
11
|
+
const base = { kind: 'lib', name: 'demo', purpose: '测试', sources: [npm] };
|
|
12
|
+
|
|
13
|
+
function errorsOf(need: unknown): readonly string[] {
|
|
14
|
+
return needProblemsOf('demo', need, 0).errors;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
describe('needs 校验矩阵', () => {
|
|
18
|
+
it('★ 四种 kind 的最小声明都过;注册表与 NEED_KINDS 一一对应', () => {
|
|
19
|
+
expect(
|
|
20
|
+
needsProblemsOf('demo', [
|
|
21
|
+
{ kind: 'bin', name: 'gitops', purpose: '部署' },
|
|
22
|
+
{ kind: 'extension', runtime: 'opencli', name: 'demo', purpose: '面板', sources: [npm] },
|
|
23
|
+
base,
|
|
24
|
+
{ kind: 'env', name: 'DSH_TOKEN', secret: true, purpose: '只读接口' },
|
|
25
|
+
]).errors,
|
|
26
|
+
).toEqual([]);
|
|
27
|
+
expect(Object.keys(NEED_KIND_SPECS).sort()).toEqual([...NEED_KINDS].sort());
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('未知 kind / 未知 source.kind → 红,并点名', () => {
|
|
31
|
+
const unknownKind = errorsOf({ kind: 'mcp', name: 'x', purpose: '测试' });
|
|
32
|
+
expect(unknownKind.join(' ')).toContain('needs[0].kind 不认识');
|
|
33
|
+
const unknownSource = errorsOf({ ...base, sources: [{ kind: 'tarball', url: 'x' }] });
|
|
34
|
+
expect(unknownSource.join(' ')).toContain('sources[0].kind 不认识');
|
|
35
|
+
expect(new Set(Object.values(NEED_KIND_SPECS).flatMap((spec) => spec.sources))).toEqual(
|
|
36
|
+
new Set(SUPPLY_SOURCE_KINDS),
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('bin / env 写了 sources → 红(没有安装路径)', () => {
|
|
41
|
+
expect(errorsOf({ kind: 'bin', name: 'x', purpose: '测试', sources: [npm] }).join(' ')).toContain(
|
|
42
|
+
'不支持 sources',
|
|
43
|
+
);
|
|
44
|
+
expect(errorsOf({ kind: 'env', name: 'X', purpose: '测试', sources: [npm] }).join(' ')).toContain(
|
|
45
|
+
'不支持 sources',
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('lib 只认 npm 源;sources 空数组 → 红(不代装就整条删掉)', () => {
|
|
50
|
+
expect(errorsOf({ ...base, sources: [{ kind: 'git', url: 'github:acme/demo' }] }).join(' ')).toContain(
|
|
51
|
+
'只支持 npm',
|
|
52
|
+
);
|
|
53
|
+
expect(errorsOf({ ...base, sources: [] }).join(' ')).toContain('空数组');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('必填项:purpose、extension.runtime、name、required 类型、id 空串', () => {
|
|
57
|
+
expect(errorsOf({ ...base, purpose: '' }).join(' ')).toContain('purpose 没写');
|
|
58
|
+
expect(errorsOf({ kind: 'extension', name: 'x', purpose: '测试' }).join(' ')).toContain('runtime 没写');
|
|
59
|
+
expect(errorsOf({ ...base, name: '' }).join(' ')).toContain('name 没写');
|
|
60
|
+
expect(errorsOf({ ...base, required: 'yes' }).join(' ')).toContain('required 要是布尔');
|
|
61
|
+
expect(errorsOf({ ...base, id: '' }).join(' ')).toContain('id 是空串');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('★ need 内未知字段只是警告;x- 前缀直接忽略(不为可选字段升协议版本)', () => {
|
|
65
|
+
const read = needProblemsOf('demo', { ...base, future: 1, 'x-vendor': true }, 0);
|
|
66
|
+
expect(read.errors).toEqual([]);
|
|
67
|
+
expect(read.warnings.join(' ')).toContain('不认识的字段 future');
|
|
68
|
+
expect(read.warnings.join(' ')).not.toContain('x-vendor');
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('没写 needs → 空表不报', () => {
|
|
72
|
+
expect(needsProblemsOf('demo', undefined)).toEqual({ errors: [], warnings: [] });
|
|
73
|
+
});
|
|
74
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import type { Need } from '../needs.js';
|
|
3
|
+
import { needsOf, provisionableNeedsOf, type UnitManifest } from '../unit.js';
|
|
4
|
+
|
|
5
|
+
function manifest(needs?: readonly Need[]): UnitManifest {
|
|
6
|
+
return {
|
|
7
|
+
id: 'issues',
|
|
8
|
+
card: { titleKey: 'issues.mine', order: 10 },
|
|
9
|
+
tools: [],
|
|
10
|
+
host: { inject: [] },
|
|
11
|
+
...(needs === undefined ? {} : { needs }),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const npm = { kind: 'npm' as const, registryEnv: 'WB_NPM', registryDefault: 'https://registry.example/' };
|
|
16
|
+
|
|
17
|
+
describe('provisionableNeedsOf(缺来源时那条回退口径,宿主与浏览器共用一份)', () => {
|
|
18
|
+
it('写了 sources 的 extension / lib → 宿主可代装', () => {
|
|
19
|
+
const needs: Need[] = [
|
|
20
|
+
{ kind: 'extension', runtime: 'opencli', name: 'demo', purpose: '测试', sources: [npm] },
|
|
21
|
+
{ kind: 'lib', name: 'opencli-workflow', purpose: '测试', sources: [npm] },
|
|
22
|
+
];
|
|
23
|
+
expect(provisionableNeedsOf(manifest(needs)).map((need) => need.name)).toEqual([
|
|
24
|
+
'demo',
|
|
25
|
+
'opencli-workflow',
|
|
26
|
+
]);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('★ 没写 sources 的 extension、bin、env 都不算供给 —— 它们不是市场门槛,只是「我自己装,你帮我判」', () => {
|
|
30
|
+
const needs: Need[] = [
|
|
31
|
+
{ kind: 'extension', runtime: 'opencli', name: 'demo', purpose: '测试' },
|
|
32
|
+
{ kind: 'bin', name: 'gitops', purpose: '测试' },
|
|
33
|
+
{ kind: 'env', name: 'DSH_TOKEN', purpose: '测试' },
|
|
34
|
+
];
|
|
35
|
+
expect(provisionableNeedsOf(manifest(needs))).toEqual([]);
|
|
36
|
+
expect(provisionableNeedsOf(manifest([]))).toEqual([]);
|
|
37
|
+
expect(provisionableNeedsOf(manifest())).toEqual([]);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('needsOf 没写就是空表', () => {
|
|
41
|
+
expect(needsOf(manifest())).toEqual([]);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
export interface DataRequestBase {
|
|
2
|
+
readonly timeoutMs?: number;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export interface HttpDataRequest extends DataRequestBase {
|
|
6
|
+
readonly kind: 'http';
|
|
7
|
+
readonly url: string;
|
|
8
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface BrowserDataRequest extends DataRequestBase {
|
|
12
|
+
readonly kind: 'browser';
|
|
13
|
+
readonly script: string;
|
|
14
|
+
readonly url?: string;
|
|
15
|
+
readonly loginUrl?: string;
|
|
16
|
+
readonly session?: string;
|
|
17
|
+
readonly open?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface CommandDataRequest extends DataRequestBase {
|
|
21
|
+
readonly kind: 'command';
|
|
22
|
+
readonly command: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type DataRequest = HttpDataRequest | BrowserDataRequest | CommandDataRequest;
|
|
26
|
+
|
|
27
|
+
export type DataErrorCode = 'invalid-request' | 'http' | 'auth' | 'timeout' | 'parse' | 'command' | 'browser';
|
|
28
|
+
|
|
29
|
+
export interface DataError {
|
|
30
|
+
readonly code: DataErrorCode;
|
|
31
|
+
readonly message: string;
|
|
32
|
+
readonly status?: number;
|
|
33
|
+
readonly detail?: string;
|
|
34
|
+
readonly hint?: string;
|
|
35
|
+
readonly helpUrl?: string;
|
|
36
|
+
readonly pageCode?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface DataSuccess<T = unknown> {
|
|
40
|
+
readonly ok: true;
|
|
41
|
+
readonly data: T;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface DataFailure {
|
|
45
|
+
readonly ok: false;
|
|
46
|
+
readonly error: DataError;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export type DataResult<T = unknown> = DataSuccess<T> | DataFailure;
|
|
50
|
+
|
|
51
|
+
export interface CredentialSourceCookie {
|
|
52
|
+
readonly kind: 'cookie';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface CredentialSourceCookieValue {
|
|
56
|
+
readonly kind: 'cookieValue';
|
|
57
|
+
readonly name: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface CredentialSourceEndpoint {
|
|
61
|
+
readonly kind: 'endpoint';
|
|
62
|
+
readonly url: string;
|
|
63
|
+
readonly method?: 'GET' | 'POST';
|
|
64
|
+
readonly body?: unknown;
|
|
65
|
+
readonly path: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface CredentialSourceMeta {
|
|
69
|
+
readonly kind: 'meta';
|
|
70
|
+
readonly name: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface CredentialSourceGlobal {
|
|
74
|
+
readonly kind: 'global';
|
|
75
|
+
readonly path: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface CredentialSourceStorage {
|
|
79
|
+
readonly kind: 'storage';
|
|
80
|
+
readonly area: 'local' | 'session';
|
|
81
|
+
readonly key: string;
|
|
82
|
+
readonly path?: string;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export type CredentialSource =
|
|
86
|
+
| CredentialSourceCookie
|
|
87
|
+
| CredentialSourceCookieValue
|
|
88
|
+
| CredentialSourceEndpoint
|
|
89
|
+
| CredentialSourceMeta
|
|
90
|
+
| CredentialSourceGlobal
|
|
91
|
+
| CredentialSourceStorage;
|
|
92
|
+
|
|
93
|
+
export type CredentialPlace =
|
|
94
|
+
| { readonly in: 'cookie' }
|
|
95
|
+
| { readonly in: 'header'; readonly name: string; readonly prefix?: string }
|
|
96
|
+
| { readonly in: 'query'; readonly name: string }
|
|
97
|
+
| { readonly in: 'body'; readonly field: string };
|
|
98
|
+
|
|
99
|
+
export type RecipeAuth =
|
|
100
|
+
| { readonly kind: 'none' }
|
|
101
|
+
| { readonly kind?: undefined; readonly source: CredentialSource; readonly place: CredentialPlace };
|
|
102
|
+
|
|
103
|
+
export interface RecipeRequest {
|
|
104
|
+
readonly method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
105
|
+
readonly path: string;
|
|
106
|
+
readonly query?: Readonly<Record<string, string | number | boolean>>;
|
|
107
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
108
|
+
readonly body?: unknown;
|
|
109
|
+
readonly contentType?: 'json' | 'form';
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface RecipeResponse {
|
|
113
|
+
readonly kind: 'json' | 'text';
|
|
114
|
+
readonly path?: string;
|
|
115
|
+
readonly maxBytes?: number;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface RequestRecipe {
|
|
119
|
+
readonly origin: string;
|
|
120
|
+
readonly loginUrl?: string;
|
|
121
|
+
readonly session?: string;
|
|
122
|
+
readonly timeoutMs?: number;
|
|
123
|
+
readonly auth?: RecipeAuth;
|
|
124
|
+
readonly request: RecipeRequest;
|
|
125
|
+
readonly response?: RecipeResponse;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface CallOverrides {
|
|
129
|
+
readonly path?: string;
|
|
130
|
+
readonly query?: Readonly<Record<string, string | number | boolean>>;
|
|
131
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
132
|
+
readonly body?: unknown;
|
|
133
|
+
readonly response?: Partial<RecipeResponse>;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export type RecipeCalls = Readonly<Record<string, CallOverrides>>;
|
|
137
|
+
|
|
138
|
+
export type RecipeResults<T = unknown> = Readonly<Record<string, DataResult<T>>>;
|
|
139
|
+
|
|
140
|
+
export interface DataReader {
|
|
141
|
+
read<T = unknown>(request: DataRequest): Promise<DataResult<T>>;
|
|
142
|
+
request<T = unknown>(recipe: RequestRecipe, overrides?: CallOverrides): Promise<DataResult<T>>;
|
|
143
|
+
requestMany<T = unknown>(recipe: RequestRecipe, calls: RecipeCalls): Promise<RecipeResults<T>>;
|
|
144
|
+
submit<T = unknown>(recipe: RequestRecipe, overrides?: CallOverrides): Promise<DataResult<T>>;
|
|
145
|
+
}
|