@massdriver/backstage-plugin 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 (346) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +196 -0
  3. package/dist/MassdriverRouter.esm.js +78 -0
  4. package/dist/MassdriverRouter.esm.js.map +1 -0
  5. package/dist/api.esm.js +119 -0
  6. package/dist/api.esm.js.map +1 -0
  7. package/dist/assets/massdriver-logo-dark.svg +55 -0
  8. package/dist/assets/massdriver-logo-light.svg +50 -0
  9. package/dist/components/AttributesColumn.esm.js +95 -0
  10. package/dist/components/AttributesColumn.esm.js.map +1 -0
  11. package/dist/components/AttributesSummaryCell.esm.js +103 -0
  12. package/dist/components/AttributesSummaryCell.esm.js.map +1 -0
  13. package/dist/components/AuthedIcon.esm.js +26 -0
  14. package/dist/components/AuthedIcon.esm.js.map +1 -0
  15. package/dist/components/ConditionsCell.esm.js +48 -0
  16. package/dist/components/ConditionsCell.esm.js.map +1 -0
  17. package/dist/components/DisabledAction.esm.js +30 -0
  18. package/dist/components/DisabledAction.esm.js.map +1 -0
  19. package/dist/components/EntityMassdriverContent/EntityMassdriverContent.esm.js +80 -0
  20. package/dist/components/EntityMassdriverContent/EntityMassdriverContent.esm.js.map +1 -0
  21. package/dist/components/EntityMassdriverContent/index.esm.js +6 -0
  22. package/dist/components/EntityMassdriverContent/index.esm.js.map +1 -0
  23. package/dist/components/EntityMassdriverOverviewCard/EntityMassdriverOverviewCard.esm.js +75 -0
  24. package/dist/components/EntityMassdriverOverviewCard/EntityMassdriverOverviewCard.esm.js.map +1 -0
  25. package/dist/components/EntityMassdriverOverviewCard/index.esm.js +6 -0
  26. package/dist/components/EntityMassdriverOverviewCard/index.esm.js.map +1 -0
  27. package/dist/components/ForkPill.esm.js +84 -0
  28. package/dist/components/ForkPill.esm.js.map +1 -0
  29. package/dist/components/InstanceStatusIndicator.esm.js +21 -0
  30. package/dist/components/InstanceStatusIndicator.esm.js.map +1 -0
  31. package/dist/components/InstanceStatusPill.esm.js +67 -0
  32. package/dist/components/InstanceStatusPill.esm.js.map +1 -0
  33. package/dist/components/MassdriverIcon.esm.js +13 -0
  34. package/dist/components/MassdriverIcon.esm.js.map +1 -0
  35. package/dist/components/MassdriverSidebarItem.esm.js +45 -0
  36. package/dist/components/MassdriverSidebarItem.esm.js.map +1 -0
  37. package/dist/components/NotFound.esm.js +44 -0
  38. package/dist/components/NotFound.esm.js.map +1 -0
  39. package/dist/components/OpenInMassdriverButton.esm.js +24 -0
  40. package/dist/components/OpenInMassdriverButton.esm.js.map +1 -0
  41. package/dist/components/PageLayout.esm.js +88 -0
  42. package/dist/components/PageLayout.esm.js.map +1 -0
  43. package/dist/components/RouterLinkAdapter.esm.js +12 -0
  44. package/dist/components/RouterLinkAdapter.esm.js.map +1 -0
  45. package/dist/components/VersionBadge.esm.js +57 -0
  46. package/dist/components/VersionBadge.esm.js.map +1 -0
  47. package/dist/components/grantColumns.esm.js +56 -0
  48. package/dist/components/grantColumns.esm.js.map +1 -0
  49. package/dist/components/icons/BundleIcon.esm.js +7 -0
  50. package/dist/components/icons/BundleIcon.esm.js.map +1 -0
  51. package/dist/components/icons/FolderOutlinedIcon.esm.js +7 -0
  52. package/dist/components/icons/FolderOutlinedIcon.esm.js.map +1 -0
  53. package/dist/components/icons/TokenIcon.esm.js +7 -0
  54. package/dist/components/icons/TokenIcon.esm.js.map +1 -0
  55. package/dist/entity.esm.js +23 -0
  56. package/dist/entity.esm.js.map +1 -0
  57. package/dist/features/environment/CompareDeploymentsDialog/CompareDeploymentsDialog.esm.js +115 -0
  58. package/dist/features/environment/CompareDeploymentsDialog/CompareDeploymentsDialog.esm.js.map +1 -0
  59. package/dist/features/environment/CompareDeploymentsDialog/ResultsStep.esm.js +165 -0
  60. package/dist/features/environment/CompareDeploymentsDialog/ResultsStep.esm.js.map +1 -0
  61. package/dist/features/environment/CompareDeploymentsDialog/SelectStep.esm.js +216 -0
  62. package/dist/features/environment/CompareDeploymentsDialog/SelectStep.esm.js.map +1 -0
  63. package/dist/features/environment/CompareDeploymentsDialog/compareColumns.esm.js +86 -0
  64. package/dist/features/environment/CompareDeploymentsDialog/compareColumns.esm.js.map +1 -0
  65. package/dist/features/environment/CompareDeploymentsDialog/flattenDeploymentComparison.esm.js +57 -0
  66. package/dist/features/environment/CompareDeploymentsDialog/flattenDeploymentComparison.esm.js.map +1 -0
  67. package/dist/features/environment/CompareDeploymentsDialog/queries.esm.js +53 -0
  68. package/dist/features/environment/CompareDeploymentsDialog/queries.esm.js.map +1 -0
  69. package/dist/features/environment/CompareEnvironmentsDialog/CompareEnvironmentsDialog.esm.js +94 -0
  70. package/dist/features/environment/CompareEnvironmentsDialog/CompareEnvironmentsDialog.esm.js.map +1 -0
  71. package/dist/features/environment/CompareEnvironmentsDialog/ComparisonValueCell.esm.js +67 -0
  72. package/dist/features/environment/CompareEnvironmentsDialog/ComparisonValueCell.esm.js.map +1 -0
  73. package/dist/features/environment/CompareEnvironmentsDialog/ResultsStep.esm.js +202 -0
  74. package/dist/features/environment/CompareEnvironmentsDialog/ResultsStep.esm.js.map +1 -0
  75. package/dist/features/environment/CompareEnvironmentsDialog/SelectStep.esm.js +183 -0
  76. package/dist/features/environment/CompareEnvironmentsDialog/SelectStep.esm.js.map +1 -0
  77. package/dist/features/environment/CompareEnvironmentsDialog/compareColumns.esm.js +73 -0
  78. package/dist/features/environment/CompareEnvironmentsDialog/compareColumns.esm.js.map +1 -0
  79. package/dist/features/environment/CompareEnvironmentsDialog/flattenComparison.esm.js +70 -0
  80. package/dist/features/environment/CompareEnvironmentsDialog/flattenComparison.esm.js.map +1 -0
  81. package/dist/features/environment/CompareEnvironmentsDialog/queries.esm.js +32 -0
  82. package/dist/features/environment/CompareEnvironmentsDialog/queries.esm.js.map +1 -0
  83. package/dist/features/environment/EnvironmentGraphPage.esm.js +131 -0
  84. package/dist/features/environment/EnvironmentGraphPage.esm.js.map +1 -0
  85. package/dist/features/environment/GraphHeader/EnvironmentDefaults.esm.js +252 -0
  86. package/dist/features/environment/GraphHeader/EnvironmentDefaults.esm.js.map +1 -0
  87. package/dist/features/environment/GraphHeader/GraphHeader.esm.js +247 -0
  88. package/dist/features/environment/GraphHeader/GraphHeader.esm.js.map +1 -0
  89. package/dist/features/environment/GraphHeader/HeaderActions.esm.js +127 -0
  90. package/dist/features/environment/GraphHeader/HeaderActions.esm.js.map +1 -0
  91. package/dist/features/environment/GraphHeader/Switcher.esm.js +75 -0
  92. package/dist/features/environment/GraphHeader/Switcher.esm.js.map +1 -0
  93. package/dist/features/environment/GraphHeader/queries.esm.js +60 -0
  94. package/dist/features/environment/GraphHeader/queries.esm.js.map +1 -0
  95. package/dist/features/environment/InstanceDrawer/AlarmCard.esm.js +151 -0
  96. package/dist/features/environment/InstanceDrawer/AlarmCard.esm.js.map +1 -0
  97. package/dist/features/environment/InstanceDrawer/InstanceDrawer.esm.js +165 -0
  98. package/dist/features/environment/InstanceDrawer/InstanceDrawer.esm.js.map +1 -0
  99. package/dist/features/environment/InstanceDrawer/InstanceDrawerHeader.esm.js +241 -0
  100. package/dist/features/environment/InstanceDrawer/InstanceDrawerHeader.esm.js.map +1 -0
  101. package/dist/features/environment/InstanceDrawer/InstanceTabs.esm.js +119 -0
  102. package/dist/features/environment/InstanceDrawer/InstanceTabs.esm.js.map +1 -0
  103. package/dist/features/environment/InstanceDrawer/TabState.esm.js +30 -0
  104. package/dist/features/environment/InstanceDrawer/TabState.esm.js.map +1 -0
  105. package/dist/features/environment/InstanceDrawer/formsDataSource.esm.js +25 -0
  106. package/dist/features/environment/InstanceDrawer/formsDataSource.esm.js.map +1 -0
  107. package/dist/features/environment/InstanceDrawer/helpers.esm.js +282 -0
  108. package/dist/features/environment/InstanceDrawer/helpers.esm.js.map +1 -0
  109. package/dist/features/environment/InstanceDrawer/queries.esm.js +281 -0
  110. package/dist/features/environment/InstanceDrawer/queries.esm.js.map +1 -0
  111. package/dist/features/environment/InstanceDrawer/tabs/ConfigTab.esm.js +170 -0
  112. package/dist/features/environment/InstanceDrawer/tabs/ConfigTab.esm.js.map +1 -0
  113. package/dist/features/environment/InstanceDrawer/tabs/DependenciesTab.esm.js +413 -0
  114. package/dist/features/environment/InstanceDrawer/tabs/DependenciesTab.esm.js.map +1 -0
  115. package/dist/features/environment/InstanceDrawer/tabs/DeploymentLogsPanel.esm.js +191 -0
  116. package/dist/features/environment/InstanceDrawer/tabs/DeploymentLogsPanel.esm.js.map +1 -0
  117. package/dist/features/environment/InstanceDrawer/tabs/DeploymentReadOnlyActions.esm.js +63 -0
  118. package/dist/features/environment/InstanceDrawer/tabs/DeploymentReadOnlyActions.esm.js.map +1 -0
  119. package/dist/features/environment/InstanceDrawer/tabs/GuideTab.esm.js +48 -0
  120. package/dist/features/environment/InstanceDrawer/tabs/GuideTab.esm.js.map +1 -0
  121. package/dist/features/environment/InstanceDrawer/tabs/HistoryTab.esm.js +446 -0
  122. package/dist/features/environment/InstanceDrawer/tabs/HistoryTab.esm.js.map +1 -0
  123. package/dist/features/environment/InstanceDrawer/tabs/MonitorTab.esm.js +146 -0
  124. package/dist/features/environment/InstanceDrawer/tabs/MonitorTab.esm.js.map +1 -0
  125. package/dist/features/environment/InstanceDrawer/tabs/OverviewTab.esm.js +572 -0
  126. package/dist/features/environment/InstanceDrawer/tabs/OverviewTab.esm.js.map +1 -0
  127. package/dist/features/environment/InstanceDrawer/tabs/ResourcesTab.esm.js +471 -0
  128. package/dist/features/environment/InstanceDrawer/tabs/ResourcesTab.esm.js.map +1 -0
  129. package/dist/features/environment/InstanceDrawer/tabs/SecretsTab.esm.js +109 -0
  130. package/dist/features/environment/InstanceDrawer/tabs/SecretsTab.esm.js.map +1 -0
  131. package/dist/features/environment/InstanceDrawer/tabs/ViewDeploymentDetails.esm.js +384 -0
  132. package/dist/features/environment/InstanceDrawer/tabs/ViewDeploymentDetails.esm.js.map +1 -0
  133. package/dist/features/environment/InstanceDrawer/tabs/flattenParams.esm.js +23 -0
  134. package/dist/features/environment/InstanceDrawer/tabs/flattenParams.esm.js.map +1 -0
  135. package/dist/features/environment/InstanceDrawer/useInstanceApiQuery.esm.js +6 -0
  136. package/dist/features/environment/InstanceDrawer/useInstanceApiQuery.esm.js.map +1 -0
  137. package/dist/features/environment/InstanceDrawer/useOverflowMeasure.esm.js +55 -0
  138. package/dist/features/environment/InstanceDrawer/useOverflowMeasure.esm.js.map +1 -0
  139. package/dist/features/environment/InstanceDrawer/useResizableWidth.esm.js +44 -0
  140. package/dist/features/environment/InstanceDrawer/useResizableWidth.esm.js.map +1 -0
  141. package/dist/features/environment/components/InstanceStatusPill.esm.js +54 -0
  142. package/dist/features/environment/components/InstanceStatusPill.esm.js.map +1 -0
  143. package/dist/features/environment/graph/Diagram.esm.js +143 -0
  144. package/dist/features/environment/graph/Diagram.esm.js.map +1 -0
  145. package/dist/features/environment/graph/DiagramNode.constants.esm.js +5 -0
  146. package/dist/features/environment/graph/DiagramNode.constants.esm.js.map +1 -0
  147. package/dist/features/environment/graph/DiagramNode.esm.js +221 -0
  148. package/dist/features/environment/graph/DiagramNode.esm.js.map +1 -0
  149. package/dist/features/environment/graph/NodeMeta.esm.js +182 -0
  150. package/dist/features/environment/graph/NodeMeta.esm.js.map +1 -0
  151. package/dist/features/environment/graph/NodeVersionBadges.esm.js +150 -0
  152. package/dist/features/environment/graph/NodeVersionBadges.esm.js.map +1 -0
  153. package/dist/features/environment/graph/diagramFactory.esm.js +151 -0
  154. package/dist/features/environment/graph/diagramFactory.esm.js.map +1 -0
  155. package/dist/features/environment/graph/handles/ExpandableHandleWrapper.esm.js +174 -0
  156. package/dist/features/environment/graph/handles/ExpandableHandleWrapper.esm.js.map +1 -0
  157. package/dist/features/environment/graph/handles/NodeHandle.esm.js +45 -0
  158. package/dist/features/environment/graph/handles/NodeHandle.esm.js.map +1 -0
  159. package/dist/features/environment/graph/handles/NodeHandleTooltip.esm.js +134 -0
  160. package/dist/features/environment/graph/handles/NodeHandleTooltip.esm.js.map +1 -0
  161. package/dist/features/environment/graph/handles/handleTypes.esm.js +170 -0
  162. package/dist/features/environment/graph/handles/handleTypes.esm.js.map +1 -0
  163. package/dist/features/environment/graph/handles/useAnimationFrameSync.esm.js +19 -0
  164. package/dist/features/environment/graph/handles/useAnimationFrameSync.esm.js.map +1 -0
  165. package/dist/features/environment/graph/handles/useRadialPositions.esm.js +37 -0
  166. package/dist/features/environment/graph/handles/useRadialPositions.esm.js.map +1 -0
  167. package/dist/features/environment/graph/handles/useTransitionLifecycle.esm.js +19 -0
  168. package/dist/features/environment/graph/handles/useTransitionLifecycle.esm.js.map +1 -0
  169. package/dist/features/environment/graph/hasUndeployedPlan.esm.js +43 -0
  170. package/dist/features/environment/graph/hasUndeployedPlan.esm.js.map +1 -0
  171. package/dist/features/environment/graph/queries.esm.js +103 -0
  172. package/dist/features/environment/graph/queries.esm.js.map +1 -0
  173. package/dist/features/environment/graph/useDiagramSnapshot.esm.js +43 -0
  174. package/dist/features/environment/graph/useDiagramSnapshot.esm.js.map +1 -0
  175. package/dist/features/environment/realtime/RealtimeProvider.esm.js +43 -0
  176. package/dist/features/environment/realtime/RealtimeProvider.esm.js.map +1 -0
  177. package/dist/features/environment/realtime/queries.esm.js +76 -0
  178. package/dist/features/environment/realtime/queries.esm.js.map +1 -0
  179. package/dist/features/environment/realtime/useLiveRelayQuery.esm.js +36 -0
  180. package/dist/features/environment/realtime/useLiveRelayQuery.esm.js.map +1 -0
  181. package/dist/features/project/ProjectDetailsPage.esm.js +101 -0
  182. package/dist/features/project/ProjectDetailsPage.esm.js.map +1 -0
  183. package/dist/features/project/tabs/ComponentsTab.esm.js +149 -0
  184. package/dist/features/project/tabs/ComponentsTab.esm.js.map +1 -0
  185. package/dist/features/project/tabs/EnvStatus.esm.js +149 -0
  186. package/dist/features/project/tabs/EnvStatus.esm.js.map +1 -0
  187. package/dist/features/project/tabs/EnvironmentsTab.esm.js +199 -0
  188. package/dist/features/project/tabs/EnvironmentsTab.esm.js.map +1 -0
  189. package/dist/features/project/tabs/OverviewTab.esm.js +420 -0
  190. package/dist/features/project/tabs/OverviewTab.esm.js.map +1 -0
  191. package/dist/features/projects/ProjectsListPage.esm.js +50 -0
  192. package/dist/features/projects/ProjectsListPage.esm.js.map +1 -0
  193. package/dist/features/projects/ProjectsListPageLazy.esm.js +12 -0
  194. package/dist/features/projects/ProjectsListPageLazy.esm.js.map +1 -0
  195. package/dist/features/projects/projectColumns.esm.js +38 -0
  196. package/dist/features/projects/projectColumns.esm.js.map +1 -0
  197. package/dist/features/projects/useProjects.esm.js +48 -0
  198. package/dist/features/projects/useProjects.esm.js.map +1 -0
  199. package/dist/features/repo/DeploymentLogsDrawer.esm.js +213 -0
  200. package/dist/features/repo/DeploymentLogsDrawer.esm.js.map +1 -0
  201. package/dist/features/repo/DeploymentLogsDrawer.loading.esm.js +43 -0
  202. package/dist/features/repo/DeploymentLogsDrawer.loading.esm.js.map +1 -0
  203. package/dist/features/repo/FileTree.esm.js +179 -0
  204. package/dist/features/repo/FileTree.esm.js.map +1 -0
  205. package/dist/features/repo/FileViewer.esm.js +115 -0
  206. package/dist/features/repo/FileViewer.esm.js.map +1 -0
  207. package/dist/features/repo/FileViewer.helpers.esm.js +54 -0
  208. package/dist/features/repo/FileViewer.helpers.esm.js.map +1 -0
  209. package/dist/features/repo/RepoDetailsPage.esm.js +127 -0
  210. package/dist/features/repo/RepoDetailsPage.esm.js.map +1 -0
  211. package/dist/features/repo/RepoEmptyState.esm.js +58 -0
  212. package/dist/features/repo/RepoEmptyState.esm.js.map +1 -0
  213. package/dist/features/repo/RepoNoVersionsState.esm.js +29 -0
  214. package/dist/features/repo/RepoNoVersionsState.esm.js.map +1 -0
  215. package/dist/features/repo/RepoTabHeader.esm.js +30 -0
  216. package/dist/features/repo/RepoTabHeader.esm.js.map +1 -0
  217. package/dist/features/repo/RepoTabLayout.esm.js +18 -0
  218. package/dist/features/repo/RepoTabLayout.esm.js.map +1 -0
  219. package/dist/features/repo/RepoVersionSelect.esm.js +176 -0
  220. package/dist/features/repo/RepoVersionSelect.esm.js.map +1 -0
  221. package/dist/features/repo/ViewDeploymentDetailsDialog.esm.js +427 -0
  222. package/dist/features/repo/ViewDeploymentDetailsDialog.esm.js.map +1 -0
  223. package/dist/features/repo/deploymentHelpers.esm.js +74 -0
  224. package/dist/features/repo/deploymentHelpers.esm.js.map +1 -0
  225. package/dist/features/repo/fileTreeHelpers.esm.js +45 -0
  226. package/dist/features/repo/fileTreeHelpers.esm.js.map +1 -0
  227. package/dist/features/repo/flattenParams.esm.js +23 -0
  228. package/dist/features/repo/flattenParams.esm.js.map +1 -0
  229. package/dist/features/repo/queries.esm.js +239 -0
  230. package/dist/features/repo/queries.esm.js.map +1 -0
  231. package/dist/features/repo/repoFilter.esm.js +9 -0
  232. package/dist/features/repo/repoFilter.esm.js.map +1 -0
  233. package/dist/features/repo/repoTabs.esm.js +22 -0
  234. package/dist/features/repo/repoTabs.esm.js.map +1 -0
  235. package/dist/features/repo/resolveVersion.esm.js +22 -0
  236. package/dist/features/repo/resolveVersion.esm.js.map +1 -0
  237. package/dist/features/repo/tabs/DeploymentRow.esm.js +201 -0
  238. package/dist/features/repo/tabs/DeploymentRow.esm.js.map +1 -0
  239. package/dist/features/repo/tabs/DeploymentsTab.esm.js +188 -0
  240. package/dist/features/repo/tabs/DeploymentsTab.esm.js.map +1 -0
  241. package/dist/features/repo/tabs/DeploymentsTab.helpers.esm.js +46 -0
  242. package/dist/features/repo/tabs/DeploymentsTab.helpers.esm.js.map +1 -0
  243. package/dist/features/repo/tabs/DeploymentsTab.loading.esm.js +37 -0
  244. package/dist/features/repo/tabs/DeploymentsTab.loading.esm.js.map +1 -0
  245. package/dist/features/repo/tabs/FilesTab.esm.js +142 -0
  246. package/dist/features/repo/tabs/FilesTab.esm.js.map +1 -0
  247. package/dist/features/repo/tabs/InstanceRow.esm.js +121 -0
  248. package/dist/features/repo/tabs/InstanceRow.esm.js.map +1 -0
  249. package/dist/features/repo/tabs/InstancesTab.esm.js +147 -0
  250. package/dist/features/repo/tabs/InstancesTab.esm.js.map +1 -0
  251. package/dist/features/repo/tabs/InstancesTab.helpers.esm.js +44 -0
  252. package/dist/features/repo/tabs/InstancesTab.helpers.esm.js.map +1 -0
  253. package/dist/features/repo/tabs/InstancesTab.loading.esm.js +33 -0
  254. package/dist/features/repo/tabs/InstancesTab.loading.esm.js.map +1 -0
  255. package/dist/features/repo/tabs/OverviewTab.esm.js +77 -0
  256. package/dist/features/repo/tabs/OverviewTab.esm.js.map +1 -0
  257. package/dist/features/repo/tabs/PermissionsTab.esm.js +56 -0
  258. package/dist/features/repo/tabs/PermissionsTab.esm.js.map +1 -0
  259. package/dist/features/repo/tabs/VersionsTab.esm.js +152 -0
  260. package/dist/features/repo/tabs/VersionsTab.esm.js.map +1 -0
  261. package/dist/features/repo/useInfiniteRelayList.esm.js +92 -0
  262. package/dist/features/repo/useInfiniteRelayList.esm.js.map +1 -0
  263. package/dist/features/repo/useInfiniteScroll.esm.js +21 -0
  264. package/dist/features/repo/useInfiniteScroll.esm.js.map +1 -0
  265. package/dist/features/repos/ReposListPage.esm.js +53 -0
  266. package/dist/features/repos/ReposListPage.esm.js.map +1 -0
  267. package/dist/features/repos/queries.esm.js +40 -0
  268. package/dist/features/repos/queries.esm.js.map +1 -0
  269. package/dist/features/repos/repoColumns.esm.js +121 -0
  270. package/dist/features/repos/repoColumns.esm.js.map +1 -0
  271. package/dist/features/repos/useRepos.esm.js +22 -0
  272. package/dist/features/repos/useRepos.esm.js.map +1 -0
  273. package/dist/features/resource/OriginChip.esm.js +42 -0
  274. package/dist/features/resource/OriginChip.esm.js.map +1 -0
  275. package/dist/features/resource/ResourceDetailsPage.esm.js +167 -0
  276. package/dist/features/resource/ResourceDetailsPage.esm.js.map +1 -0
  277. package/dist/features/resource/queries.esm.js +141 -0
  278. package/dist/features/resource/queries.esm.js.map +1 -0
  279. package/dist/features/resource/tabs/GeneralTab.esm.js +247 -0
  280. package/dist/features/resource/tabs/GeneralTab.esm.js.map +1 -0
  281. package/dist/features/resource/tabs/GeneralTab.loading.esm.js +76 -0
  282. package/dist/features/resource/tabs/GeneralTab.loading.esm.js.map +1 -0
  283. package/dist/features/resource/tabs/PermissionsTab.esm.js +57 -0
  284. package/dist/features/resource/tabs/PermissionsTab.esm.js.map +1 -0
  285. package/dist/features/resource/tabs/SettingsTabLayout.esm.js +18 -0
  286. package/dist/features/resource/tabs/SettingsTabLayout.esm.js.map +1 -0
  287. package/dist/features/resource/tabs/TabHeader.esm.js +30 -0
  288. package/dist/features/resource/tabs/TabHeader.esm.js.map +1 -0
  289. package/dist/features/resource/tabs/UsagePanel.esm.js +35 -0
  290. package/dist/features/resource/tabs/UsagePanel.esm.js.map +1 -0
  291. package/dist/features/resource/tabs/UsageTab.esm.js +91 -0
  292. package/dist/features/resource/tabs/UsageTab.esm.js.map +1 -0
  293. package/dist/features/resource/tabs/UsageTab.helpers.esm.js +168 -0
  294. package/dist/features/resource/tabs/UsageTab.helpers.esm.js.map +1 -0
  295. package/dist/features/resources/ResourcesEmptyState.esm.js +148 -0
  296. package/dist/features/resources/ResourcesEmptyState.esm.js.map +1 -0
  297. package/dist/features/resources/ResourcesListPage.esm.js +115 -0
  298. package/dist/features/resources/ResourcesListPage.esm.js.map +1 -0
  299. package/dist/features/resources/queries.esm.js +50 -0
  300. package/dist/features/resources/queries.esm.js.map +1 -0
  301. package/dist/features/resources/resourceColumns.esm.js +158 -0
  302. package/dist/features/resources/resourceColumns.esm.js.map +1 -0
  303. package/dist/features/resources/resourceConstants.esm.js +7 -0
  304. package/dist/features/resources/resourceConstants.esm.js.map +1 -0
  305. package/dist/features/resources/toResourceRow.esm.js +29 -0
  306. package/dist/features/resources/toResourceRow.esm.js.map +1 -0
  307. package/dist/hooks/useAuthedSvg.esm.js +34 -0
  308. package/dist/hooks/useAuthedSvg.esm.js.map +1 -0
  309. package/dist/hooks/useCursorPagination.esm.js +40 -0
  310. package/dist/hooks/useCursorPagination.esm.js.map +1 -0
  311. package/dist/hooks/useMassdriverSubscription.esm.js +61 -0
  312. package/dist/hooks/useMassdriverSubscription.esm.js.map +1 -0
  313. package/dist/hooks/usePaginatedRelayQuery.esm.js +68 -0
  314. package/dist/hooks/usePaginatedRelayQuery.esm.js.map +1 -0
  315. package/dist/index.d.ts +256 -0
  316. package/dist/index.esm.js +8 -0
  317. package/dist/index.esm.js.map +1 -0
  318. package/dist/internalRoutes.esm.js +29 -0
  319. package/dist/internalRoutes.esm.js.map +1 -0
  320. package/dist/plugin.esm.js +57 -0
  321. package/dist/plugin.esm.js.map +1 -0
  322. package/dist/queries.esm.js +54 -0
  323. package/dist/queries.esm.js.map +1 -0
  324. package/dist/routes.esm.js +6 -0
  325. package/dist/routes.esm.js.map +1 -0
  326. package/dist/shell/MassdriverHeader.esm.js +37 -0
  327. package/dist/shell/MassdriverHeader.esm.js.map +1 -0
  328. package/dist/shell/MassdriverShell.esm.js +30 -0
  329. package/dist/shell/MassdriverShell.esm.js.map +1 -0
  330. package/dist/theme/MassdriverThemeScope.esm.js +30 -0
  331. package/dist/theme/MassdriverThemeScope.esm.js.map +1 -0
  332. package/dist/theme/ThemeModeContext.esm.js +35 -0
  333. package/dist/theme/ThemeModeContext.esm.js.map +1 -0
  334. package/dist/theme/muiClassNameAudit.esm.js +11 -0
  335. package/dist/theme/muiClassNameAudit.esm.js.map +1 -0
  336. package/dist/useInstances.esm.js +39 -0
  337. package/dist/useInstances.esm.js.map +1 -0
  338. package/dist/utils/attributes.esm.js +28 -0
  339. package/dist/utils/attributes.esm.js.map +1 -0
  340. package/dist/utils/conditions.esm.js +20 -0
  341. package/dist/utils/conditions.esm.js.map +1 -0
  342. package/dist/utils/formatRelativeTime.esm.js +40 -0
  343. package/dist/utils/formatRelativeTime.esm.js.map +1 -0
  344. package/dist/utils/instanceStatuses.esm.js +74 -0
  345. package/dist/utils/instanceStatuses.esm.js.map +1 -0
  346. package/package.json +92 -0
@@ -0,0 +1,115 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useApi } from '@backstage/frontend-plugin-api';
3
+ import { resourcesUrl } from '@massdriver/backstage-plugin-common';
4
+ import Alert from '@massdriver/ui/Alert';
5
+ import Box from '@massdriver/ui/Box';
6
+ import DataList from '@massdriver/ui/DataList';
7
+ import Select from '@massdriver/ui/Select';
8
+ import stylin from '@massdriver/ui/stylin';
9
+ import { useState } from 'react';
10
+ import { massdriverApiRef } from '../../api.esm.js';
11
+ import { OpenInMassdriverButton } from '../../components/OpenInMassdriverButton.esm.js';
12
+ import { PageLayout } from '../../components/PageLayout.esm.js';
13
+ import { usePaginatedRelayQuery } from '../../hooks/usePaginatedRelayQuery.esm.js';
14
+ import { RESOURCES_QUERY } from './queries.esm.js';
15
+ import { buildResourceColumns } from './resourceColumns.esm.js';
16
+ import { ResourcesEmptyState } from './ResourcesEmptyState.esm.js';
17
+ import { toResourceRow } from './toResourceRow.esm.js';
18
+
19
+ const ORIGIN_OPTIONS = [
20
+ { value: "all", label: "All resources" },
21
+ { value: "IMPORTED", label: "Imported only" },
22
+ { value: "PROVISIONED", label: "Provisioned only" }
23
+ ];
24
+ const ResourcesListPage = () => {
25
+ const api = useApi(massdriverApiRef);
26
+ const [origin, setOrigin] = useState("all");
27
+ const importUrl = `${resourcesUrl(
28
+ api.appUrl,
29
+ api.organizationId
30
+ )}?importResource=true`;
31
+ return /* @__PURE__ */ jsx(
32
+ PageLayout,
33
+ {
34
+ title: "Resources",
35
+ description: "All resources for your organization \u2014 both imported and provisioned. Resources flow into Massdriver automatically as instances deploy, or you can import existing resources by hand.",
36
+ actions: /* @__PURE__ */ jsx(OpenInMassdriverButton, { url: importUrl, children: "Import Resource" }),
37
+ children: /* @__PURE__ */ jsx(
38
+ ResourcesList,
39
+ {
40
+ origin,
41
+ onOriginChange: setOrigin,
42
+ importUrl
43
+ },
44
+ origin
45
+ )
46
+ }
47
+ );
48
+ };
49
+ const ResourcesList = ({
50
+ origin,
51
+ onOriginChange,
52
+ importUrl
53
+ }) => {
54
+ const baseFilter = origin === "all" ? void 0 : { origin: { eq: origin } };
55
+ const { items, loading, error, hasMore, dataListParams } = usePaginatedRelayQuery(RESOURCES_QUERY, {
56
+ responseKey: "resources",
57
+ sortFieldMap: { name: "NAME", createdAt: "CREATED_AT" },
58
+ defaultSort: { field: "name", direction: "asc" },
59
+ pageSize: 25,
60
+ baseFilter
61
+ });
62
+ const api = useApi(massdriverApiRef);
63
+ const columns = buildResourceColumns({
64
+ appUrl: api.appUrl,
65
+ organizationId: api.organizationId
66
+ });
67
+ const rows = items.map(toResourceRow);
68
+ const filtersActive = origin !== "all" || Boolean(dataListParams.state.search);
69
+ const showEmptyState = !loading && !error && !filtersActive && rows.length === 0;
70
+ if (showEmptyState) {
71
+ return /* @__PURE__ */ jsx(ResourcesEmptyState, { importUrl });
72
+ }
73
+ return /* @__PURE__ */ jsxs(Wrap, { children: [
74
+ /* @__PURE__ */ jsx(Toolbar, { children: /* @__PURE__ */ jsx(
75
+ FilterSelect,
76
+ {
77
+ size: "small",
78
+ label: "Show",
79
+ options: ORIGIN_OPTIONS,
80
+ value: origin,
81
+ onChange: (event) => onOriginChange(event.target.value)
82
+ }
83
+ ) }),
84
+ error ? /* @__PURE__ */ jsx(Alert, { severity: "error", children: String(error.message ?? error) }) : /* @__PURE__ */ jsx(
85
+ DataList,
86
+ {
87
+ rows,
88
+ columns,
89
+ loading,
90
+ serverSide: true,
91
+ searchable: true,
92
+ searchPlaceholder: "Search resources\u2026",
93
+ hasMore,
94
+ emptyMessage: "No resources match.",
95
+ variant: "outlined",
96
+ ...dataListParams
97
+ }
98
+ )
99
+ ] });
100
+ };
101
+ const Wrap = stylin(Box)(({ theme }) => ({
102
+ display: "flex",
103
+ flexDirection: "column",
104
+ gap: theme.spacing(2)
105
+ }));
106
+ const Toolbar = stylin(Box)({
107
+ display: "flex",
108
+ alignItems: "center"
109
+ });
110
+ const FilterSelect = stylin(Select)(({ theme }) => ({
111
+ minWidth: theme.spacing(28)
112
+ }));
113
+
114
+ export { ResourcesListPage };
115
+ //# sourceMappingURL=ResourcesListPage.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResourcesListPage.esm.js","sources":["../../../src/features/resources/ResourcesListPage.tsx"],"sourcesContent":["import { useApi } from '@backstage/frontend-plugin-api';\nimport { resourcesUrl } from '@massdriver/backstage-plugin-common';\nimport Alert from '@massdriver/ui/Alert';\nimport Box from '@massdriver/ui/Box';\nimport DataList from '@massdriver/ui/DataList';\nimport Select from '@massdriver/ui/Select';\nimport stylin from '@massdriver/ui/stylin';\nimport { useState } from 'react';\nimport { massdriverApiRef } from '../../api';\nimport { OpenInMassdriverButton } from '../../components/OpenInMassdriverButton';\nimport { PageLayout } from '../../components/PageLayout';\nimport { usePaginatedRelayQuery } from '../../hooks/usePaginatedRelayQuery';\nimport { RESOURCES_QUERY } from './queries';\nimport { buildResourceColumns } from './resourceColumns';\nimport { ResourcesEmptyState } from './ResourcesEmptyState';\nimport { ResourceListItem, toResourceRow } from './toResourceRow';\n\n// Ported from apps/web/features/resources/pages/ResourcesPage.js and\n// sections/ResourcesList/. The web app's \"Import Resource\" opens a dialog; here\n// it deep-links into Massdriver (read-only parity).\n\ntype Origin = 'all' | 'IMPORTED' | 'PROVISIONED';\n\nconst ORIGIN_OPTIONS = [\n { value: 'all', label: 'All resources' },\n { value: 'IMPORTED', label: 'Imported only' },\n { value: 'PROVISIONED', label: 'Provisioned only' },\n];\n\n/** Read-only resources list, mirroring the web app's Resources page. */\nexport const ResourcesListPage = () => {\n const api = useApi(massdriverApiRef);\n const [origin, setOrigin] = useState<Origin>('all');\n const importUrl = `${resourcesUrl(\n api.appUrl,\n api.organizationId,\n )}?importResource=true`;\n\n return (\n <PageLayout\n title=\"Resources\"\n description=\"All resources for your organization — both imported and provisioned. Resources flow into Massdriver automatically as instances deploy, or you can import existing resources by hand.\"\n actions={\n <OpenInMassdriverButton url={importUrl}>\n Import Resource\n </OpenInMassdriverButton>\n }\n >\n {/* Remount on origin change so paging state resets (mirrors the web's\n UsagePanel key pattern). */}\n <ResourcesList\n key={origin}\n origin={origin}\n onOriginChange={setOrigin}\n importUrl={importUrl}\n />\n </PageLayout>\n );\n};\n\nconst ResourcesList = ({\n origin,\n onOriginChange,\n importUrl,\n}: {\n origin: Origin;\n onOriginChange: (origin: Origin) => void;\n importUrl: string;\n}) => {\n const baseFilter = origin === 'all' ? undefined : { origin: { eq: origin } };\n\n const { items, loading, error, hasMore, dataListParams } =\n usePaginatedRelayQuery<ResourceListItem>(RESOURCES_QUERY, {\n responseKey: 'resources',\n sortFieldMap: { name: 'NAME', createdAt: 'CREATED_AT' },\n defaultSort: { field: 'name', direction: 'asc' },\n pageSize: 25,\n baseFilter,\n });\n\n const api = useApi(massdriverApiRef);\n const columns = buildResourceColumns({\n appUrl: api.appUrl,\n organizationId: api.organizationId,\n });\n const rows = items.map(toResourceRow);\n\n const filtersActive =\n origin !== 'all' || Boolean(dataListParams.state.search);\n const showEmptyState =\n !loading && !error && !filtersActive && rows.length === 0;\n\n // With no resources and no active filters, the web shows a catalog-onboarding\n // card in place of the toolbar + table.\n if (showEmptyState) {\n return <ResourcesEmptyState importUrl={importUrl} />;\n }\n\n return (\n <Wrap>\n <Toolbar>\n <FilterSelect\n size=\"small\"\n label=\"Show\"\n options={ORIGIN_OPTIONS}\n value={origin}\n onChange={(event: { target: { value: Origin } }) =>\n onOriginChange(event.target.value)\n }\n />\n </Toolbar>\n {error ? (\n <Alert severity=\"error\">{String(error.message ?? error)}</Alert>\n ) : (\n <DataList\n rows={rows}\n columns={columns}\n loading={loading}\n serverSide\n searchable\n searchPlaceholder=\"Search resources…\"\n hasMore={hasMore}\n emptyMessage=\"No resources match.\"\n variant=\"outlined\"\n {...dataListParams}\n />\n )}\n </Wrap>\n );\n};\n\nconst Wrap = stylin(Box)(({ theme }: { theme: any }) => ({\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(2),\n}));\n\nconst Toolbar = stylin(Box)({\n display: 'flex',\n alignItems: 'center',\n});\n\nconst FilterSelect = stylin(Select)(({ theme }: { theme: any }) => ({\n minWidth: theme.spacing(28),\n}));\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ const RESOURCES_QUERY = `
2
+ query MassdriverResourcesList(
3
+ $organizationId: ID!
4
+ $filter: ResourcesFilter
5
+ $sort: ResourcesSort
6
+ $cursor: Cursor
7
+ ) {
8
+ resources(
9
+ organizationId: $organizationId
10
+ filter: $filter
11
+ sort: $sort
12
+ cursor: $cursor
13
+ ) {
14
+ cursor {
15
+ next
16
+ previous
17
+ }
18
+ items {
19
+ id
20
+ name
21
+ origin
22
+ formats
23
+ attributes
24
+ effectiveAttributes
25
+ createdAt
26
+ updatedAt
27
+ resourceType {
28
+ id
29
+ name
30
+ icon
31
+ }
32
+ instance {
33
+ id
34
+ name
35
+ environment {
36
+ id
37
+ name
38
+ project {
39
+ id
40
+ name
41
+ }
42
+ }
43
+ }
44
+ }
45
+ }
46
+ }
47
+ `;
48
+
49
+ export { RESOURCES_QUERY };
50
+ //# sourceMappingURL=queries.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.esm.js","sources":["../../../src/features/resources/queries.ts"],"sourcesContent":["// Ported from apps/web/features/resources/hooks/useResourcesQuery.js\n\n/** Paginated resources list. `$organizationId` is injected by the relay. */\nexport const RESOURCES_QUERY = `\n query MassdriverResourcesList(\n $organizationId: ID!\n $filter: ResourcesFilter\n $sort: ResourcesSort\n $cursor: Cursor\n ) {\n resources(\n organizationId: $organizationId\n filter: $filter\n sort: $sort\n cursor: $cursor\n ) {\n cursor {\n next\n previous\n }\n items {\n id\n name\n origin\n formats\n attributes\n effectiveAttributes\n createdAt\n updatedAt\n resourceType {\n id\n name\n icon\n }\n instance {\n id\n name\n environment {\n id\n name\n project {\n id\n name\n }\n }\n }\n }\n }\n }\n`;\n"],"names":[],"mappings":"AAGO,MAAM,eAAA,GAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;"}
@@ -0,0 +1,158 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import Box from '@massdriver/ui/Box';
3
+ import { col } from '@massdriver/ui/DataList';
4
+ import IconTile from '@massdriver/ui/IconTile';
5
+ import Typography from '@massdriver/ui/Typography';
6
+ import DeleteIcon from '@massdriver/ui/icons/DeleteIcon';
7
+ import EditIcon from '@massdriver/ui/icons/EditIcon';
8
+ import ExtensionIcon from '@massdriver/ui/icons/ExtensionIcon';
9
+ import stylin from '@massdriver/ui/stylin';
10
+ import { resourceUrl } from '@massdriver/backstage-plugin-common';
11
+ import { buildAttributesColumn, Code } from '../../components/AttributesColumn.esm.js';
12
+ import { RouterLinkAdapter } from '../../components/RouterLinkAdapter.esm.js';
13
+ import { internalRoutes } from '../../internalRoutes.esm.js';
14
+ import { formatAbsoluteTime } from '../../utils/formatRelativeTime.esm.js';
15
+ import { PROVISIONED_EDIT_TOOLTIP, IMPORTED_EDIT_TOOLTIP, PROVISIONED_DELETE_TOOLTIP, IMPORTED_DELETE_TOOLTIP } from './resourceConstants.esm.js';
16
+
17
+ const renderType = (_value, row) => /* @__PURE__ */ jsxs(TypeCell, { children: [
18
+ /* @__PURE__ */ jsx(
19
+ IconTile,
20
+ {
21
+ src: row.resourceTypeIcon,
22
+ alt: row.resourceTypeName,
23
+ size: "small",
24
+ fallback: /* @__PURE__ */ jsx(FallbackIcon, {})
25
+ }
26
+ ),
27
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", noWrap: true, title: row.resourceTypeName, children: row.resourceTypeName })
28
+ ] });
29
+ const renderLocation = (_value, row) => {
30
+ const { location } = row;
31
+ if (!location) {
32
+ return /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", children: "\u2014" });
33
+ }
34
+ const { projectId, environmentId, projectName, environmentName } = location;
35
+ return /* @__PURE__ */ jsxs(LocationCell, { title: `${projectName} : ${environmentName}`, children: [
36
+ /* @__PURE__ */ jsx(
37
+ LocationLink,
38
+ {
39
+ component: RouterLinkAdapter,
40
+ href: internalRoutes.project(projectId),
41
+ children: projectName
42
+ }
43
+ ),
44
+ /* @__PURE__ */ jsx(LocationSeparator, { children: " : " }),
45
+ environmentId ? /* @__PURE__ */ jsx(
46
+ LocationLink,
47
+ {
48
+ component: RouterLinkAdapter,
49
+ href: internalRoutes.environment(projectId, environmentId),
50
+ children: environmentName
51
+ }
52
+ ) : /* @__PURE__ */ jsx("span", { children: environmentName })
53
+ ] });
54
+ };
55
+ const buildActionsColumn = ({
56
+ appUrl,
57
+ organizationId
58
+ }) => col.actions([
59
+ {
60
+ icon: /* @__PURE__ */ jsx(EditIcon, { fontSize: "small" }),
61
+ tooltip: (row) => row.origin === "PROVISIONED" ? PROVISIONED_EDIT_TOOLTIP : IMPORTED_EDIT_TOOLTIP,
62
+ href: (row) => resourceUrl(appUrl, organizationId, row.id),
63
+ target: "_blank",
64
+ rel: "noopener noreferrer",
65
+ disabled: (row) => row.origin === "PROVISIONED"
66
+ },
67
+ {
68
+ icon: /* @__PURE__ */ jsx(DeleteIcon, { fontSize: "small" }),
69
+ tooltip: (row) => row.origin === "PROVISIONED" ? PROVISIONED_DELETE_TOOLTIP : IMPORTED_DELETE_TOOLTIP,
70
+ href: (row) => resourceUrl(appUrl, organizationId, row.id),
71
+ target: "_blank",
72
+ rel: "noopener noreferrer",
73
+ disabled: (row) => row.origin === "PROVISIONED",
74
+ color: "error"
75
+ }
76
+ ]);
77
+ const buildResourceColumns = ({
78
+ appUrl,
79
+ organizationId
80
+ }) => [
81
+ col.link(
82
+ "name",
83
+ "Name",
84
+ (row) => internalRoutes.resourceTab(row.id, "general"),
85
+ {
86
+ flex: 2,
87
+ minWidth: 180,
88
+ LinkComponent: RouterLinkAdapter
89
+ }
90
+ ),
91
+ col.custom("resourceTypeName", "Type", renderType, {
92
+ flex: 1.4,
93
+ minWidth: 160,
94
+ sortable: false
95
+ }),
96
+ col.custom("location", "Project : Environment", renderLocation, {
97
+ flex: 1.4,
98
+ minWidth: 160,
99
+ sortable: false,
100
+ searchable: false
101
+ }),
102
+ buildAttributesColumn({
103
+ directText: "Key-value attributes assigned directly to this resource.",
104
+ effectiveText: /* @__PURE__ */ jsxs(Fragment, { children: [
105
+ "The full attribute map the authorization system evaluates policies against for this resource \u2014 the resource's own user attributes plus auto-injected ",
106
+ /* @__PURE__ */ jsx(Code, { children: "md-*" }),
107
+ " system attributes."
108
+ ] }),
109
+ flex: 1.4,
110
+ minWidth: 180
111
+ }),
112
+ col.text("originLabel", "Origin", {
113
+ flex: 0.8,
114
+ minWidth: 124,
115
+ sortable: false,
116
+ searchable: false
117
+ }),
118
+ col.text("createdAtRelative", "Created", {
119
+ flex: 1,
120
+ minWidth: 120,
121
+ sortable: false,
122
+ searchable: false,
123
+ tooltip: (_value, row) => formatAbsoluteTime(row.createdAt)
124
+ }),
125
+ buildActionsColumn({ appUrl, organizationId })
126
+ ];
127
+ const TypeCell = stylin(Box)(({ theme }) => ({
128
+ display: "flex",
129
+ alignItems: "center",
130
+ gap: theme.spacing(1),
131
+ minWidth: 0
132
+ }));
133
+ const FallbackIcon = stylin(ExtensionIcon)({
134
+ fontSize: 16
135
+ });
136
+ const LocationCell = stylin(Box)({
137
+ display: "-webkit-box",
138
+ WebkitLineClamp: 2,
139
+ WebkitBoxOrient: "vertical",
140
+ overflow: "hidden",
141
+ textOverflow: "ellipsis",
142
+ wordBreak: "break-word",
143
+ fontSize: "0.875rem",
144
+ lineHeight: 1.43,
145
+ minWidth: 0
146
+ });
147
+ const LocationLink = stylin(Box)(({ theme }) => ({
148
+ color: theme.palette.text.primary,
149
+ textDecoration: "none",
150
+ "&:hover": { textDecoration: "underline" }
151
+ }));
152
+ const LocationSeparator = stylin("span")(({ theme }) => ({
153
+ color: theme.palette.text.secondary,
154
+ margin: `0 ${theme.spacing(0.5)}`
155
+ }));
156
+
157
+ export { buildResourceColumns };
158
+ //# sourceMappingURL=resourceColumns.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resourceColumns.esm.js","sources":["../../../src/features/resources/resourceColumns.tsx"],"sourcesContent":["import Box from '@massdriver/ui/Box';\nimport { col } from '@massdriver/ui/DataList';\nimport IconTile from '@massdriver/ui/IconTile';\nimport Typography from '@massdriver/ui/Typography';\nimport DeleteIcon from '@massdriver/ui/icons/DeleteIcon';\nimport EditIcon from '@massdriver/ui/icons/EditIcon';\nimport ExtensionIcon from '@massdriver/ui/icons/ExtensionIcon';\nimport stylin from '@massdriver/ui/stylin';\nimport { resourceUrl } from '@massdriver/backstage-plugin-common';\nimport { buildAttributesColumn, Code } from '../../components/AttributesColumn';\nimport { RouterLinkAdapter } from '../../components/RouterLinkAdapter';\nimport { internalRoutes } from '../../internalRoutes';\nimport { formatAbsoluteTime } from '../../utils/formatRelativeTime';\nimport {\n IMPORTED_DELETE_TOOLTIP,\n IMPORTED_EDIT_TOOLTIP,\n PROVISIONED_DELETE_TOOLTIP,\n PROVISIONED_EDIT_TOOLTIP,\n} from './resourceConstants';\nimport type { ResourceRow } from './toResourceRow';\n\n// Ported from apps/web/features/resources/hooks/useResourceColumns.js. The web\n// app's Edit/Delete row actions mutate: for imported resources they deep-link\n// out to the resource in the Massdriver web app; for provisioned resources they\n// stay disabled with the same tooltips the web app shows (it disables them too).\n\nconst renderType = (_value: unknown, row: ResourceRow) => (\n <TypeCell>\n <IconTile\n src={row.resourceTypeIcon}\n alt={row.resourceTypeName}\n size=\"small\"\n fallback={<FallbackIcon />}\n />\n <Typography variant=\"body2\" noWrap title={row.resourceTypeName}>\n {row.resourceTypeName}\n </Typography>\n </TypeCell>\n);\n\nconst renderLocation = (_value: unknown, row: ResourceRow) => {\n const { location } = row;\n if (!location) {\n return (\n <Typography variant=\"body2\" color=\"text.secondary\">\n —\n </Typography>\n );\n }\n const { projectId, environmentId, projectName, environmentName } = location;\n return (\n <LocationCell title={`${projectName} : ${environmentName}`}>\n <LocationLink\n component={RouterLinkAdapter}\n href={internalRoutes.project(projectId)}\n >\n {projectName}\n </LocationLink>\n <LocationSeparator> : </LocationSeparator>\n {environmentId ? (\n <LocationLink\n component={RouterLinkAdapter}\n href={internalRoutes.environment(projectId, environmentId)}\n >\n {environmentName}\n </LocationLink>\n ) : (\n <span>{environmentName}</span>\n )}\n </LocationCell>\n );\n};\n\nconst buildActionsColumn = ({\n appUrl,\n organizationId,\n}: {\n appUrl: string;\n organizationId: string;\n}) =>\n col.actions([\n {\n icon: <EditIcon fontSize=\"small\" />,\n tooltip: (row: ResourceRow) =>\n row.origin === 'PROVISIONED'\n ? PROVISIONED_EDIT_TOOLTIP\n : IMPORTED_EDIT_TOOLTIP,\n href: (row: ResourceRow) => resourceUrl(appUrl, organizationId, row.id),\n target: '_blank',\n rel: 'noopener noreferrer',\n disabled: (row: ResourceRow) => row.origin === 'PROVISIONED',\n },\n {\n icon: <DeleteIcon fontSize=\"small\" />,\n tooltip: (row: ResourceRow) =>\n row.origin === 'PROVISIONED'\n ? PROVISIONED_DELETE_TOOLTIP\n : IMPORTED_DELETE_TOOLTIP,\n href: (row: ResourceRow) => resourceUrl(appUrl, organizationId, row.id),\n target: '_blank',\n rel: 'noopener noreferrer',\n disabled: (row: ResourceRow) => row.origin === 'PROVISIONED',\n color: 'error',\n },\n ]);\n\nexport const buildResourceColumns = ({\n appUrl,\n organizationId,\n}: {\n appUrl: string;\n organizationId: string;\n}) => [\n col.link(\n 'name',\n 'Name',\n (row: ResourceRow) => internalRoutes.resourceTab(row.id, 'general'),\n {\n flex: 2,\n minWidth: 180,\n LinkComponent: RouterLinkAdapter,\n },\n ),\n col.custom('resourceTypeName', 'Type', renderType, {\n flex: 1.4,\n minWidth: 160,\n sortable: false,\n }),\n col.custom('location', 'Project : Environment', renderLocation, {\n flex: 1.4,\n minWidth: 160,\n sortable: false,\n searchable: false,\n }),\n buildAttributesColumn({\n directText: 'Key-value attributes assigned directly to this resource.',\n effectiveText: (\n <>\n The full attribute map the authorization system evaluates policies\n against for this resource — the resource's own user attributes plus\n auto-injected <Code>md-*</Code> system attributes.\n </>\n ),\n flex: 1.4,\n minWidth: 180,\n }),\n col.text('originLabel', 'Origin', {\n flex: 0.8,\n minWidth: 124,\n sortable: false,\n searchable: false,\n }),\n col.text('createdAtRelative', 'Created', {\n flex: 1,\n minWidth: 120,\n sortable: false,\n searchable: false,\n tooltip: (_value: unknown, row: ResourceRow) =>\n formatAbsoluteTime(row.createdAt),\n }),\n buildActionsColumn({ appUrl, organizationId }),\n];\n\nconst TypeCell = stylin(Box)(({ theme }: { theme: any }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n minWidth: 0,\n}));\n\nconst FallbackIcon = stylin(ExtensionIcon)({\n fontSize: 16,\n});\n\nconst LocationCell = stylin(Box)({\n display: '-webkit-box',\n WebkitLineClamp: 2,\n WebkitBoxOrient: 'vertical',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n wordBreak: 'break-word',\n fontSize: '0.875rem',\n lineHeight: 1.43,\n minWidth: 0,\n});\n\nconst LocationLink = stylin(Box)(({ theme }: { theme: any }) => ({\n color: theme.palette.text.primary,\n textDecoration: 'none',\n '&:hover': { textDecoration: 'underline' },\n}));\n\nconst LocationSeparator = stylin('span')(({ theme }: { theme: any }) => ({\n color: theme.palette.text.secondary,\n margin: `0 ${theme.spacing(0.5)}`,\n}));\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ const PROVISIONED_EDIT_TOOLTIP = "You can't rename a provisioned resource. Edit its instance configuration instead.";
2
+ const PROVISIONED_DELETE_TOOLTIP = "You can't delete a provisioned resource. Decommission its instance instead.";
3
+ const IMPORTED_EDIT_TOOLTIP = "Resources are edited in Massdriver";
4
+ const IMPORTED_DELETE_TOOLTIP = "Resources are deleted in Massdriver";
5
+
6
+ export { IMPORTED_DELETE_TOOLTIP, IMPORTED_EDIT_TOOLTIP, PROVISIONED_DELETE_TOOLTIP, PROVISIONED_EDIT_TOOLTIP };
7
+ //# sourceMappingURL=resourceConstants.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resourceConstants.esm.js","sources":["../../../src/features/resources/resourceConstants.ts"],"sourcesContent":["// Ported from apps/web/features/resources/utils/resourceConstants.js\n\nexport const PROVISIONED_EDIT_TOOLTIP =\n \"You can't rename a provisioned resource. Edit its instance configuration instead.\";\n\nexport const PROVISIONED_DELETE_TOOLTIP =\n \"You can't delete a provisioned resource. Decommission its instance instead.\";\n\n// Read-only parity: the web app's edit/delete row actions mutate, so here they\n// stay visible but disabled with a tooltip pointing at Massdriver.\nexport const IMPORTED_EDIT_TOOLTIP = 'Resources are edited in Massdriver';\n\nexport const IMPORTED_DELETE_TOOLTIP = 'Resources are deleted in Massdriver';\n"],"names":[],"mappings":"AAEO,MAAM,wBAAA,GACX;AAEK,MAAM,0BAAA,GACX;AAIK,MAAM,qBAAA,GAAwB;AAE9B,MAAM,uBAAA,GAA0B;;;;"}
@@ -0,0 +1,29 @@
1
+ import { parseInstanceId } from '@massdriver/backstage-plugin-common';
2
+ import { formatRelativeTime } from '../../utils/formatRelativeTime.esm.js';
3
+
4
+ const ORIGIN_LABELS = {
5
+ IMPORTED: "Imported",
6
+ PROVISIONED: "Provisioned"
7
+ };
8
+ const buildLocation = (instance) => {
9
+ if (!instance?.id) return null;
10
+ const { projectId, scopedEnvironmentId } = parseInstanceId(instance.id);
11
+ if (!projectId || !scopedEnvironmentId) return null;
12
+ return {
13
+ projectId,
14
+ environmentId: instance.environment?.id ?? null,
15
+ projectName: instance.environment?.project?.name ?? projectId,
16
+ environmentName: instance.environment?.name ?? scopedEnvironmentId
17
+ };
18
+ };
19
+ const toResourceRow = (resource) => ({
20
+ ...resource,
21
+ resourceTypeName: resource.resourceType?.name ?? "\u2014",
22
+ resourceTypeIcon: resource.resourceType?.icon ?? null,
23
+ originLabel: ORIGIN_LABELS[resource.origin] ?? resource.origin,
24
+ location: buildLocation(resource.instance),
25
+ createdAtRelative: formatRelativeTime(resource.createdAt)
26
+ });
27
+
28
+ export { toResourceRow };
29
+ //# sourceMappingURL=toResourceRow.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toResourceRow.esm.js","sources":["../../../src/features/resources/toResourceRow.ts"],"sourcesContent":["import { parseInstanceId } from '@massdriver/backstage-plugin-common';\nimport { formatRelativeTime } from '../../utils/formatRelativeTime';\n\n// Ported from apps/web/features/resources/utils/resourceColumns.js\n// (transformResourcesResponse + buildLocation).\n\nconst ORIGIN_LABELS: Record<string, string> = {\n IMPORTED: 'Imported',\n PROVISIONED: 'Provisioned',\n};\n\n/** Where a provisioned resource lives, resolved for the Project : Environment cell. */\nexport interface ResourceLocation {\n projectId: string;\n /** Full composite environment id, for `internalRoutes.environment`. */\n environmentId: string | null;\n projectName: string;\n environmentName: string;\n}\n\n/** A resource as returned by the list query. */\nexport interface ResourceListItem {\n id: string;\n name: string;\n origin: string;\n formats?: string[] | null;\n attributes?: unknown;\n effectiveAttributes?: unknown;\n createdAt?: string | null;\n updatedAt?: string | null;\n resourceType?: {\n id: string;\n name?: string | null;\n icon?: string | null;\n } | null;\n instance?: {\n id: string;\n name?: string | null;\n environment?: {\n id: string;\n name?: string | null;\n project?: { id: string; name?: string | null } | null;\n } | null;\n } | null;\n}\n\n/** A resource row as rendered in the DataList. */\nexport interface ResourceRow extends ResourceListItem {\n resourceTypeName: string;\n resourceTypeIcon: string | null;\n originLabel: string;\n location: ResourceLocation | null;\n createdAtRelative: string;\n}\n\nconst buildLocation = (\n instance: ResourceListItem['instance'],\n): ResourceLocation | null => {\n if (!instance?.id) return null;\n const { projectId, scopedEnvironmentId } = parseInstanceId(instance.id);\n if (!projectId || !scopedEnvironmentId) return null;\n return {\n projectId,\n environmentId: instance.environment?.id ?? null,\n projectName: instance.environment?.project?.name ?? projectId,\n environmentName: instance.environment?.name ?? scopedEnvironmentId,\n };\n};\n\n/** Transform a raw resource into a display row (mirrors `transformResourcesResponse`). */\nexport const toResourceRow = (resource: ResourceListItem): ResourceRow => ({\n ...resource,\n resourceTypeName: resource.resourceType?.name ?? '—',\n resourceTypeIcon: resource.resourceType?.icon ?? null,\n originLabel: ORIGIN_LABELS[resource.origin] ?? resource.origin,\n location: buildLocation(resource.instance),\n createdAtRelative: formatRelativeTime(resource.createdAt),\n});\n"],"names":[],"mappings":";;;AAMA,MAAM,aAAA,GAAwC;AAAA,EAC5C,QAAA,EAAU,UAAA;AAAA,EACV,WAAA,EAAa;AACf,CAAA;AA8CA,MAAM,aAAA,GAAgB,CACpB,QAAA,KAC4B;AAC5B,EAAA,IAAI,CAAC,QAAA,EAAU,EAAA,EAAI,OAAO,IAAA;AAC1B,EAAA,MAAM,EAAE,SAAA,EAAW,mBAAA,EAAoB,GAAI,eAAA,CAAgB,SAAS,EAAE,CAAA;AACtE,EAAA,IAAI,CAAC,SAAA,IAAa,CAAC,mBAAA,EAAqB,OAAO,IAAA;AAC/C,EAAA,OAAO;AAAA,IACL,SAAA;AAAA,IACA,aAAA,EAAe,QAAA,CAAS,WAAA,EAAa,EAAA,IAAM,IAAA;AAAA,IAC3C,WAAA,EAAa,QAAA,CAAS,WAAA,EAAa,OAAA,EAAS,IAAA,IAAQ,SAAA;AAAA,IACpD,eAAA,EAAiB,QAAA,CAAS,WAAA,EAAa,IAAA,IAAQ;AAAA,GACjD;AACF,CAAA;AAGO,MAAM,aAAA,GAAgB,CAAC,QAAA,MAA6C;AAAA,EACzE,GAAG,QAAA;AAAA,EACH,gBAAA,EAAkB,QAAA,CAAS,YAAA,EAAc,IAAA,IAAQ,QAAA;AAAA,EACjD,gBAAA,EAAkB,QAAA,CAAS,YAAA,EAAc,IAAA,IAAQ,IAAA;AAAA,EACjD,WAAA,EAAa,aAAA,CAAc,QAAA,CAAS,MAAM,KAAK,QAAA,CAAS,MAAA;AAAA,EACxD,QAAA,EAAU,aAAA,CAAc,QAAA,CAAS,QAAQ,CAAA;AAAA,EACzC,iBAAA,EAAmB,kBAAA,CAAmB,QAAA,CAAS,SAAS;AAC1D,CAAA;;;;"}
@@ -0,0 +1,34 @@
1
+ import { useApi } from '@backstage/frontend-plugin-api';
2
+ import { useState, useEffect } from 'react';
3
+ import { massdriverApiRef } from '../api.esm.js';
4
+
5
+ const useAuthedSvg = (url) => {
6
+ const api = useApi(massdriverApiRef);
7
+ const [svg, setSvg] = useState(null);
8
+ const [loading, setLoading] = useState(false);
9
+ useEffect(() => {
10
+ if (!url) {
11
+ setSvg(null);
12
+ setLoading(false);
13
+ return void 0;
14
+ }
15
+ let cancelled = false;
16
+ setLoading(true);
17
+ api.fetchText(url).then((text) => {
18
+ if (cancelled) return;
19
+ setSvg(text);
20
+ setLoading(false);
21
+ }).catch(() => {
22
+ if (cancelled) return;
23
+ setSvg(null);
24
+ setLoading(false);
25
+ });
26
+ return () => {
27
+ cancelled = true;
28
+ };
29
+ }, [api, url]);
30
+ return { svg, loading };
31
+ };
32
+
33
+ export { useAuthedSvg as default, useAuthedSvg };
34
+ //# sourceMappingURL=useAuthedSvg.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAuthedSvg.esm.js","sources":["../../src/hooks/useAuthedSvg.ts"],"sourcesContent":["import { useApi } from '@backstage/frontend-plugin-api';\nimport { useEffect, useState } from 'react';\nimport { massdriverApiRef } from '../api';\n\n// Ported from apps/web/shared/hooks/useAuthedSvg.js. The web app fetches the\n// SVG directly with the browser's bearer token; here the fetch goes through\n// the backend content proxy (api.fetchText) since the browser holds no token.\nexport const useAuthedSvg = (url?: string | null) => {\n const api = useApi(massdriverApiRef);\n const [svg, setSvg] = useState<string | null>(null);\n const [loading, setLoading] = useState(false);\n\n useEffect(() => {\n if (!url) {\n setSvg(null);\n setLoading(false);\n return undefined;\n }\n\n let cancelled = false;\n setLoading(true);\n\n api\n .fetchText(url)\n .then(text => {\n if (cancelled) return;\n setSvg(text);\n setLoading(false);\n })\n .catch(() => {\n if (cancelled) return;\n setSvg(null);\n setLoading(false);\n });\n\n return () => {\n cancelled = true;\n };\n }, [api, url]);\n\n return { svg, loading };\n};\n\nexport default useAuthedSvg;\n"],"names":[],"mappings":";;;;AAOO,MAAM,YAAA,GAAe,CAAC,GAAA,KAAwB;AACnD,EAAA,MAAM,GAAA,GAAM,OAAO,gBAAgB,CAAA;AACnC,EAAA,MAAM,CAAC,GAAA,EAAK,MAAM,CAAA,GAAI,SAAwB,IAAI,CAAA;AAClD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,KAAK,CAAA;AAE5C,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,MAAA,CAAO,IAAI,CAAA;AACX,MAAA,UAAA,CAAW,KAAK,CAAA;AAChB,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,IAAI,SAAA,GAAY,KAAA;AAChB,IAAA,UAAA,CAAW,IAAI,CAAA;AAEf,IAAA,GAAA,CACG,SAAA,CAAU,GAAG,CAAA,CACb,IAAA,CAAK,CAAA,IAAA,KAAQ;AACZ,MAAA,IAAI,SAAA,EAAW;AACf,MAAA,MAAA,CAAO,IAAI,CAAA;AACX,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA,IAClB,CAAC,CAAA,CACA,KAAA,CAAM,MAAM;AACX,MAAA,IAAI,SAAA,EAAW;AACf,MAAA,MAAA,CAAO,IAAI,CAAA;AACX,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA,IAClB,CAAC,CAAA;AAEH,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,GAAY,IAAA;AAAA,IACd,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,GAAA,EAAK,GAAG,CAAC,CAAA;AAEb,EAAA,OAAO,EAAE,KAAK,OAAA,EAAQ;AACxB;;;;"}
@@ -0,0 +1,40 @@
1
+ import { useRef } from 'react';
2
+
3
+ const mapSort = (sort, fieldMap) => {
4
+ if (!sort) {
5
+ return void 0;
6
+ }
7
+ const field = fieldMap[sort.field];
8
+ if (!field) {
9
+ return void 0;
10
+ }
11
+ return { field, order: sort.direction === "asc" ? "ASC" : "DESC" };
12
+ };
13
+ const useCursorPagination = ({
14
+ state,
15
+ sortFieldMap = {}
16
+ }) => {
17
+ const cursorsRef = useRef(/* @__PURE__ */ new Map());
18
+ const prevSortKeyRef = useRef("");
19
+ const sort = mapSort(state.sort, sortFieldMap);
20
+ const sortKey = `${sort?.field}-${sort?.order}-${state.pageSize}-${state.search}`;
21
+ if (sortKey !== prevSortKeyRef.current) {
22
+ cursorsRef.current = /* @__PURE__ */ new Map();
23
+ prevSortKeyRef.current = sortKey;
24
+ }
25
+ const next = state.page > 0 ? cursorsRef.current.get(state.page) : void 0;
26
+ const cursor = {
27
+ limit: state.pageSize,
28
+ ...next ? { next } : {}
29
+ };
30
+ const processPage = (page) => {
31
+ if (page?.cursor?.next) {
32
+ cursorsRef.current.set(state.page + 1, page.cursor.next);
33
+ }
34
+ return { hasMore: !!page?.cursor?.next };
35
+ };
36
+ return { cursor, sort, processPage };
37
+ };
38
+
39
+ export { useCursorPagination };
40
+ //# sourceMappingURL=useCursorPagination.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCursorPagination.esm.js","sources":["../../src/hooks/useCursorPagination.ts"],"sourcesContent":["import { useRef } from 'react';\n\nexport interface DataListSort {\n field: string;\n direction: 'asc' | 'desc';\n}\nexport interface DataListState {\n search: string;\n page: number;\n pageSize: number;\n sort: DataListSort | null;\n}\n\ninterface PageResult {\n cursor?: { next?: string | null } | null;\n}\n\nconst mapSort = (\n sort: DataListSort | null,\n fieldMap: Record<string, string>,\n): { field: string; order: 'ASC' | 'DESC' } | undefined => {\n if (!sort) {\n return undefined;\n }\n const field = fieldMap[sort.field];\n if (!field) {\n return undefined;\n }\n return { field, order: sort.direction === 'asc' ? 'ASC' : 'DESC' };\n};\n\n/**\n * Cursor pagination bridge for DataList's page-index model, ported from the web\n * app. Tracks the next-cursor for each page and resets when sort/pageSize\n * change.\n */\nexport const useCursorPagination = ({\n state,\n sortFieldMap = {},\n}: {\n state: DataListState;\n sortFieldMap?: Record<string, string>;\n}) => {\n const cursorsRef = useRef(new Map<number, string>());\n const prevSortKeyRef = useRef('');\n\n const sort = mapSort(state.sort, sortFieldMap);\n\n // Cursors are only valid for the exact query shape that produced them —\n // reset the map when sort, pageSize, or search change (a cursor from one\n // filter set is meaningless in another).\n const sortKey = `${sort?.field}-${sort?.order}-${state.pageSize}-${state.search}`;\n if (sortKey !== prevSortKeyRef.current) {\n cursorsRef.current = new Map();\n prevSortKeyRef.current = sortKey;\n }\n\n const next = state.page > 0 ? cursorsRef.current.get(state.page) : undefined;\n const cursor = {\n limit: state.pageSize,\n ...(next ? { next } : {}),\n };\n\n const processPage = (page: PageResult | null | undefined) => {\n if (page?.cursor?.next) {\n cursorsRef.current.set(state.page + 1, page.cursor.next);\n }\n return { hasMore: !!page?.cursor?.next };\n };\n\n return { cursor, sort, processPage };\n};\n"],"names":[],"mappings":";;AAiBA,MAAM,OAAA,GAAU,CACd,IAAA,EACA,QAAA,KACyD;AACzD,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,IAAA,CAAK,KAAK,CAAA;AACjC,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,KAAK,SAAA,KAAc,KAAA,GAAQ,QAAQ,MAAA,EAAO;AACnE,CAAA;AAOO,MAAM,sBAAsB,CAAC;AAAA,EAClC,KAAA;AAAA,EACA,eAAe;AACjB,CAAA,KAGM;AACJ,EAAA,MAAM,UAAA,GAAa,MAAA,iBAAO,IAAI,GAAA,EAAqB,CAAA;AACnD,EAAA,MAAM,cAAA,GAAiB,OAAO,EAAE,CAAA;AAEhC,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,KAAA,CAAM,IAAA,EAAM,YAAY,CAAA;AAK7C,EAAA,MAAM,OAAA,GAAU,CAAA,EAAG,IAAA,EAAM,KAAK,CAAA,CAAA,EAAI,IAAA,EAAM,KAAK,CAAA,CAAA,EAAI,KAAA,CAAM,QAAQ,CAAA,CAAA,EAAI,KAAA,CAAM,MAAM,CAAA,CAAA;AAC/E,EAAA,IAAI,OAAA,KAAY,eAAe,OAAA,EAAS;AACtC,IAAA,UAAA,CAAW,OAAA,uBAAc,GAAA,EAAI;AAC7B,IAAA,cAAA,CAAe,OAAA,GAAU,OAAA;AAAA,EAC3B;AAEA,EAAA,MAAM,IAAA,GAAO,MAAM,IAAA,GAAO,CAAA,GAAI,WAAW,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,GAAI,MAAA;AACnE,EAAA,MAAM,MAAA,GAAS;AAAA,IACb,OAAO,KAAA,CAAM,QAAA;AAAA,IACb,GAAI,IAAA,GAAO,EAAE,IAAA,KAAS;AAAC,GACzB;AAEA,EAAA,MAAM,WAAA,GAAc,CAAC,IAAA,KAAwC;AAC3D,IAAA,IAAI,IAAA,EAAM,QAAQ,IAAA,EAAM;AACtB,MAAA,UAAA,CAAW,QAAQ,GAAA,CAAI,KAAA,CAAM,OAAO,CAAA,EAAG,IAAA,CAAK,OAAO,IAAI,CAAA;AAAA,IACzD;AACA,IAAA,OAAO,EAAE,OAAA,EAAS,CAAC,CAAC,IAAA,EAAM,QAAQ,IAAA,EAAK;AAAA,EACzC,CAAA;AAEA,EAAA,OAAO,EAAE,MAAA,EAAQ,IAAA,EAAM,WAAA,EAAY;AACrC;;;;"}
@@ -0,0 +1,61 @@
1
+ import { useRef, useEffect } from 'react';
2
+ import { useApi } from '@backstage/frontend-plugin-api';
3
+ import { massdriverApiRef } from '../api.esm.js';
4
+
5
+ const MAX_BACKOFF_MS = 1e4;
6
+ const backoffDelay = (attempt) => Math.min(1e3 * 2 ** Math.max(0, attempt - 1), MAX_BACKOFF_MS);
7
+ const sleep = (ms, signal) => new Promise((resolve) => {
8
+ const timer = setTimeout(resolve, ms);
9
+ signal.addEventListener(
10
+ "abort",
11
+ () => {
12
+ clearTimeout(timer);
13
+ resolve();
14
+ },
15
+ { once: true }
16
+ );
17
+ });
18
+ const useMassdriverSubscription = (query, variables, {
19
+ onData,
20
+ onError,
21
+ skip
22
+ }) => {
23
+ const api = useApi(massdriverApiRef);
24
+ const onDataRef = useRef(onData);
25
+ const onErrorRef = useRef(onError);
26
+ onDataRef.current = onData;
27
+ onErrorRef.current = onError;
28
+ const variablesKey = JSON.stringify(variables ?? {});
29
+ useEffect(() => {
30
+ if (skip) return void 0;
31
+ const controller = new AbortController();
32
+ const attempt = { count: 0 };
33
+ const fatal = { seen: false };
34
+ const handleData = (data) => {
35
+ attempt.count = 0;
36
+ onDataRef.current(data);
37
+ };
38
+ const handleError = (error) => {
39
+ if (error.fatal) fatal.seen = true;
40
+ onErrorRef.current?.(error);
41
+ };
42
+ const run = async () => {
43
+ while (!controller.signal.aborted) {
44
+ await api.subscribe(
45
+ query,
46
+ variables,
47
+ { onData: handleData, onError: handleError },
48
+ controller.signal
49
+ );
50
+ if (controller.signal.aborted || fatal.seen) break;
51
+ attempt.count += 1;
52
+ await sleep(backoffDelay(attempt.count), controller.signal);
53
+ }
54
+ };
55
+ void run();
56
+ return () => controller.abort();
57
+ }, [api, query, variablesKey, skip]);
58
+ };
59
+
60
+ export { useMassdriverSubscription as default, useMassdriverSubscription };
61
+ //# sourceMappingURL=useMassdriverSubscription.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMassdriverSubscription.esm.js","sources":["../../src/hooks/useMassdriverSubscription.ts"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport { useApi } from '@backstage/frontend-plugin-api';\nimport { massdriverApiRef, type MassdriverSubscriptionError } from '../api';\n\nconst MAX_BACKOFF_MS = 10_000;\n\nconst backoffDelay = (attempt: number): number =>\n Math.min(1000 * 2 ** Math.max(0, attempt - 1), MAX_BACKOFF_MS);\n\n// Abortable sleep — resolves after `ms`, or immediately if the signal aborts.\nconst sleep = (ms: number, signal: AbortSignal): Promise<void> =>\n new Promise<void>(resolve => {\n const timer = setTimeout(resolve, ms);\n signal.addEventListener(\n 'abort',\n () => {\n clearTimeout(timer);\n resolve();\n },\n { once: true },\n );\n });\n\n/**\n * Subscribe to a Massdriver GraphQL subscription through the backend SSE relay.\n *\n * Opens one SSE stream per (query, variables) and re-subscribes when they\n * change. `onData` / `onError` are held in refs so passing fresh inline\n * callbacks each render does not tear the stream down. If the stream ends\n * (server close or transport error) it reconnects with exponential backoff\n * — a healthy message resets the backoff. Aborted on unmount / when `skip`\n * flips true.\n */\nexport const useMassdriverSubscription = <T = unknown>(\n query: string,\n variables: Record<string, unknown> | undefined,\n {\n onData,\n onError,\n skip,\n }: {\n onData: (data: T) => void;\n onError?: (error: Error) => void;\n skip?: boolean;\n },\n) => {\n const api = useApi(massdriverApiRef);\n const onDataRef = useRef(onData);\n const onErrorRef = useRef(onError);\n onDataRef.current = onData;\n onErrorRef.current = onError;\n\n const variablesKey = JSON.stringify(variables ?? {});\n\n useEffect(() => {\n if (skip) return undefined;\n const controller = new AbortController();\n const attempt = { count: 0 };\n // Fatal errors (auth/validation — see MassdriverSubscriptionError) can't\n // heal on retry; stop the loop instead of reconnecting forever.\n const fatal = { seen: false };\n\n const handleData = (data: T) => {\n attempt.count = 0; // healthy stream → reset backoff\n onDataRef.current(data);\n };\n const handleError = (error: MassdriverSubscriptionError) => {\n if (error.fatal) fatal.seen = true;\n onErrorRef.current?.(error);\n };\n\n const run = async () => {\n while (!controller.signal.aborted) {\n await api.subscribe<T>(\n query,\n variables,\n { onData: handleData, onError: handleError },\n controller.signal,\n );\n if (controller.signal.aborted || fatal.seen) break;\n attempt.count += 1;\n await sleep(backoffDelay(attempt.count), controller.signal);\n }\n };\n\n void run();\n return () => controller.abort();\n // `variables` is compared by value via `variablesKey`.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [api, query, variablesKey, skip]);\n};\n\nexport default useMassdriverSubscription;\n"],"names":[],"mappings":";;;;AAIA,MAAM,cAAA,GAAiB,GAAA;AAEvB,MAAM,YAAA,GAAe,CAAC,OAAA,KACpB,IAAA,CAAK,GAAA,CAAI,GAAA,GAAO,CAAA,IAAK,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAA,GAAU,CAAC,GAAG,cAAc,CAAA;AAG/D,MAAM,QAAQ,CAAC,EAAA,EAAY,MAAA,KACzB,IAAI,QAAc,CAAA,OAAA,KAAW;AAC3B,EAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,OAAA,EAAS,EAAE,CAAA;AACpC,EAAA,MAAA,CAAO,gBAAA;AAAA,IACL,OAAA;AAAA,IACA,MAAM;AACJ,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,OAAA,EAAQ;AAAA,IACV,CAAA;AAAA,IACA,EAAE,MAAM,IAAA;AAAK,GACf;AACF,CAAC,CAAA;AAYI,MAAM,yBAAA,GAA4B,CACvC,KAAA,EACA,SAAA,EACA;AAAA,EACE,MAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA,KAKG;AACH,EAAA,MAAM,GAAA,GAAM,OAAO,gBAAgB,CAAA;AACnC,EAAA,MAAM,SAAA,GAAY,OAAO,MAAM,CAAA;AAC/B,EAAA,MAAM,UAAA,GAAa,OAAO,OAAO,CAAA;AACjC,EAAA,SAAA,CAAU,OAAA,GAAU,MAAA;AACpB,EAAA,UAAA,CAAW,OAAA,GAAU,OAAA;AAErB,EAAA,MAAM,YAAA,GAAe,IAAA,CAAK,SAAA,CAAU,SAAA,IAAa,EAAE,CAAA;AAEnD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,MAAM,OAAO,MAAA;AACjB,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,OAAA,GAAU,EAAE,KAAA,EAAO,CAAA,EAAE;AAG3B,IAAA,MAAM,KAAA,GAAQ,EAAE,IAAA,EAAM,KAAA,EAAM;AAE5B,IAAA,MAAM,UAAA,GAAa,CAAC,IAAA,KAAY;AAC9B,MAAA,OAAA,CAAQ,KAAA,GAAQ,CAAA;AAChB,MAAA,SAAA,CAAU,QAAQ,IAAI,CAAA;AAAA,IACxB,CAAA;AACA,IAAA,MAAM,WAAA,GAAc,CAAC,KAAA,KAAuC;AAC1D,MAAA,IAAI,KAAA,CAAM,KAAA,EAAO,KAAA,CAAM,IAAA,GAAO,IAAA;AAC9B,MAAA,UAAA,CAAW,UAAU,KAAK,CAAA;AAAA,IAC5B,CAAA;AAEA,IAAA,MAAM,MAAM,YAAY;AACtB,MAAA,OAAO,CAAC,UAAA,CAAW,MAAA,CAAO,OAAA,EAAS;AACjC,QAAA,MAAM,GAAA,CAAI,SAAA;AAAA,UACR,KAAA;AAAA,UACA,SAAA;AAAA,UACA,EAAE,MAAA,EAAQ,UAAA,EAAY,OAAA,EAAS,WAAA,EAAY;AAAA,UAC3C,UAAA,CAAW;AAAA,SACb;AACA,QAAA,IAAI,UAAA,CAAW,MAAA,CAAO,OAAA,IAAW,KAAA,CAAM,IAAA,EAAM;AAC7C,QAAA,OAAA,CAAQ,KAAA,IAAS,CAAA;AACjB,QAAA,MAAM,MAAM,YAAA,CAAa,OAAA,CAAQ,KAAK,CAAA,EAAG,WAAW,MAAM,CAAA;AAAA,MAC5D;AAAA,IACF,CAAA;AAEA,IAAA,KAAK,GAAA,EAAI;AACT,IAAA,OAAO,MAAM,WAAW,KAAA,EAAM;AAAA,EAGhC,GAAG,CAAC,GAAA,EAAK,KAAA,EAAO,YAAA,EAAc,IAAI,CAAC,CAAA;AACrC;;;;"}