@termix-ssh/plugin-sdk 1.0.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.
Files changed (236) hide show
  1. package/README.md +52 -0
  2. package/cli/commands/build.mjs +246 -0
  3. package/cli/commands/migrations.mjs +248 -0
  4. package/cli/commands/pack.mjs +42 -0
  5. package/cli/commands/sign.mjs +83 -0
  6. package/cli/commands/test.mjs +33 -0
  7. package/cli/commands/validate.mjs +215 -0
  8. package/cli/index.mjs +65 -0
  9. package/cli/lib/changelog.mjs +126 -0
  10. package/cli/lib/externals.mjs +46 -0
  11. package/cli/lib/plugin-dir.mjs +29 -0
  12. package/cli/lib/signing.mjs +86 -0
  13. package/cli/lib/static-url-imports.mjs +54 -0
  14. package/cli/lib/tmxplug.mjs +106 -0
  15. package/cli/patches/guacamole-common-js-flush.cjs +76 -0
  16. package/cli/patches/xterm-android-ime.cjs +130 -0
  17. package/client.d.ts +13 -0
  18. package/dist/backend.d.ts +1777 -0
  19. package/dist/backend.js +84 -0
  20. package/dist/capabilities.d.ts +38 -0
  21. package/dist/capabilities.js +71 -0
  22. package/dist/db.d.ts +112 -0
  23. package/dist/db.js +189 -0
  24. package/dist/ddl.d.ts +76 -0
  25. package/dist/ddl.js +678 -0
  26. package/dist/desktop.d.ts +346 -0
  27. package/dist/desktop.js +5 -0
  28. package/dist/frontend.d.ts +1206 -0
  29. package/dist/frontend.js +388 -0
  30. package/dist/host/chunk-F3SDZDDG.js +6017 -0
  31. package/dist/host/chunk-XGWE7BTJ.js +90 -0
  32. package/dist/host/chunk-XH5NXL6Y.js +56314 -0
  33. package/dist/host/chunk-YC2MAKSP.js +14 -0
  34. package/dist/host/linked-server-FZGWQW32.js +12 -0
  35. package/dist/host/rbac-api-6KDMBVDZ.js +52 -0
  36. package/dist/host/testing-host.js +414 -0
  37. package/dist/host/theme.css +91 -0
  38. package/dist/host/types/src/types/auth-protocols.d.ts +10 -0
  39. package/dist/host/types/src/types/connection-log.d.ts +13 -0
  40. package/dist/host/types/src/types/credential-sidebar-preferences.d.ts +38 -0
  41. package/dist/host/types/src/types/host-defaults.d.ts +60 -0
  42. package/dist/host/types/src/types/host-sidebar-preferences.d.ts +55 -0
  43. package/dist/host/types/src/types/index.d.ts +298 -0
  44. package/dist/host/types/src/types/keybindings.d.ts +27 -0
  45. package/dist/host/types/src/types/ui-preferences.d.ts +102 -0
  46. package/dist/host/types/src/types/ui-types.d.ts +260 -0
  47. package/dist/host/types/src/ui/api/admin-user-data-api.d.ts +11 -0
  48. package/dist/host/types/src/ui/api/auth-methods-api.d.ts +63 -0
  49. package/dist/host/types/src/ui/api/credential-sidebar-preferences-api.d.ts +3 -0
  50. package/dist/host/types/src/ui/api/credentials-api.d.ts +56 -0
  51. package/dist/host/types/src/ui/api/dashboard-api.d.ts +23 -0
  52. package/dist/host/types/src/ui/api/external-account-api.d.ts +8 -0
  53. package/dist/host/types/src/ui/api/host-sidebar-preferences-api.d.ts +3 -0
  54. package/dist/host/types/src/ui/api/host-status-api.d.ts +11 -0
  55. package/dist/host/types/src/ui/api/open-tabs-api.d.ts +74 -0
  56. package/dist/host/types/src/ui/api/plugins-api.d.ts +128 -0
  57. package/dist/host/types/src/ui/api/rbac-api.d.ts +167 -0
  58. package/dist/host/types/src/ui/api/settings-api.d.ts +22 -0
  59. package/dist/host/types/src/ui/api/ssh-host-management-api.d.ts +65 -0
  60. package/dist/host/types/src/ui/api/sync-api.d.ts +93 -0
  61. package/dist/host/types/src/ui/api/system-status-api.d.ts +49 -0
  62. package/dist/host/types/src/ui/api/ui-preferences-api.d.ts +8 -0
  63. package/dist/host/types/src/ui/api/user-management-api.d.ts +80 -0
  64. package/dist/host/types/src/ui/auth/Auth.d.ts +12 -0
  65. package/dist/host/types/src/ui/auth/auth-bits.d.ts +11 -0
  66. package/dist/host/types/src/ui/auth/silent-signin.d.ts +2 -0
  67. package/dist/host/types/src/ui/components/FullScreenAppWrapper.d.ts +9 -0
  68. package/dist/host/types/src/ui/components/alert-dialog.d.ts +14 -0
  69. package/dist/host/types/src/ui/components/alert.d.ts +9 -0
  70. package/dist/host/types/src/ui/components/badge.d.ts +9 -0
  71. package/dist/host/types/src/ui/components/button.d.ts +13 -0
  72. package/dist/host/types/src/ui/components/card-grid/CardGridCanvas.d.ts +22 -0
  73. package/dist/host/types/src/ui/components/card-grid/layout-utils.d.ts +26 -0
  74. package/dist/host/types/src/ui/components/card-grid/types.d.ts +29 -0
  75. package/dist/host/types/src/ui/components/card-masonry.d.ts +16 -0
  76. package/dist/host/types/src/ui/components/card.d.ts +11 -0
  77. package/dist/host/types/src/ui/components/charts/BarSeries.d.ts +16 -0
  78. package/dist/host/types/src/ui/components/charts/LineChart.d.ts +17 -0
  79. package/dist/host/types/src/ui/components/charts/RadialGauge.d.ts +18 -0
  80. package/dist/host/types/src/ui/components/charts/Sparkline.d.ts +22 -0
  81. package/dist/host/types/src/ui/components/charts/StatRow.d.ts +15 -0
  82. package/dist/host/types/src/ui/components/charts/geometry.d.ts +20 -0
  83. package/dist/host/types/src/ui/components/charts/index.d.ts +4 -0
  84. package/dist/host/types/src/ui/components/checkbox.d.ts +4 -0
  85. package/dist/host/types/src/ui/components/connection/ConnectionGate.d.ts +56 -0
  86. package/dist/host/types/src/ui/components/connection/ConnectionLogPanel.d.ts +9 -0
  87. package/dist/host/types/src/ui/components/connection/ConnectionScreen.d.ts +34 -0
  88. package/dist/host/types/src/ui/components/connection/connection-status.d.ts +1 -0
  89. package/dist/host/types/src/ui/components/data-view.d.ts +32 -0
  90. package/dist/host/types/src/ui/components/dialog.d.ts +17 -0
  91. package/dist/host/types/src/ui/components/dropdown-menu.d.ts +29 -0
  92. package/dist/host/types/src/ui/components/empty-state.d.ts +19 -0
  93. package/dist/host/types/src/ui/components/form-fields.d.ts +115 -0
  94. package/dist/host/types/src/ui/components/input.d.ts +3 -0
  95. package/dist/host/types/src/ui/components/kbd.d.ts +12 -0
  96. package/dist/host/types/src/ui/components/label.d.ts +4 -0
  97. package/dist/host/types/src/ui/components/manager-card.d.ts +25 -0
  98. package/dist/host/types/src/ui/components/meter.d.ts +14 -0
  99. package/dist/host/types/src/ui/components/metric-card.d.ts +18 -0
  100. package/dist/host/types/src/ui/components/panel-layout.d.ts +83 -0
  101. package/dist/host/types/src/ui/components/password-input.d.ts +4 -0
  102. package/dist/host/types/src/ui/components/popover.d.ts +7 -0
  103. package/dist/host/types/src/ui/components/scroll-area.d.ts +5 -0
  104. package/dist/host/types/src/ui/components/section-card.d.ts +29 -0
  105. package/dist/host/types/src/ui/components/select.d.ts +15 -0
  106. package/dist/host/types/src/ui/components/select2.d.ts +8 -0
  107. package/dist/host/types/src/ui/components/separator.d.ts +4 -0
  108. package/dist/host/types/src/ui/components/sheet.d.ts +14 -0
  109. package/dist/host/types/src/ui/components/sidebar.d.ts +69 -0
  110. package/dist/host/types/src/ui/components/skeleton.d.ts +2 -0
  111. package/dist/host/types/src/ui/components/slider.d.ts +4 -0
  112. package/dist/host/types/src/ui/components/sonner.d.ts +4 -0
  113. package/dist/host/types/src/ui/components/surface/prompt-styles.d.ts +4 -0
  114. package/dist/host/types/src/ui/components/surface/surface-scope.d.ts +79 -0
  115. package/dist/host/types/src/ui/components/switch.d.ts +4 -0
  116. package/dist/host/types/src/ui/components/tab-strip.d.ts +19 -0
  117. package/dist/host/types/src/ui/components/tabs.d.ts +7 -0
  118. package/dist/host/types/src/ui/components/textarea.d.ts +4 -0
  119. package/dist/host/types/src/ui/components/theme-provider.d.ts +14 -0
  120. package/dist/host/types/src/ui/components/tooltip.d.ts +7 -0
  121. package/dist/host/types/src/ui/contexts/BrandingContext.d.ts +15 -0
  122. package/dist/host/types/src/ui/contexts/UiPreferencesContext.d.ts +38 -0
  123. package/dist/host/types/src/ui/contexts/branding-document.d.ts +10 -0
  124. package/dist/host/types/src/ui/dashboard/dashboard-cards-registry.d.ts +30 -0
  125. package/dist/host/types/src/ui/hooks/use-action-slot.d.ts +10 -0
  126. package/dist/host/types/src/ui/hooks/use-adaptive-polling.d.ts +5 -0
  127. package/dist/host/types/src/ui/hooks/use-mobile.d.ts +1 -0
  128. package/dist/host/types/src/ui/hooks/use-permissions.d.ts +29 -0
  129. package/dist/host/types/src/ui/hooks/use-status-color-scheme.d.ts +12 -0
  130. package/dist/host/types/src/ui/hooks/use-sync-status.d.ts +4 -0
  131. package/dist/host/types/src/ui/hooks/useSshAuthProviders.d.ts +17 -0
  132. package/dist/host/types/src/ui/i18n/i18n.d.ts +52 -0
  133. package/dist/host/types/src/ui/lib/ServerStatusContext.d.ts +33 -0
  134. package/dist/host/types/src/ui/lib/adaptive-polling.d.ts +29 -0
  135. package/dist/host/types/src/ui/lib/adaptive-resource-budget.d.ts +39 -0
  136. package/dist/host/types/src/ui/lib/app-keyboard-shortcuts.d.ts +8 -0
  137. package/dist/host/types/src/ui/lib/base-path.d.ts +1 -0
  138. package/dist/host/types/src/ui/lib/clipboard-provider.d.ts +9 -0
  139. package/dist/host/types/src/ui/lib/clipboard.d.ts +20 -0
  140. package/dist/host/types/src/ui/lib/connection-origin.d.ts +47 -0
  141. package/dist/host/types/src/ui/lib/db-health-monitor.d.ts +34 -0
  142. package/dist/host/types/src/ui/lib/device-id.d.ts +1 -0
  143. package/dist/host/types/src/ui/lib/electron.d.ts +1 -0
  144. package/dist/host/types/src/ui/lib/embedded-server-status.d.ts +15 -0
  145. package/dist/host/types/src/ui/lib/error-message.d.ts +9 -0
  146. package/dist/host/types/src/ui/lib/frontend-logger.d.ts +67 -0
  147. package/dist/host/types/src/ui/lib/global-shortcut-handler.d.ts +3 -0
  148. package/dist/host/types/src/ui/lib/host-defaults-context.d.ts +48 -0
  149. package/dist/host/types/src/ui/lib/hosts-request-cache.d.ts +9 -0
  150. package/dist/host/types/src/ui/lib/keybinding-match.d.ts +3 -0
  151. package/dist/host/types/src/ui/lib/linked-server.d.ts +10 -0
  152. package/dist/host/types/src/ui/lib/local-adaptive-engine.d.ts +40 -0
  153. package/dist/host/types/src/ui/lib/permissions.d.ts +16 -0
  154. package/dist/host/types/src/ui/lib/plugin-i18n.d.ts +11 -0
  155. package/dist/host/types/src/ui/lib/plugin-icon.d.ts +11 -0
  156. package/dist/host/types/src/ui/lib/plugin-transport.d.ts +50 -0
  157. package/dist/host/types/src/ui/lib/registry.d.ts +29 -0
  158. package/dist/host/types/src/ui/lib/rem.d.ts +7 -0
  159. package/dist/host/types/src/ui/lib/remote-server-api.d.ts +11 -0
  160. package/dist/host/types/src/ui/lib/server-status-store.d.ts +37 -0
  161. package/dist/host/types/src/ui/lib/sync-events.d.ts +2 -0
  162. package/dist/host/types/src/ui/lib/sync-status.d.ts +6 -0
  163. package/dist/host/types/src/ui/lib/tab-jump-hotkey.d.ts +4 -0
  164. package/dist/host/types/src/ui/lib/theme.d.ts +21 -0
  165. package/dist/host/types/src/ui/lib/ttl-request-cache.d.ts +10 -0
  166. package/dist/host/types/src/ui/lib/usage-color.d.ts +5 -0
  167. package/dist/host/types/src/ui/lib/utils.d.ts +2 -0
  168. package/dist/host/types/src/ui/lib/visible-interval.d.ts +5 -0
  169. package/dist/host/types/src/ui/lib/widget-title.d.ts +8 -0
  170. package/dist/host/types/src/ui/lib/ws-auth.d.ts +1 -0
  171. package/dist/host/types/src/ui/main-axios.d.ts +170 -0
  172. package/dist/host/types/src/ui/plugin-host/PluginViewPlaceholder.d.ts +13 -0
  173. package/dist/host/types/src/ui/plugin-host/app.d.ts +18 -0
  174. package/dist/host/types/src/ui/plugin-host/auth-registry.d.ts +50 -0
  175. package/dist/host/types/src/ui/plugin-host/bridge.d.ts +26 -0
  176. package/dist/host/types/src/ui/plugin-host/component-registry.d.ts +24 -0
  177. package/dist/host/types/src/ui/plugin-host/desktop.d.ts +7 -0
  178. package/dist/host/types/src/ui/plugin-host/extension-registry.d.ts +16 -0
  179. package/dist/host/types/src/ui/plugin-host/host-scope.d.ts +26 -0
  180. package/dist/host/types/src/ui/plugin-host/loader.d.ts +52 -0
  181. package/dist/host/types/src/ui/plugin-host/plugin-store.d.ts +40 -0
  182. package/dist/host/types/src/ui/plugin-host/scope.d.ts +20 -0
  183. package/dist/host/types/src/ui/plugin-host/sdk-ui.d.ts +99 -0
  184. package/dist/host/types/src/ui/plugin-host/shell-bridge.d.ts +67 -0
  185. package/dist/host/types/src/ui/plugin-host/view-ownership.d.ts +31 -0
  186. package/dist/host/types/src/ui/settings/HostPluginSections.d.ts +31 -0
  187. package/dist/host/types/src/ui/settings/SettingsFields.d.ts +22 -0
  188. package/dist/host/types/src/ui/settings/host-feature-tabs.d.ts +11 -0
  189. package/dist/host/types/src/ui/settings/settings-components.d.ts +32 -0
  190. package/dist/host/types/src/ui/settings/settings-fields-util.d.ts +11 -0
  191. package/dist/host/types/src/ui/shell/ActionSlot.d.ts +41 -0
  192. package/dist/host/types/src/ui/shell/TabContext.d.ts +30 -0
  193. package/dist/host/types/src/ui/shell/action-registry.d.ts +99 -0
  194. package/dist/host/types/src/ui/shell/keybinding-registry.d.ts +62 -0
  195. package/dist/host/types/src/ui/shell/palette-registry.d.ts +55 -0
  196. package/dist/host/types/src/ui/shell/panel-registry.d.ts +24 -0
  197. package/dist/host/types/src/ui/shell/tab-registry.d.ts +92 -0
  198. package/dist/host/types/src/ui/sidebar/HostManagerTabs.d.ts +65 -0
  199. package/dist/host/types/src/ui/sidebar/host-contributions.d.ts +72 -0
  200. package/dist/host/types/src/ui/sidebar/host-defaults/catalog.d.ts +17 -0
  201. package/dist/host/types/src/ui/sidebar/host-protocols.d.ts +49 -0
  202. package/dist/host/types/src/ui/sidebar/quick-connect-host.d.ts +21 -0
  203. package/dist/host/types/src/ui/sidebar/rail-items.d.ts +103 -0
  204. package/dist/host/types/src/ui/ssh/connection-log/ConnectionLogContext.d.ts +17 -0
  205. package/dist/host/types/src/ui/ssh/dialogs/BrowserSignInDialog.d.ts +18 -0
  206. package/dist/host/types/src/ui/ssh/dialogs/HostKeyVerificationDialog.d.ts +17 -0
  207. package/dist/host/types/src/ui/ssh/dialogs/PassphraseDialog.d.ts +15 -0
  208. package/dist/host/types/src/ui/ssh/dialogs/SSHAuthDialog.d.ts +20 -0
  209. package/dist/host/types/src/ui/ssh/dialogs/TOTPDialog.d.ts +13 -0
  210. package/dist/host/ui.d.ts +1 -0
  211. package/dist/host/ui.js +31754 -0
  212. package/dist/host/use-permissions-NULZL43J.js +18 -0
  213. package/dist/host-commands.d.ts +89 -0
  214. package/dist/host-commands.js +387 -0
  215. package/dist/manifest.d.ts +461 -0
  216. package/dist/manifest.js +1499 -0
  217. package/dist/settings.d.ts +43 -0
  218. package/dist/settings.js +168 -0
  219. package/dist/ssh-certs.d.ts +25 -0
  220. package/dist/ssh-certs.js +234 -0
  221. package/dist/ssh-options.d.ts +23 -0
  222. package/dist/ssh-options.js +1 -0
  223. package/dist/table-builder.d.ts +26 -0
  224. package/dist/table-builder.js +87 -0
  225. package/dist/testing/safe-ports.d.ts +10 -0
  226. package/dist/testing/safe-ports.js +59 -0
  227. package/dist/testing/setup.d.ts +7 -0
  228. package/dist/testing/setup.js +146 -0
  229. package/dist/testing.d.ts +537 -0
  230. package/dist/testing.js +1451 -0
  231. package/dist/vitest-preset.d.ts +54 -0
  232. package/dist/vitest-preset.js +96 -0
  233. package/package.json +143 -0
  234. package/schema/changelog.schema.json +67 -0
  235. package/schema/manifest.schema.json +1160 -0
  236. package/tsconfig.plugin.json +31 -0
@@ -0,0 +1,388 @@
1
+ /**
2
+ * The frontend contract: what a plugin's frontend entry receives, and the
3
+ * hooks its components use.
4
+ *
5
+ * A plugin frontend is `src/frontend/index.tsx` exporting `activate(app)` and
6
+ * optionally `deactivate()`. Everything it contributes goes through `app`, and
7
+ * everything registered there is removed when the plugin is disabled, without
8
+ * a page reload.
9
+ *
10
+ * This module has no runtime dependencies. The hooks delegate to a host that
11
+ * core installs at startup (`__setPluginHost`), because React, i18next and the
12
+ * shell's state all live in core and must be one instance across the shell
13
+ * and every plugin bundle.
14
+ */
15
+ import { useCallback, useEffect, useRef, useState } from "react";
16
+ /** Stands in for a saved protocol secret the editor has not changed. */
17
+ export const HOST_PROTOCOL_SECRET_KEPT = "existing_protocol_secret";
18
+ export function definePluginFrontend(plugin) {
19
+ return plugin;
20
+ }
21
+ let host = null;
22
+ /**
23
+ * Called once by core, before any plugin loads. Not part of the plugin API:
24
+ * once set it cannot be swapped, so a plugin cannot replace the bridge every
25
+ * other plugin talks through.
26
+ */
27
+ export function __setPluginHost(bridge) {
28
+ if (host && bridge !== host) {
29
+ throw new Error("@termix-ssh/plugin-sdk/frontend: the plugin host is already set");
30
+ }
31
+ host = bridge;
32
+ }
33
+ /**
34
+ * Set by the shared test setup, so a plugin component rendered on its own in a
35
+ * unit test still has hooks. A global rather than an import, because the test
36
+ * setup and the component can load different copies of this module.
37
+ */
38
+ const TEST_HOST_KEY = "__termixTestPluginHost";
39
+ function requireHost() {
40
+ const fallback = globalThis[TEST_HOST_KEY];
41
+ if (!host && fallback)
42
+ return fallback;
43
+ if (!host) {
44
+ throw new Error("@termix-ssh/plugin-sdk/frontend: no plugin host. Hooks only work inside Termix or renderWithApp().");
45
+ }
46
+ return host;
47
+ }
48
+ /** The id of the plugin that registered the component being rendered. */
49
+ export function usePluginId() {
50
+ return requireHost().usePluginId();
51
+ }
52
+ /**
53
+ * Translation bound to this plugin's namespace. Keys the plugin does not
54
+ * define fall back to core's shared strings (common.*, hosts.*).
55
+ */
56
+ export function useTranslation() {
57
+ const bridge = requireHost();
58
+ return bridge.useTranslation(bridge.usePluginId());
59
+ }
60
+ /**
61
+ * Whether the current user holds a permission. A short name resolves to this
62
+ * plugin's own namespace, a dotted id is taken as given. UI only: the backend
63
+ * route checks again.
64
+ */
65
+ export function usePermission(permission) {
66
+ const bridge = requireHost();
67
+ return bridge.usePermission(bridge.usePluginId(), permission);
68
+ }
69
+ export function useSettings(scope, hostId) {
70
+ const bridge = requireHost();
71
+ return bridge.useSettings(bridge.usePluginId(), scope, hostId);
72
+ }
73
+ export function useHost(hostId) {
74
+ return requireHost().useHost(hostId);
75
+ }
76
+ export function useHosts() {
77
+ return requireHost().useHosts();
78
+ }
79
+ /**
80
+ * Core's status for one host, kept current by the shell's own polling. Null
81
+ * outside the app shell (a standalone window) and for hosts with status
82
+ * checks off.
83
+ */
84
+ export function useHostStatus(hostId) {
85
+ return requireHost().useHostStatus(hostId);
86
+ }
87
+ export function useCurrentUser() {
88
+ return requireHost().useCurrentUser();
89
+ }
90
+ export function useTheme() {
91
+ return requireHost().useTheme();
92
+ }
93
+ export function useToast() {
94
+ return requireHost().toast;
95
+ }
96
+ export function logActivity(type, hostId, hostName) {
97
+ return requireHost().core.logActivity(type, hostId, hostName);
98
+ }
99
+ /** Tells the shell hosts were added or changed, so its lists reload. */
100
+ export function notifyHostsChanged() {
101
+ requireHost().core.notifyHostsChanged();
102
+ }
103
+ /** How the user wants host status shown: the brand accent, or green/red. */
104
+ export function getHostStatusColorScheme() {
105
+ return requireHost().core.getHostStatusColorScheme();
106
+ }
107
+ /** The desktop app's local backend token, or null in a browser. */
108
+ export function getLocalAuthToken() {
109
+ return requireHost().core.getLocalAuthToken();
110
+ }
111
+ export function getHostPassword(hostId, field) {
112
+ return requireHost().core.getHostPassword(hostId, field);
113
+ }
114
+ export function patchOpenTab(instanceId, updates) {
115
+ return requireHost().core.patchOpenTab(instanceId, updates);
116
+ }
117
+ export function getCustomKeybindings() {
118
+ return requireHost().core.getCustomKeybindings();
119
+ }
120
+ export function runKeybindingAction(action, context) {
121
+ return requireHost().core.runKeybindingAction(action, context);
122
+ }
123
+ export function getClientPreference(name) {
124
+ return requireHost().core.getClientPreference(name);
125
+ }
126
+ export function setClientPreference(name, value) {
127
+ requireHost().core.setClientPreference(name, value);
128
+ }
129
+ export function listCredentials() {
130
+ return requireHost().core.listCredentials();
131
+ }
132
+ export function usePluginApi() {
133
+ const bridge = requireHost();
134
+ return bridge.getApi(bridge.usePluginId());
135
+ }
136
+ /**
137
+ * This plugin's client for a resolved connection origin: "remote" reaches the
138
+ * desktop app's connected remote server, anything else is usePluginApi's.
139
+ */
140
+ export function usePluginApiFor(origin) {
141
+ const bridge = requireHost();
142
+ return bridge.getApiFor(bridge.usePluginId(), origin);
143
+ }
144
+ /**
145
+ * This plugin's Appearance area: the preset it declared in
146
+ * contributes.uiPresets for the user's level, with the user's changes on top.
147
+ * `set` saves one change; null clears it back to the preset.
148
+ */
149
+ export function usePluginUiPreferences() {
150
+ const bridge = requireHost();
151
+ return bridge.usePluginUiPreferences(bridge.usePluginId());
152
+ }
153
+ /**
154
+ * Grid or list and row density for one of this plugin's views, kept in its
155
+ * Appearance area as `<prefix>viewMode` and `<prefix>density`. Declare those
156
+ * keys in contributes.uiPresets so each preset level can pick a default.
157
+ */
158
+ export function usePluginPanelView(prefix = "") {
159
+ const { values, set } = usePluginUiPreferences();
160
+ const view = values[`${prefix}viewMode`] === "list" ? "list" : "grid";
161
+ const density = values[`${prefix}density`] === "compact" ? "compact" : "comfortable";
162
+ return {
163
+ view,
164
+ density,
165
+ compact: density === "compact",
166
+ setView: (next) => set(`${prefix}viewMode`, next),
167
+ setDensity: (next) => set(`${prefix}density`, next),
168
+ };
169
+ }
170
+ export function useTabs() {
171
+ return requireHost().useTabs();
172
+ }
173
+ /**
174
+ * The SSH auth types this server can connect with, core's and every enabled
175
+ * plugin's, for pickers such as a default auth type.
176
+ */
177
+ export function useSshAuthTypes() {
178
+ return requireHost().useSshAuthTypes();
179
+ }
180
+ /**
181
+ * The visible contributions to a slot another plugin owns, with their
182
+ * metadata (id, titleKey, component). For an owner that needs to build a
183
+ * catalog from what was contributed rather than just render it in place, e.g.
184
+ * host-metrics listing manager cards plugins added to "host-metrics.managers"
185
+ * next to its own. Same permission and `when` filtering as ComponentSlot;
186
+ * `context` is what each contribution's `when` sees.
187
+ */
188
+ /**
189
+ * The connection protocols a host has switched on: "ssh" plus every protocol
190
+ * a running plugin registered with registerHostProtocol. Lets a
191
+ * plugin offer a protocol without knowing which plugin owns its settings.
192
+ */
193
+ export function hostProtocols(record) {
194
+ return requireHost().hostProtocols(record);
195
+ }
196
+ export function useSlotContributions(slotId, context) {
197
+ return requireHost().useSlotContributions(slotId, context);
198
+ }
199
+ /**
200
+ * Every host action any running plugin (and core) registered with
201
+ * registerHostAction, for a plugin that offers a picker over "what can I do
202
+ * with this host" without knowing which plugin provides each one - a quick
203
+ * connect widget, say. Reactive: it re-renders as plugins enable and disable.
204
+ */
205
+ export function useHostActions() {
206
+ return requireHost().useHostActions();
207
+ }
208
+ /**
209
+ * Recent-activity types every registered tab claims (registerTab's
210
+ * activityTypes), core's and plugins'. For a filter that lists what a user
211
+ * can pick, without knowing which plugin owns each activity type.
212
+ */
213
+ export function useActivityTypes() {
214
+ return requireHost().useActivityTypes();
215
+ }
216
+ /**
217
+ * What a recent-activity entry of this type opens and how it is labelled -
218
+ * the tab type claiming it through registerTab's activityTypes, core's or a
219
+ * plugin's. undefined for a type nothing claims (its plugin is gone).
220
+ */
221
+ export function activityTarget(type) {
222
+ return requireHost().activityTarget(type);
223
+ }
224
+ /**
225
+ * Every item any running plugin added to `pointId` with registerExtension.
226
+ * Reactive: it re-renders as plugins enable and disable.
227
+ */
228
+ export function useExtensions(pointId) {
229
+ return requireHost().useExtensions(pointId);
230
+ }
231
+ /** A single item added to `pointId`, by id, or undefined if none. */
232
+ export function getExtension(pointId, id) {
233
+ return requireHost().getExtension(pointId, id);
234
+ }
235
+ /**
236
+ * The component another plugin registered under `id` with
237
+ * app.registerComponent, or undefined while that plugin is off.
238
+ */
239
+ export function usePluginComponent(id) {
240
+ return requireHost().usePluginComponent(id);
241
+ }
242
+ /**
243
+ * Runs an action another plugin registered, from anywhere in a plugin's code.
244
+ * Resolves undefined when nobody registered it, so an optional dependency
245
+ * that is switched off reads as "nothing there".
246
+ */
247
+ export function invokeAction(id, ...args) {
248
+ return requireHost().invokeAction(id, ...args);
249
+ }
250
+ const COUNTDOWN_TICK_MS = 250;
251
+ const RETRY_JITTER_RATIO = 0.1;
252
+ export function computeReconnectDelay(attempt, baseDelayMs, maxDelayMs, random = Math.random) {
253
+ const base = Math.min(baseDelayMs * Math.pow(2, Math.max(0, attempt - 1)), maxDelayMs);
254
+ const jitter = base * RETRY_JITTER_RATIO * (random() * 2 - 1);
255
+ return Math.max(baseDelayMs, Math.min(maxDelayMs, Math.round(base + jitter)));
256
+ }
257
+ /**
258
+ * Exponential-backoff reconnect with jitter, for a plugin's own connect flow
259
+ * (docker's console, host-metrics polling, remote desktop tokens, the file
260
+ * manager). Promoted here once a fourth plugin needed its own copy of the
261
+ * same hook.
262
+ */
263
+ export function useConnectionRetry({ connect, maxAttempts = 8, baseDelayMs = 2000, maxDelayMs = 8000, enabled = true, autoStart = true, }) {
264
+ const [status, setStatus] = useState("connecting");
265
+ const [attempt, setAttempt] = useState(0);
266
+ const [nextRetryInMs, setNextRetryInMs] = useState(null);
267
+ const connectRef = useRef(connect);
268
+ connectRef.current = connect;
269
+ const enabledRef = useRef(enabled);
270
+ enabledRef.current = enabled;
271
+ const attemptRef = useRef(0);
272
+ const retryTimeoutRef = useRef(null);
273
+ const countdownIntervalRef = useRef(null);
274
+ const isMountedRef = useRef(true);
275
+ const markFailedRef = useRef(() => { });
276
+ const clearTimers = useCallback(() => {
277
+ if (retryTimeoutRef.current) {
278
+ clearTimeout(retryTimeoutRef.current);
279
+ retryTimeoutRef.current = null;
280
+ }
281
+ if (countdownIntervalRef.current) {
282
+ clearInterval(countdownIntervalRef.current);
283
+ countdownIntervalRef.current = null;
284
+ }
285
+ }, []);
286
+ const runConnect = useCallback(() => {
287
+ if (!isMountedRef.current)
288
+ return;
289
+ setStatus("connecting");
290
+ try {
291
+ void Promise.resolve(connectRef.current()).catch(() => {
292
+ markFailedRef.current();
293
+ });
294
+ }
295
+ catch {
296
+ markFailedRef.current();
297
+ }
298
+ }, []);
299
+ const scheduleRetry = useCallback(() => {
300
+ if (attemptRef.current >= maxAttempts) {
301
+ setStatus("disconnected");
302
+ setNextRetryInMs(null);
303
+ return;
304
+ }
305
+ attemptRef.current += 1;
306
+ setAttempt(attemptRef.current);
307
+ const delay = computeReconnectDelay(attemptRef.current, baseDelayMs, maxDelayMs);
308
+ let remaining = delay;
309
+ setNextRetryInMs(remaining);
310
+ countdownIntervalRef.current = setInterval(() => {
311
+ remaining = Math.max(0, remaining - COUNTDOWN_TICK_MS);
312
+ setNextRetryInMs(remaining);
313
+ }, COUNTDOWN_TICK_MS);
314
+ retryTimeoutRef.current = setTimeout(() => {
315
+ clearTimers();
316
+ if (!isMountedRef.current || !enabledRef.current)
317
+ return;
318
+ runConnect();
319
+ }, delay);
320
+ }, [baseDelayMs, maxDelayMs, maxAttempts, clearTimers, runConnect]);
321
+ const markConnected = useCallback(() => {
322
+ clearTimers();
323
+ attemptRef.current = 0;
324
+ setAttempt(0);
325
+ setNextRetryInMs(null);
326
+ if (isMountedRef.current)
327
+ setStatus("connected");
328
+ }, [clearTimers]);
329
+ const markFailed = useCallback(() => {
330
+ clearTimers();
331
+ if (!isMountedRef.current)
332
+ return;
333
+ setStatus("error");
334
+ if (enabledRef.current) {
335
+ scheduleRetry();
336
+ }
337
+ else {
338
+ setNextRetryInMs(null);
339
+ }
340
+ }, [clearTimers, scheduleRetry]);
341
+ markFailedRef.current = markFailed;
342
+ const retryNow = useCallback(() => {
343
+ clearTimers();
344
+ attemptRef.current = 0;
345
+ setAttempt(0);
346
+ setNextRetryInMs(null);
347
+ runConnect();
348
+ }, [clearTimers, runConnect]);
349
+ const reset = useCallback(() => {
350
+ clearTimers();
351
+ attemptRef.current = 0;
352
+ setAttempt(0);
353
+ setNextRetryInMs(null);
354
+ if (isMountedRef.current)
355
+ setStatus("connecting");
356
+ }, [clearTimers]);
357
+ useEffect(() => {
358
+ isMountedRef.current = true;
359
+ if (autoStart) {
360
+ runConnect();
361
+ }
362
+ return () => {
363
+ isMountedRef.current = false;
364
+ clearTimers();
365
+ };
366
+ // eslint-disable-next-line react-hooks/exhaustive-deps
367
+ }, []);
368
+ useEffect(() => {
369
+ if (enabled && status === "error" && !retryTimeoutRef.current) {
370
+ scheduleRetry();
371
+ }
372
+ if (!enabled) {
373
+ clearTimers();
374
+ setNextRetryInMs(null);
375
+ }
376
+ // eslint-disable-next-line react-hooks/exhaustive-deps
377
+ }, [enabled]);
378
+ return {
379
+ status,
380
+ attempt,
381
+ maxAttempts,
382
+ nextRetryInMs,
383
+ markConnected,
384
+ markFailed,
385
+ retryNow,
386
+ reset,
387
+ };
388
+ }