@env-hopper/frontend-core 2.0.1-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/apple-touch-180x180.png +0 -0
- package/dist/disable.well-known/appspecific/com.chrome.devtools.json +6 -0
- package/dist/env-hopper-16x16.png +0 -0
- package/dist/env-hopper-192x192.png +0 -0
- package/dist/env-hopper-32x32.png +0 -0
- package/dist/env-hopper-48x48.png +0 -0
- package/dist/env-hopper-512x512.png +0 -0
- package/dist/env-hopper-square.svg +114 -0
- package/dist/esm/App.d.ts +12 -0
- package/dist/esm/App.js +12 -0
- package/dist/esm/App.js.map +1 -0
- package/dist/esm/__tests__/modules/fuzzyMatchLogic/autoCompleteFilter.test.d.ts +1 -0
- package/dist/esm/__tests__/modules/fuzzyMatchLogic/features/prefixFracTokenMiddles.test.d.ts +1 -0
- package/dist/esm/__tests__/modules/fuzzyMatchLogic/fixLayout.test.d.ts +1 -0
- package/dist/esm/__tests__/modules/fuzzyMatchLogic/postFiltration.test.d.ts +1 -0
- package/dist/esm/__tests__/modules/fuzzyMatchLogic/testUtils.d.ts +2 -0
- package/dist/esm/__tests__/modules/fuzzyMatchLogic/tokenize.test.d.ts +1 -0
- package/dist/esm/__tests__/modules/resouceJump/findBestMatchByUrl.test.d.ts +1 -0
- package/dist/esm/__tests__/setupTests.d.ts +0 -0
- package/dist/esm/__tests__/util/availabilityMatrixUtils.test.d.ts +1 -0
- package/dist/esm/api/ApiQueryMagazine.d.ts +12 -0
- package/dist/esm/api/ApiQueryMagazine.js +16 -0
- package/dist/esm/api/ApiQueryMagazine.js.map +1 -0
- package/dist/esm/api/data/useQueryBootstrapConfig.d.ts +3 -0
- package/dist/esm/api/data/useQueryBootstrapConfig.js +14 -0
- package/dist/esm/api/data/useQueryBootstrapConfig.js.map +1 -0
- package/dist/esm/api/infra/createQueryClient.d.ts +7 -0
- package/dist/esm/api/infra/createQueryClient.js +23 -0
- package/dist/esm/api/infra/createQueryClient.js.map +1 -0
- package/dist/esm/api/infra/trpc.d.ts +93 -0
- package/dist/esm/api/infra/trpc.js +8 -0
- package/dist/esm/api/infra/trpc.js.map +1 -0
- package/dist/esm/api/unsorted/indexDataFetcher.d.ts +11 -0
- package/dist/esm/api/unsorted/indexDataFetcher.js +35 -0
- package/dist/esm/api/unsorted/indexDataFetcher.js.map +1 -0
- package/dist/esm/appPropsFactory.d.ts +2 -0
- package/dist/esm/appPropsFactory.js +32 -0
- package/dist/esm/appPropsFactory.js.map +1 -0
- package/dist/esm/assets/env-hopper-logo.svg.js +16 -0
- package/dist/esm/assets/env-hopper-logo.svg.js.map +1 -0
- package/dist/esm/components/ThemeSwitcher.d.ts +1 -0
- package/dist/esm/components/ThemeSwitcher.js +25 -0
- package/dist/esm/components/ThemeSwitcher.js.map +1 -0
- package/dist/esm/components/theme-provider.d.ts +2 -0
- package/dist/esm/components/theme-provider.js +10 -0
- package/dist/esm/components/theme-provider.js.map +1 -0
- package/dist/esm/components/ui/badge.d.ts +9 -0
- package/dist/esm/components/ui/breadcrumb.d.ts +46 -0
- package/dist/esm/components/ui/button.d.ts +16 -0
- package/dist/esm/components/ui/button.js +52 -0
- package/dist/esm/components/ui/button.js.map +1 -0
- package/dist/esm/components/ui/card.d.ts +38 -0
- package/dist/esm/components/ui/collapsible.d.ts +5 -0
- package/dist/esm/components/ui/dialog.d.ts +21 -0
- package/dist/esm/components/ui/dropdown-menu.d.ts +25 -0
- package/dist/esm/components/ui/input.d.ts +10 -0
- package/dist/esm/components/ui/popover.d.ts +7 -0
- package/dist/esm/components/ui/popover.js +14 -0
- package/dist/esm/components/ui/popover.js.map +1 -0
- package/dist/esm/components/ui/scroll-area.d.ts +5 -0
- package/dist/esm/components/ui/separator.d.ts +4 -0
- package/dist/esm/components/ui/separator.js +27 -0
- package/dist/esm/components/ui/separator.js.map +1 -0
- package/dist/esm/components/ui/tabs.d.ts +7 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/lib/utils.d.ts +2 -0
- package/dist/esm/lib/utils.js +9 -0
- package/dist/esm/lib/utils.js.map +1 -0
- package/dist/esm/main.d.ts +0 -0
- package/dist/esm/modules/config/BootstrapConfigContext.d.ts +9 -0
- package/dist/esm/modules/config/BootstrapConfigContext.js +25 -0
- package/dist/esm/modules/config/BootstrapConfigContext.js.map +1 -0
- package/dist/esm/modules/config/GlobalConfigContext.d.ts +14 -0
- package/dist/esm/modules/config/GlobalConfigContext.js +21 -0
- package/dist/esm/modules/config/GlobalConfigContext.js.map +1 -0
- package/dist/esm/modules/environment/ApiQueryMagazineEnvironment.d.ts +12 -0
- package/dist/esm/modules/environment/ApiQueryMagazineEnvironment.js +13 -0
- package/dist/esm/modules/environment/ApiQueryMagazineEnvironment.js.map +1 -0
- package/dist/esm/modules/environment/EnvironmentContext.d.ts +15 -0
- package/dist/esm/modules/environment/EnvironmentContext.js +67 -0
- package/dist/esm/modules/environment/EnvironmentContext.js.map +1 -0
- package/dist/esm/modules/environment/types.d.ts +4 -0
- package/dist/esm/modules/environment/ui/EhEnvSelector.d.ts +9 -0
- package/dist/esm/modules/environment/ui/EhEnvSelector.js +167 -0
- package/dist/esm/modules/environment/ui/EhEnvSelector.js.map +1 -0
- package/dist/esm/modules/fuzzyMatchLogic/autoCompleteFilter.d.ts +3 -0
- package/dist/esm/modules/fuzzyMatchLogic/autoCompleteFilter.js +43 -0
- package/dist/esm/modules/fuzzyMatchLogic/autoCompleteFilter.js.map +1 -0
- package/dist/esm/modules/fuzzyMatchLogic/features/prefixFrac.d.ts +1 -0
- package/dist/esm/modules/fuzzyMatchLogic/features/prefixFrac.js +12 -0
- package/dist/esm/modules/fuzzyMatchLogic/features/prefixFrac.js.map +1 -0
- package/dist/esm/modules/fuzzyMatchLogic/features/prefixFracTokenMiddles.d.ts +2 -0
- package/dist/esm/modules/fuzzyMatchLogic/fixLayout.d.ts +2 -0
- package/dist/esm/modules/fuzzyMatchLogic/postFiltration.d.ts +2 -0
- package/dist/esm/modules/fuzzyMatchLogic/scoring.d.ts +2 -0
- package/dist/esm/modules/fuzzyMatchLogic/scoring.js +23 -0
- package/dist/esm/modules/fuzzyMatchLogic/scoring.js.map +1 -0
- package/dist/esm/modules/fuzzyMatchLogic/tokenize.d.ts +3 -0
- package/dist/esm/modules/fuzzyMatchLogic/types.d.ts +25 -0
- package/dist/esm/modules/fuzzyMatchLogic/utils.d.ts +2 -0
- package/dist/esm/modules/fuzzyMatchLogic/utils.js +12 -0
- package/dist/esm/modules/fuzzyMatchLogic/utils.js.map +1 -0
- package/dist/esm/modules/pluginCore/PluginManagerContext.d.ts +24 -0
- package/dist/esm/modules/pluginCore/PluginManagerContext.js +62 -0
- package/dist/esm/modules/pluginCore/PluginManagerContext.js.map +1 -0
- package/dist/esm/modules/pluginCore/makePluginManagerContext.d.ts +7 -0
- package/dist/esm/modules/pluginCore/makePluginManagerContext.js +27 -0
- package/dist/esm/modules/pluginCore/makePluginManagerContext.js.map +1 -0
- package/dist/esm/modules/pluginCore/types.d.ts +36 -0
- package/dist/esm/modules/pluginCore/types.js +7 -0
- package/dist/esm/modules/pluginCore/types.js.map +1 -0
- package/dist/esm/modules/resourceJump/ApiQueryMagazineResourceJump.d.ts +27 -0
- package/dist/esm/modules/resourceJump/ApiQueryMagazineResourceJump.js +26 -0
- package/dist/esm/modules/resourceJump/ApiQueryMagazineResourceJump.js.map +1 -0
- package/dist/esm/modules/resourceJump/ResourceJumpContext.d.ts +17 -0
- package/dist/esm/modules/resourceJump/ResourceJumpContext.js +88 -0
- package/dist/esm/modules/resourceJump/ResourceJumpContext.js.map +1 -0
- package/dist/esm/modules/resourceJump/buildJumpUrl.d.ts +2 -0
- package/dist/esm/modules/resourceJump/buildJumpUrl.js +32 -0
- package/dist/esm/modules/resourceJump/buildJumpUrl.js.map +1 -0
- package/dist/esm/modules/resourceJump/findBestMatchByUrl.d.ts +17 -0
- package/dist/esm/modules/resourceJump/findBestMatchByUrl.js +85 -0
- package/dist/esm/modules/resourceJump/findBestMatchByUrl.js.map +1 -0
- package/dist/esm/modules/resourceJump/helpers.d.ts +28 -0
- package/dist/esm/modules/resourceJump/helpers.js +19 -0
- package/dist/esm/modules/resourceJump/helpers.js.map +1 -0
- package/dist/esm/modules/resourceJump/routeLoader.d.ts +11 -0
- package/dist/esm/modules/resourceJump/routeLoader.js +43 -0
- package/dist/esm/modules/resourceJump/routeLoader.js.map +1 -0
- package/dist/esm/modules/resourceJump/types.d.ts +18 -0
- package/dist/esm/modules/resourceJump/ui/EhJumpResourceSelector.d.ts +20 -0
- package/dist/esm/modules/resourceJump/ui/EhJumpResourceSelector.js +209 -0
- package/dist/esm/modules/resourceJump/ui/EhJumpResourceSelector.js.map +1 -0
- package/dist/esm/modules/resourceJump/ui/JumpALink.d.ts +14 -0
- package/dist/esm/modules/resourceJump/ui/JumpALink.js +38 -0
- package/dist/esm/modules/resourceJump/ui/JumpALink.js.map +1 -0
- package/dist/esm/modules/resourceJump/ui/JumpMainButton.d.ts +5 -0
- package/dist/esm/modules/resourceJump/ui/JumpMainButton.js +66 -0
- package/dist/esm/modules/resourceJump/ui/JumpMainButton.js.map +1 -0
- package/dist/esm/modules/resourceJump/ui/ResouceJumpLayout.d.ts +5 -0
- package/dist/esm/modules/resourceJump/ui/ResouceJumpLayout.js +42 -0
- package/dist/esm/modules/resourceJump/ui/ResouceJumpLayout.js.map +1 -0
- package/dist/esm/plugins/builtin/pageUrl/PageUrlPluginContext.d.ts +9 -0
- package/dist/esm/plugins/builtin/pageUrl/PageUrlPluginContext.js +36 -0
- package/dist/esm/plugins/builtin/pageUrl/PageUrlPluginContext.js.map +1 -0
- package/dist/esm/plugins/builtin/pageUrl/pageUrlAutoCompletePlugin.d.ts +11 -0
- package/dist/esm/plugins/builtin/pageUrl/pageUrlAutoCompletePlugin.js +44 -0
- package/dist/esm/plugins/builtin/pageUrl/pageUrlAutoCompletePlugin.js.map +1 -0
- package/dist/esm/plugins/builtin/pageUrl/pageUrlJumpPlugin.d.ts +7 -0
- package/dist/esm/plugins/builtin/pageUrl/pageUrlJumpPlugin.js +29 -0
- package/dist/esm/plugins/builtin/pageUrl/pageUrlJumpPlugin.js.map +1 -0
- package/dist/esm/plugins/builtin/pageUrl/pageUrlTypes.d.ts +11 -0
- package/dist/esm/routeTree.gen.d.ts +142 -0
- package/dist/esm/routeTree.gen.js +77 -0
- package/dist/esm/routeTree.gen.js.map +1 -0
- package/dist/esm/routes/__root.d.ts +2 -0
- package/dist/esm/routes/__root.js +22 -0
- package/dist/esm/routes/__root.js.map +1 -0
- package/dist/esm/routes/_layout/app/$appSlug/sub/$subValue.d.ts +1 -0
- package/dist/esm/routes/_layout/app/$appSlug.d.ts +1 -0
- package/dist/esm/routes/_layout/app/_appSlug/sub/_subValue.js +18 -0
- package/dist/esm/routes/_layout/app/_appSlug/sub/_subValue.js.map +1 -0
- package/dist/esm/routes/_layout/app/_appSlug.js +18 -0
- package/dist/esm/routes/_layout/app/_appSlug.js.map +1 -0
- package/dist/esm/routes/_layout/env/$envSlug/app/$appSlug/sub/$subValue.d.ts +1 -0
- package/dist/esm/routes/_layout/env/$envSlug/app/$appSlug.d.ts +1 -0
- package/dist/esm/routes/_layout/env/$envSlug/sub/$subValue.d.ts +1 -0
- package/dist/esm/routes/_layout/env/$envSlug.d.ts +1 -0
- package/dist/esm/routes/_layout/env/_envSlug/app/_appSlug/sub/_subValue.js +20 -0
- package/dist/esm/routes/_layout/env/_envSlug/app/_appSlug/sub/_subValue.js.map +1 -0
- package/dist/esm/routes/_layout/env/_envSlug/app/_appSlug.js +18 -0
- package/dist/esm/routes/_layout/env/_envSlug/app/_appSlug.js.map +1 -0
- package/dist/esm/routes/_layout/env/_envSlug/sub/_subValue.js +18 -0
- package/dist/esm/routes/_layout/env/_envSlug/sub/_subValue.js.map +1 -0
- package/dist/esm/routes/_layout/env/_envSlug.js +18 -0
- package/dist/esm/routes/_layout/env/_envSlug.js.map +1 -0
- package/dist/esm/routes/_layout/index.d.ts +1 -0
- package/dist/esm/routes/_layout/index.js +18 -0
- package/dist/esm/routes/_layout/index.js.map +1 -0
- package/dist/esm/routes/_layout.d.ts +1 -0
- package/dist/esm/routes/_layout.js +12 -0
- package/dist/esm/routes/_layout.js.map +1 -0
- package/dist/esm/types/ehTypes.d.ts +31 -0
- package/dist/esm/types/slateTypes.d.ts +28 -0
- package/dist/esm/types/tanstackQuery.d.ts +11 -0
- package/dist/esm/types/types.d.ts +16 -0
- package/dist/esm/types/userBehaviourTypes.d.ts +76 -0
- package/dist/esm/types/utilityTypes.d.ts +1 -0
- package/dist/esm/ui/components/ActionCard.d.ts +9 -0
- package/dist/esm/ui/components/AppIcon.d.ts +7 -0
- package/dist/esm/ui/components/commandInput/EhBaseSelector.d.ts +6 -0
- package/dist/esm/ui/components/commandInput/EhBaseSelector.js +22 -0
- package/dist/esm/ui/components/commandInput/EhBaseSelector.js.map +1 -0
- package/dist/esm/ui/components/commandInput/types.d.ts +13 -0
- package/dist/esm/ui/components/contextDebug.d.ts +2 -0
- package/dist/esm/ui/components/contextDebug.js +12 -0
- package/dist/esm/ui/components/contextDebug.js.map +1 -0
- package/dist/esm/ui/components/controlPanel/BaseDropdownSelector.d.ts +11 -0
- package/dist/esm/ui/components/controlPanel/env/EnvDropdownContent.d.ts +5 -0
- package/dist/esm/ui/components/controlPanel/env/EnvDropdownSelector.d.ts +1 -0
- package/dist/esm/ui/components/error/DefaultErrorComponent.d.ts +2 -0
- package/dist/esm/ui/components/error/DefaultErrorComponent.js +13 -0
- package/dist/esm/ui/components/error/DefaultErrorComponent.js.map +1 -0
- package/dist/esm/ui/components/error/RooutErrorPage.d.ts +2 -0
- package/dist/esm/ui/components/error/RooutErrorPage.js +12 -0
- package/dist/esm/ui/components/error/RooutErrorPage.js.map +1 -0
- package/dist/esm/ui/components/footer/Footer.d.ts +1 -0
- package/dist/esm/ui/components/footer/Footer.js +38 -0
- package/dist/esm/ui/components/footer/Footer.js.map +1 -0
- package/dist/esm/ui/components/header/PlaygroundHeader.d.ts +1 -0
- package/dist/esm/ui/components/header/PlaygroundHeader.js +23 -0
- package/dist/esm/ui/components/header/PlaygroundHeader.js.map +1 -0
- package/dist/esm/ui/components/leftPanel/LeftPanel.d.ts +5 -0
- package/dist/esm/ui/components/quickBar/EnvQuickJumpBar.d.ts +5 -0
- package/dist/esm/ui/components/quickBar/EnvQuickJumpBar.js +52 -0
- package/dist/esm/ui/components/quickBar/EnvQuickJumpBar.js.map +1 -0
- package/dist/esm/ui/components/quickBar/QuickJumpBar.d.ts +5 -0
- package/dist/esm/ui/components/widgetPanel/AddWidgetCard.d.ts +5 -0
- package/dist/esm/ui/components/widgetPanel/WidgetGrid.d.ts +6 -0
- package/dist/esm/ui/components/widgets/CredentialsWidget.d.ts +11 -0
- package/dist/esm/ui/components/widgets/VersionWidget.d.ts +7 -0
- package/dist/esm/ui/error/NotFoundError.d.ts +1 -0
- package/dist/esm/ui/error/NotFoundError.js +16 -0
- package/dist/esm/ui/error/NotFoundError.js.map +1 -0
- package/dist/esm/ui/layout/Footer.d.ts +1 -0
- package/dist/esm/ui/layout/Header.d.ts +1 -0
- package/dist/esm/ui/layout/LoadingScreen.d.ts +4 -0
- package/dist/esm/ui/layout/LoadingScreen.js +14 -0
- package/dist/esm/ui/layout/LoadingScreen.js.map +1 -0
- package/dist/esm/ui/layout/MainLayout.d.ts +5 -0
- package/dist/esm/ui/layout/MainLayout.js +18 -0
- package/dist/esm/ui/layout/MainLayout.js.map +1 -0
- package/dist/esm/ui/layout/SideColumn.d.ts +1 -0
- package/dist/esm/ui/layout/TopLevelProviders.d.ts +5 -0
- package/dist/esm/ui/layout/TopLevelProviders.js +42 -0
- package/dist/esm/ui/layout/TopLevelProviders.js.map +1 -0
- package/dist/esm/ui/main/JumpTabContent.d.ts +1 -0
- package/dist/esm/ui/main/Tabs.d.ts +4 -0
- package/dist/esm/userDb/DbContext.d.ts +9 -0
- package/dist/esm/userDb/DbContext.js +18 -0
- package/dist/esm/userDb/DbContext.js.map +1 -0
- package/dist/esm/userDb/EhDb.d.ts +12 -0
- package/dist/esm/userDb/EhDb.js +20 -0
- package/dist/esm/userDb/EhDb.js.map +1 -0
- package/dist/esm/util/availabilityMatrixUtils.d.ts +12 -0
- package/dist/esm/util/availabilityMatrixUtils.js +57 -0
- package/dist/esm/util/availabilityMatrixUtils.js.map +1 -0
- package/dist/esm/util/createEhRouter.d.ts +7 -0
- package/dist/esm/util/createEhRouter.js +16 -0
- package/dist/esm/util/createEhRouter.js.map +1 -0
- package/dist/esm/util/highlightMatches.d.ts +2 -0
- package/dist/esm/util/highlightMatches.js +19 -0
- package/dist/esm/util/highlightMatches.js.map +1 -0
- package/dist/esm/util/reactQueryUtils.d.ts +6 -0
- package/dist/esm/util/reactQueryUtils.js +10 -0
- package/dist/esm/util/reactQueryUtils.js.map +1 -0
- package/dist/esm/util/route-utils.d.ts +6 -0
- package/dist/esm/util/route-utils.js +72 -0
- package/dist/esm/util/route-utils.js.map +1 -0
- package/dist/favicon.ico +0 -0
- package/dist/robots.txt +2 -0
- package/package.json +110 -0
- package/src/App.tsx +28 -0
- package/src/__tests__/modules/fuzzyMatchLogic/autoCompleteFilter.test.ts +185 -0
- package/src/__tests__/modules/fuzzyMatchLogic/features/prefixFracTokenMiddles.test.ts +23 -0
- package/src/__tests__/modules/fuzzyMatchLogic/fixLayout.test.ts +11 -0
- package/src/__tests__/modules/fuzzyMatchLogic/postFiltration.test.ts +15 -0
- package/src/__tests__/modules/fuzzyMatchLogic/testUtils.ts +8 -0
- package/src/__tests__/modules/fuzzyMatchLogic/tokenize.test.ts +65 -0
- package/src/__tests__/modules/resouceJump/findBestMatchByUrl.test.ts +234 -0
- package/src/__tests__/setupTests.tsx +0 -0
- package/src/__tests__/util/availabilityMatrixUtils.test.ts +61 -0
- package/src/api/ApiQueryMagazine.ts +15 -0
- package/src/api/data/useQueryBootstrapConfig.ts +17 -0
- package/src/api/infra/createQueryClient.ts +25 -0
- package/src/api/infra/trpc.ts +6 -0
- package/src/api/unsorted/indexDataFetcher.ts +46 -0
- package/src/appPropsFactory.ts +35 -0
- package/src/assets/env-hopper-logo.svg +114 -0
- package/src/components/ThemeSwitcher.tsx +22 -0
- package/src/components/theme-provider.tsx +8 -0
- package/src/components/ui/badge.tsx +37 -0
- package/src/components/ui/breadcrumb.tsx +128 -0
- package/src/components/ui/button.tsx +60 -0
- package/src/components/ui/card.tsx +95 -0
- package/src/components/ui/collapsible.tsx +31 -0
- package/src/components/ui/dialog.tsx +182 -0
- package/src/components/ui/dropdown-menu.tsx +257 -0
- package/src/components/ui/input.tsx +28 -0
- package/src/components/ui/popover.tsx +48 -0
- package/src/components/ui/scroll-area.tsx +58 -0
- package/src/components/ui/separator.tsx +26 -0
- package/src/components/ui/tabs.tsx +65 -0
- package/src/index.css +211 -0
- package/src/index.tsx +3 -0
- package/src/lib/utils.ts +7 -0
- package/src/main.tsx +53 -0
- package/src/modules/config/BootstrapConfigContext.tsx +33 -0
- package/src/modules/config/GlobalConfigContext.tsx +42 -0
- package/src/modules/environment/ApiQueryMagazineEnvironment.ts +12 -0
- package/src/modules/environment/EnvironmentContext.tsx +115 -0
- package/src/modules/environment/types.ts +4 -0
- package/src/modules/environment/ui/EhEnvSelector.tsx +191 -0
- package/src/modules/fuzzyMatchLogic/autoCompleteFilter.ts +186 -0
- package/src/modules/fuzzyMatchLogic/features/prefixFrac.ts +13 -0
- package/src/modules/fuzzyMatchLogic/features/prefixFracTokenMiddles.ts +29 -0
- package/src/modules/fuzzyMatchLogic/fixLayout.ts +24 -0
- package/src/modules/fuzzyMatchLogic/postFiltration.ts +35 -0
- package/src/modules/fuzzyMatchLogic/scoring.ts +42 -0
- package/src/modules/fuzzyMatchLogic/tokenize.ts +32 -0
- package/src/modules/fuzzyMatchLogic/types.ts +33 -0
- package/src/modules/fuzzyMatchLogic/utils.ts +18 -0
- package/src/modules/pluginCore/PluginManagerContext.tsx +107 -0
- package/src/modules/pluginCore/makePluginManagerContext.ts +35 -0
- package/src/modules/pluginCore/types.ts +54 -0
- package/src/modules/resourceJump/ApiQueryMagazineResourceJump.ts +31 -0
- package/src/modules/resourceJump/ResourceJumpContext.tsx +142 -0
- package/src/modules/resourceJump/buildJumpUrl.ts +40 -0
- package/src/modules/resourceJump/findBestMatchByUrl.ts +121 -0
- package/src/modules/resourceJump/helpers.ts +117 -0
- package/src/modules/resourceJump/routeLoader.ts +58 -0
- package/src/modules/resourceJump/types.ts +21 -0
- package/src/modules/resourceJump/ui/EhJumpResourceSelector.tsx +259 -0
- package/src/modules/resourceJump/ui/JumpALink.tsx +54 -0
- package/src/modules/resourceJump/ui/JumpMainButton.tsx +97 -0
- package/src/modules/resourceJump/ui/ResouceJumpLayout.tsx +73 -0
- package/src/plugins/builtin/pageUrl/PageUrlPluginContext.tsx +55 -0
- package/src/plugins/builtin/pageUrl/pageUrlAutoCompletePlugin.ts +66 -0
- package/src/plugins/builtin/pageUrl/pageUrlJumpPlugin.ts +36 -0
- package/src/plugins/builtin/pageUrl/pageUrlTypes.ts +17 -0
- package/src/routeTree.gen.ts +249 -0
- package/src/routes/__root.tsx +23 -0
- package/src/routes/_layout/app/$appSlug/sub/$subValue.tsx +15 -0
- package/src/routes/_layout/app/$appSlug.tsx +15 -0
- package/src/routes/_layout/env/$envSlug/app/$appSlug/sub/$subValue.tsx +17 -0
- package/src/routes/_layout/env/$envSlug/app/$appSlug.tsx +15 -0
- package/src/routes/_layout/env/$envSlug/sub/$subValue.tsx +15 -0
- package/src/routes/_layout/env/$envSlug.tsx +15 -0
- package/src/routes/_layout/index.tsx +16 -0
- package/src/routes/_layout.tsx +9 -0
- package/src/types/ehTypes.ts +40 -0
- package/src/types/slateTypes.ts +22 -0
- package/src/types/tanstackQuery.ts +14 -0
- package/src/types/types.ts +20 -0
- package/src/types/userBehaviourTypes.ts +100 -0
- package/src/types/utilityTypes.ts +1 -0
- package/src/types/vite-env.d.ts +1 -0
- package/src/ui/components/ActionCard.tsx +30 -0
- package/src/ui/components/AppIcon.tsx +48 -0
- package/src/ui/components/commandInput/EhBaseSelector.tsx +51 -0
- package/src/ui/components/commandInput/types.ts +22 -0
- package/src/ui/components/contextDebug.tsx +13 -0
- package/src/ui/components/controlPanel/BaseDropdownSelector.tsx +163 -0
- package/src/ui/components/controlPanel/env/EnvDropdownContent.tsx +114 -0
- package/src/ui/components/controlPanel/env/EnvDropdownSelector.tsx +21 -0
- package/src/ui/components/error/DefaultErrorComponent.tsx +38 -0
- package/src/ui/components/error/RooutErrorPage.tsx +10 -0
- package/src/ui/components/footer/Footer.tsx +32 -0
- package/src/ui/components/header/PlaygroundHeader.tsx +26 -0
- package/src/ui/components/leftPanel/LeftPanel.tsx +194 -0
- package/src/ui/components/quickBar/EnvQuickJumpBar.tsx +65 -0
- package/src/ui/components/quickBar/QuickJumpBar.tsx +101 -0
- package/src/ui/components/widgetPanel/AddWidgetCard.tsx +17 -0
- package/src/ui/components/widgetPanel/WidgetGrid.tsx +18 -0
- package/src/ui/components/widgets/CredentialsWidget.tsx +55 -0
- package/src/ui/components/widgets/VersionWidget.tsx +29 -0
- package/src/ui/error/NotFoundError.tsx +13 -0
- package/src/ui/layout/Footer.tsx +16 -0
- package/src/ui/layout/Header.tsx +14 -0
- package/src/ui/layout/LoadingScreen.tsx +17 -0
- package/src/ui/layout/MainLayout.tsx +27 -0
- package/src/ui/layout/SideColumn.tsx +3 -0
- package/src/ui/layout/TopLevelProviders.tsx +52 -0
- package/src/ui/main/JumpTabContent.tsx +12 -0
- package/src/ui/main/Tabs.tsx +29 -0
- package/src/userDb/DbContext.tsx +22 -0
- package/src/userDb/EhDb.ts +22 -0
- package/src/util/availabilityMatrixUtils.ts +80 -0
- package/src/util/createEhRouter.ts +20 -0
- package/src/util/highlightMatches.tsx +29 -0
- package/src/util/reactQueryUtils.ts +12 -0
- package/src/util/route-utils.ts +71 -0
package/src/App.tsx
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { QueryClientProvider } from '@tanstack/react-query'
|
|
2
|
+
import { RouterProvider } from '@tanstack/react-router'
|
|
3
|
+
import { DbProvider } from './userDb/DbContext'
|
|
4
|
+
import type { TRPCRouter } from '@env-hopper/backend-core'
|
|
5
|
+
import type { QueryClient } from '@tanstack/react-query'
|
|
6
|
+
import type { TRPCClient } from '@trpc/client'
|
|
7
|
+
import type { EhDb } from './userDb/EhDb'
|
|
8
|
+
import type { createEhRouter } from '~/util/createEhRouter'
|
|
9
|
+
import { TRPCProvider } from '~/api/infra/trpc'
|
|
10
|
+
|
|
11
|
+
export interface AppProps {
|
|
12
|
+
router: ReturnType<typeof createEhRouter>
|
|
13
|
+
queryClient: QueryClient
|
|
14
|
+
trpcClient: TRPCClient<TRPCRouter>
|
|
15
|
+
db: EhDb
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function App({ router, queryClient, trpcClient, db }: AppProps) {
|
|
19
|
+
return (
|
|
20
|
+
<QueryClientProvider client={queryClient}>
|
|
21
|
+
<TRPCProvider queryClient={queryClient} trpcClient={trpcClient}>
|
|
22
|
+
<DbProvider db={db}>
|
|
23
|
+
<RouterProvider router={router} />
|
|
24
|
+
</DbProvider>
|
|
25
|
+
</TRPCProvider>
|
|
26
|
+
</QueryClientProvider>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { makeInputEntry } from './testUtils'
|
|
3
|
+
import type { FuzzySearchInputEntry } from '~/modules/fuzzyMatchLogic/types'
|
|
4
|
+
import {
|
|
5
|
+
fuzzySearch,
|
|
6
|
+
makeFuzzySearchIndex,
|
|
7
|
+
} from '~/modules/fuzzyMatchLogic/autoCompleteFilter'
|
|
8
|
+
|
|
9
|
+
const randomEnvironmentNames = [
|
|
10
|
+
'uat-0916',
|
|
11
|
+
'Prod-02a',
|
|
12
|
+
'Pipeline-delta11',
|
|
13
|
+
'BUILD-08',
|
|
14
|
+
'Dev-107',
|
|
15
|
+
'staging-envc',
|
|
16
|
+
'Backup-gammae',
|
|
17
|
+
'Infra-temporale',
|
|
18
|
+
'STAGING-BETAB',
|
|
19
|
+
'Backup-21',
|
|
20
|
+
'Sig-betac',
|
|
21
|
+
'Prod-production14',
|
|
22
|
+
'Staging-deployb',
|
|
23
|
+
'BACKUP-TEMPORAL',
|
|
24
|
+
'acc-2198',
|
|
25
|
+
'node-productiona',
|
|
26
|
+
'shared-21',
|
|
27
|
+
'Sig-deploy',
|
|
28
|
+
'SIG-01',
|
|
29
|
+
'uat-temporal',
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
describe.skip('env search a bit fuzzy', () => {
|
|
33
|
+
let db: Array<FuzzySearchInputEntry> = []
|
|
34
|
+
|
|
35
|
+
function given(strings: Array<string>) {
|
|
36
|
+
db = strings.map((title) => makeInputEntry(title))
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function searchResults(search: string) {
|
|
40
|
+
const index = makeFuzzySearchIndex({
|
|
41
|
+
entries: db,
|
|
42
|
+
})
|
|
43
|
+
return fuzzySearch(search, { index })
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
it('case 1', () => {
|
|
47
|
+
given(['env-a', 'env-b'])
|
|
48
|
+
expect(searchResults('a')).toEqual(['env-a'])
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('case 2', () => {
|
|
52
|
+
given(['x abcdev', 'abc-dev'])
|
|
53
|
+
expect(searchResults('abcdev')).toMatchInlineSnapshot(`
|
|
54
|
+
[
|
|
55
|
+
"abc-dev",
|
|
56
|
+
"x abcdev",
|
|
57
|
+
]
|
|
58
|
+
`)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it('case 3 - firstLetters', () => {
|
|
62
|
+
given(['x abcdev', 'abcXXX-devXXX'])
|
|
63
|
+
expect(searchResults('abc-dev')).toEqual(['abcXXX-devXXX', 'x abcdev'])
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it('case 4', () => {
|
|
67
|
+
given(['env-xxx-1', 'env-xxx-3'])
|
|
68
|
+
expect(searchResults('env1')).toEqual(['env-xxx-1'])
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it('case 5', () => {
|
|
72
|
+
given(['env-xxxx-33', 'env-xxx-33', 'env-xxx-3'])
|
|
73
|
+
expect(searchResults('env-xxx-3')).toEqual([
|
|
74
|
+
'env-xxx-3',
|
|
75
|
+
'env-xxx-33',
|
|
76
|
+
'env-xxxx-33',
|
|
77
|
+
])
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('user can find split text without splitters', () => {
|
|
81
|
+
given(['Abc-Rev'])
|
|
82
|
+
expect(searchResults('Abcrev')).toEqual(['Abc-Rev'])
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
it('case 6', () => {
|
|
86
|
+
given(randomEnvironmentNames)
|
|
87
|
+
expect(searchResults('pro14')).toEqual(['Prod-production14'])
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
it('case 7', () => {
|
|
91
|
+
given(randomEnvironmentNames)
|
|
92
|
+
expect(searchResults('B')).toEqual([
|
|
93
|
+
'BUILD-08',
|
|
94
|
+
'Backup-21',
|
|
95
|
+
'Backup-gammae',
|
|
96
|
+
'BACKUP-TEMPORAL',
|
|
97
|
+
'Sig-betac',
|
|
98
|
+
'STAGING-BETAB',
|
|
99
|
+
'Staging-deployb',
|
|
100
|
+
])
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
it('Case insensitive', () => {
|
|
104
|
+
given(['Abc Review', 'AbcRev'])
|
|
105
|
+
expect(searchResults('Rev')).toEqual(['AbcRev', 'Abc Review'])
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('prefix is priority', () => {
|
|
109
|
+
given(['EPIC-ENV-A64', 'A64-ENV-01'])
|
|
110
|
+
expect(searchResults('a64')).toEqual(['A64-ENV-01', 'EPIC-ENV-A64'])
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
// TODO: treat numeric/letter boundaries with different priorities compared with separators like '-'
|
|
114
|
+
it.skip('should respect delimiter', () => {
|
|
115
|
+
given(['g32pe-01', 'g32-dev-01'])
|
|
116
|
+
expect(searchResults('g32')).toEqual(['g32-dev-01', 'g32pe-01'])
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
it('fuzzy will not match inverted', () => {
|
|
120
|
+
given(['env-33'])
|
|
121
|
+
expect(searchResults('33-env')).toEqual([])
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
it('Upper case is a word separator', () => {
|
|
125
|
+
given(['camelCase', 'PascalCase', 'case'])
|
|
126
|
+
expect(searchResults('case')).toEqual(['case', 'camelCase', 'PascalCase'])
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
it('000 Leading zeros can be omitted', () => {
|
|
130
|
+
given(['env-001', 'env-1'])
|
|
131
|
+
expect(searchResults('1')).toEqual(['env-1', 'env-001'])
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
it('ru keyboard layout is working too', () => {
|
|
135
|
+
given(['env-001'])
|
|
136
|
+
expect(searchResults('утм')).toEqual(['env-001'])
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
it('special symbols will be working if they are standalone', () => {
|
|
140
|
+
given(['a order', 'b order #', 'c order'])
|
|
141
|
+
expect(searchResults('order #')).toEqual(['b order #'])
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
it('favorites, then recent, are priority - case sensitive', () => {
|
|
145
|
+
given(['a order', 'a order - recent', 'a order - favorite'])
|
|
146
|
+
expect(searchResults('a')).toEqual([
|
|
147
|
+
'a order - favorite',
|
|
148
|
+
'a order - recent',
|
|
149
|
+
'a order',
|
|
150
|
+
])
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
it('favorites, then recent, are priority - case insensitive', () => {
|
|
154
|
+
given(['A order', 'A order - recent', 'A order - favorite'])
|
|
155
|
+
expect(searchResults('a')).toEqual([
|
|
156
|
+
'A order - favorite',
|
|
157
|
+
'A order - recent',
|
|
158
|
+
'A order',
|
|
159
|
+
])
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
it('favorites, then recent, are priority - substring', () => {
|
|
163
|
+
given(['A order', 'A order - recent', 'A order - favorite'])
|
|
164
|
+
expect(searchResults('rd')).toEqual([
|
|
165
|
+
'A order - favorite',
|
|
166
|
+
'A order - recent',
|
|
167
|
+
'A order',
|
|
168
|
+
])
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
it('doubl dashes', () => {
|
|
172
|
+
given(['abc-uat-01'])
|
|
173
|
+
expect(searchResults('abcuat-01')).toEqual(['abc-uat-01'])
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
it('dash-separator', () => {
|
|
177
|
+
given(['abc-uat'])
|
|
178
|
+
expect(searchResults('abcuat')).toEqual(['abc-uat'])
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
it('does not match substrings', () => {
|
|
182
|
+
given(['abc'])
|
|
183
|
+
expect(searchResults('b')).toEqual([])
|
|
184
|
+
})
|
|
185
|
+
})
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { makeInputEntry } from '../testUtils'
|
|
3
|
+
import { prefixFracAcrossTokens } from '~/modules/fuzzyMatchLogic/features/prefixFracTokenMiddles'
|
|
4
|
+
|
|
5
|
+
describe('prefixFracAcrossTokens', () => {
|
|
6
|
+
it('not found', () => {
|
|
7
|
+
const input = makeInputEntry('env-001')
|
|
8
|
+
const actual = prefixFracAcrossTokens(input, ['002'])
|
|
9
|
+
expect(actual.toFixed(2)).toEqual('0.00')
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
it('1 token match full', () => {
|
|
13
|
+
const input = makeInputEntry('env-001-abc')
|
|
14
|
+
const actual = prefixFracAcrossTokens(input, ['001', 'abc'])
|
|
15
|
+
expect(actual.toFixed(2)).toEqual('1.00')
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
it('1 token match partial l', () => {
|
|
19
|
+
const input = makeInputEntry('env-001-abc')
|
|
20
|
+
const actual = prefixFracAcrossTokens(input, ['001', 'ab'])
|
|
21
|
+
expect(actual.toFixed(2)).toEqual('0.83')
|
|
22
|
+
})
|
|
23
|
+
})
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { fixRuLayout, isRuLayout } from '~/modules/fuzzyMatchLogic/fixLayout'
|
|
3
|
+
|
|
4
|
+
describe('ru -> en fix', () => {
|
|
5
|
+
it('can detect ru layout', () => {
|
|
6
|
+
expect(isRuLayout('йцукен')).toBe(true)
|
|
7
|
+
})
|
|
8
|
+
it('can fix ru layout', () => {
|
|
9
|
+
expect(fixRuLayout('здуфыу ашч ьу')).toBe('please fix me')
|
|
10
|
+
})
|
|
11
|
+
})
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { makeInputEntry } from './testUtils'
|
|
3
|
+
import { isTokensConsequent } from '~/modules/fuzzyMatchLogic/postFiltration'
|
|
4
|
+
|
|
5
|
+
describe('isTokensConsequent', () => {
|
|
6
|
+
it('in order', () => {
|
|
7
|
+
const actual = isTokensConsequent(['env', '3'], makeInputEntry('env-xxx-3'))
|
|
8
|
+
expect(actual).toBeTruthy()
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
it('reversed', () => {
|
|
12
|
+
const actual = isTokensConsequent(['3', 'env'], makeInputEntry('env-xxx-3'))
|
|
13
|
+
expect(actual).toBeFalsy()
|
|
14
|
+
})
|
|
15
|
+
})
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { tokenize } from '~/modules/fuzzyMatchLogic/tokenize'
|
|
3
|
+
|
|
4
|
+
describe('tokenize', () => {
|
|
5
|
+
it('at the start start', () => {
|
|
6
|
+
const result = tokenize('# 12foo')
|
|
7
|
+
expect(result).toMatchInlineSnapshot(`
|
|
8
|
+
[
|
|
9
|
+
"12",
|
|
10
|
+
"foo",
|
|
11
|
+
]
|
|
12
|
+
`)
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
it('Tokenize complex expression', () => {
|
|
16
|
+
const result = tokenize('123abc12 CamelABCCaseX foo-bar_baz,HelloWorld')
|
|
17
|
+
expect(result).toMatchInlineSnapshot(`
|
|
18
|
+
[
|
|
19
|
+
"123",
|
|
20
|
+
"abc",
|
|
21
|
+
"12",
|
|
22
|
+
"camel",
|
|
23
|
+
"abc",
|
|
24
|
+
"case",
|
|
25
|
+
"x",
|
|
26
|
+
"foo",
|
|
27
|
+
"bar",
|
|
28
|
+
"baz",
|
|
29
|
+
"hello",
|
|
30
|
+
"world",
|
|
31
|
+
]
|
|
32
|
+
`)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('in the end', () => {
|
|
36
|
+
const result = tokenize('12foo #')
|
|
37
|
+
expect(result).toMatchInlineSnapshot(`
|
|
38
|
+
[
|
|
39
|
+
"12",
|
|
40
|
+
"foo",
|
|
41
|
+
]
|
|
42
|
+
`)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('camelCase', () => {
|
|
46
|
+
const result = tokenize('camelCase')
|
|
47
|
+
expect(result).toMatchInlineSnapshot(`
|
|
48
|
+
[
|
|
49
|
+
"camel",
|
|
50
|
+
"case",
|
|
51
|
+
]
|
|
52
|
+
`)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('international', () => {
|
|
56
|
+
const result = tokenize('РусскийТекстΣ')
|
|
57
|
+
expect(result).toMatchInlineSnapshot(`
|
|
58
|
+
[
|
|
59
|
+
"русский",
|
|
60
|
+
"текст",
|
|
61
|
+
"σ",
|
|
62
|
+
]
|
|
63
|
+
`)
|
|
64
|
+
})
|
|
65
|
+
})
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { objectify } from 'radashi'
|
|
2
|
+
import { describe, expect, it } from 'vitest'
|
|
3
|
+
import type {
|
|
4
|
+
AvailiabilityMatrixData as AvailabilityMatrixData,
|
|
5
|
+
AvailabilityVariant,
|
|
6
|
+
EhEnvIndexed,
|
|
7
|
+
} from '@env-hopper/backend-core'
|
|
8
|
+
import type { ResourceJumpItem } from '~/modules/resourceJump/types'
|
|
9
|
+
import type { FindBestMatchingResourceJumpParams } from '~/modules/resourceJump/findBestMatchByUrl'
|
|
10
|
+
import { findBestMatchByUrl } from '~/modules/resourceJump/findBestMatchByUrl'
|
|
11
|
+
|
|
12
|
+
function makeEnvs(
|
|
13
|
+
envAsCommaSeparated: string | Array<string>,
|
|
14
|
+
): Record<string, EhEnvIndexed> {
|
|
15
|
+
const envsArray = Array.isArray(envAsCommaSeparated)
|
|
16
|
+
? envAsCommaSeparated
|
|
17
|
+
: envAsCommaSeparated.split(/\s*,\s*/)
|
|
18
|
+
return objectify(
|
|
19
|
+
envsArray,
|
|
20
|
+
(slug) => slug,
|
|
21
|
+
(slug) => ({ slug, displayName: slug }),
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function makeResourceJumps(
|
|
26
|
+
resoucesAsCommaSeparated: string | Array<string>,
|
|
27
|
+
): Record<string, ResourceJumpItem> {
|
|
28
|
+
const resourceArray = Array.isArray(resoucesAsCommaSeparated)
|
|
29
|
+
? resoucesAsCommaSeparated
|
|
30
|
+
: resoucesAsCommaSeparated.split(/\s*,\s*/)
|
|
31
|
+
return objectify(
|
|
32
|
+
resourceArray,
|
|
33
|
+
(slug) => slug,
|
|
34
|
+
(slug) => ({ slug, type: 'resource' }),
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function parseUrl(url: string): {
|
|
39
|
+
urlEnvSlug: string | undefined
|
|
40
|
+
urlAppSlug: string | undefined
|
|
41
|
+
} {
|
|
42
|
+
// 3 options
|
|
43
|
+
// /env/{urlSlug}/app/{appSlug}
|
|
44
|
+
// /env/{urlSlug}
|
|
45
|
+
// /app/{appSlug}
|
|
46
|
+
const envMatch = url.match(/\/env\/([^/]+)/)
|
|
47
|
+
const appMatch = url.match(/\/app\/([^/]+)/)
|
|
48
|
+
return {
|
|
49
|
+
urlEnvSlug: envMatch ? envMatch[1] : undefined,
|
|
50
|
+
urlAppSlug: appMatch ? appMatch[1] : undefined,
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
describe('findBestMatchByUrl', () => {
|
|
55
|
+
const envs = makeEnvs(['test-env', 'staging-env', 'prod-env'])
|
|
56
|
+
const resourceJumps = makeResourceJumps(['test-app', 'appA', 'appB'])
|
|
57
|
+
|
|
58
|
+
async function run(
|
|
59
|
+
url: string,
|
|
60
|
+
override: Partial<FindBestMatchingResourceJumpParams> = {},
|
|
61
|
+
): Promise<{
|
|
62
|
+
env: string | undefined
|
|
63
|
+
resourceJump: string | undefined
|
|
64
|
+
}> {
|
|
65
|
+
const { urlEnvSlug, urlAppSlug } = parseUrl(url)
|
|
66
|
+
|
|
67
|
+
const matrixStr = `
|
|
68
|
+
env/app | test-app | appA | appB
|
|
69
|
+
test-env | v | | x
|
|
70
|
+
staging-env| | x | x
|
|
71
|
+
prod-env | | | x
|
|
72
|
+
|
|
73
|
+
v - healthy & data & deployed
|
|
74
|
+
x - unhealthy & data & deployed
|
|
75
|
+
. - not deployed, no data, not health
|
|
76
|
+
`
|
|
77
|
+
|
|
78
|
+
const matrixData = parseMatrixStrToAvailabilityMatrix(matrixStr)
|
|
79
|
+
|
|
80
|
+
const actual = await findBestMatchByUrl({
|
|
81
|
+
urlEnvSlug: urlEnvSlug,
|
|
82
|
+
urlAppSlug: urlAppSlug,
|
|
83
|
+
envs: envs,
|
|
84
|
+
resourceJumps: resourceJumps,
|
|
85
|
+
getAvailabilityMatrix: async () => await Promise.resolve(matrixData),
|
|
86
|
+
getNameMigrations: async (r) => {
|
|
87
|
+
if (r.resourceSlug === 'old-app%2Fhome') {
|
|
88
|
+
return await Promise.resolve({
|
|
89
|
+
type: 'resourceRename',
|
|
90
|
+
oldSlug: r.resourceSlug,
|
|
91
|
+
targetSlug: 'test-app',
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
return await Promise.resolve(false)
|
|
95
|
+
},
|
|
96
|
+
getEnvHistory: async () =>
|
|
97
|
+
await Promise.resolve(
|
|
98
|
+
['staging-env', 'prod-env', 'test-env'].map((envSlug, index) => ({
|
|
99
|
+
envSlug,
|
|
100
|
+
timestamp: 100 - index,
|
|
101
|
+
})),
|
|
102
|
+
),
|
|
103
|
+
...override,
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
env: actual.env?.slug,
|
|
108
|
+
resourceJump: actual.resourceJump?.slug,
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
it('env-only simple', async () => {
|
|
113
|
+
expect(await run('/env/test-env')).toEqual({
|
|
114
|
+
env: 'test-env',
|
|
115
|
+
resourceJump: undefined,
|
|
116
|
+
})
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
it('empty url', async () => {
|
|
120
|
+
expect(await run('/')).toEqual({
|
|
121
|
+
env: undefined,
|
|
122
|
+
resourceJump: undefined,
|
|
123
|
+
})
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
it('app-only simple', async () => {
|
|
127
|
+
expect(
|
|
128
|
+
await run('/app/test-app', { getEnvHistory: () => Promise.resolve([]) }),
|
|
129
|
+
).toEqual({
|
|
130
|
+
env: undefined,
|
|
131
|
+
resourceJump: 'test-app',
|
|
132
|
+
})
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
it('app & env simple', async () => {
|
|
136
|
+
expect(await run('/env/test-env/app/test-app')).toEqual({
|
|
137
|
+
env: 'test-env',
|
|
138
|
+
resourceJump: 'test-app',
|
|
139
|
+
})
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
it('migration: resourceName', async () => {
|
|
143
|
+
expect(await run('/env/test-env/app/old-app%2Fhome')).toEqual({
|
|
144
|
+
env: 'test-env',
|
|
145
|
+
resourceJump: 'test-app',
|
|
146
|
+
})
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
it('auto selection: env', async () => {
|
|
150
|
+
expect(await run('/app/test-app')).toEqual({
|
|
151
|
+
env: 'test-env',
|
|
152
|
+
resourceJump: 'test-app',
|
|
153
|
+
})
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
it('combo: auto selection + migration', async () => {
|
|
157
|
+
expect(await run('/app/old-app%2Fhome')).toEqual({
|
|
158
|
+
env: 'test-env',
|
|
159
|
+
resourceJump: 'test-app',
|
|
160
|
+
})
|
|
161
|
+
})
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
function parseMatrixStrToAvailabilityMatrix(
|
|
165
|
+
matrixStr: string,
|
|
166
|
+
): AvailabilityMatrixData {
|
|
167
|
+
const lines = matrixStr
|
|
168
|
+
.split('\n')
|
|
169
|
+
.map((l) => l.trim())
|
|
170
|
+
.filter((l) => l.includes('|')) // only keep lines with matrix data
|
|
171
|
+
|
|
172
|
+
if (lines.length === 0) {
|
|
173
|
+
return {
|
|
174
|
+
envSlugs: [],
|
|
175
|
+
resourceJumpSlugs: [],
|
|
176
|
+
availabilityVariants: [],
|
|
177
|
+
matrix: [],
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// --- Parse header row ---
|
|
182
|
+
const headerParts = lines[0]!.split('|').map((s) => s.trim())
|
|
183
|
+
const resourceJumpSlugs = headerParts.slice(1)
|
|
184
|
+
|
|
185
|
+
// --- Parse rows ---
|
|
186
|
+
const envSlugs: Array<string> = []
|
|
187
|
+
const matrix: Array<Array<number>> = []
|
|
188
|
+
const variants: Array<AvailabilityVariant> = []
|
|
189
|
+
const variantMap = new Map<string, number>() // maps symbol → variant index
|
|
190
|
+
|
|
191
|
+
function registerVariant(symbol: string): number {
|
|
192
|
+
if (!variantMap.has(symbol)) {
|
|
193
|
+
let variant: AvailabilityVariant
|
|
194
|
+
if (symbol === 'v') {
|
|
195
|
+
variant = { isDeployed: true, isHealthy: true, hasData: true }
|
|
196
|
+
} else if (symbol === 'x') {
|
|
197
|
+
variant = { isDeployed: true, isHealthy: false, hasData: true }
|
|
198
|
+
} else if (symbol === '.') {
|
|
199
|
+
variant = { isDeployed: false, isHealthy: false, hasData: false }
|
|
200
|
+
} else if (symbol === '' || symbol === ' ') {
|
|
201
|
+
// treat empty cell as no deployment
|
|
202
|
+
variant = { isDeployed: false, isHealthy: false, hasData: false }
|
|
203
|
+
symbol = '.'
|
|
204
|
+
} else {
|
|
205
|
+
throw new Error(`Unknown symbol '${symbol}'`)
|
|
206
|
+
}
|
|
207
|
+
variantMap.set(symbol, variants.length)
|
|
208
|
+
variants.push(variant)
|
|
209
|
+
}
|
|
210
|
+
return variantMap.get(symbol)!
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
for (const line of lines.slice(1)) {
|
|
214
|
+
const parts = line.split('|').map((s) => s.trim())
|
|
215
|
+
const env = parts[0]!
|
|
216
|
+
envSlugs.push(env)
|
|
217
|
+
|
|
218
|
+
const row: Array<number> = []
|
|
219
|
+
for (let j = 1; j < parts.length; j++) {
|
|
220
|
+
const cell = parts[j]
|
|
221
|
+
const symbol = cell || '.' // normalize empty → "."
|
|
222
|
+
const idx = registerVariant(symbol)
|
|
223
|
+
row.push(idx)
|
|
224
|
+
}
|
|
225
|
+
matrix.push(row)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return {
|
|
229
|
+
envSlugs,
|
|
230
|
+
resourceJumpSlugs,
|
|
231
|
+
availabilityVariants: variants,
|
|
232
|
+
matrix,
|
|
233
|
+
}
|
|
234
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { expect, it } from 'vitest'
|
|
2
|
+
import type { AvailabilityVariant } from '@env-hopper/backend-core'
|
|
3
|
+
import { findAvailableResources } from '~/util/availabilityMatrixUtils'
|
|
4
|
+
|
|
5
|
+
const variantHealthy: AvailabilityVariant = {
|
|
6
|
+
isDeployed: true,
|
|
7
|
+
hasData: true,
|
|
8
|
+
isHealthy: true,
|
|
9
|
+
}
|
|
10
|
+
const variantMissing: AvailabilityVariant = {
|
|
11
|
+
isDeployed: false,
|
|
12
|
+
hasData: false,
|
|
13
|
+
isHealthy: false,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const matrixData = {
|
|
17
|
+
envSlugs: ['env1', 'env2'],
|
|
18
|
+
resourceJumpSlugs: ['res1', 'res2'],
|
|
19
|
+
availabilityVariants: [variantHealthy, variantMissing],
|
|
20
|
+
matrix: [
|
|
21
|
+
[0, 1],
|
|
22
|
+
[1, 0],
|
|
23
|
+
],
|
|
24
|
+
}
|
|
25
|
+
it('finds available resources by envSlug', () => {
|
|
26
|
+
const result = findAvailableResources({
|
|
27
|
+
envSlug: 'env1',
|
|
28
|
+
availabilityMatrix: matrixData,
|
|
29
|
+
})
|
|
30
|
+
expect(result).toEqual([
|
|
31
|
+
{
|
|
32
|
+
envSlug: 'env1',
|
|
33
|
+
resourceJumpSlug: 'res1',
|
|
34
|
+
availabilityVariant: variantHealthy,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
envSlug: 'env1',
|
|
38
|
+
resourceJumpSlug: 'res2',
|
|
39
|
+
availabilityVariant: variantMissing,
|
|
40
|
+
},
|
|
41
|
+
])
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('finds available resources by resourceJumpSlug', () => {
|
|
45
|
+
const result = findAvailableResources({
|
|
46
|
+
resourceJumpSlug: 'res1',
|
|
47
|
+
availabilityMatrix: matrixData,
|
|
48
|
+
})
|
|
49
|
+
expect(result).toEqual([
|
|
50
|
+
{
|
|
51
|
+
envSlug: 'env1',
|
|
52
|
+
resourceJumpSlug: 'res1',
|
|
53
|
+
availabilityVariant: variantHealthy,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
envSlug: 'env2',
|
|
57
|
+
resourceJumpSlug: 'res1',
|
|
58
|
+
availabilityVariant: variantMissing,
|
|
59
|
+
},
|
|
60
|
+
])
|
|
61
|
+
})
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { queryOptions } from '@tanstack/react-query'
|
|
2
|
+
import { indexDataFetcher } from './unsorted/indexDataFetcher'
|
|
3
|
+
import type { IndexDataFetcherParams } from './unsorted/indexDataFetcher'
|
|
4
|
+
import type { BootstrapConfigData } from '@env-hopper/backend-core'
|
|
5
|
+
|
|
6
|
+
export class ApiQueryMagazine {
|
|
7
|
+
static getConfig(params: IndexDataFetcherParams) {
|
|
8
|
+
const queryFn = indexDataFetcher(params)
|
|
9
|
+
return queryOptions<BootstrapConfigData, Error>({
|
|
10
|
+
queryKey: ['config'],
|
|
11
|
+
queryFn,
|
|
12
|
+
staleTime: 0,
|
|
13
|
+
})
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
|
2
|
+
import { ApiQueryMagazine } from '../ApiQueryMagazine'
|
|
3
|
+
import type { QueryKey } from '@tanstack/react-query'
|
|
4
|
+
import { useTRPCClient } from '~/api/infra/trpc'
|
|
5
|
+
import { useDb } from '~/userDb/DbContext'
|
|
6
|
+
|
|
7
|
+
export const shouldPersist = (key: QueryKey) =>
|
|
8
|
+
Array.isArray(key) && key[0] === 'envs'
|
|
9
|
+
|
|
10
|
+
export function useQueryBootstrapConfig() {
|
|
11
|
+
// const trpc = useTRPC();
|
|
12
|
+
const trpcClient = useTRPCClient()
|
|
13
|
+
const queryClient = useQueryClient()
|
|
14
|
+
const db = useDb()
|
|
15
|
+
|
|
16
|
+
return useQuery(ApiQueryMagazine.getConfig({ trpcClient, queryClient, db }))
|
|
17
|
+
}
|