@harperfast/harper-pro 5.0.11 → 5.0.13
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/core/config/configUtils.js +8 -2
- package/core/package-lock.json +2 -2
- package/dist/cloneNode/cloneNode.js +38 -20
- package/dist/cloneNode/cloneNode.js.map +1 -1
- package/dist/core/config/configUtils.js +8 -2
- package/dist/core/config/configUtils.js.map +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/studio/web/assets/index-CUg8eaR8.css +1 -0
- package/studio/web/assets/index-DlmBuk_k.js +74 -0
- package/studio/web/assets/index-DlmBuk_k.js.map +1 -0
- package/studio/web/assets/{index.lazy-DRQKYKT0.js → index.lazy-K9dEIsCc.js} +4 -4
- package/studio/web/assets/{index.lazy-DRQKYKT0.js.map → index.lazy-K9dEIsCc.js.map} +1 -1
- package/studio/web/assets/{profile-wyN1K1z0.js → profile-F3bEc3dt.js} +2 -2
- package/studio/web/assets/{profile-wyN1K1z0.js.map → profile-F3bEc3dt.js.map} +1 -1
- package/studio/web/assets/status-CnVRDPsO.js +2 -0
- package/studio/web/assets/{status-ChrCqVc7.js.map → status-CnVRDPsO.js.map} +1 -1
- package/studio/web/assets/{vendor-react-D6IIT0sT.js → vendor-react-DyY32duL.js} +52 -52
- package/studio/web/assets/vendor-react-DyY32duL.js.map +1 -0
- package/studio/web/assets/{vendor-tanstack-zom2m6Nj.js → vendor-tanstack-D0jMvSWD.js} +2 -2
- package/studio/web/assets/{vendor-tanstack-zom2m6Nj.js.map → vendor-tanstack-D0jMvSWD.js.map} +1 -1
- package/studio/web/assets/{vendor-viz-BdK5B9uw.js → vendor-viz-Cs-GQIim.js} +2 -2
- package/studio/web/assets/{vendor-viz-BdK5B9uw.js.map → vendor-viz-Cs-GQIim.js.map} +1 -1
- package/studio/web/index.html +4 -4
- package/studio/web/assets/index-C_a0cXHU.css +0 -1
- package/studio/web/assets/index-Dk_TRrUg.js +0 -74
- package/studio/web/assets/index-Dk_TRrUg.js.map +0 -1
- package/studio/web/assets/status-ChrCqVc7.js +0 -2
- package/studio/web/assets/vendor-react-D6IIT0sT.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"mappings":"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","names":[],"ignoreList":[],"sources":["../../src/config/constants.ts","../../src/config/apiClient.ts","../../src/lib/pluralize.ts","../../src/integrations/api/replication.ts","../../src/lib/sleep.ts","../../src/integrations/api/retryGatewayErrors.ts","../../src/config/getInstanceClient.ts","../../src/features/auth/queries/getCurrentUser.ts","../../src/integrations/api/instance/auth/onInstanceLogoutSubmit.ts","../../src/integrations/api/instance/status/getInstanceUserInfo.ts","../../src/lib/urls/getOperationsUrlForCluster.ts","../../src/lib/urls/getOperationsUrlForInstance.ts","../../src/features/auth/store/authStore.ts","../../src/hooks/useAuth.ts","../../src/components/ui/buttonVariants.tsx","../../src/lib/cn.ts","../../src/components/ui/button.tsx","../../src/components/ui/card.tsx","../../src/lib/types/isLocalUser.ts","../../src/lib/urls/getDefaultSignedInCloudRouteForUser.ts","../../src/components/ErrorComponent.tsx","../../src/components/NotFoundComponent.tsx","../../src/lib/browserIsTouchBased.ts","../../src/react-query/queryClient.ts","../../src/lib/arrays/excludeFalsy.ts","../../src/integrations/datadog/datadog.ts","../../src/components/StudioLocal.tsx","../../src/router/rootRoute.ts","../../src/components/DiscordLogo.tsx","../../src/components/MainLogo.tsx","../../src/components/ui/navigation/NavigationMenuViewport.tsx","../../src/components/ui/navigation/NavigationMenu.tsx","../../src/components/ui/navigation/NavigationMenuItem.tsx","../../src/components/ui/navigation/NavigationMenuLink.tsx","../../src/components/ui/navigation/NavigationMenuList.tsx","../../src/components/ui/badgeVariants.tsx","../../src/components/Version.tsx","../../src/config/useInstanceClient.tsx","../../src/lib/storage/clearLocalStorage.ts","../../src/lib/storage/clearSessionStorage.ts","../../src/features/auth/handlers/logoutOnSuccess.ts","../../src/features/auth/hooks/useLogout.ts","../../src/hooks/usePermissions.ts","../../src/components/Navbar.tsx","../../src/features/auth/AuthLayout.tsx","../../src/integrations/reo/reo.ts","../../src/lib/string/parseCompanyFromEmail.ts","../../src/features/auth/CheckOAuth.tsx","../../src/components/ui/tooltip.tsx","../../src/lib/string/capitalizeWords.ts","../../src/components/Breadcrumbs.tsx","../../src/components/ui/form/Form.tsx","../../src/components/ui/form/formFieldContext.tsx","../../src/components/ui/form/formItemContext.tsx","../../src/components/ui/form/useFormField.tsx","../../src/components/ui/form/FormControl.tsx","../../src/components/ui/form/FormField.tsx","../../src/components/ui/form/FormItem.tsx","../../src/components/ui/label.tsx","../../src/components/ui/form/FormLabel.tsx","../../src/components/ui/form/FormMessage.tsx","../../src/components/ui/input.tsx","../../src/config/clusterStatuses.ts","../../src/config/deepLinks.ts","../../src/integrations/api/instance/auth/useInstanceLoginMutation.ts","../../src/features/auth/hooks/useClusterInstanceSignIn.ts","../../src/features/cluster/queries/getClusterInfoQuery.ts","../../src/lib/zod/email.ts","../../src/lib/zod/password.ts","../../src/lib/zod/username.ts","../../src/integrations/api/instance/auth/signInSchema.ts","../../src/integrations/api/instance/status/getInstanceHealth.ts","../../src/lib/urls/detectCrossLocalhostUrls.ts","../../src/features/auth/ClusterInstanceSignIn.tsx","../../src/features/auth/hooks/useForgotPassword.ts","../../src/features/auth/ForgotPassword.tsx","../../src/features/auth/hooks/useResetPassword.ts","../../src/features/auth/ResetPassword.tsx","../../src/features/auth/components/GitHubAuthenticationButton.tsx","../../src/features/auth/components/GoogleAuthenticationButton.tsx","../../src/features/auth/hooks/useCloudSignIn.ts","../../src/features/auth/SignIn.tsx","../../src/lib/string/regex/personNameRegex.ts","../../src/features/auth/hooks/useSignUp.ts","../../src/features/auth/SignUp.tsx","../../src/features/auth/hooks/useResendEmailVerification.ts","../../src/features/auth/hooks/useVerifyEmail.ts","../../src/features/auth/VerifyEmail.tsx","../../src/features/auth/Verifying.tsx","../../src/features/auth/routes.ts","../../src/components/SubNavMenu.tsx","../../src/components/ui/utils/badgeStatus.tsx","../../src/components/ui/dialog.tsx","../../src/components/ConfirmDeletionModal.tsx","../../src/components/ui/badge.tsx","../../src/components/ui/dropdownMenu.tsx","../../src/integrations/api/clusterIsSelfManaged.ts","../../src/features/clusters/components/ClusterCardAction.tsx","../../src/lib/arrays/mapBy.ts","../../src/features/clusters/components/ClusterProgress.tsx","../../src/features/clusters/mutations/terminateCluster.ts","../../src/hooks/useCopyToClipboard.tsx","../../src/lib/string/safeParse.ts","../../src/lib/storage/getLocalStorage.ts","../../src/lib/storage/setLocalStorage.ts","../../src/hooks/useLocalStorage.ts","../../src/lib/storage/localStorageKeys.ts","../../src/features/clusters/components/ClusterCard.tsx","../../src/components/ContactUs.tsx","../../src/components/Loading.tsx","../../src/components/SubNavSimpleLayout.tsx","../../src/features/cluster/queries/getPlanTypesQuery.ts","../../src/features/clusters/queries/getHarperVersionsQuery.ts","../../src/features/clusters/queries/getRegionLocationsQuery.ts","../../src/lib/arrays/sort/byField.ts","../../src/lib/numbers/ipAddressToNumber.ts","../../src/lib/string/isIpAddress.ts","../../src/lib/arrays/sort/byInstanceFqdnThenPort.ts","../../src/lib/groupBy.ts","../../src/lib/keyBy.ts","../../src/lib/groupThenKeyBy.ts","../../src/lib/string/wasAReleasedBeforeB.ts","../../src/components/ProgressBar.tsx","../../src/components/EstimatedProgressBar.tsx","../../src/features/clusters/hooks/useCreateNewCluster.ts","../../src/features/clusters/hooks/useUpdateCluster.ts","../../src/features/organization/queries/getOrganizationQuery.ts","../../src/integrations/api/orgType.ts","../../src/lib/string/collapseKebabsToMaxLength.ts","../../src/lib/string/stringsShareAPrefix.ts","../../src/lib/string/to-kebab-case.ts","../../src/features/organization/mutations/payments/attachPaymentMethodToOrganization.ts","../../src/integrations/stripe/useProcessStripePaymentMethod.tsx","../../src/integrations/stripe/useStripeOptions.tsx","../../src/features/organization/billing/paymentMethod/AddNewPaymentMethodForm.tsx","../../src/integrations/stripe/addStripeToOrganizationAndGetIntent.ts","../../src/integrations/stripe/getNewStripeIntentForOrganization.ts","../../src/integrations/stripe/useGetStripeClientSecret.ts","../../src/integrations/stripe/StripeContext.tsx","../../src/features/organization/billing/paymentMethod/AddNewPaymentMethod.tsx","../../src/integrations/stripe/paymentMethodStatus.ts","../../src/integrations/stripe/translateStripePaymentMethodStatus.tsx","../../src/lib/formatMonthAndYear.ts","../../src/features/organization/billing/paymentMethod/PaymentMethodsDisplay.tsx","../../src/lib/types/isPositive.ts","../../src/features/clusters/upsert/ClusterBilling.tsx","../../src/lib/string/regex/hostNameRegex.ts","../../src/lib/types/portNumbers.ts","../../src/features/clusters/upsert/upsertClusterSchema.ts","../../src/features/clusters/upsert/fields/ClusterAbbreviatedName.tsx","../../src/components/TextLoadingSkeleton.tsx","../../src/components/ui/select.tsx","../../src/features/clusters/upsert/fields/ClusterDeploymentDescription.tsx","../../src/features/clusters/upsert/fields/ClusterFQDN.tsx","../../src/features/clusters/upsert/fields/ClusterName.tsx","../../src/features/clusters/upsert/fields/ClusterPerformanceDescription.tsx","../../src/components/ui/form/FormDescription.tsx","../../src/features/clusters/upsert/fields/ClusterSkipGtmWait.tsx","../../src/features/clusters/upsert/fields/ClusterVersion.tsx","../../src/lib/arrays/sort/byNumberPrefix.ts","../../src/lib/units.ts","../../src/lib/humanFileSize.ts","../../src/lib/addCommasToNumbers.ts","../../src/lib/humanNumber.ts","../../src/features/clusters/upsert/components/ResourcesPerInstance.tsx","../../src/features/clusters/upsert/components/RegionFormInputs.tsx","../../src/features/clusters/upsert/ClusterRegions.tsx","../../src/features/clusters/upsert/components/InstanceFormInputs.tsx","../../src/features/clusters/upsert/components/ClusterInstances.tsx","../../src/features/clusters/upsert/ClusterDetails.tsx","../../src/features/clusters/upsert/lib/calculateInstanceFQDN.ts","../../src/features/clusters/upsert/lib/calculateDefaultDeploymentPerformanceAndRegionPlans.ts","../../src/features/clusters/upsert/lib/pickDefaultDeploymentPerformanceAndRegionPlans.ts","../../src/features/clusters/upsert/PriceDisplay.tsx","../../src/features/clusters/upsert/ClusterForm.tsx","../../src/features/clusters/upsert/isUpsertClusterSchema.ts","../../src/features/clusters/upsert/index.tsx","../../src/lib/arrays/sort/byClusterStatusThenName.ts","../../src/lib/string/filterByFuzzySearch.ts","../../src/features/clusters/ClustersList.tsx","../../src/lib/urls/currentUrlAfterHash.ts","../../src/lib/urls/currentUrlIncludingHash.ts","../../src/features/organization/billing/confirm/ProcessSetupIntent.tsx","../../src/features/organization/billing/confirm/ConfirmSetupIntent.tsx","../../src/lib/urls/buildAbsoluteLinkToPage.ts","../../src/features/organization/billing/index.tsx","../../src/components/ui/table.tsx","../../src/components/SimpleBrowseDataTable.tsx","../../src/integrations/stripe/translateStripeStatusToVariant.tsx","../../src/lib/toUSD.ts","../../src/lib/translateSecondsToAgo.ts","../../src/features/organization/billing/invoices/constants/tableDefinition.tsx","../../src/hooks/useRefreshClick.ts","../../src/integrations/stripe/useGetStripeInvoices.ts","../../src/features/organization/billing/invoices/Invoices.tsx","../../src/features/organization/billing/routes.ts","../../src/features/organization/queries/getOrganizationRoles.ts","../../src/features/organization/roles/constants/tableDefinition.ts","../../src/features/organization/mutations/addOrganizationRole.ts","../../src/features/organization/mutations/OrganizationRoleFormSchema.ts","../../src/features/organization/roles/modals/AddOrganizationRoleModal.tsx","../../src/features/organization/mutations/deleteOrganizationRole.ts","../../src/features/organization/mutations/updateOrganizationRole.ts","../../src/features/organization/queries/getOrganizationRoleInfo.ts","../../src/features/organization/roles/modals/ConfirmDeletionContent.tsx","../../src/features/organization/roles/modals/EditOrganizationRoleModal.tsx","../../src/features/organization/roles/index.tsx","../../src/features/organization/users/constants/tableDefinition.ts","../../src/features/organization/mutations/addUserToOrganizationRole.ts","../../src/features/organization/mutations/inviteUserToOrganizationRole.ts","../../src/features/organization/users/modals/AddUserModal.tsx","../../src/features/organization/mutations/removeUserFromOrganizationRole.ts","../../src/hooks/useCheckboxCallback.ts","../../src/features/organization/users/components/OrgUserRoleCheckbox.tsx","../../src/features/organization/users/modals/EditUserModal.tsx","../../src/lib/arrays/sort/byEmail.ts","../../src/features/organization/users/index.tsx","../../src/features/organizations/components/OrgCard.tsx","../../src/features/organizations/mutations/deleteOrganization.ts","../../src/features/organizations/hooks/useCreateNewOrganization.ts","../../src/features/organizations/mutations/newOrganizationSchema.ts","../../src/features/organizations/components/NewOrgForm.tsx","../../src/features/organizations/NewOrg.tsx","../../src/features/organizations/index.tsx","../../src/features/layouts/Dashboard.tsx","../../src/lib/urls/buildRedirectInSearch.ts","../../src/router/dashboardRoute.ts","../../src/features/organizations/routes.ts","../../src/features/organization/routes.ts","../../src/features/clusters/routes.ts","../../src/features/cluster/ClusterLayout.tsx","../../src/features/cluster/clusterLayoutRoute.ts","../../src/components/NestedContentWithSubNavMenu.tsx","../../src/lib/string/extractDomainFromTLD.ts","../../src/features/cluster/domains/AssociateDomainWithCluster.tsx","../../src/features/cluster/domains/components/CertificateProgress.tsx","../../src/integrations/api/instance/database/getSearchByValue.ts","../../src/features/cluster/domains/queries/getChallengeCertificates.ts","../../src/features/cluster/domains/VerifyDomainOwnership.tsx","../../src/features/clusters/mutations/setDomainIdsOnCluster.ts","../../src/features/organization/mutations/deleteDomain.ts","../../src/lib/arrays/unique.ts","../../src/features/cluster/domains/constants/tableDefinition.tsx","../../src/features/organization/mutations/addDomainToOrganization.ts","../../src/features/organization/mutations/validateDomainInOrganization.ts","../../src/features/organization/queries/getOrganizationDomains.ts","../../src/features/cluster/domains/Management.tsx","../../src/features/cluster/domains/Page.tsx","../../src/integrations/api/instance/auth/addUserFormSchema.ts","../../src/features/cluster/queries/resetPasswordUpdater.ts","../../src/integrations/api/instance/auth/addUser.ts","../../src/integrations/api/instance/auth/alterUser.ts","../../src/integrations/api/instance/auth/deleteUser.ts","../../src/integrations/api/instance/auth/useInstanceResetPasswordMutation.ts","../../src/features/cluster/FinishSetup.tsx","../../src/components/DataTable.tsx","../../src/features/cluster/EmptyCluster.tsx","../../src/features/cluster/InstanceLogInCell.tsx","../../src/integrations/api/instance/status/getStatus.ts","../../src/integrations/api/instance/status/setStatus.ts","../../src/features/cluster/InstanceStatusCell.tsx","../../src/features/cluster/Instances.tsx","../../src/features/cluster/Scaling.tsx","../../src/features/cluster/StartingUp.tsx","../../src/features/cluster/routes.ts","../../src/features/instance/apis/routes.ts","../../src/lib/arrays/shallowCompareObjects.ts","../../src/hooks/useEffectedState.ts","../../src/lib/events/listener.ts","../../src/lib/storage/getSessionStorage.ts","../../src/lib/storage/setSessionStorage.ts","../../src/hooks/useSessionStorage.ts","../../src/hooks/useSessionToggler.ts","../../src/features/instance/applications/context/EditorViewContext.tsx","../../src/features/instance/applications/hooks/useEditorView.ts","../../src/integrations/api/instance/applications/dropComponent.ts","../../src/lib/string/parseFileExtension.ts","../../src/lib/string/hasImageFileExtension.ts","../../src/integrations/api/instance/applications/getComponentFile.ts","../../src/integrations/api/instance/applications/setComponentFile.ts","../../src/features/instance/applications/hooks/useRenameFiles.tsx","../../src/lib/types/itemKeyIsDefined.ts","../../src/lib/arrays/excludePropertyFalsy.ts","../../src/lib/events/watcher.ts","../../src/features/instance/applications/shortcuts/index.ts","../../src/features/instance/applications/shortcuts/deleteShortcut.ts","../../src/features/instance/applications/shortcuts/newDirectoryShortcut.ts","../../src/features/instance/applications/shortcuts/newFileShortcut.ts","../../src/features/instance/applications/shortcuts/renameFileShortcut.ts","../../src/features/instance/applications/shortcuts/revertFileShortcut.ts","../../src/features/instance/applications/shortcuts/saveChangesShortcut.ts","../../src/lib/string/paths/extractFileNameFromPath.ts","../../src/lib/string/paths/joinPath.ts","../../src/features/instance/applications/context/isDirectory.ts","../../src/features/instance/applications/components/ApplicationsSidebar/specialItems.ts","../../src/features/instance/applications/components/ApplicationsSidebar/buildItems.tsx","../../src/features/instance/applications/components/ApplicationsSidebar/useDraggingHook.ts","../../src/lib/storage/readAsDataURL.ts","../../src/features/instance/applications/components/ApplicationsSidebar/DropTarget.tsx","../../src/features/instance/applications/components/ApplicationsSidebar/getItemTitle.tsx","../../src/features/instance/applications/context/editorFileContent.ts","../../src/features/instance/applications/components/ApplicationsSidebar/constants.ts","../../src/features/instance/applications/components/ApplicationsSidebar/DirectoryIcon.tsx","../../src/features/instance/applications/components/ApplicationsSidebar/FileTypeIcon.tsx","../../src/features/instance/applications/components/ApplicationsSidebar/LockedIcon.tsx","../../src/features/instance/applications/components/ApplicationsSidebar/NewApplicationIcon.tsx","../../src/features/instance/applications/components/ApplicationsSidebar/ItemTitle.tsx","../../src/features/instance/applications/components/ApplicationsSidebar/index.tsx","../../src/lib/axiosRetry.ts","../../src/integrations/api/instance/status/restartInstance.ts","../../src/hooks/useRestartClusterClick.tsx","../../src/hooks/useRestartInstanceClick.ts","../../src/components/RestartButton.tsx","../../src/features/instance/applications/components/ContentActions.tsx","../../src/features/instance/applications/lib/readMeUrlTransform.ts","../../src/components/ui/separator.tsx","../../src/components/ui/tabs.tsx","../../src/lib/arrays/findBy.ts","../../src/features/instance/applications/components/NewApplication/useCLISteps.tsx","../../src/features/instance/applications/components/NewApplication/CLIInstructions.tsx","../../src/features/instance/applications/components/NewApplication/CommonInstructions.tsx","../../src/components/ui/alertVariants.tsx","../../src/components/ui/alert.tsx","../../src/features/instance/applications/components/NewApplication/ImportInstructions.tsx","../../src/features/instance/applications/components/NewApplication/templates.ts","../../src/features/instance/applications/components/NewApplication/schema.ts","../../src/components/ui/radioGroup.tsx","../../src/lib/onClickStopPropagation.ts","../../src/features/instance/applications/components/NewApplication/TemplateInstructions.tsx","../../src/features/instance/applications/components/NewApplication/useCheckCLI.ts","../../src/integrations/api/instance/applications/addComponent.ts","../../src/features/instance/applications/components/NewApplication/useCreateFromTemplate.ts","../../src/integrations/api/instance/applications/deployComponent.ts","../../src/features/instance/applications/components/NewApplication/useImportApplication.ts","../../src/features/instance/applications/components/NewApplication/index.tsx","../../src/features/instance/applications/components/TextEditorView/index.tsx","../../src/features/instance/applications/components/ContentViewer.tsx","../../src/lib/urls/linkify.ts","../../src/lib/urls/getRestUrlForCluster.ts","../../src/config/useEntityRestURL.ts","../../src/lib/arrays/transformNodes.ts","../../src/features/instance/applications/components/ApplicationsSidebar/calculateRootEntries.ts","../../src/features/instance/applications/lib/parseReadMe.ts","../../src/integrations/api/instance/applications/getComponents.ts","../../src/features/instance/applications/context/EditorViewProvider.tsx","../../src/lib/attemptToRestoreFocus.ts","../../src/features/instance/applications/modals/AddDirectoryOrFileModal.tsx","../../src/features/instance/applications/modals/DeleteDirectoryOrFileModal.tsx","../../src/integrations/api/instance/applications/packageComponent.ts","../../src/features/instance/applications/modals/DownloadApplicationModal.tsx","../../src/hooks/useToggler.ts","../../src/features/instance/applications/components/NewTableForm/DatabaseName.tsx","../../src/integrations/api/instance/database/fieldType.ts","../../src/integrations/api/instance/database/schemaRegex.ts","../../src/integrations/api/instance/database/databaseNameSchema.ts","../../src/integrations/api/instance/database/fieldNameSchema.ts","../../src/integrations/api/instance/database/tableNameSchema.ts","../../src/features/instance/applications/components/NewTableForm/newTableSchema.ts","../../src/features/instance/applications/components/NewTableForm/OptionalExpiration.tsx","../../src/features/instance/applications/components/NewTableForm/index.tsx","../../src/features/instance/applications/modals/NewTableModal.tsx","../../src/features/instance/applications/modals/RedeployApplicationModal.tsx","../../src/lib/string/paths/removeFileNameFromPath.ts","../../src/lib/string/paths/renameFileInPath.ts","../../src/features/instance/applications/modals/RenameFileModal.tsx","../../src/features/instance/applications/index.tsx","../../src/features/instance/applications/routes.ts","../../src/integrations/api/instance/certificates/listCertificates.ts","../../src/features/instance/config/certificates/constants/tableDefinition.ts","../../src/components/ui/switch.tsx","../../src/components/ui/textarea.tsx","../../src/integrations/api/instance/certificates/addCertificate.ts","../../src/integrations/api/instance/certificates/useAddCertificate.ts","../../src/features/instance/config/certificates/modals/AddCertificateModal.tsx","../../src/integrations/api/instance/certificates/removeCertificate.ts","../../src/integrations/api/instance/certificates/useRemoveCertificate.ts","../../src/features/instance/config/certificates/modals/ViewCertificateModal.tsx","../../src/features/instance/config/certificates/index.tsx","../../src/features/instance/config/domains/index.tsx","../../src/features/instance/config/index.tsx","../../src/features/cluster/queries/getInstanceInfoQuery.ts","../../src/features/instance/config/overview/components/HarperVersion.tsx","../../src/integrations/api/instance/status/setConfiguration.ts","../../src/hooks/useRollingConfigUpdate.tsx","../../src/integrations/api/instance/status/getConfiguration.ts","../../src/integrations/api/instance/status/getRegistrationInfo.ts","../../src/integrations/api/instance/status/getUsageLicenses.ts","../../src/features/instance/config/overview/configRestrictions.ts","../../src/features/instance/config/overview/index.tsx","../../src/features/instance/config/roles/constants/tableDefinition.ts","../../src/integrations/api/instance/auth/addRole.ts","../../src/integrations/api/instance/auth/addRoleFormSchema.ts","../../src/features/instance/config/roles/modals/AddRoleModal.tsx","../../src/integrations/api/instance/auth/getListRoles.ts","../../src/features/instance/config/roles/defaultCalculator.ts","../../src/integrations/api/instance/auth/alterRole.ts","../../src/integrations/api/instance/auth/deleteRole.ts","../../src/integrations/api/instance/database/getDescribeAll.ts","../../src/features/instance/config/roles/modals/EditRoleModal.tsx","../../src/features/instance/config/roles/index.tsx","../../src/integrations/api/instance/ssh/listSSHKeys.ts","../../src/features/instance/config/sshKeys/constants/tableDefinition.ts","../../src/integrations/api/instance/ssh/getSSHKnownHosts.ts","../../src/integrations/api/instance/ssh/setSSHKnownHosts.ts","../../src/features/instance/config/sshKeys/KnownHosts.tsx","../../src/integrations/api/instance/ssh/addSSHKey.ts","../../src/features/instance/config/sshKeys/modals/AddSSHKeyModal.tsx","../../src/integrations/api/instance/ssh/deleteSSHKey.ts","../../src/integrations/api/instance/ssh/getSSHKey.ts","../../src/integrations/api/instance/ssh/updateSSHKey.ts","../../src/features/instance/config/sshKeys/modals/EditSSHKeyModal.tsx","../../src/features/instance/config/sshKeys/index.tsx","../../src/features/instance/config/users/constants/tableDefinition.ts","../../src/features/instance/config/users/modals/AddUserModal.tsx","../../src/integrations/api/instance/auth/alterUserFormSchema.ts","../../src/features/instance/config/users/components/AlterUserForm.tsx","../../src/integrations/api/instance/auth/deleteUserFormSchema.ts","../../src/features/instance/config/users/components/DeleteUserForm.tsx","../../src/features/instance/config/users/modals/EditUserModal.tsx","../../src/integrations/api/instance/auth/getListUsers.ts","../../src/features/instance/config/users/index.tsx","../../src/features/instance/registrationInfoLoader.ts","../../src/features/instance/config/routes.ts","../../src/lib/urls/buildAbsoluteLinkToDatabasePage.ts","../../src/components/ui/scrollArea.tsx","../../src/integrations/api/instance/database/createTable.ts","../../src/features/instance/databases/modals/CreateNewTableModal.tsx","../../src/features/instance/databases/components/DatabasesSidebar.tsx","../../src/features/instance/databases/functions/formatBrowseDataTableHeader.ts","../../src/integrations/api/instance/database/insertTableRecords.ts","../../src/features/instance/databases/modals/AddTableRowModal.tsx","../../src/integrations/api/instance/database/deleteDatabase.ts","../../src/features/instance/databases/modals/DeleteDatabaseModal.tsx","../../src/integrations/api/instance/database/deleteTable.ts","../../src/features/instance/databases/modals/DeleteTableModal.tsx","../../src/features/instance/databases/modals/EditTableRowModal.tsx","../../src/integrations/api/instance/database/addCSVData.ts","../../src/integrations/api/instance/database/addCSVDataFormSchema.ts","../../src/features/instance/databases/modals/ImportCSVModal.tsx","../../src/integrations/api/instance/database/cleanupOrphanBlobs.ts","../../src/integrations/api/instance/database/deleteTableRecords.ts","../../src/integrations/api/instance/database/getDescribeTable.ts","../../src/lib/boolean/translateKnownBooleanTypedValue.ts","../../src/lib/numbers/isNumber.ts","../../src/lib/numbers/autoCasterIsNumberCheck.ts","../../src/lib/casting/autoCast.ts","../../src/integrations/api/instance/database/getSearchByConditions.ts","../../src/integrations/api/instance/database/getSearchById.ts","../../src/integrations/api/instance/database/updateTableRecords.ts","../../src/features/instance/databases/components/ColumnFilters.tsx","../../src/features/instance/databases/components/PickColumnsDropdown.tsx","../../src/components/LoadingSubtle.tsx","../../src/features/instance/databases/components/TableView.tsx","../../src/features/instance/databases/components/DatabaseTableView.tsx","../../src/features/instance/databases/index.tsx","../../src/features/instance/databases/routes.ts","../../src/features/instance/InstanceNavBar.tsx","../../src/features/instance/applications/components/Chat/tools/collectFeedback/clientTool.ts","../../src/features/instance/applications/components/Chat/tools/createApp/clientTool.ts","../../src/features/instance/applications/components/Chat/tools/deleteTableRecords/clientTool.ts","../../src/features/instance/applications/components/Chat/tools/dropComponentFile/clientTool.ts","../../src/integrations/api/instance/status/getAnalytics.ts","../../src/features/instance/applications/components/Chat/tools/getAnalytics/clientTool.ts","../../src/features/instance/applications/components/Chat/tools/getComponentFile/clientTool.ts","../../src/features/instance/applications/components/Chat/tools/getComponents/clientTool.ts","../../src/features/instance/applications/components/Chat/tools/getDescribeAll/clientTool.ts","../../src/features/instance/applications/components/Chat/tools/getDescribeTable/clientTool.ts","../../src/features/instance/applications/components/Chat/tools/getUserContext/clientTool.ts","../../src/features/instance/applications/components/Chat/tools/insertTableRecords/clientTool.ts","../../src/features/instance/applications/components/Chat/tools/readHarperSkill/clientTool.ts","../../src/integrations/api/instance/status/getReadLog.ts","../../src/features/instance/applications/components/Chat/tools/readLogs/clientTool.ts","../../src/features/instance/applications/components/Chat/tools/readTableRecords/clientTool.ts","../../src/features/instance/applications/components/Chat/tools/restartHTTPService/clientTool.ts","../../src/features/instance/applications/components/Chat/tools/setComponentFile/clientTool.ts","../../src/features/instance/applications/components/Chat/tools/updateTableRecords/clientTool.ts","../../src/features/instance/InstanceLayout.tsx","../../src/features/instance/instanceLayoutRoute.ts","../../src/components/ui/toggleVariants.tsx","../../src/components/ui/toggle.tsx","../../src/components/ui/utils/badgeLogLevel.tsx","../../src/components/ui/utils/badgeNode.tsx","../../src/features/instance/log/LogsDataTable.tsx","../../src/features/instance/log/modals/ViewLogModal.tsx","../../src/integrations/api/instance/status/logFiltersFormSchema.ts","../../src/features/instance/log/components/LogsFiltersForm.tsx","../../src/features/instance/log/index.tsx","../../src/features/instance/log/routes.ts","../../src/features/instance/status/routes.ts","../../src/features/instance/routes.ts","../../src/features/profile/routes.ts","../../src/router/rootRouteTree.ts","../../src/router/useNewRouter.ts","../../src/AppRouted.tsx","../../src/components/ui/sonner.tsx","../../src/integrations/google/gtm.ts","../../src/App.tsx","../../src/main.tsx"],"sourcesContent":["export const forceBasicAuth = import.meta.env.VITE_FORCE_BASIC_AUTH === 'true';\nexport const isLocalStudio = import.meta.env.VITE_LOCAL_STUDIO === 'true';\nexport const localStudioDevUrl = import.meta.env.VITE_LOCAL_STUDIO_DEV_URL;\nexport const defaultOperationsApiPort = 9925;\nexport const defaultOperationsApiSecure = true;\nexport const defaultClusterUsername = 'HDB_ADMIN';\n\nexport const defaultInstanceRoute = '/';\nexport const defaultInstanceRouteUpOne = '../';\n\nexport const maxUploadFileSize = 1024 /* mb */ * 1024 /* kb */ * 1024 /* b */;\nexport const maxFabricConnectUploadFileSize = 100 /* mb */ * 1024 /* kb */ * 1024 /* b */;\n","import axios from 'axios';\nimport type { TypedAxios } from './typedAxios';\n\nexport const apiClient = axios.create({\n\twithCredentials: true,\n\tbaseURL: import.meta.env.VITE_CENTRAL_MANAGER_API_URL,\n\ttimeout: 15000,\n\theaders: {\n\t\t'Content-Type': 'application/json',\n\t},\n}) as TypedAxios;\n","export function pluralize(value: number | string, singular: string, plural: string): string {\n\tif (value === 1 || value === '1') {\n\t\treturn `${value} ${singular}`;\n\t}\n\treturn `${value} ${plural}`;\n}\n","import { pluralize } from '@/lib/pluralize';\nimport type { AxiosResponse } from 'axios';\n\nexport interface ReplicatedResponse {\n\tmessage: string;\n\treplicated?: Array<ReplicatedResponseSuccess | ReplicatedResponseFailure>;\n}\n\ninterface ReplicatedResponseNarrowed extends ReplicatedResponse {\n\treplicated: Array<ReplicatedResponseSuccess | ReplicatedResponseFailure>;\n}\n\nexport interface ReplicatedResponseSuccess {\n\tnode: string;\n\tmessage: boolean;\n\trequestId: number;\n}\n\nexport interface ReplicatedResponseFailure {\n\tnode: string;\n\treason: string;\n\tstatus: 'failed';\n}\n\nexport function replicationFailed(response: ReplicatedResponse): response is ReplicatedResponseNarrowed {\n\treturn response.replicated?.some(r => isReplicatedResponseFailure(r)) ?? false;\n}\n\nexport function isReplicatedResponseSuccess(\n\tmessage: ReplicatedResponseSuccess | ReplicatedResponseFailure,\n): message is ReplicatedResponseSuccess {\n\treturn (message as ReplicatedResponseFailure).status !== 'failed';\n}\n\nexport function isReplicatedResponseFailure(\n\tmessage: ReplicatedResponseSuccess | ReplicatedResponseFailure,\n): message is ReplicatedResponseFailure {\n\treturn (message as ReplicatedResponseFailure).status === 'failed';\n}\n\nexport function rejectReplicationFailures(response: Pick<AxiosResponse<ReplicatedResponse>, 'data'>) {\n\tif (replicationFailed(response.data)) {\n\t\tconst successes = response.data.replicated.filter(isReplicatedResponseSuccess);\n\t\tconst failures = response.data.replicated.filter(isReplicatedResponseFailure);\n\t\tconst explanation = successes.length\n\t\t\t? `The operation partially succeeded, but ${pluralize(failures.length, 'node', 'nodes')} failed:`\n\t\t\t: failures.length === 1\n\t\t\t? `The operation failed on the single node:`\n\t\t\t: `The operation failed on all ${failures.length} nodes:`;\n\t\tconst details = failures.map(f => `${f.node}: ${f.reason}`).join('\\n');\n\t\treturn Promise.reject(explanation + '\\n' + details);\n\t}\n\treturn response as AxiosResponse<ReplicatedResponse>;\n}\n","export function sleep(msToSleep: number = 1000) {\n\treturn new Promise((resolve) => {\n\t\tsetTimeout(() => {\n\t\t\tresolve(true);\n\t\t}, msToSleep);\n\t});\n}\n","import { sleep } from '@/lib/sleep';\nimport { AxiosInstance } from 'axios';\n\nexport function curryRetryGatewayErrors(client: Pick<AxiosInstance, 'request'>) {\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\treturn async (error: any) => {\n\t\tconst status = error?.response?.status as number | undefined;\n\t\tconst config = error?.config;\n\t\tif (!config) {\n\t\t\treturn Promise.reject(error);\n\t\t}\n\n\t\tconst shouldRetry = status === 502 || status === 503 || status === 504;\n\t\tif (!shouldRetry) {\n\t\t\treturn Promise.reject(error);\n\t\t}\n\n\t\tconst maxRetries = 3;\n\t\tconfig.__retryCount = config.__retryCount || 0;\n\t\tif (config.__retryCount >= maxRetries) {\n\t\t\treturn Promise.reject(error);\n\t\t}\n\n\t\tconfig.__retryCount += 1;\n\n\t\t// 1x, 2x, 4x\n\t\tconst retryPower = Math.pow(2, config.__retryCount - 1);\n\t\t// 5s, 10s, 20s\n\t\tconst delay = 5_000 * retryPower;\n\t\tawait sleep(delay);\n\n\t\treturn client.request(config);\n\t};\n}\n","import { apiClient } from '@/config/apiClient';\nimport { authStore, EntityIds, OverallAppSignIn } from '@/features/auth/store/authStore';\nimport { rejectReplicationFailures } from '@/integrations/api/replication';\nimport { curryRetryGatewayErrors } from '@/integrations/api/retryGatewayErrors';\nimport axios from 'axios';\n\ninterface InstanceClient {\n\tid?: EntityIds;\n\toperationsUrl?: string | null;\n\tport?: number;\n\tsecure?: boolean;\n}\n\nexport function getInstanceClient(\n\t{\n\t\tid = OverallAppSignIn,\n\t\toperationsUrl,\n\t\tport,\n\t\tsecure,\n\t\tforceFabricConnect,\n\t\tdisableFabricConnect,\n\t}: InstanceClient & {\n\t\tforceFabricConnect?: boolean;\n\t\tdisableFabricConnect?: boolean;\n\t} = {},\n) {\n\tlet baseURL = operationsUrl || authStore.getOperationsUrl(id);\n\tif (baseURL) {\n\t\tif (port || secure !== undefined) {\n\t\t\tconst newURL = new URL(baseURL);\n\t\t\tif (port) {\n\t\t\t\tnewURL.port = String(port);\n\t\t\t}\n\t\t\tif (secure !== undefined) {\n\t\t\t\tnewURL.protocol = secure ? 'https:' : 'http:';\n\t\t\t}\n\t\t\tbaseURL = newURL.toString();\n\t\t}\n\t}\n\n\tconst fabricConnect = !disableFabricConnect && (forceFabricConnect || authStore.checkForFabricConnect(id));\n\tif (fabricConnect) {\n\t\tif (id.startsWith('clu-')) {\n\t\t\tbaseURL = apiClient.defaults.baseURL + `/Cluster/${id}/operation`;\n\t\t} else if (id.startsWith('ins-')) {\n\t\t\tbaseURL = apiClient.defaults.baseURL + `/HDBInstance/${id}/operation`;\n\t\t}\n\t}\n\n\tconst basicAuth = authStore.checkForBasicAuth(id);\n\n\tconst client = axios.create({\n\t\tauth: fabricConnect ? undefined : basicAuth,\n\t\twithCredentials: fabricConnect || !basicAuth,\n\t\ttimeout: 15000,\n\t\theaders: {\n\t\t\t'Content-Type': 'application/json',\n\t\t},\n\t\tbaseURL,\n\t});\n\tclient.interceptors.response.use(\n\t\trejectReplicationFailures,\n\t\tcurryRetryGatewayErrors(client),\n\t);\n\treturn client;\n}\n","import { apiClient } from '@/config/apiClient';\nimport { User } from '@/integrations/api/api.patch';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport async function getCurrentUser(): Promise<User> {\n\tconst { data } = await apiClient.get('/User/current' as '/User/{id}');\n\t// TODO: The roles the API returns is a map instead of an array, so we have to map through unknown.\n\treturn data as unknown as User;\n}\n\nexport const currentUserQueryKey = ['current-user'];\n\nexport function getCurrentUserQueryOptions() {\n\treturn queryOptions({\n\t\tqueryKey: currentUserQueryKey,\n\t\tqueryFn: getCurrentUser,\n\t\tretry: false,\n\t});\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { authStore } from '@/features/auth/store/authStore';\n\ninterface LogoutInfoResponse {\n\tmessage: string;\n}\n\nexport async function onInstanceLogoutSubmit(\n\t{ instanceClient, entityId }: InstanceClientIdConfig,\n): Promise<LogoutInfoResponse> {\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation: 'logout',\n\t});\n\tauthStore.flagForBasicAuth(entityId, null);\n\tif (data) {\n\t\treturn data;\n\t} else {\n\t\tthrow new Error('Something went wrong');\n\t}\n}\n","import { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { LocalUser } from '@/integrations/api/api.patch';\nimport type { AxiosRequestConfig } from 'axios';\n\nexport async function getInstanceUserInfo({ instanceClient, ...config }: InstanceClientConfig & AxiosRequestConfig) {\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation: 'user_info',\n\t}, config);\n\treturn data as LocalUser;\n}\n","import { defaultOperationsApiPort, defaultOperationsApiSecure } from '@/config/constants';\nimport { Cluster } from '@/integrations/api/api.patch';\n\nexport function getOperationsUrlForCluster(cluster: undefined | Pick<Cluster, 'fqdn'>): string | null {\n\tlet fqdn = cluster?.fqdn;\n\tif (!fqdn) {\n\t\treturn null;\n\t}\n\tif (!fqdn.match(/^https?:\\/\\//i)) {\n\t\tfqdn = `https://${fqdn}`;\n\t}\n\tconst url = new URL(fqdn);\n\tif (!fqdn.match(/:\\d+/)) {\n\t\turl.port = String(defaultOperationsApiPort);\n\t}\n\tif (!fqdn.includes('://')) {\n\t\turl.protocol = defaultOperationsApiSecure ? 'https:' : 'http:';\n\t}\n\t// if (cluster.operationsApiPort) {\n\t// \turl.port = String(cluster.operationsApiPort);\n\t// }\n\t// if (cluster.operationsApiSecure !== undefined) {\n\t// \turl.protocol = cluster.operationsApiSecure ? 'https:' : 'http:';\n\t// }\n\treturn url.toString();\n}\n","import { Instance } from '@/integrations/api/api.patch';\n\nexport function getOperationsUrlForInstance(\n\tinstance: Pick<Instance, 'instanceFqdn' | 'operationsApiSecure' | 'operationsApiPort'>,\n): string {\n\tlet fqdn = instance.instanceFqdn;\n\tif (!fqdn.match(/^https?:\\/\\//i)) {\n\t\tfqdn = `https://${fqdn}`;\n\t}\n\tconst url = new URL(fqdn);\n\tif (instance.operationsApiPort) {\n\t\turl.port = String(instance.operationsApiPort);\n\t}\n\tif (instance.operationsApiSecure !== undefined) {\n\t\turl.protocol = instance.operationsApiSecure ? 'https:' : 'http:';\n\t}\n\treturn url.toString();\n}\n","import { isLocalStudio, localStudioDevUrl } from '@/config/constants';\nimport { getInstanceClient } from '@/config/getInstanceClient';\nimport { getCurrentUser } from '@/features/auth/queries/getCurrentUser';\nimport { SchemaCluster, SchemaHdbInstance } from '@/integrations/api/api.gen';\nimport { Cluster, Instance, LocalUser, User } from '@/integrations/api/api.patch';\nimport { onInstanceLogoutSubmit } from '@/integrations/api/instance/auth/onInstanceLogoutSubmit';\nimport { getInstanceUserInfo } from '@/integrations/api/instance/status/getInstanceUserInfo';\nimport { sleep } from '@/lib/sleep';\nimport { isCluster } from '@/lib/types/isCluster';\nimport { isInstance } from '@/lib/types/isInstance';\nimport { getOperationsUrlForCluster } from '@/lib/urls/getOperationsUrlForCluster';\nimport { getOperationsUrlForInstance } from '@/lib/urls/getOperationsUrlForInstance';\n\ntype AuthStoreListenerCleanup = () => void;\n\nexport type AuthenticatedConnectionKey =\n\t| OverallAppSignInType\n\t| Required<SchemaHdbInstance>['instanceFqdn']\n\t| Required<SchemaCluster>['fqdn'];\n\nexport interface AuthenticatedConnection {\n\tisLoading: boolean;\n\tuser: User | LocalUser | null;\n}\n\nexport interface AuthenticatedInstanceConnection {\n\tisLoading: boolean;\n\tuser: LocalUser | null;\n}\n\nexport interface AuthenticatedCloudConnection {\n\tisLoading: boolean;\n\tuser: User | null;\n}\n\nexport const OverallAppSignIn = 'OverallAppSignIn' as const;\ntype OverallAppSignInType = typeof OverallAppSignIn;\n\nexport type EntityIds = OverallAppSignInType | Instance['id'] | Cluster['id'];\ntype EntityTypes = OverallAppSignInType | Instance | Cluster | null;\n\nclass AuthStore {\n\tprivate readonly broadListeners: Array<(connection: AuthenticatedConnection, id: EntityIds) => void> = [];\n\tprivate readonly specificListeners: Record<\n\t\tEntityIds,\n\t\tArray<(connection: AuthenticatedConnection, id: EntityIds) => void>\n\t> = {};\n\n\tprivate readonly potentiallyAuthenticatedKey = 'Studio:PotentiallyAuthenticated';\n\tprivate readonly basicAuthKeyPrefix = 'Studio:BasicAuth:';\n\tprivate readonly fabricConnectKeyPrefix = 'Studio:FabricConnect:';\n\tprivate readonly potentiallyAuthenticated: Record<EntityIds, AuthenticatedConnectionKey>;\n\tprivate readonly checkedAuthentication: Record<EntityIds, boolean> = {};\n\tprivate readonly allConnections: Record<EntityIds, AuthenticatedConnection> = {};\n\n\tconstructor() {\n\t\tthis.potentiallyAuthenticated = JSON.parse(localStorage.getItem(this.potentiallyAuthenticatedKey) || '{}');\n\t}\n\n\tpublic getAllConnections(): Record<EntityIds, AuthenticatedConnection> {\n\t\tif (!this.potentiallyAuthenticated.OverallAppSignIn) {\n\t\t\tthis.allConnections[OverallAppSignIn] = {\n\t\t\t\tuser: null,\n\t\t\t\tisLoading: false,\n\t\t\t};\n\t\t}\n\t\treturn this.allConnections;\n\t}\n\n\tpublic getConnectionById(id: EntityIds): AuthenticatedConnection {\n\t\tif (!this.allConnections[id]) {\n\t\t\tthis.allConnections[id] = {\n\t\t\t\tuser: null,\n\t\t\t\tisLoading: !!this.potentiallyAuthenticated[id],\n\t\t\t};\n\t\t}\n\t\treturn this.allConnections[id];\n\t}\n\n\tpublic listenToAllEntities(\n\t\tlistener: (connection: AuthenticatedConnection, id: EntityIds) => void,\n\t): AuthStoreListenerCleanup | undefined {\n\t\tif (!this.broadListeners.includes(listener)) {\n\t\t\tthis.broadListeners.push(listener);\n\t\t}\n\t\tfor (const id in this.potentiallyAuthenticated) {\n\t\t\tvoid this.ensureUserIsLoaded(id);\n\t\t}\n\t\treturn () => {\n\t\t\tconst index = this.broadListeners.indexOf(listener);\n\t\t\tif (index >= 0) {\n\t\t\t\tthis.broadListeners.splice(index, 1);\n\t\t\t}\n\t\t};\n\t}\n\n\tpublic listenToEntity(\n\t\tid: EntityIds | null | undefined,\n\t\tlistener: (connection: AuthenticatedConnection) => void,\n\t): AuthStoreListenerCleanup | undefined {\n\t\tif (!id) {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (!this.specificListeners[id]) {\n\t\t\tthis.specificListeners[id] = [];\n\t\t}\n\t\tif (!this.specificListeners[id].includes(listener)) {\n\t\t\tthis.specificListeners[id].push(listener);\n\t\t}\n\t\tvoid this.ensureUserIsLoaded(id);\n\t\treturn () => {\n\t\t\tconst index = this.specificListeners[id].indexOf(listener);\n\t\t\tif (index >= 0) {\n\t\t\t\tthis.specificListeners[id].splice(index, 1);\n\t\t\t}\n\t\t};\n\t}\n\n\tpublic setUserForEntity(entity: EntityTypes, user: AuthenticatedConnection['user']): void {\n\t\tconst id = this.calculateIdFromEntity(entity);\n\t\tconst key = this.calculateKeyFromEntity(entity);\n\t\tif (!id || !key) {\n\t\t\treturn;\n\t\t}\n\t\treturn this.setUserForIdAndKey(id, key, user);\n\t}\n\n\tpublic setUserForIdAndKey(\n\t\tid: EntityIds,\n\t\tkey: AuthenticatedConnectionKey,\n\t\tuser: AuthenticatedConnection['user'],\n\t): void {\n\t\tif (user) {\n\t\t\tthis.flagKeyAsSignedIn(id, key);\n\t\t} else {\n\t\t\tthis.flagKeyAsSignedOut(id);\n\t\t}\n\t\tthis.updateConnectionIfChanged(id, false, user);\n\t}\n\n\tpublic updateUserForEntity(entity: EntityTypes, changes: Partial<AuthenticatedConnection['user']>): void {\n\t\tconst id = this.calculateIdFromEntity(entity);\n\t\tif (!id) {\n\t\t\treturn;\n\t\t}\n\t\tconst connection = this.getConnectionById(id);\n\t\tif (!connection.user) {\n\t\t\treturn;\n\t\t}\n\t\tthis.updateConnectionIfChanged(id, false, {\n\t\t\t...connection.user,\n\t\t\t...changes,\n\t\t});\n\t}\n\n\tpublic calculateIdFromEntity(entity: EntityTypes | EntityIds | undefined): EntityIds | undefined {\n\t\tif (isLocalStudio || entity === OverallAppSignIn) {\n\t\t\treturn OverallAppSignIn;\n\t\t}\n\t\tif (isInstance(entity)) {\n\t\t\treturn entity.id;\n\t\t}\n\t\tif (isCluster(entity)) {\n\t\t\treturn entity.id;\n\t\t}\n\t\tif (typeof entity === 'string') {\n\t\t\treturn entity;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tpublic flagForBasicAuth(id: EntityIds, credentials: null | { username: string; password: string }) {\n\t\tif (credentials !== null) {\n\t\t\tlocalStorage.setItem(this.basicAuthKeyPrefix + id, btoa(JSON.stringify(credentials)));\n\t\t} else {\n\t\t\tlocalStorage.removeItem(this.basicAuthKeyPrefix + id);\n\t\t}\n\t}\n\n\tpublic flagForFabricConnect(id: EntityIds, toggled: boolean) {\n\t\tif (toggled) {\n\t\t\tlocalStorage.setItem(this.fabricConnectKeyPrefix + id, 'true');\n\t\t} else {\n\t\t\tlocalStorage.removeItem(this.fabricConnectKeyPrefix + id);\n\t\t}\n\t}\n\n\tpublic checkForBasicAuth(id: EntityIds): undefined | { username: string; password: string } {\n\t\tconst value = localStorage.getItem(this.basicAuthKeyPrefix + id);\n\t\treturn value ? JSON.parse(atob(value)) : undefined;\n\t}\n\n\tpublic checkForFabricConnect(id: EntityIds): boolean {\n\t\treturn localStorage.getItem(this.fabricConnectKeyPrefix + id) === 'true';\n\t}\n\n\tpublic async signOutFromPotentiallyAuthenticatedInstances() {\n\t\tfor (const entityId in this.potentiallyAuthenticated) {\n\t\t\tthis.allConnections[entityId].user = null;\n\t\t\tthis.allConnections[entityId].isLoading = false;\n\t\t\tthis.flagKeyAsSignedOut(entityId);\n\t\t\tif (entityId === OverallAppSignIn) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst instanceClient = getInstanceClient({ id: entityId });\n\t\t\t\tawait onInstanceLogoutSubmit({ entityId, instanceClient });\n\t\t\t} catch (err: unknown) {\n\t\t\t\tconsole.error(`Failed to log out from ${entityId}, carrying on`, err);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate calculateKeyFromEntity(entity: EntityTypes): AuthenticatedConnectionKey | undefined {\n\t\tif (isLocalStudio || entity === OverallAppSignIn) {\n\t\t\treturn OverallAppSignIn;\n\t\t}\n\t\tif (isInstance(entity)) {\n\t\t\treturn getOperationsUrlForInstance(entity);\n\t\t}\n\t\tif (isCluster(entity)) {\n\t\t\treturn getOperationsUrlForCluster(entity) || undefined;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate updateConnectionIfChanged(id: EntityIds, isLoading: boolean, user: AuthenticatedConnection['user']) {\n\t\tthis.checkedAuthentication[id] = true;\n\t\tconst connection = this.getConnectionById(id);\n\t\tlet changes = false;\n\t\tif (connection.isLoading !== isLoading) {\n\t\t\tconnection.isLoading = isLoading;\n\t\t\tchanges = true;\n\t\t}\n\t\tif (connection.user !== user) {\n\t\t\tconnection.user = user;\n\t\t\tchanges = true;\n\t\t}\n\t\tif (changes) {\n\t\t\tvoid this.updateListeners(id);\n\t\t}\n\t}\n\n\tprivate flagKeyAsSignedIn(id: EntityIds, key: AuthenticatedConnectionKey) {\n\t\tif (this.potentiallyAuthenticated[id] !== key) {\n\t\t\tthis.potentiallyAuthenticated[id] = key;\n\t\t\tlocalStorage.setItem(this.potentiallyAuthenticatedKey, JSON.stringify(this.potentiallyAuthenticated));\n\t\t}\n\t}\n\n\tprivate flagKeyAsSignedOut(id: EntityIds) {\n\t\tif (this.potentiallyAuthenticated[id]) {\n\t\t\tdelete this.potentiallyAuthenticated[id];\n\t\t\tlocalStorage.setItem(this.potentiallyAuthenticatedKey, JSON.stringify(this.potentiallyAuthenticated));\n\t\t}\n\t}\n\n\tprivate async updateListeners(id: EntityIds): Promise<void> {\n\t\tawait sleep(1);\n\t\tif (this.broadListeners) {\n\t\t\tfor (const listener of this.broadListeners) {\n\t\t\t\tthis.updateListener(id, listener);\n\t\t\t}\n\t\t}\n\t\tif (this.specificListeners[id]) {\n\t\t\tfor (const listener of this.specificListeners[id]) {\n\t\t\t\tthis.updateListener(id, listener);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate updateListener(id: EntityIds, listener: (connection: AuthenticatedConnection, id: EntityIds) => void) {\n\t\tlistener(this.getConnectionById(id), id);\n\t}\n\n\tprivate async ensureUserIsLoaded(id: EntityIds): Promise<void> {\n\t\tif (this.checkedAuthentication[id]) {\n\t\t\treturn;\n\t\t}\n\t\tawait this.reloadUser(id);\n\t}\n\n\tpublic getOperationsUrl(id: EntityIds): string | undefined {\n\t\tif (isLocalStudio) {\n\t\t\treturn localStudioDevUrl;\n\t\t}\n\t\tif (id === OverallAppSignIn) {\n\t\t\treturn this.potentiallyAuthenticated[OverallAppSignIn];\n\t\t}\n\t\treturn this.potentiallyAuthenticated[id];\n\t}\n\n\tpublic async reloadUser(id: EntityIds): Promise<AuthenticatedConnection['user']> {\n\t\tif (!this.potentiallyAuthenticated[id]) {\n\t\t\tthis.updateConnectionIfChanged(id, false, null);\n\t\t\treturn null;\n\t\t}\n\t\treturn this.loadUser(id);\n\t}\n\n\tprivate async loadUser(id: EntityIds): Promise<AuthenticatedConnection['user']> {\n\t\tconst key = this.potentiallyAuthenticated[id];\n\t\tthis.updateConnectionIfChanged(id, true, null);\n\t\tlet user: AuthenticatedConnection['user'] = null;\n\t\ttry {\n\t\t\tif (id === OverallAppSignIn) {\n\t\t\t\tif (isLocalStudio) {\n\t\t\t\t\tuser = await getInstanceUserInfo({ instanceClient: getInstanceClient() });\n\t\t\t\t} else {\n\t\t\t\t\tuser = await getCurrentUser();\n\t\t\t\t}\n\t\t\t} else if (id) {\n\t\t\t\tuser = await getInstanceUserInfo({ instanceClient: getInstanceClient({ id }) });\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// TODO: Only catch the errors we expect here (401? 403? w/e)\n\t\t\tconsole.error(error);\n\t\t\tuser = null;\n\t\t}\n\t\tif (user) {\n\t\t\tthis.flagKeyAsSignedIn(id, key);\n\t\t} else {\n\t\t\tthis.flagKeyAsSignedOut(id);\n\t\t}\n\t\tthis.updateConnectionIfChanged(id, false, user);\n\t\treturn user;\n\t}\n}\n\nexport const authStore = new AuthStore();\n","import { isLocalStudio } from '@/config/constants';\nimport {\n\tAuthenticatedCloudConnection,\n\tAuthenticatedConnection,\n\tAuthenticatedInstanceConnection,\n\tauthStore,\n\tEntityIds,\n\tOverallAppSignIn,\n} from '@/features/auth/store/authStore';\nimport { useParams } from '@tanstack/react-router';\nimport { useEffect, useState } from 'react';\n\nexport function useRootAuthenticationContext(): Record<EntityIds, AuthenticatedConnection> {\n\tconst [connections, setConnections] = useState(authStore.getAllConnections());\n\tuseEffect(() =>\n\t\tauthStore.listenToAllEntities((connection, id) => {\n\t\t\tsetConnections({ ...connections, [id]: connection });\n\t\t}), [connections]);\n\treturn connections;\n}\n\nexport function useOverallAuth(): AuthenticatedConnection {\n\tconst id = authStore.calculateIdFromEntity(OverallAppSignIn);\n\tconst [connection, setConnection] = useState<AuthenticatedConnection>(authStore.getConnectionById(OverallAppSignIn));\n\tuseEffect(() => authStore.listenToEntity(id, setConnection), [id]);\n\treturn connection;\n}\n\nexport function useCloudAuth(): AuthenticatedCloudConnection {\n\treturn useOverallAuth() as AuthenticatedCloudConnection;\n}\n\nexport function useAdminMode(): boolean {\n\tconst { user } = useCloudAuth();\n\treturn user?.fabricRole === 'fabric_admin' || user?.fabricRole === 'super_user';\n}\n\nexport function useInstanceAuth(entityId?: EntityIds): AuthenticatedInstanceConnection {\n\tconst key = isLocalStudio ? OverallAppSignIn : entityId;\n\tconst { clusterId, instanceId }: { instanceId?: string; clusterId: string } = useParams({ strict: false });\n\tconst [connection, setConnection] = useState<AuthenticatedConnection>(\n\t\tauthStore.getConnectionById(key ?? instanceId ?? clusterId),\n\t);\n\tuseEffect(() => authStore.listenToEntity(key, setConnection), [key]);\n\treturn connection as AuthenticatedInstanceConnection;\n}\n","import { cva } from 'class-variance-authority';\n\nconst hoverBounce = 'hover:-translate-y-1 transition duration-200';\nconst outlineCommon = 'border bg-transparent border-2 text-white shadow-xs hover:bg-grey-700/40';\nexport const buttonVariants = cva(\n\t`inline-flex\n items-center\n justify-center\n gap-2\n whitespace-nowrap\n rounded-lg\n text-sm\n transition-[color,box-shadow]\n disabled:pointer-events-none\n disabled:opacity-50\n [&_svg]:pointer-events-none\n [&_svg:not([class*='size-'])]:size-4\n [&_svg]:shrink-0\n ring-ring/10\n dark:ring-ring/20\n dark:outline-ring/40\n outline-ring/50\n focus-visible:ring-1\n focus-visible:outline-1\n focus-visible:ring-purple-200\n aria-invalid:focus-visible:ring-0`,\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: 'bg-primary text-primary-foreground shadow-sm hover:bg-primary/90',\n\t\t\t\tsubmit:\n\t\t\t\t\t'bg-gradient-to-r from-blue-100 from-0% to-blue to-100% hover:bg-gradient-to-r hover:from-blue text-primary-foreground shadow-sm',\n\t\t\t\tdestructive: 'bg-destructive shadow-xs hover:bg-destructive/90',\n\t\t\t\tsecondary: 'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',\n\t\t\t\tghost: 'hover:bg-accent hover:text-muted-foreground',\n\t\t\t\tdestructiveGhost: 'hover:bg-accent hover:text-red',\n\t\t\t\tlink: 'text-primary underline-offset-4 hover:underline',\n\t\t\t\tpositive: 'bg-green text-white shadow-xs hover:bg-green/90',\n\t\t\t\twarning: 'bg-yellow text-white shadow-xs hover:bg-yellow/90',\n\t\t\t\toutline: `${outlineCommon} ${hoverBounce}`,\n\t\t\t\tghostOutline: `${outlineCommon} ${hoverBounce} border-none`,\n\t\t\t\tpositiveOutline: `${outlineCommon} ${hoverBounce} border-green`,\n\t\t\t\tdestructiveOutline: `${outlineCommon} ${hoverBounce} border-destructive`,\n\t\t\t\tdefaultOutline: `${outlineCommon} ${hoverBounce} border-primary`,\n\t\t\t},\n\t\t\tsize: {\n\t\t\t\tdefault: 'h-9 px-4 py-2 has-[>svg]:px-3',\n\t\t\t\tsm: 'h-8 rounded-md px-3 has-[>svg]:px-2.5',\n\t\t\t\tlg: 'h-10 rounded-md px-6 has-[>svg]:px-4 text-md',\n\t\t\t\ticon: 'size-9',\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tvariant: 'default',\n\t\t\tsize: 'default',\n\t\t},\n\t},\n);\n","import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","import { buttonVariants } from '@/components/ui/buttonVariants';\nimport { cn } from '@/lib/cn';\nimport { Slot } from '@radix-ui/react-slot';\nimport { type VariantProps } from 'class-variance-authority';\nimport * as React from 'react';\n\nexport function Button({\n\tclassName,\n\tvariant,\n\tsize,\n\tasChild = false,\n\t...props\n}:\n\t& React.ComponentProps<'button'>\n\t& VariantProps<typeof buttonVariants>\n\t& {\n\t\tasChild?: boolean;\n\t})\n{\n\tconst Comp = asChild ? Slot : 'button';\n\n\treturn <Comp data-slot=\"button\" className={cn(buttonVariants({ variant, size, className }))} {...props} />;\n}\n","import * as React from 'react';\n\nimport { cn } from '@/lib/cn';\n\nfunction Card({ className, ...props }: React.ComponentProps<'div'>) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"card\"\n\t\t\tclassName={cn('bg-card text-card-foreground flex flex-col gap-6 rounded-xl py-4 shadow-deep', className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<'div'>) {\n\treturn <div data-slot=\"card-header\" className={cn('flex flex-col gap-1.5 px-6', className)} {...props} />;\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<'div'>) {\n\treturn <div data-slot=\"card-title\" className={cn('leading-none text-lg', className)} {...props} />;\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<'div'>) {\n\treturn <div data-slot=\"card-description\" className={cn('text-muted-foreground text-xs', className)} {...props} />;\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<'div'>) {\n\treturn <div data-slot=\"card-content\" className={cn('px-6', className)} {...props} />;\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<'div'>) {\n\treturn <div data-slot=\"card-footer\" className={cn('flex items-center px-6', className)} {...props} />;\n}\n\nexport { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle };\n","import { LocalUser, User } from '@/integrations/api/api.patch';\n\nexport function isLocalUser(user: User | LocalUser | null): user is LocalUser {\n\treturn user !== null && !!(user as LocalUser).username;\n}\n","import { LocalUser, User } from '@/integrations/api/api.patch';\nimport { isLocalUser } from '@/lib/types/isLocalUser';\n\nexport function getDefaultSignedInCloudRouteForUser(user: User | LocalUser | null): string {\n\tif (user && !isLocalUser(user)) {\n\t\tconst orgIds = Object.keys(user.roles);\n\t\tif (orgIds.length === 1) {\n\t\t\treturn `/${orgIds[0]}`;\n\t\t}\n\t}\n\treturn '/';\n}\n","import { Button } from '@/components/ui/button';\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';\nimport { defaultInstanceRoute, isLocalStudio } from '@/config/constants';\nimport { useOverallAuth } from '@/hooks/useAuth';\nimport { cn } from '@/lib/cn';\nimport { getDefaultSignedInCloudRouteForUser } from '@/lib/urls/getDefaultSignedInCloudRouteForUser';\nimport { Link } from '@tanstack/react-router';\nimport { ArrowLeft } from 'lucide-react';\nimport { ReactNode } from 'react';\n\ninterface ErrorProps {\n\tclassName?: string | undefined;\n\terror: Error | { message: string | ReactNode };\n\ttitle?: string;\n\tshowReturnToHome?: boolean;\n\tchildren?: ReactNode;\n}\n\nexport function ErrorComponent({ className, error, title, showReturnToHome, children }: ErrorProps) {\n\tconst { user, isLoading: isUserLoading } = useOverallAuth();\n\tconst defaultCloudRoute = getDefaultSignedInCloudRouteForUser(user);\n\n\treturn (\n\t\t<Card className={cn('text-red p-5 border border-red rounded-md m-12 mt-36', className)}>\n\t\t\t<CardHeader>\n\t\t\t\t<CardTitle className=\"text-2xl\">\n\t\t\t\t\t<h2>{title ?? 'Component Error'}</h2>\n\t\t\t\t</CardTitle>\n\t\t\t\t<CardDescription>{error.message}</CardDescription>\n\t\t\t</CardHeader>\n\t\t\t<CardContent>\n\t\t\t\t{children}\n\t\t\t\t{showReturnToHome !== false && (user && !isUserLoading\n\t\t\t\t\t? (\n\t\t\t\t\t\t<Link to={isLocalStudio ? defaultInstanceRoute : defaultCloudRoute}>\n\t\t\t\t\t\t\t<Button>\n\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t<ArrowLeft /> Return to Home\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t)\n\t\t\t\t\t: (\n\t\t\t\t\t\t<Link to=\"/sign-in\">\n\t\t\t\t\t\t\t<Button>\n\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t<ArrowLeft /> Go to Sign In Page\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t))}\n\t\t\t</CardContent>\n\t\t</Card>\n\t);\n}\n","import { Button } from '@/components/ui/button';\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';\nimport { defaultInstanceRoute, isLocalStudio } from '@/config/constants';\nimport { useOverallAuth } from '@/hooks/useAuth';\nimport { getDefaultSignedInCloudRouteForUser } from '@/lib/urls/getDefaultSignedInCloudRouteForUser';\nimport { Link } from '@tanstack/react-router';\nimport { ArrowLeft } from 'lucide-react';\n\nexport function NotFoundComponent() {\n\tconst { user, isLoading: isUserLoading } = useOverallAuth();\n\tconst defaultCloudRoute = getDefaultSignedInCloudRouteForUser(user);\n\treturn (\n\t\t<div className=\"flex items-center justify-center h-screen px-3\">\n\t\t\t<Card className=\"text-red p-5 border border-red rounded-md w-full max-w-md\">\n\t\t\t\t<CardHeader>\n\t\t\t\t\t<CardTitle className=\"text-2xl\">\n\t\t\t\t\t\t<h2>Sorry, Page Not Found</h2>\n\t\t\t\t\t</CardTitle>\n\t\t\t\t</CardHeader>\n\t\t\t\t<CardContent>\n\t\t\t\t\t{user && !isUserLoading\n\t\t\t\t\t\t? (\n\t\t\t\t\t\t\t<Link to={isLocalStudio ? defaultInstanceRoute : defaultCloudRoute}>\n\t\t\t\t\t\t\t\t<Button>\n\t\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t\t<ArrowLeft /> Return to Home\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t)\n\t\t\t\t\t\t: (\n\t\t\t\t\t\t\t<Link to=\"/sign-in\">\n\t\t\t\t\t\t\t\t<Button>\n\t\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t\t<ArrowLeft /> Go Sign In Page\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t)}\n\t\t\t\t</CardContent>\n\t\t\t</Card>\n\t\t</div>\n\t);\n}\n","export function browserIsTouchBased(): boolean {\n\treturn 'ontouchstart' in window || navigator['maxTouchPoints'] > 0;\n}\n","import { MutationCache, QueryCache, QueryClient } from '@tanstack/react-query';\nimport { AxiosError } from 'axios';\nimport { toast } from 'sonner';\n\nexport function errorHandler(rawErr: unknown) {\n\tlet errorTitle = 'Error';\n\tlet errorMsg = 'We had some trouble!';\n\tconsole.error(rawErr);\n\tconst axiosWrappedErr = rawErr as AxiosError<string | { error?: string; message?: string }>;\n\tconst otherErr = rawErr as { message?: string };\n\tif (typeof rawErr === 'string') {\n\t\terrorMsg = rawErr;\n\t} else if (axiosWrappedErr?.response?.data) {\n\t\tif (typeof axiosWrappedErr.response.data === 'string') {\n\t\t\terrorMsg = axiosWrappedErr.response.data;\n\t\t} else if (axiosWrappedErr.response.data.error) {\n\t\t\terrorMsg = axiosWrappedErr.response.data.error;\n\t\t} else if (axiosWrappedErr.response.data.message) {\n\t\t\terrorMsg = axiosWrappedErr.response.data.message;\n\t\t}\n\t} else if (otherErr?.message) {\n\t\terrorMsg = otherErr.message;\n\t}\n\tif (errorMsg.includes(':')) {\n\t\tconst split = errorMsg.split(':');\n\t\terrorTitle = split.shift()!;\n\t\terrorMsg = split.join(':');\n\t}\n\ttoast.error(errorTitle, {\n\t\tdescription: errorMsg,\n\t\taction: {\n\t\t\tlabel: 'Dismiss',\n\t\t\tonClick: () => toast.dismiss(),\n\t\t},\n\t});\n}\n\nexport const queryClient = new QueryClient({\n\tqueryCache: new QueryCache({\n\t\tonError: errorHandler,\n\t}),\n\tmutationCache: new MutationCache({\n\t\tonError: errorHandler,\n\t}),\n});\n","export function excludeFalsy<T>(item: T | undefined | 0 | false | null): item is T {\n\treturn !!item;\n}\n","import { isLocalStudio } from '@/config/constants';\nimport { useOverallAuth } from '@/hooks/useAuth';\nimport { translateUrlForDatadog } from '@/integrations/datadog/translateUrlForDatadog';\nimport { excludeFalsy } from '@/lib/arrays/excludeFalsy';\nimport { isLocalUser } from '@/lib/types/isLocalUser';\nimport { datadogRum } from '@datadog/browser-rum';\nimport { reactPlugin } from '@datadog/browser-rum-react';\nimport { useLocation, useRouter } from '@tanstack/react-router';\nimport { useEffect } from 'react';\n\nlet initialized = false;\nconst enabled = !import.meta.env.DEV && !isLocalStudio;\n\nexport function useDatadog() {\n\tuseEffect(() => {\n\t\tif (initialized) {\n\t\t\treturn;\n\t\t}\n\t\tinitialized = true;\n\t\tif (enabled) {\n\t\t\tdatadogRum.init({\n\t\t\t\tapplicationId: 'f590deee-4bac-49b4-a202-3b6963d9721d',\n\t\t\t\tclientToken: 'pub27aa29cea521492f4fef73032f86a023',\n\n\t\t\t\t// proxy: ({ path, parameters }) => `/Drink/?pour=${btoa(`${path}?${parameters}`)}`,\n\n\t\t\t\tsite: 'datadoghq.com',\n\t\t\t\tservice: 'studio',\n\t\t\t\tenv: import.meta.env.VITE_ENV_NAME,\n\t\t\t\tversion: import.meta.env.VITE_STUDIO_VERSION,\n\n\t\t\t\ttrackViewsManually: true,\n\t\t\t\ttrackUserInteractions: true,\n\n\t\t\t\tsessionSampleRate: 100,\n\t\t\t\tsessionReplaySampleRate: 0,\n\t\t\t\tdefaultPrivacyLevel: 'mask',\n\n\t\t\t\tplugins: [reactPlugin()],\n\t\t\t});\n\n\t\t\tdatadogRum.onReady(() => {\n\t\t\t\tdatadogRum.startView({\n\t\t\t\t\tservice: 'studio',\n\t\t\t\t\tversion: import.meta.env.VITE_STUDIO_VERSION,\n\t\t\t\t\tname: window.location.pathname || 'initial',\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t}, []);\n}\n\nexport function useOnRouteLoadTracker() {\n\tconst location = useLocation();\n\tconst router = useRouter();\n\tconst { user } = useOverallAuth();\n\n\tuseEffect(() => {\n\t\tconst currentMatches = router.matchRoutes(router.state.location);\n\t\tconst name = translateUrlForDatadog(\n\t\t\tlocation.href,\n\t\t\tcurrentMatches.map((m) => m.params),\n\t\t);\n\t\tif (!enabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tdatadogRum.onReady(() => {\n\t\t\tdatadogRum.startView({\n\t\t\t\tservice: 'studio',\n\t\t\t\tversion: import.meta.env.VITE_STUDIO_VERSION,\n\t\t\t\tname,\n\t\t\t});\n\t\t});\n\t}, [location.href, router]);\n\n\tuseEffect(() => {\n\t\tif (!enabled) {\n\t\t\treturn;\n\t\t}\n\t\tif (user && !isLocalUser(user)) {\n\t\t\tdatadogRum.setUser({\n\t\t\t\tid: user.id,\n\t\t\t\tname: [user.firstname, user.lastname].filter(excludeFalsy).join(' ') || undefined,\n\t\t\t\temail: user.email,\n\t\t\t});\n\t\t} else {\n\t\t\tdatadogRum.clearUser();\n\t\t}\n\t}, [user]);\n}\n\nexport function loginSuccessDatadogAction(data: { id: string; email: string; firstname: string; lastname: string }) {\n\tif (!enabled) { return; }\n\n\tdatadogRum.setUser({\n\t\tid: data.id,\n\t\temail: data.email,\n\t\tname: [data.firstname, data.lastname].filter(Boolean).join(' ') || undefined,\n\t});\n\n\t// First vs return login (per user)\n\tconst hasLoggedInKey = `hasLoggedInBefore:${data.id}`;\n\tconst hasLoggedInBefore = !!localStorage.getItem(hasLoggedInKey);\n\n\tif (hasLoggedInBefore) {\n\t\tdatadogRum.addAction('return_login');\n\t} else {\n\t\tdatadogRum.addAction('first_time_login');\n\t\tlocalStorage.setItem(hasLoggedInKey, 'true');\n\t}\n\n\t// Time between logins (per user)\n\tconst lastLoginKey = `lastLoginTimestamp:${data.id}`;\n\tconst lastLogin = localStorage.getItem(lastLoginKey);\n\tconst now = Date.now();\n\n\tif (lastLogin) {\n\t\tconst seconds = Math.floor((now - Number(lastLogin)) / 1000);\n\t\tif (!Number.isNaN(seconds) && seconds >= 0) {\n\t\t\tdatadogRum.addAction('login_time_gap', { value: seconds });\n\t\t}\n\t}\n\n\tlocalStorage.setItem(lastLoginKey, String(now));\n\n\tdatadogRum.addAction('login_success', { userId: data.id });\n}\n","import { Outlet } from '@tanstack/react-router';\n\nexport function StudioLocal() {\n\treturn (\n\t\t<>\n\t\t\t<Outlet />\n\t\t</>\n\t);\n}\n","import { StudioCloud } from '@/components/StudioCloud';\nimport { StudioLocal } from '@/components/StudioLocal';\nimport { isLocalStudio } from '@/config/constants';\nimport { AuthenticatedConnection, EntityIds } from '@/features/auth/store/authStore';\nimport { QueryClient } from '@tanstack/react-query';\nimport { createRootRouteWithContext } from '@tanstack/react-router';\n\nexport const rootRoute = createRootRouteWithContext<{\n\tqueryClient: QueryClient;\n\tauthentication: Record<EntityIds, AuthenticatedConnection>;\n}>()({\n\tcomponent: isLocalStudio ? StudioLocal : StudioCloud,\n});\n","export function DiscordLogo() {\n\treturn (\n\t\t<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 126.644 96\" width={24} height={24}>\n\t\t\t<path\n\t\t\t\tfill=\"currentColor\"\n\t\t\t\td=\"M81.15,0c-1.2376,2.1973-2.3489,4.4704-3.3591,6.794-9.5975-1.4396-19.3718-1.4396-28.9945,0-.985-2.3236-2.1216-4.5967-3.3591-6.794-9.0166,1.5407-17.8059,4.2431-26.1405,8.0568C2.779,32.5304-1.6914,56.3725.5312,79.8863c9.6732,7.1476,20.5083,12.603,32.0505,16.0884,2.6014-3.4854,4.8998-7.1981,6.8698-11.0623-3.738-1.3891-7.3497-3.1318-10.8098-5.1523.9092-.6567,1.7932-1.3386,2.6519-1.9953,20.281,9.547,43.7696,9.547,64.0758,0,.8587.7072,1.7427,1.3891,2.6519,1.9953-3.4601,2.0457-7.0718,3.7632-10.835,5.1776,1.97,3.8642,4.2683,7.5769,6.8698,11.0623,11.5419-3.4854,22.3769-8.9156,32.0509-16.0631,2.626-27.2771-4.496-50.9172-18.817-71.8548C98.9811,4.2684,90.1918,1.5659,81.1752.0505l-.0252-.0505ZM42.2802,65.4144c-6.2383,0-11.4159-5.6575-11.4159-12.6535s4.9755-12.6788,11.3907-12.6788,11.5169,5.708,11.4159,12.6788c-.101,6.9708-5.026,12.6535-11.3907,12.6535ZM84.3576,65.4144c-6.2637,0-11.3907-5.6575-11.3907-12.6535s4.9755-12.6788,11.3907-12.6788,11.4917,5.708,11.3906,12.6788c-.101,6.9708-5.026,12.6535-11.3906,12.6535Z\"\n\t\t\t/>\n\t\t</svg>\n\t);\n}\n","import { isLocalStudio } from '@/config/constants';\n\nexport function MainLogo() {\n\treturn (\n\t\t<>\n\t\t\t{isLocalStudio\n\t\t\t\t? <img src=\"/harper-studio_white.png\" alt=\"Harper Studio\" className=\"w-64 hidden md:inline-block\" />\n\t\t\t\t: <img src=\"/harper-fabric_white.png\" alt=\"Harper Fabric\" className=\"w-64 hidden md:inline-block\" />}\n\t\t\t<img src=\"/HDBDogOnly.svg\" width=\"50px\" height=\"44px\" alt=\"Harper\" className=\"inline-block md:hidden\" />\n\t\t</>\n\t);\n}\n","import { cn } from '@/lib/cn';\nimport * as NavigationMenuPrimitive from '@radix-ui/react-navigation-menu';\nimport * as React from 'react';\n\nexport function NavigationMenuViewport({\n\tclassName,\n\t...props\n}: React.ComponentProps<typeof NavigationMenuPrimitive.Viewport>) {\n\treturn (\n\t\t<div className={cn('absolute top-full left-0 isolate z-50 flex justify-center')}>\n\t\t\t<NavigationMenuPrimitive.Viewport\n\t\t\t\tdata-slot=\"navigation-menu-viewport\"\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'origin-top-center bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border shadow md:w-[var(--radix-navigation-menu-viewport-width)]',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n","import { NavigationMenuViewport } from '@/components/ui/navigation/NavigationMenuViewport';\nimport { cn } from '@/lib/cn';\nimport * as NavigationMenuPrimitive from '@radix-ui/react-navigation-menu';\nimport * as React from 'react';\n\nexport function NavigationMenu({\n\tclassName,\n\tchildren,\n\tviewport = true,\n\t...props\n}: React.ComponentProps<typeof NavigationMenuPrimitive.Root> & {\n\tviewport?: boolean;\n}) {\n\treturn (\n\t\t<NavigationMenuPrimitive.Root\n\t\t\tdata-slot=\"navigation-menu\"\n\t\t\tdata-viewport={viewport}\n\t\t\tclassName={cn('group/navigation-menu relative flex max-w-max flex-1 items-center justify-center', className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t\t{viewport && <NavigationMenuViewport />}\n\t\t</NavigationMenuPrimitive.Root>\n\t);\n}\n","import { cn } from '@/lib/cn';\nimport * as NavigationMenuPrimitive from '@radix-ui/react-navigation-menu';\nimport * as React from 'react';\n\nexport function NavigationMenuItem({ className, ...props }: React.ComponentProps<typeof NavigationMenuPrimitive.Item>) {\n\treturn (\n\t\t<NavigationMenuPrimitive.Item data-slot=\"navigation-menu-item\" className={cn('relative', className)} {...props} />\n\t);\n}\n","import { cn } from '@/lib/cn';\nimport * as NavigationMenuPrimitive from '@radix-ui/react-navigation-menu';\nimport * as React from 'react';\n\nexport function NavigationMenuLink({ className, ...props }: React.ComponentProps<typeof NavigationMenuPrimitive.Link>) {\n\treturn (\n\t\t<NavigationMenuPrimitive.Link\n\t\t\tdata-slot=\"navigation-menu-link\"\n\t\t\tclassName={cn(\n\t\t\t\t\"hover:text-white ring-ring/10 dark:ring-ring/20 dark:outline-ring/40 outline-ring/50 flex flex-col gap-1 rounded-sm p-2 text-sm transition-[color,box-shadow] focus-visible:ring-4 focus-visible:outline-1 [&_svg:not([class*='size-'])]:size-4\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n","import { cn } from '@/lib/cn';\nimport * as NavigationMenuPrimitive from '@radix-ui/react-navigation-menu';\nimport * as React from 'react';\n\nexport function NavigationMenuList({ className, ...props }: React.ComponentProps<typeof NavigationMenuPrimitive.List>) {\n\treturn (\n\t\t<NavigationMenuPrimitive.List\n\t\t\tdata-slot=\"navigation-menu-list\"\n\t\t\tclassName={cn('group flex flex-1 list-none items-center justify-center gap-1', className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n","import { cva } from 'class-variance-authority';\n\nexport const badgeVariants = cva(\n\t'inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-auto',\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: 'border-primary bg-primary/40 text-primary-foreground [a&]:hover:bg-primary/90',\n\t\t\t\tsecondary: 'border-secondary bg-secondary/40 text-secondary-foreground [a&]:hover:bg-secondary/90',\n\t\t\t\twarning: 'border-yellow bg-yellow/40 text-white [a&]:hover:bg-yellow/90',\n\t\t\t\tsuccess: 'border-green bg-green/40 text-white [a&]:hover:bg-green/90',\n\t\t\t\tdestructive:\n\t\t\t\t\t'border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40',\n\t\t\t\toutline: 'text-white [a&]:hover:bg-accent [a&]:hover:text-accent-foreground',\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tvariant: 'default',\n\t\t},\n\t},\n);\n","import { badgeVariants } from '@/components/ui/badgeVariants';\nimport { cn } from '@/lib/cn';\n\nexport function Version() {\n\tlet studioVersion = import.meta.env.VITE_STUDIO_VERSION;\n\tconst link = studioVersion?.startsWith('v')\n\t\t? `https://github.com/HarperFast/studio/releases/tag/${studioVersion}`\n\t\t: 'https://github.com/HarperFast/studio/releases';\n\treturn (\n\t\t<a href={link} target=\"_blank\" rel=\"noopener noreferrer\">\n\t\t\t<span className={cn(badgeVariants({ variant: 'default' }), 'text-xs inline-block ml-2 align-text-top')}>\n\t\t\t\t{studioVersion} BETA\n\t\t\t</span>\n\t\t</a>\n\t);\n}\n","import { isLocalStudio } from '@/config/constants';\nimport { getInstanceClient } from '@/config/getInstanceClient';\nimport { InstanceClientConfig, InstanceClientIdConfig, InstanceTypeConfig } from '@/config/instanceClientConfig';\nimport { OverallAppSignIn } from '@/features/auth/store/authStore';\nimport { useParams } from '@tanstack/react-router';\nimport { useMemo } from 'react';\n\ninterface UseParams {\n\tclusterId?: string;\n\tdisableFabricConnect?: boolean;\n\tforceFabricConnect?: boolean;\n\tinstanceId?: string;\n\toperationsUrl?: string | null;\n\tport?: number;\n\tsecure?: boolean;\n}\n\nexport function useInstanceClient(\n\tparams: UseParams = {},\n) {\n\tconst { instanceId, clusterId }: { instanceId?: string; clusterId?: string } = useParams({ strict: false });\n\tconst id = isLocalStudio ? OverallAppSignIn : params.instanceId ?? instanceId ?? params.clusterId ?? clusterId;\n\treturn getInstanceClient({ id, ...params });\n}\n\nexport function useInstanceClientParams(\n\tparams: UseParams = {},\n): InstanceClientConfig & InstanceTypeConfig {\n\tconst { instanceId, clusterId }: { instanceId?: string; clusterId?: string } = useParams({ strict: false });\n\tconst id = isLocalStudio ? OverallAppSignIn : params.instanceId ?? instanceId ?? params.clusterId ?? clusterId;\n\treturn {\n\t\tinstanceClient: getInstanceClient({ id, ...params }),\n\t\tentityType: (isLocalStudio || instanceId) ? 'instance' : 'cluster',\n\t};\n}\n\nexport function useInstanceClientIdParams(\n\tparams: UseParams = {},\n): InstanceClientIdConfig & InstanceTypeConfig {\n\tconst { instanceId, clusterId }: { instanceId?: string; clusterId?: string } = useParams({ strict: false });\n\treturn useMemo(\n\t\t() => getInstanceClientIdFromParams({ instanceId, clusterId, ...params }),\n\t\t[\n\t\t\tparams.instanceId ?? instanceId,\n\t\t\tparams.clusterId ?? clusterId,\n\t\t\tparams.operationsUrl,\n\t\t\tparams.port,\n\t\t\tparams.secure,\n\t\t\tparams.disableFabricConnect,\n\t\t\tparams.forceFabricConnect,\n\t\t],\n\t);\n}\n\nexport function getInstanceClientIdFromParams({\n\tinstanceId,\n\tclusterId,\n\t...params\n}: UseParams): InstanceClientIdConfig & InstanceTypeConfig {\n\tconst id = isLocalStudio ? OverallAppSignIn : instanceId ?? clusterId;\n\tif (!id) {\n\t\tthrow new Error('id could not be automatically calculated in useInstanceClientIdParams');\n\t}\n\treturn {\n\t\tinstanceClient: getInstanceClient({ id, ...params }),\n\t\tentityId: id,\n\t\tentityType: (isLocalStudio || instanceId) ? 'instance' : 'cluster',\n\t};\n}\n","export function clearLocalStorage(): void {\n\tlocalStorage.clear();\n}\n","export function clearSessionStorage(): void {\n\tsessionStorage.clear();\n}\n","import { authStore, OverallAppSignIn } from '@/features/auth/store/authStore';\nimport { clearLocalStorage } from '@/lib/storage/clearLocalStorage';\nimport { clearSessionStorage } from '@/lib/storage/clearSessionStorage';\nimport { queryClient } from '@/react-query/queryClient';\n\nexport async function logoutOnSuccess() {\n\tauthStore.setUserForEntity(OverallAppSignIn, null);\n\tqueryClient.getQueryCache().clear();\n\tclearLocalStorage();\n\tclearSessionStorage();\n\tawait queryClient.invalidateQueries({ refetchType: 'none' });\n}\n","import { apiClient } from '@/config/apiClient';\nimport { isLocalStudio } from '@/config/constants';\nimport { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { useInstanceClient } from '@/config/useInstanceClient';\nimport { logoutOnSuccess } from '@/features/auth/handlers/logoutOnSuccess';\nimport { authStore, OverallAppSignIn } from '@/features/auth/store/authStore';\nimport { onInstanceLogoutSubmit } from '@/integrations/api/instance/auth/onInstanceLogoutSubmit';\nimport { useMutation } from '@tanstack/react-query';\n\nasync function onLogoutSubmit(instanceClientConfig: InstanceClientConfig) {\n\tawait authStore.signOutFromPotentiallyAuthenticatedInstances();\n\tif (isLocalStudio) {\n\t\tawait onInstanceLogoutSubmit({ ...instanceClientConfig, entityId: OverallAppSignIn });\n\t} else {\n\t\tawait apiClient.post('/Logout/');\n\t}\n}\n\nexport function useLogoutMutation() {\n\tconst instanceClient = useInstanceClient();\n\treturn useMutation({\n\t\tmutationFn: () => onLogoutSubmit({ instanceClient }),\n\t\tonSuccess: logoutOnSuccess,\n\t});\n}\n","import { EntityIds } from '@/features/auth/store/authStore';\nimport { useCloudAuth, useInstanceAuth } from '@/hooks/useAuth';\nimport {\n\tLocalLegacyRolePermissionTable,\n\tLocalRoleAttributePermissionAction,\n\tLocalRolePermissionAction,\n\tLocalRolePermissionTable,\n\tUser,\n} from '@/integrations/api/api.patch';\nimport { useParams } from '@tanstack/react-router';\n\ninterface UR {\n\tupdate: boolean;\n\tremove: boolean;\n}\n\ninterface CRUV {\n\tcreate: boolean;\n\tremove: boolean;\n\tupdate: boolean;\n\tview: boolean;\n}\n\nexport function useOrganizationPermissions(orgId?: string): UR {\n\tconst { user } = useCloudAuth();\n\tconst { organizationId: orgIdFromRoute }: { organizationId: string } = useParams({ strict: false });\n\tconst role = user?.roles?.[orgId ?? orgIdFromRoute];\n\tif (!role?.permission && !role?.organization) {\n\t\treturn { update: false, remove: false };\n\t}\n\tif (role.permission?.super_user) {\n\t\treturn { update: true, remove: true };\n\t}\n\treturn { update: role.organization.update, remove: role.organization.delete };\n}\n\nexport function useOrganizationRolePermissions(orgId?: string): CRUV {\n\tconst { user } = useCloudAuth();\n\tconst { organizationId: orgIdFromRoute }: { organizationId: string } = useParams({ strict: false });\n\tconst role = user?.roles?.[orgId ?? orgIdFromRoute];\n\tif (!role?.permission && !role?.organization?.roles) {\n\t\treturn { create: false, remove: false, update: false, view: false };\n\t}\n\tif (role.permission?.super_user) {\n\t\treturn { create: true, remove: true, update: true, view: true };\n\t}\n\tconst roles = role.organization.roles;\n\treturn { create: roles.create, remove: roles.delete, update: roles.update, view: roles.view };\n}\n\nexport function useOrganizationClusterPermissions(orgId?: string, clusterId?: string): CRUV {\n\tconst { user } = useCloudAuth();\n\tconst { organizationId: orgIdFromRoute, clusterId: clusterIdFromRoute }: {\n\t\torganizationId: string;\n\t\tclusterId: string;\n\t} = useParams({ strict: false });\n\n\treturn getOrganizationClusterPermissions(\n\t\tuser,\n\t\torgId ?? orgIdFromRoute,\n\t\tclusterId ?? clusterIdFromRoute,\n\t);\n}\n\nexport function getOrganizationClusterPermissions(user: User | null, orgId: string, clusterId: string): CRUV {\n\tconst role = user?.roles?.[orgId];\n\tif (!role?.permission && !role?.organization?.clusters) {\n\t\treturn { create: false, remove: false, update: false, view: false };\n\t}\n\tif (role.permission?.super_user) {\n\t\treturn { create: true, remove: true, update: true, view: true };\n\t}\n\tconst specificRoles = role.organization.clusters.resources?.find(r => r.id === clusterId);\n\tconst genericRoles = role.organization.clusters;\n\treturn {\n\t\tcreate: genericRoles.create,\n\t\tremove: specificRoles ? specificRoles.delete : genericRoles.delete,\n\t\tupdate: specificRoles ? specificRoles.update : genericRoles.update,\n\t\tview: specificRoles ? specificRoles.view : genericRoles.view,\n\t};\n}\n\nexport function useOrganizationClusterInstancePermissions(orgId?: string, clusterId?: string): CRUV {\n\tconst { user } = useCloudAuth();\n\tconst { organizationId: orgIdFromRoute, clusterId: clusterIdFromRoute }: {\n\t\torganizationId: string;\n\t\tclusterId: string;\n\t} = useParams({ strict: false });\n\n\treturn getOrganizationClusterInstancePermissions(\n\t\tuser,\n\t\torgId ?? orgIdFromRoute,\n\t\tclusterId ?? clusterIdFromRoute,\n\t);\n}\n\nexport function getOrganizationClusterInstancePermissions(user: User | null, orgId: string, clusterId: string): CRUV {\n\tconst role = user?.roles?.[orgId];\n\tif (!role?.permission && !role?.organization?.clusters) {\n\t\treturn { create: false, remove: false, update: false, view: false };\n\t}\n\tif (role.permission?.super_user) {\n\t\treturn { create: true, remove: true, update: true, view: true };\n\t}\n\tconst specificRoles = role.organization.clusters\n\t\t.resources?.find(r => r.id === clusterId)\n\t\t?.instances;\n\tconst genericRoles = role.organization.clusters;\n\treturn {\n\t\tcreate: specificRoles ? specificRoles.create : genericRoles.create,\n\t\tremove: specificRoles ? specificRoles.delete : genericRoles.delete,\n\t\tupdate: specificRoles ? specificRoles.update : genericRoles.update,\n\t\tview: specificRoles ? specificRoles.view : genericRoles.view,\n\t};\n}\n\nexport function useInstanceManagePermission(entityId?: EntityIds): boolean {\n\tconst { clusterId, instanceId }: { instanceId?: string; clusterId?: string } = useParams({ strict: false });\n\tconst { user } = useInstanceAuth(entityId ?? instanceId ?? clusterId);\n\tconst permission = user?.role?.permission;\n\tif (!permission) {\n\t\t// If we don't yet have record of their permission, deny access.\n\t\t// (We're probably still loading the user.)\n\t\treturn false;\n\t}\n\treturn permission.super_user === true;\n}\n\nexport function useInstanceBrowseManagePermission(entityId?: EntityIds): boolean {\n\tconst { clusterId, instanceId }: { instanceId?: string; clusterId?: string } = useParams({ strict: false });\n\tconst { user } = useInstanceAuth(entityId ?? instanceId ?? clusterId);\n\tconst permission = user?.role?.permission;\n\tif (!permission) {\n\t\t// If we don't yet have record of their permission, deny access.\n\t\t// (We're probably still loading the user.)\n\t\treturn false;\n\t}\n\treturn permission.super_user === true || permission.structure_user === true;\n}\n\nexport function useInstanceSchemaTablePermission(\n\tentityId: EntityIds | undefined,\n\tdatabaseName: string,\n\ttableName: string,\n\taction: LocalRolePermissionAction,\n): boolean {\n\tconst { clusterId, instanceId }: { instanceId?: string; clusterId?: string } = useParams({ strict: false });\n\tconst { user } = useInstanceAuth(entityId ?? instanceId ?? clusterId);\n\tconst permission = user?.role?.permission;\n\tif (!permission) {\n\t\t// If we don't yet have record of their permission, deny access.\n\t\t// (We're probably still loading the user.)\n\t\treturn false;\n\t}\n\tif (permission.super_user === true || permission.structure_user === true) {\n\t\treturn true;\n\t}\n\tconst specificPermission = permission[databaseName];\n\treturn specificPermission?.tables?.[tableName][action] === true;\n}\n\nexport function useInstanceSchemaTableAttributePermission(\n\tentityId: EntityIds | undefined,\n\tdatabaseName: string,\n\ttableName: string,\n\tattributeName: string,\n\taction: LocalRoleAttributePermissionAction,\n): boolean {\n\tconst { clusterId, instanceId }: { instanceId?: string; clusterId?: string } = useParams({ strict: false });\n\tconst { user } = useInstanceAuth(entityId ?? instanceId ?? clusterId);\n\tconst permission = user?.role?.permission;\n\tif (!permission) {\n\t\t// If we don't yet have record of their permission, deny access.\n\t\t// (We're probably still loading the user.)\n\t\treturn false;\n\t}\n\tif (permission.super_user === true || permission.structure_user === true) {\n\t\treturn true;\n\t}\n\tconst specificPermission = permission[databaseName];\n\tif (specificPermission?.tables?.[tableName][action] === true) {\n\t\treturn true;\n\t}\n\tconst table = specificPermission?.tables?.[tableName];\n\tconst attributePermission = ((table as LocalRolePermissionTable).attribute_permissions\n\t\t|| (table as LocalLegacyRolePermissionTable).attribute_restrictions).find(a => a.attribute_name === attributeName);\n\treturn attributePermission?.[action] === true;\n}\n","import { DiscordLogo } from '@/components/DiscordLogo';\nimport { MainLogo } from '@/components/MainLogo';\nimport { NavigationMenu } from '@/components/ui/navigation/NavigationMenu';\nimport { NavigationMenuItem } from '@/components/ui/navigation/NavigationMenuItem';\nimport { NavigationMenuLink } from '@/components/ui/navigation/NavigationMenuLink';\nimport { NavigationMenuList } from '@/components/ui/navigation/NavigationMenuList';\nimport { Version } from '@/components/Version';\nimport { defaultInstanceRoute, isLocalStudio } from '@/config/constants';\nimport { useLogoutMutation } from '@/features/auth/hooks/useLogout';\nimport { useOverallAuth } from '@/hooks/useAuth';\nimport { useOrganizationPermissions, useOrganizationRolePermissions } from '@/hooks/usePermissions';\nimport { excludeFalsy } from '@/lib/arrays/excludeFalsy';\nimport { getDefaultSignedInCloudRouteForUser } from '@/lib/urls/getDefaultSignedInCloudRouteForUser';\nimport { Link, useNavigate, useParams, useRouter } from '@tanstack/react-router';\nimport {\n\tBookOpenTextIcon,\n\tBugIcon,\n\tBuildingIcon,\n\tHandshakeIcon,\n\tLogInIcon,\n\tLogOutIcon,\n\tMenu,\n\tReceiptIcon,\n\tUserIcon,\n\tUsersIcon,\n\tX,\n} from 'lucide-react';\nimport { ReactNode, useCallback, useMemo, useState } from 'react';\nimport { toast } from 'sonner';\n\nconst activeLinkProps = { className: 'text-white' };\n\nexport function Navbar() {\n\tconst { mutate: signOut } = useLogoutMutation();\n\tconst navigate = useNavigate();\n\tconst { user } = useOverallAuth();\n\tconst router = useRouter();\n\tconst { organizationId }: { organizationId: string } = useParams({ strict: false });\n\tconst { update: canUpdateOrganization } = useOrganizationPermissions(organizationId);\n\tconst { view: showOrgUsersAndRoles } = useOrganizationRolePermissions(organizationId);\n\tconst showBilling = canUpdateOrganization;\n\n\tconst handleSignOut = useCallback(() => {\n\t\tsignOut(undefined, {\n\t\t\tonSuccess: async () => {\n\t\t\t\ttoast.success('Success', {\n\t\t\t\t\tdescription: 'You have been signed out successfully.',\n\t\t\t\t\taction: {\n\t\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tvoid navigate({ to: '/sign-in' });\n\t\t\t\tvoid router.invalidate();\n\t\t\t},\n\t\t});\n\t}, [signOut, router, navigate]);\n\n\tconst menuItems: Array<MenuGroup | MenuItem> = useMemo(\n\t\t() =>\n\t\t\t[\n\t\t\t\t!isLocalStudio && {\n\t\t\t\t\tto: '/',\n\t\t\t\t\ticon: <BuildingIcon />,\n\t\t\t\t\ttext: 'Organizations',\n\t\t\t\t\ttextBreakpoint: 'xl',\n\t\t\t\t},\n\t\t\t\t!isLocalStudio && {\n\t\t\t\t\ttext: 'SubOrganizations',\n\t\t\t\t\titems: [\n\t\t\t\t\t\tshowOrgUsersAndRoles && {\n\t\t\t\t\t\t\tto: `/${organizationId}/roles`,\n\t\t\t\t\t\t\ticon: <HandshakeIcon />,\n\t\t\t\t\t\t\ttext: 'Roles',\n\t\t\t\t\t\t\ttextBreakpoint: 'lg',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tshowOrgUsersAndRoles && {\n\t\t\t\t\t\t\tto: `/${organizationId}/users`,\n\t\t\t\t\t\t\ticon: <UsersIcon />,\n\t\t\t\t\t\t\ttext: 'Users',\n\t\t\t\t\t\t\ttextBreakpoint: 'lg',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tshowBilling && {\n\t\t\t\t\t\t\tto: `/${organizationId}/billing`,\n\t\t\t\t\t\t\ticon: <ReceiptIcon />,\n\t\t\t\t\t\t\ttext: 'Billing',\n\t\t\t\t\t\t\ttextBreakpoint: 'xl',\n\t\t\t\t\t\t},\n\t\t\t\t\t].filter(excludeFalsy),\n\t\t\t\t},\n\t\t\t\t!isLocalStudio && {\n\t\t\t\t\tto: '/profile',\n\t\t\t\t\ticon: <UserIcon />,\n\t\t\t\t\ttext: 'Profile',\n\t\t\t\t\ttextBreakpoint: 'xl',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tto: 'https://docs.harperdb.io/docs',\n\t\t\t\t\ttarget: '_blank',\n\t\t\t\t\ticon: <BookOpenTextIcon />,\n\t\t\t\t\ttext: 'Docs',\n\t\t\t\t\ttextBreakpoint: isLocalStudio ? 'md' : 'xl',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tto: 'https://github.com/HarperFast/studio/issues',\n\t\t\t\t\ttarget: '_blank',\n\t\t\t\t\ticon: <BugIcon />,\n\t\t\t\t\ttext: 'Report an Issue',\n\t\t\t\t\ttextBreakpoint: isLocalStudio ? 'lg' : 'xl',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tto: 'https://discord.gg/VzZuaw3Xay',\n\t\t\t\t\ttarget: '_blank',\n\t\t\t\t\ticon: <DiscordLogo />,\n\t\t\t\t\ttext: 'Discord',\n\t\t\t\t\ttextBreakpoint: isLocalStudio ? 'lg' : 'xl',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tonClick: handleSignOut,\n\t\t\t\t\ticon: <LogOutIcon />,\n\t\t\t\t\ttext: 'Sign Out',\n\t\t\t\t\ttextBreakpoint: isLocalStudio ? 'md' : 'xl',\n\t\t\t\t},\n\t\t\t].filter(excludeFalsy) satisfies Array<MenuGroup | MenuItem>,\n\t\t[organizationId, showBilling, showOrgUsersAndRoles, handleSignOut],\n\t);\n\n\tif (!user) {\n\t\treturn <AnonymousNav />;\n\t}\n\treturn (\n\t\t<>\n\t\t\t<MobileNav menuItems={menuItems} />\n\t\t\t<DesktopNav menuItems={menuItems} />\n\t\t</>\n\t);\n}\n\ninterface MenuGroup {\n\ttext: string;\n\titems: MenuItem[];\n}\n\ninterface MenuItem {\n\tto?: string;\n\tonClick?: () => void;\n\ticon: ReactNode;\n\ttext: string;\n\ttarget?: string;\n\ttextBreakpoint?: string;\n}\n\nfunction isMenuGroup(item: MenuGroup | MenuItem): item is MenuGroup {\n\treturn (item as MenuGroup).items !== undefined;\n}\n\nfunction AnonymousNav() {\n\treturn (\n\t\t<div className=\"flex items-center justify-between\">\n\t\t\t<div className=\"inline-block\">\n\t\t\t\t<Link to=\"/sign-in\">\n\t\t\t\t\t<MainLogo />\n\t\t\t\t</Link>\n\t\t\t\t<Version />\n\t\t\t</div>\n\t\t\t<NavigationMenu>\n\t\t\t\t<NavigationMenuList className=\"text-grey-400\">\n\t\t\t\t\t<NavigationMenuItem>\n\t\t\t\t\t\t<NavigationMenuLink asChild>\n\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\tto=\"https://docs.harperdb.io/docs\"\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\trel=\"noreferrer noopener\"\n\t\t\t\t\t\t\t\tclassName=\"flex-row items-center\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<BookOpenTextIcon /> <span className=\"hidden md:inline-block\">Docs</span>\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</NavigationMenuLink>\n\t\t\t\t\t</NavigationMenuItem>\n\t\t\t\t\t<NavigationMenuItem>\n\t\t\t\t\t\t<NavigationMenuLink asChild>\n\t\t\t\t\t\t\t<Link to=\"/sign-in\" className=\"flex-row items-center\" activeProps={activeLinkProps}>\n\t\t\t\t\t\t\t\t<LogInIcon /> Sign In\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</NavigationMenuLink>\n\t\t\t\t\t</NavigationMenuItem>\n\t\t\t\t</NavigationMenuList>\n\t\t\t</NavigationMenu>\n\t\t</div>\n\t);\n}\n\nfunction DesktopNav({ menuItems }: { menuItems: Array<MenuGroup | MenuItem> }) {\n\tconst { user } = useOverallAuth();\n\tconst defaultCloudRoute = getDefaultSignedInCloudRouteForUser(user);\n\n\treturn (\n\t\t<div className=\"hidden md:block\">\n\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t<div className=\"inline-block\">\n\t\t\t\t\t<Link to={isLocalStudio ? defaultInstanceRoute : defaultCloudRoute}>\n\t\t\t\t\t\t<MainLogo />\n\t\t\t\t\t</Link>\n\t\t\t\t\t<Version />\n\t\t\t\t</div>\n\t\t\t\t<NavigationMenu>\n\t\t\t\t\t<NavigationMenuList className=\"text-grey-400\">\n\t\t\t\t\t\t{menuItems.map(menuItem =>\n\t\t\t\t\t\t\tisMenuGroup(menuItem)\n\t\t\t\t\t\t\t\t? !!menuItem.items.length && (\n\t\t\t\t\t\t\t\t\t<div key={menuItem.text} className=\"bg-black rounded-2xl flex\">\n\t\t\t\t\t\t\t\t\t\t{menuItem.items.map(innerMenuItem => (\n\t\t\t\t\t\t\t\t\t\t\t<DesktopNavItem key={innerMenuItem.text} menuItem={innerMenuItem} />\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t: <DesktopNavItem key={menuItem.text} menuItem={menuItem} />\n\t\t\t\t\t\t)}\n\t\t\t\t\t</NavigationMenuList>\n\t\t\t\t</NavigationMenu>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nfunction DesktopNavItem({ menuItem }: { menuItem: MenuItem }) {\n\treturn (\n\t\t<NavigationMenuItem className=\"text-gray-400 hover:text-white\">\n\t\t\t<NavigationMenuLink asChild>\n\t\t\t\t<Link\n\t\t\t\t\tto={menuItem.to}\n\t\t\t\t\tonClick={menuItem.onClick}\n\t\t\t\t\tclassName=\"flex-row items-center\"\n\t\t\t\t\ttarget={menuItem.target}\n\t\t\t\t\tactiveProps={menuItem.to ? activeLinkProps : undefined}\n\t\t\t\t>\n\t\t\t\t\t{menuItem.icon}\n\t\t\t\t\t<span className={`hidden ${menuItem.textBreakpoint}:inline-block`}>{menuItem.text}</span>\n\t\t\t\t\t<span className={`${menuItem.textBreakpoint}:hidden`}> </span>\n\t\t\t\t</Link>\n\t\t\t</NavigationMenuLink>\n\t\t</NavigationMenuItem>\n\t);\n}\n\nfunction MobileNav({ menuItems }: { menuItems: Array<MenuGroup | MenuItem> }) {\n\tconst { user } = useOverallAuth();\n\tconst defaultCloudRoute = getDefaultSignedInCloudRouteForUser(user);\n\tconst [isMenuOpen, setIsMenuOpen] = useState(false);\n\tconst toggleMenu = useCallback(() => setIsMenuOpen(open => !open), []);\n\tconst closeMenu = useCallback(() => setIsMenuOpen(false), []);\n\n\treturn (\n\t\t<div className=\"md:hidden\" id=\"mobile-menu\">\n\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t<Link to={isLocalStudio ? defaultInstanceRoute : defaultCloudRoute}>\n\t\t\t\t\t<MainLogo />\n\t\t\t\t</Link>\n\t\t\t\t<Version />\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"shadow-xs text-grey-400 hover:text-white hover:bg-black-dark\"\n\t\t\t\t\tonClick={toggleMenu}\n\t\t\t\t>\n\t\t\t\t\t<span className=\"sr-only\">{isMenuOpen ? 'Close menu' : 'Open menu'}</span>\n\t\t\t\t\t{isMenuOpen ? <X /> : <Menu />}\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t<div\n\t\t\t\tclassName={`${isMenuOpen ? 'fixed' : 'hidden'} top-40 bottom-0 left-0 right-0 bg-black-dark opacity-70`}\n\t\t\t\tonClick={closeMenu}\n\t\t\t>\n\t\t\t</div>\n\t\t\t<div\n\t\t\t\tclassName={`${\n\t\t\t\t\tisMenuOpen ? 'block' : 'hidden'\n\t\t\t\t} md:hidden z-50 space-y-1 pb-3 bg-black-dark absolute left-0 top-full w-full rounded-b-md`}\n\t\t\t>\n\t\t\t\t{menuItems.map(menuItem =>\n\t\t\t\t\tisMenuGroup(menuItem)\n\t\t\t\t\t\t? !!menuItem.items.length && (\n\t\t\t\t\t\t\t<div key={menuItem.text} className=\"bg-black pl-10 pr-2 py-2\">\n\t\t\t\t\t\t\t\t{menuItem.items.map(innerMenuItem => (\n\t\t\t\t\t\t\t\t\t<MobileNavItem key={innerMenuItem.text} menuItem={innerMenuItem} onClick={closeMenu} />\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)\n\t\t\t\t\t\t: <MobileNavItem key={menuItem.text} menuItem={menuItem} onClick={closeMenu} />\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nfunction MobileNavItem({ menuItem, onClick }: { menuItem: MenuItem; onClick: () => void }) {\n\tconst linkOnClick = useCallback(() => {\n\t\tmenuItem.onClick?.();\n\t\tonClick();\n\t}, [menuItem, onClick]);\n\treturn (\n\t\t<Link\n\t\t\tto={menuItem.to}\n\t\t\tonClick={linkOnClick}\n\t\t\ttarget={menuItem.target}\n\t\t\tclassName=\"flex flex-row px-3 py-2 text-base font-medium rounded-md text-gray-400 hover:text-white\"\n\t\t\tactiveProps={menuItem.to ? activeLinkProps : undefined}\n\t\t>\n\t\t\t{menuItem.icon}\n\t\t\t<span className=\"ml-4\">\n\t\t\t\t{menuItem.text}\n\t\t\t</span>\n\t\t</Link>\n\t);\n}\n","import { Navbar } from '@/components/Navbar';\nimport { Outlet } from '@tanstack/react-router';\n\nexport function AuthLayout() {\n\treturn (\n\t\t<>\n\t\t\t<header className=\"fixed top-0 z-40 w-full h-20 p-4 bg-black-dark dark:bg-black-dark dark:border-b dark:border-black md:px-12\">\n\t\t\t\t<Navbar />\n\t\t\t</header>\n\t\t\t<div className=\"pt-20 grid h-screen grid-cols-1 md:grid-cols-2\">\n\t\t\t\t<section className=\"items-center justify-center hidden text-white md:flex px-6 fabricSignupTextContainer\">\n\t\t\t\t\t<img\n\t\t\t\t\t\tclassName=\"object-scale-down max-h-[calc(100vh-80px-40px)] min-h-115\"\n\t\t\t\t\t\tsrc=\"/fabric-signup-text.png\"\n\t\t\t\t\t\talt=\"One Runtime: App, database, Cache and Messaging. Distributed by design, free to deploy, and live in minutes. Deploy!\"\n\t\t\t\t\t/>\n\t\t\t\t</section>\n\t\t\t\t<section className=\"flex items-center justify-center px-6 bg-linear-(--purple-gradient) dark:bg-linear-(--black-dark-gradient)\">\n\t\t\t\t\t<Outlet />\n\t\t\t\t</section>\n\t\t\t</div>\n\t\t</>\n\t);\n}\n","import { useEffect } from 'react';\nimport { loadReoScript, ReoClient } from 'reodotdev';\n\nexport let reoClient: ReoClient | undefined;\n\nexport function useReo() {\n\tuseEffect(() => {\n\t\tif (import.meta.env.VITE_REO_DEV_CLIENT_ID && import.meta.env.VITE_REO_DEV_CLIENT_ID !== '0') {\n\t\t\tloadReoScript({ clientID: import.meta.env.VITE_REO_DEV_CLIENT_ID })\n\t\t\t\t.then((Reo) => {\n\t\t\t\t\tReo?.init?.({ clientID: import.meta.env.VITE_REO_DEV_CLIENT_ID });\n\t\t\t\t\treturn reoClient = Reo;\n\t\t\t\t});\n\t\t}\n\t}, []);\n}\n","const commonProviders = [\n\t'gmail.com',\n\t'yahoo.com',\n\t'hotmail.com',\n\t'outlook.com',\n\t'icloud.com',\n\t'aol.com',\n\t'protonmail.com',\n\t'mail.com',\n\t'zoho.com',\n\t'yandex.com',\n\t'gmx.com',\n\t'live.com',\n\t'msn.com',\n\t'me.com',\n\t'inbox.com',\n];\n\nexport function parseCompanyFromEmail(email: string): string | null {\n\tif (!email || !email.includes('@')) {\n\t\treturn null;\n\t}\n\n\tconst domain = email.split('@').pop() || '';\n\tif (!domain) {\n\t\treturn null;\n\t}\n\n\t// Check if the domain is a common provider or a subdomain of a common provider\n\tfor (const provider of commonProviders) {\n\t\tif (domain === provider || domain.endsWith('.' + provider)) {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\treturn domain;\n}\n","import { currentUserQueryKey, getCurrentUser } from '@/features/auth/queries/getCurrentUser';\nimport { authStore, OverallAppSignIn } from '@/features/auth/store/authStore';\nimport { loginSuccessDatadogAction } from '@/integrations/datadog/datadog';\nimport { reoClient } from '@/integrations/reo/reo';\nimport { parseCompanyFromEmail } from '@/lib/string/parseCompanyFromEmail';\nimport { getDefaultSignedInCloudRouteForUser } from '@/lib/urls/getDefaultSignedInCloudRouteForUser';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { Link, useNavigate, useRouter, useSearch } from '@tanstack/react-router';\nimport { useEffect } from 'react';\nimport { toast } from 'sonner';\n\nlet checking: Promise<void> | null = null;\n\nexport function CheckOAuth() {\n\tconst navigate = useNavigate();\n\tconst router = useRouter();\n\tconst queryClient = useQueryClient();\n\tconst { redirect } = useSearch({ strict: false });\n\n\tuseEffect(() => {\n\t\tif (checking) {\n\t\t\treturn;\n\t\t}\n\t\tchecking = (async function() {\n\t\t\tconst user = await getCurrentUser().catch(() => null);\n\t\t\tif (!user) {\n\t\t\t\ttoast.error('We were not able to verify your sign-in. Please try signing in again.', {\n\t\t\t\t\tduration: 10_000,\n\t\t\t\t});\n\t\t\t\tawait navigate({ to: '/sign-in' });\n\t\t\t} else {\n\t\t\t\tauthStore.setUserForEntity(OverallAppSignIn, user);\n\t\t\t\tconst defaultCloudRoute = getDefaultSignedInCloudRouteForUser(user);\n\n\t\t\t\tloginSuccessDatadogAction(user);\n\n\t\t\t\tconst company = parseCompanyFromEmail(user.email);\n\t\t\t\treoClient?.identify?.({\n\t\t\t\t\tusername: user.email,\n\t\t\t\t\ttype: 'email',\n\t\t\t\t\t...(company ? { company } : {}),\n\t\t\t\t});\n\t\t\t\tawait queryClient.invalidateQueries({ queryKey: currentUserQueryKey, refetchType: 'none' });\n\t\t\t\tawait router.invalidate();\n\t\t\t\tawait navigate({ to: redirect?.startsWith('/') ? redirect : defaultCloudRoute });\n\t\t\t}\n\n\t\t\tchecking = null;\n\t\t})();\n\t\t// We only want this to fire once.\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, []);\n\n\treturn (\n\t\t<div className=\"text-white w-lg flex flex-col gap-4\">\n\t\t\t<h1 className=\"text-3xl font-light\">\n\t\t\t\t<span\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\tclassName=\"text-2xl animate-flower-dance mr-4\"\n\t\t\t\t\ttitle=\"Loading\"\n\t\t\t\t>\n\t\t\t\t\t🌼\n\t\t\t\t</span>\n\t\t\t\tChecking...\n\t\t\t</h1>\n\n\t\t\t<div className=\"underline flex gap-4\">\n\t\t\t\t<Link className=\"text-sm opacity-50 hover:text-blue-300\" to=\"/sign-in\">\n\t\t\t\t\tTry signing in again\n\t\t\t\t</Link>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","'use client';\n\nimport * as TooltipPrimitive from '@radix-ui/react-tooltip';\nimport * as React from 'react';\n\nimport { cn } from '@/lib/cn';\n\nfunction TooltipProvider({\n\tdelayDuration = 0,\n\t...props\n}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {\n\treturn (\n\t\t<TooltipPrimitive.Provider\n\t\t\tdata-slot=\"tooltip-provider\"\n\t\t\tdelayDuration={delayDuration}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction Tooltip({\n\t...props\n}: React.ComponentProps<typeof TooltipPrimitive.Root>) {\n\treturn (\n\t\t<TooltipProvider>\n\t\t\t<TooltipPrimitive.Root data-slot=\"tooltip\" {...props} />\n\t\t</TooltipProvider>\n\t);\n}\n\nfunction TooltipTrigger({\n\t...props\n}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {\n\treturn <TooltipPrimitive.Trigger data-slot=\"tooltip-trigger\" {...props} />;\n}\n\ntype TooltipContentProps = React.ComponentProps<typeof TooltipPrimitive.Content> & {\n\tarrowClassName?: string;\n};\n\nfunction TooltipContent({\n\tclassName,\n\tsideOffset = 0,\n\tarrowClassName,\n\tchildren,\n\t...props\n}: TooltipContentProps) {\n\treturn (\n\t\t<TooltipPrimitive.Portal>\n\t\t\t<TooltipPrimitive.Content\n\t\t\t\tdata-slot=\"tooltip-content\"\n\t\t\t\tsideOffset={sideOffset}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t\t<TooltipPrimitive.Arrow\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]',\n\t\t\t\t\t\tarrowClassName,\n\t\t\t\t\t)}\n\t\t\t\t/>\n\t\t\t</TooltipPrimitive.Content>\n\t\t</TooltipPrimitive.Portal>\n\t);\n}\n\nexport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };\n","const capitalizedCache = new Map<string, string>();\n\nexport function capitalizeWords(name: string): string {\n\tif (!name) {\n\t\treturn '';\n\t}\n\n\tif (capitalizedCache.has(name)) {\n\t\treturn capitalizedCache.get(name) as string;\n\t}\n\n\t// Normalize separators to single spaces and trim\n\tconst s = name\n\t\t.replace(/[-_]+/g, ' ')\n\t\t.replace(/\\s+/g, ' ')\n\t\t.trim();\n\tif (!s) {\n\t\tcapitalizedCache.set(name, '');\n\t\treturn '';\n\t}\n\n\t// Split into tokens handling camelCase/PascalCase, acronyms, and numbers\n\t// Pattern parts:\n\t// - [A-Z]+(?=[A-Z][a-z]) captures acronym at the start of a PascalCase word (e.g., \"APIResponse\" -> \"API\", \"Response\")\n\t// - [A-Z]?[a-z]+ captures normal words (camel/pascal or lowercase)\n\t// - [A-Z]+ captures remaining all-caps (acronyms)\n\t// - [0-9]+ captures numbers\n\tconst baseTokens = s.match(/([A-Z]+(?=[A-Z][a-z])|[A-Z]?[a-z]+|[A-Z]+|[0-9]+)/g);\n\tif (!baseTokens) {\n\t\tcapitalizedCache.set(name, '');\n\t\treturn '';\n\t}\n\n\t// Merge plural 's' following an acronym (length>=2), e.g., [\"ID\", \"s\"] -> [\"IDs\"]\n\tconst tokens: string[] = [];\n\tfor (let i = 0; i < baseTokens.length; i++) {\n\t\tconst token = baseTokens[i];\n\t\tconst next = i + 1 < baseTokens.length ? baseTokens[i + 1] : undefined;\n\t\tif (\n\t\t\t// Case 1: full acronym then plural 's' as separate token -> merge\n\t\t\t/^[A-Z]{2,}$/.test(token)\n\t\t\t&& next\n\t\t\t&& /[A-Z]*s$/.test(next)\n\t\t) {\n\t\t\ttokens.push(token + next);\n\t\t\ti++; // skip the 's'\n\t\t} else if (\n\t\t\t// Case 2: single leading capital followed by capital + 's' (e.g., 'I' + 'Ds') -> merge to 'IDs'\n\t\t\t/^[A-Z]$/.test(token)\n\t\t\t&& next !== undefined\n\t\t\t&& /^[A-Z]s$/.test(next)\n\t\t) {\n\t\t\ttokens.push(token + next);\n\t\t\ti++; // skip merged next\n\t\t} else {\n\t\t\ttokens.push(token);\n\t\t}\n\t}\n\n\tconst words = tokens.map(capitalizeTokenWordsAppropriately);\n\n\tconst result = words.join(' ');\n\tcapitalizedCache.set(name, result);\n\treturn result;\n}\n\nfunction capitalizeTokenWordsAppropriately(t: string): string {\n\tif (/^[A-Z]{2,3}s?$/.test(t)) {\n\t\t// Acronym (e.g., ID, API) possibly with plural 's' -> keep as is\n\t\treturn t;\n\t}\n\tif (/^[0-9]+$/.test(t)) {\n\t\t// numbers unchanged\n\t\treturn t;\n\t}\n\t// Normal word: capitalize first letter, lowercase rest\n\treturn t.charAt(0).toUpperCase() + t.slice(1).toLowerCase();\n}\n","import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';\nimport { isLocalStudio } from '@/config/constants';\nimport { Cluster, Instance, Organization } from '@/integrations/api/api.patch';\nimport { capitalizeWords } from '@/lib/string/capitalizeWords';\nimport { Link, useLocation, useRouteContext } from '@tanstack/react-router';\nimport { HomeIcon } from 'lucide-react';\nimport { useMemo } from 'react';\n\nexport function Breadcrumbs({ restartRequired }: { restartRequired?: boolean }) {\n\tconst location = useLocation();\n\n\tconst { organization, instance, cluster }: {\n\t\torganization?: Organization;\n\t\tinstance?: Instance;\n\t\tcluster?: Cluster;\n\t} = useRouteContext({ strict: false });\n\tconst targetNoun = (instance || isLocalStudio) ? 'Instance' : 'Cluster';\n\n\tconst breadcrumbs = useMemo(() => {\n\t\tconst routeHistory = location.pathname.split('/')\n\t\t\t.filter((x) => x && x.length > 0);\n\n\t\tconst breadcrumbs = [\n\t\t\t<Link key=\"home\" to=\"/\">\n\t\t\t\t<HomeIcon aria-hidden=\"true\" className=\"size-5 shrink-0\" />\n\t\t\t\t<span className=\"sr-only\">Home</span>\n\t\t\t</Link>,\n\t\t];\n\n\t\tfor (let index = 0; index < routeHistory.length; index++) {\n\t\t\tconst route = routeHistory[index];\n\t\t\tif (route === 'instance') {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlet path = `/${routeHistory.slice(0, index + 1).join('/')}`;\n\t\t\tlet name = capitalizeWords(route);\n\t\t\tif (route === 'databases' && routeHistory.length === index + 3) {\n\t\t\t\tname = routeHistory[index + 2];\n\t\t\t\tindex += 2;\n\t\t\t} else if (name.startsWith('Org ')) {\n\t\t\t\tname = organization?.name || 'Org';\n\t\t\t} else if (name.startsWith('Clu ')) {\n\t\t\t\tname = cluster?.name || 'Cluster';\n\t\t\t\tif (routeHistory[index + 1] === 'instance') {\n\t\t\t\t\tpath += '/instances';\n\t\t\t\t}\n\t\t\t} else if (name.startsWith('Ins ')) {\n\t\t\t\tname = instance?.name?.split('.')?.shift() || 'Instance';\n\t\t\t} else if (name === 'Apis') {\n\t\t\t\tname = 'APIs';\n\t\t\t}\n\n\t\t\tbreadcrumbs.push(\n\t\t\t\t<svg\n\t\t\t\t\tkey={breadcrumbs.length + '-dash'}\n\t\t\t\t\tfill=\"currentColor\"\n\t\t\t\t\tviewBox=\"0 0 20 20\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\tclassName=\"size-5 shrink-0 text-grey\"\n\t\t\t\t>\n\t\t\t\t\t<path d=\"M5.555 17.776l8-16 .894.448-8 16-.894-.448z\" />\n\t\t\t\t</svg>,\n\t\t\t\t<Link\n\t\t\t\t\tkey={path}\n\t\t\t\t\tto={path}\n\t\t\t\t\tclassName=\"text-xs md:text-sm font-medium hover:text-grey truncate max-w-48\"\n\t\t\t\t>\n\t\t\t\t\t{name}\n\t\t\t\t</Link>,\n\t\t\t);\n\t\t}\n\n\t\treturn breadcrumbs;\n\t}, [location.pathname, cluster?.name, instance?.name, organization?.name]);\n\n\treturn (\n\t\t<div role=\"list\" className=\"flex items-center space-x-2 xl:space-x-4 sm:max-w-9/10 max-w-[calc(100%-56px)]\">\n\t\t\t{...breadcrumbs}\n\t\t\t{restartRequired && (\n\t\t\t\t<Tooltip>\n\t\t\t\t\t<TooltipTrigger asChild>\n\t\t\t\t\t\t<div className=\"text-xs italic text-muted-foreground\">\n\t\t\t\t\t\t\t* Restart <span className=\"hidden lg:inline-block\">Requested</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</TooltipTrigger>\n\t\t\t\t\t<TooltipContent side=\"bottom\">\n\t\t\t\t\t\tThis {targetNoun} is requesting a restart, when convenient, to apply your latest changes.\n\t\t\t\t\t\t<br />You can do this from the Apps or Config pages.\n\t\t\t\t\t</TooltipContent>\n\t\t\t\t</Tooltip>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import { FormProvider } from 'react-hook-form';\n\nexport const Form = FormProvider;\n","import { createContext } from 'react';\nimport { FieldPath, FieldValues } from 'react-hook-form';\n\nexport type FormFieldContextValue<\n\tTFieldValues extends FieldValues = FieldValues,\n\tTName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n> = {\n\tname: TName;\n};\nexport const FormFieldContext = createContext<FormFieldContextValue>({} as FormFieldContextValue);\n","import { createContext } from 'react';\n\ntype FormItemContextValue = {\n\tid: string;\n};\nexport const FormItemContext = createContext<FormItemContextValue>({} as FormItemContextValue);\n","import { FormFieldContext } from '@/components/ui/form/formFieldContext';\nimport { FormItemContext } from '@/components/ui/form/formItemContext';\nimport { useContext } from 'react';\nimport { useFormContext, useFormState } from 'react-hook-form';\n\nexport function useFormField() {\n\tconst fieldContext = useContext(FormFieldContext);\n\tconst itemContext = useContext(FormItemContext);\n\tconst { getFieldState } = useFormContext();\n\tconst formState = useFormState({ name: fieldContext.name });\n\tconst fieldState = getFieldState(fieldContext.name, formState);\n\n\tif (!fieldContext) {\n\t\tthrow new Error('useFormField should be used within <FormField>');\n\t}\n\n\tconst { id } = itemContext;\n\n\treturn {\n\t\tid,\n\t\tname: fieldContext.name,\n\t\tformItemId: `${id}-form-item`,\n\t\tformDescriptionId: `${id}-form-item-description`,\n\t\tformMessageId: `${id}-form-item-message`,\n\t\t...fieldState,\n\t};\n}\n","import { useFormField } from '@/components/ui/form/useFormField';\nimport { Slot } from '@radix-ui/react-slot';\nimport { ComponentProps } from 'react';\n\nexport function FormControl({ ...props }: ComponentProps<typeof Slot>) {\n\tconst { error, formItemId, formDescriptionId, formMessageId } = useFormField();\n\n\treturn (\n\t\t<Slot\n\t\t\tdata-slot=\"form-control\"\n\t\t\tid={formItemId}\n\t\t\taria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`}\n\t\t\taria-invalid={!!error}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n","import { FormFieldContext as FormFieldContext1 } from '@/components/ui/form/formFieldContext';\nimport { Controller, ControllerProps, FieldPath, FieldValues } from 'react-hook-form';\n\nexport function FormField<\n\tTFieldValues extends FieldValues = FieldValues,\n\tTName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n>({\n\t...props\n}: ControllerProps<TFieldValues, TName>) {\n\treturn (\n\t\t<FormFieldContext1 value={{ name: props.name }}>\n\t\t\t<Controller {...props} />\n\t\t</FormFieldContext1>\n\t);\n}\n","import { FormItemContext as FormItemContext1 } from '@/components/ui/form/formItemContext';\nimport { cn } from '@/lib/cn';\nimport { ComponentProps, useId } from 'react';\n\nexport function FormItem({ className, ...props }: ComponentProps<'div'>) {\n\tconst id = useId();\n\n\treturn (\n\t\t<FormItemContext1 value={{ id }}>\n\t\t\t<div data-slot=\"form-item\" className={cn('grid gap-2', className)} {...props} />\n\t\t</FormItemContext1>\n\t);\n}\n","'use client';\n\nimport * as LabelPrimitive from '@radix-ui/react-label';\nimport * as React from 'react';\n\nimport { cn } from '@/lib/cn';\n\nfunction Label({\n\tclassName,\n\t...props\n}: React.ComponentProps<typeof LabelPrimitive.Root>) {\n\treturn (\n\t\t<LabelPrimitive.Root\n\t\t\tdata-slot=\"label\"\n\t\t\tclassName={cn(\n\t\t\t\t'text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport { Label };\n","import { useFormField } from '@/components/ui/form/useFormField';\nimport { Label } from '@/components/ui/label';\nimport { cn } from '@/lib/cn';\nimport * as LabelPrimitive from '@radix-ui/react-label';\nimport { ComponentProps } from 'react';\n\nexport function FormLabel({ className, ...props }: ComponentProps<typeof LabelPrimitive.Root>) {\n\tconst { error, formItemId } = useFormField();\n\n\treturn (\n\t\t<Label\n\t\t\tdata-slot=\"form-label\"\n\t\t\tdata-error={!!error}\n\t\t\tclassName={cn('data-[error=true]:text-destructive', className)}\n\t\t\thtmlFor={formItemId}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n","import { useFormField } from '@/components/ui/form/useFormField';\nimport { cn } from '@/lib/cn';\nimport { ComponentProps } from 'react';\n\nexport function FormMessage({ className, ...props }: ComponentProps<'p'>) {\n\tconst { error, formMessageId } = useFormField();\n\tconst body = error ? String(error?.message) : props.children;\n\n\tif (!body) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<p data-slot=\"form-message\" id={formMessageId} className={cn('text-destructive text-sm', className)} {...props}>\n\t\t\t{body}\n\t\t</p>\n\t);\n}\n","import * as React from 'react';\n\nimport { cn } from '@/lib/cn';\n\nfunction Input({ className, type, ...props }: React.ComponentProps<'input'>) {\n\treturn (\n\t\t<input\n\t\t\ttype={type}\n\t\t\tdata-slot=\"input\"\n\t\t\tclassName={cn(\n\t\t\t\t`border-input file:text-foreground placeholder:text-muted-foreground selection:bg-purple\n selection:text-primary-foreground\n dark:aria-invalid:outline-destructive dark:aria-invalid:ring-destructive/50 ring-ring/10\n dark:ring-ring/20 dark:outline-ring/40 outline-ring/50 aria-invalid:outline-destructive/60\n aria-invalid:ring-destructive/20 aria-invalid:border-destructive/60 dark:aria-invalid:border-destructive\n flex h-9 w-full min-w-0 rounded-md border bg-grey-700 px-3 py-1 text-base text-white\n file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium\n focus-visible:ring-1 focus-visible:outline-none focus-visible:ring-purple disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50\n aria-invalid:focus-visible:ring-[1px] aria-invalid:focus-visible:outline-none md:text-sm dark:aria-invalid:focus-visible:ring-1`,\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport { Input };\n","export const activeClusterStatuses = ['RUNNING'];\nexport const deletedClusterStatuses = ['TERMINATING', 'TERMINATED', 'REMOVED'];\n","export function calculateCreateClusterDeepLink() {\n\t// NOTE: This is also embedded in public/running.js\n\treturn 'https://fabric.harper.fast/#/?createCluster=' + encodeURIComponent(JSON.stringify({\n\t\tdeploymentDescription: 'Self-Hosted',\n\t\tperformanceDescription: 'Self Supported and Managed',\n\t\tinstances: [\n\t\t\t{\n\t\t\t\tsecure: String(location.protocol === 'https:'),\n\t\t\t\tfqdn: location.hostname,\n\t\t\t\tport: parseInt(location.port, 10),\n\t\t\t},\n\t\t],\n\t}));\n}\n","import { forceBasicAuth, isLocalStudio } from '@/config/constants';\nimport { getInstanceClient } from '@/config/getInstanceClient';\nimport { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { authStore } from '@/features/auth/store/authStore';\nimport { LocalUser } from '@/integrations/api/api.patch';\nimport { getInstanceUserInfo } from '@/integrations/api/instance/status/getInstanceUserInfo';\nimport { useMutation } from '@tanstack/react-query';\nimport { AxiosInstance } from 'axios';\n\ninterface InstanceLoginCredentials extends InstanceClientIdConfig {\n\tusername: string;\n\tpassword: string;\n}\n\nexport interface LoginInfoResponse {\n\tmessage: string;\n\tuser: LocalUser;\n\tinstanceClient?: AxiosInstance;\n}\n\nexport async function onInstanceLoginSubmit({\n\tusername,\n\tpassword,\n\tinstanceClient,\n\tentityId,\n}: InstanceLoginCredentials): Promise<LoginInfoResponse> {\n\tconst auth = {\n\t\tusername,\n\t\tpassword,\n\t};\n\tif (authStore.checkForBasicAuth(entityId)) {\n\t\tinstanceClient.defaults.auth = auth;\n\t\tinstanceClient.defaults.withCredentials = false;\n\t}\n\n\tconst { data: { message } } = await instanceClient.post('/', {\n\t\toperation: 'login',\n\t\tusername,\n\t\tpassword,\n\t});\n\n\tif (!forceBasicAuth && !authStore.checkForBasicAuth(entityId)) {\n\t\t// Attempt to use the login with session storage only.\n\t\ttry {\n\t\t\tconst user = await getInstanceUserInfo({ instanceClient });\n\t\t\treturn {\n\t\t\t\tmessage,\n\t\t\t\tuser,\n\t\t\t};\n\t\t} catch (err) {\n\t\t\tconsole.error('Failed to get user after login, trying basic auth', err);\n\t\t}\n\t}\n\n\ttry {\n\t\tinstanceClient.defaults.auth = auth;\n\t\tinstanceClient.defaults.withCredentials = false;\n\t\tconst user = await getInstanceUserInfo({\n\t\t\tinstanceClient,\n\t\t\tauth,\n\t\t});\n\t\tauthStore.flagForBasicAuth(entityId, auth);\n\t\treturn {\n\t\t\tmessage,\n\t\t\tuser,\n\t\t};\n\t} catch (err) {\n\t\tinstanceClient.defaults.auth = undefined;\n\t\tinstanceClient.defaults.withCredentials = true;\n\t\tif (isLocalStudio) {\n\t\t\tthrow err;\n\t\t}\n\t\tconsole.error('Failed to get user with basic auth, trying Fabric Connect', err);\n\t}\n\n\tconst fabricInstanceClient = getInstanceClient({\n\t\tid: entityId,\n\t\tforceFabricConnect: true,\n\t});\n\tconst user = await getInstanceUserInfo({\n\t\tinstanceClient: fabricInstanceClient,\n\t});\n\tauthStore.flagForFabricConnect(entityId, true);\n\treturn {\n\t\tmessage,\n\t\tuser,\n\t\tinstanceClient: fabricInstanceClient,\n\t};\n}\n\nexport function useInstanceLoginMutation() {\n\treturn useMutation<LoginInfoResponse, Error, InstanceLoginCredentials>({\n\t\tmutationFn: onInstanceLoginSubmit,\n\t});\n}\n","import { defaultInstanceRoute, defaultInstanceRouteUpOne, isLocalStudio } from '@/config/constants';\nimport { InstanceClientIdConfig, InstanceTypeConfig } from '@/config/instanceClientConfig';\nimport { authStore, OverallAppSignIn } from '@/features/auth/store/authStore';\nimport { SchemaHdbInstance } from '@/integrations/api/api.gen';\nimport { Cluster } from '@/integrations/api/api.patch';\nimport { UsernameSignInSchema } from '@/integrations/api/instance/auth/signInSchema';\nimport { useInstanceLoginMutation } from '@/integrations/api/instance/auth/useInstanceLoginMutation';\nimport { useNavigate, useRouter, useSearch } from '@tanstack/react-router';\nimport { useCallback } from 'react';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\n\nexport function useClusterInstanceSignIn({\n\tcluster,\n\tinstance,\n\tinstanceParams,\n}: {\n\tcluster: Cluster | undefined;\n\tinstance: SchemaHdbInstance | undefined;\n\tinstanceParams: InstanceClientIdConfig & InstanceTypeConfig;\n}) {\n\tconst navigate = useNavigate();\n\tconst router = useRouter();\n\tconst { redirect } = useSearch({ strict: false });\n\n\tconst { mutate: submitInstanceLogin, isPending } = useInstanceLoginMutation();\n\n\tconst submitForm = useCallback(async (formData: z.infer<typeof UsernameSignInSchema>) => {\n\t\tsubmitInstanceLogin(\n\t\t\t{\n\t\t\t\t...formData,\n\t\t\t\t...instanceParams,\n\t\t\t},\n\t\t\t{\n\t\t\t\tonSuccess: async ({ message, user }) => {\n\t\t\t\t\ttoast.success(message);\n\t\t\t\t\t// If we sign in to the cluster, we've authenticated against all of its instances too.\n\t\t\t\t\tif (cluster?.instances?.length && !instance) {\n\t\t\t\t\t\tfor (const clusterInstance of cluster.instances) {\n\t\t\t\t\t\t\tauthStore.setUserForEntity(clusterInstance, user);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tconst entity = isLocalStudio ? OverallAppSignIn : instance || cluster;\n\t\t\t\t\tif (!entity) {\n\t\t\t\t\t\tthrow new Error('Sign in failed due to missing cluster or instance.');\n\t\t\t\t\t}\n\t\t\t\t\tauthStore.setUserForEntity(entity, user);\n\t\t\t\t\tvoid router.invalidate();\n\t\t\t\t\tawait navigate({\n\t\t\t\t\t\tto: redirect?.startsWith('/')\n\t\t\t\t\t\t\t? redirect\n\t\t\t\t\t\t\t: isLocalStudio\n\t\t\t\t\t\t\t? defaultInstanceRoute\n\t\t\t\t\t\t\t: defaultInstanceRouteUpOne,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}, [cluster, instance, instanceParams, navigate, redirect, router, submitInstanceLogin]);\n\n\treturn {\n\t\tisPending,\n\t\tsubmitForm,\n\t};\n}\n","import { apiClient } from '@/config/apiClient';\nimport { Cluster } from '@/integrations/api/api.patch';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport async function getClusterInfo(clusterId: string) {\n\tconst { data } = await apiClient.get(`/Cluster/${clusterId}` as '/Cluster/{id}');\n\treturn data as Cluster;\n}\n\nexport function getClusterInfoQueryOptions(clusterId?: string | false, refetch?: boolean | number) {\n\treturn queryOptions({\n\t\tqueryKey: [clusterId],\n\t\tqueryFn: () => getClusterInfo(clusterId as string),\n\t\tretry: false,\n\t\tstaleTime: 1_900,\n\t\tenabled: !!clusterId,\n\t\trefetchInterval: refetch\n\t\t\t? refetch === true\n\t\t\t\t? 10_000\n\t\t\t\t: refetch\n\t\t\t: undefined,\n\t});\n}\n","import { z } from 'zod';\n\nexport const zodRequireEmail = z\n\t.email({\n\t\terror: 'Please enter a valid email address.',\n\t})\n\t.toLowerCase()\n\t.trim();\n","import { z } from 'zod';\n\nexport const zodRequirePassword = z\n\t.string()\n\t.nonempty({ error: 'Please enter your password.' });\n","import { z } from 'zod';\n\nexport const zodRequireUsername = z\n\t.string()\n\t.nonempty({ error: 'Please enter a username.' });\n","import { zodRequireEmail } from '@/lib/zod/email';\nimport { zodRequirePassword } from '@/lib/zod/password';\nimport { zodRequireUsername } from '@/lib/zod/username';\nimport { z } from 'zod';\n\nexport const UsernameSignInSchema = z.object({\n\tusername: zodRequireUsername,\n\tpassword: zodRequirePassword,\n});\n\nexport const EmailSignInSchema = z.object({\n\temail: zodRequireEmail,\n\tpassword: zodRequirePassword,\n});\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport function getInstanceHealthQueryOptions({\n\tentityId,\n\tinstanceClient,\n}: InstanceClientIdConfig) {\n\treturn queryOptions({\n\t\tqueryKey: [entityId, 'health'] as const,\n\t\tqueryFn: async () => {\n\t\t\ttry {\n\t\t\t\tawait instanceClient.get('/health');\n\t\t\t\treturn true;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\tretry: 2,\n\t\trefetchInterval: 5000,\n\t});\n}\n","const localHostnames = [\n\t'localhost',\n\t'127.0.0.1',\n];\n\nexport const enum CrossLocalhostIssueType {\n\tMixedLoopback = 'MixedLoopback',\n\tInsecureCookieOutsideChromeAndFirefox = 'InsecureCookieOutsideChromeAndFirefox',\n}\n\nexport function detectCrossLocalhostUrls(\n\tuserAgent: string | undefined,\n\tbrowserHostname: string | undefined,\n\toperationsUrl: string | undefined | null,\n): CrossLocalhostIssueType | null {\n\tif (!operationsUrl || !browserHostname || !userAgent) {\n\t\treturn null;\n\t}\n\tconst serverHostname = new URL(operationsUrl).hostname;\n\tconst browserIsLocal = localHostnames.includes(browserHostname);\n\tconst serverIsLocal = localHostnames.includes(serverHostname);\n\n\tif (browserIsLocal && serverIsLocal && serverHostname !== browserHostname) {\n\t\t// When running Studio locally and self-managing locally, warn when we mix localhost and 127.0.0.1.\n\t\treturn CrossLocalhostIssueType.MixedLoopback;\n\t}\n\n\tif (!browserIsLocal && serverIsLocal) {\n\t\tconst isChromium = userAgent.indexOf('Chrome') >= 0;\n\t\tconst isFirefox = userAgent.indexOf('Firefox') >= 0;\n\t\tif (!isChromium && !isFirefox) {\n\t\t\t// When running Studio in the cloud, and signing in to a local instance, Chrome and Firefox allow the\n\t\t\t// cookies to cross to the insecure localhost because they consider it to be secure enough.\n\t\t\t// https://github.com/httpwg/http-extensions/issues/2605\n\t\t\treturn CrossLocalhostIssueType.InsecureCookieOutsideChromeAndFirefox;\n\t\t}\n\t}\n\n\treturn null;\n}\n","import { Breadcrumbs } from '@/components/Breadcrumbs';\nimport { Button } from '@/components/ui/button';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { activeClusterStatuses } from '@/config/clusterStatuses';\nimport { isLocalStudio } from '@/config/constants';\nimport { calculateCreateClusterDeepLink } from '@/config/deepLinks';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { useClusterInstanceSignIn } from '@/features/auth/hooks/useClusterInstanceSignIn';\nimport { authStore } from '@/features/auth/store/authStore';\nimport { getClusterInfoQueryOptions } from '@/features/cluster/queries/getClusterInfoQuery';\nimport { SchemaHdbInstance } from '@/integrations/api/api.gen';\nimport { UsernameSignInSchema } from '@/integrations/api/instance/auth/signInSchema';\nimport { getInstanceHealthQueryOptions } from '@/integrations/api/instance/status/getInstanceHealth';\nimport { CrossLocalhostIssueType, detectCrossLocalhostUrls } from '@/lib/urls/detectCrossLocalhostUrls';\nimport { getOperationsUrlForCluster } from '@/lib/urls/getOperationsUrlForCluster';\nimport { getOperationsUrlForInstance } from '@/lib/urls/getOperationsUrlForInstance';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useQuery } from '@tanstack/react-query';\nimport { Link, Navigate, useParams } from '@tanstack/react-router';\nimport { useMemo } from 'react';\nimport { useForm } from 'react-hook-form';\n\nexport function ClusterInstanceSignIn() {\n\tconst { clusterId, instanceId }: { instanceId?: string; clusterId?: string } = useParams({ strict: false });\n\tconst { data: cluster } = useQuery(\n\t\tgetClusterInfoQueryOptions(clusterId, true),\n\t);\n\n\tconst instance: SchemaHdbInstance | undefined = useMemo(\n\t\t() => instanceId && cluster && cluster?.instances?.find(i => i.id === instanceId) || undefined,\n\t\t[cluster, instanceId],\n\t);\n\tconst isActive = useMemo(() => cluster?.status && activeClusterStatuses.includes(cluster.status), [cluster?.status]);\n\n\tconst properNoun = isLocalStudio ? 'Local' : instanceId ? 'Instance' : 'Cluster';\n\tconst commonNoun = isLocalStudio ? 'instance' : instanceId ? 'instance' : 'cluster';\n\n\tconst operationsUrl = useMemo(() => {\n\t\tif (cluster) {\n\t\t\tif (instance) {\n\t\t\t\tauthStore.flagForFabricConnect(instance.id, false);\n\t\t\t\treturn getOperationsUrlForInstance(instance);\n\t\t\t} else {\n\t\t\t\tauthStore.flagForFabricConnect(cluster.id, false);\n\t\t\t\treturn getOperationsUrlForCluster(cluster);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}, [cluster, instance]);\n\n\tconst instanceParams = useInstanceClientIdParams({ operationsUrl });\n\tconst warnAboutLocalDeviceAccess = useMemo(\n\t\t() => operationsUrl?.includes('localhost') || operationsUrl?.includes('127.0.0.1'),\n\t\t[operationsUrl],\n\t);\n\tconst warnAboutLoginCookieIssues = useMemo(\n\t\t() => detectCrossLocalhostUrls(navigator.userAgent, location.hostname, operationsUrl),\n\t\t[operationsUrl],\n\t);\n\tconst { data: healthy } = useQuery(\n\t\tgetInstanceHealthQueryOptions(instanceParams),\n\t);\n\n\tconst methods = useForm({\n\t\tresolver: zodResolver(UsernameSignInSchema),\n\t\tdefaultValues: {\n\t\t\tusername: '',\n\t\t\tpassword: '',\n\t\t},\n\t});\n\tconst { control, handleSubmit } = methods;\n\n\tconst { submitForm, isPending } = useClusterInstanceSignIn({\n\t\tcluster,\n\t\tinstance,\n\t\tinstanceParams,\n\t});\n\n\tif (!instanceId && cluster && !cluster?.fqdn) {\n\t\treturn <Navigate to=\"../instances\" replace={true} />;\n\t}\n\n\tif (isActive && cluster?.resetPassword) {\n\t\treturn <Navigate to={`/${cluster.organizationId}/${cluster.id}/finish-setup`} replace={true} />;\n\t}\n\tif (!isActive && cluster?.resetPassword) {\n\t\treturn <Navigate to={`/${cluster.organizationId}/${cluster.id}/starting-up`} replace={true} />;\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t{!isLocalStudio && (\n\t\t\t\t<nav className=\"fixed top-20 w-full h-12 z-39 px-4 md:px-12 bg-grey-700 flex items-center\">\n\t\t\t\t\t<Breadcrumbs />\n\t\t\t\t</nav>\n\t\t\t)}\n\t\t\t<div className=\"h-screen items-center justify-center flex\">\n\t\t\t\t<div className=\"text-white w-xs\">\n\t\t\t\t\t<h2 className=\"text-2xl font-light\">\n\t\t\t\t\t\tSign in to Harper {properNoun}\n\t\t\t\t\t</h2>\n\t\t\t\t\t<Form {...methods}>\n\t\t\t\t\t\t<form\n\t\t\t\t\t\t\tid={`auth-${commonNoun}-signin-form`}\n\t\t\t\t\t\t\tname={`auth-${commonNoun}-signin-form`}\n\t\t\t\t\t\t\tonSubmit={handleSubmit(submitForm)}\n\t\t\t\t\t\t\tclassName=\"my-4\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\t\t\tname=\"username\"\n\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t<FormItem className=\"my-4\">\n\t\t\t\t\t\t\t\t\t\t<FormLabel>Username</FormLabel>\n\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"username\"\n\t\t\t\t\t\t\t\t\t\t\t\tautoFocus={true}\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\t\t\tname=\"password\"\n\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t<FormItem className=\"my-4\">\n\t\t\t\t\t\t\t\t\t\t<FormLabel>Password</FormLabel>\n\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<Button disabled={isPending} type=\"submit\" variant=\"submit\" className=\"w-full my-2 rounded-full\">\n\t\t\t\t\t\t\t\tSign In\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t{healthy === false && (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tclassName=\"p-4 mt-4 text-sm text-yellow-800 rounded-lg bg-yellow-50 dark:bg-gray-800 dark:text-yellow-300\"\n\t\t\t\t\t\t\t\t\trole=\"alert\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span className=\"font-medium\">Warning!</span> This {commonNoun} is not responding to GET{' '}\n\t\t\t\t\t\t\t\t\t<a href={`${operationsUrl}health`} className=\"underline\" target=\"_blank\">{operationsUrl}health</a>\n\t\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t\tchecks.\n\t\t\t\t\t\t\t\t\t<ol className=\"list-decimal ml-8 mt-2\">\n\t\t\t\t\t\t\t\t\t\t<li>Is the server running?</li>\n\t\t\t\t\t\t\t\t\t\t<li>\n\t\t\t\t\t\t\t\t\t\t\tHave you{' '}\n\t\t\t\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\t\t\t\thref=\"https://docs.harperdb.io/docs/developers/security/configuration#cors\"\n\t\t\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"underline\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\tenabled CORS\n\t\t\t\t\t\t\t\t\t\t\t</a>{' '}\n\t\t\t\t\t\t\t\t\t\t\tfor the operations API?\n\t\t\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t\t\t\t{warnAboutLocalDeviceAccess && (\n\t\t\t\t\t\t\t\t\t\t\t<li>\n\t\t\t\t\t\t\t\t\t\t\t\tHave you allowed{' '}\n\t\t\t\t\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\t\t\t\t\thref=\"https://www.google.com/search?q=How+do+I+enable+local+network+access+in+my+browser%3F\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"underline\"\n\t\t\t\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\tlocal network access\n\t\t\t\t\t\t\t\t\t\t\t\t</a>{' '}\n\t\t\t\t\t\t\t\t\t\t\t\tin your browser?\n\t\t\t\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</ol>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{warnAboutLoginCookieIssues === CrossLocalhostIssueType.MixedLoopback && (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tclassName=\"p-4 mt-4 text-sm text-yellow-800 rounded-lg bg-yellow-50 dark:bg-gray-800 dark:text-yellow-300\"\n\t\t\t\t\t\t\t\t\trole=\"alert\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span className=\"font-medium\">Warning!</span>{' '}\n\t\t\t\t\t\t\t\t\tYour login might not work because you're mixing 127.0.0.1 and localhost. Pick one or the other.\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{warnAboutLoginCookieIssues === CrossLocalhostIssueType.InsecureCookieOutsideChromeAndFirefox && (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tclassName=\"p-4 mt-4 text-sm text-yellow-800 rounded-lg bg-yellow-50 dark:bg-gray-800 dark:text-yellow-300\"\n\t\t\t\t\t\t\t\t\trole=\"alert\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span className=\"font-medium\">Warning!</span>{' '}\n\t\t\t\t\t\t\t\t\tYour login might not work because your browser doesn't consider localhost to be secure, so it doesn't\n\t\t\t\t\t\t\t\t\tpass the cookies along. Firefox or Chromium based browsers should pass the cookies properly.\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{isLocalStudio && (\n\t\t\t\t\t\t\t\t<div className=\"p-4 mt-4 text-sm rounded-lg bg-purple-950\" role=\"alert\">\n\t\t\t\t\t\t\t\t\t<span className=\"font-medium\">Did you know?</span>{' '}\n\t\t\t\t\t\t\t\t\tYou can add this instance to your Harper account to manage it remotely.\n\t\t\t\t\t\t\t\t\t<div className=\"text-center pt-2\">\n\t\t\t\t\t\t\t\t\t\t<Link to={calculateCreateClusterDeepLink()} target=\"_blank\">\n\t\t\t\t\t\t\t\t\t\t\t<Button type=\"button\" variant=\"positive\">\n\t\t\t\t\t\t\t\t\t\t\t\tConnect to Harper Fabric\n\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</form>\n\t\t\t\t\t</Form>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</>\n\t);\n}\n","import { apiClient } from '@/config/apiClient';\nimport { useMutation } from '@tanstack/react-query';\n\nexport type ForgotPasswordCredential = {\n\temail: string;\n};\n\ntype ForgotPasswordResponse = {\n\temail: string;\n};\n\nexport async function onResetPasswordSubmit({ email }: ForgotPasswordCredential): Promise<ForgotPasswordResponse> {\n\tconst { data } = await apiClient.post('/ForgotPassword/', {\n\t\temail,\n\t});\n\tif (data) {\n\t\t// TODO: The OpenAPI description isn't accurate.\n\t\treturn data as ForgotPasswordResponse;\n\t} else {\n\t\tthrow new Error('Something went wrong');\n\t}\n}\n\nexport function useForgotPasswordMutation() {\n\treturn useMutation<ForgotPasswordResponse, Error, ForgotPasswordCredential>({\n\t\tmutationFn: (loginData) => onResetPasswordSubmit(loginData),\n\t});\n}\n","import { Button } from '@/components/ui/button';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { zodRequireEmail } from '@/lib/zod/email';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { Link, useNavigate, useSearch } from '@tanstack/react-router';\nimport { useEffect } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useForgotPasswordMutation } from './hooks/useForgotPassword';\n\nconst ForgotPasswordSchema = z.object({\n\temail: zodRequireEmail,\n});\n\nexport function ForgotPassword() {\n\tconst navigate = useNavigate();\n\tconst { me: formPersistenceEmail } = useSearch({ strict: false });\n\tconst methods = useForm({\n\t\tresolver: zodResolver(ForgotPasswordSchema),\n\t\tdefaultValues: {\n\t\t\temail: formPersistenceEmail || '',\n\t\t},\n\t});\n\tconst email = methods.watch('email');\n\tconst { setFocus, control, handleSubmit } = methods;\n\n\tuseEffect(() => {\n\t\tsetFocus('email');\n\t}, [setFocus]);\n\n\tconst { mutate: submitForgotPasswordData, isPending } = useForgotPasswordMutation();\n\n\tconst submitForm = async (formData: z.infer<typeof ForgotPasswordSchema>) => {\n\t\tsubmitForgotPasswordData(formData, {\n\t\t\tonSuccess: (message) => {\n\t\t\t\ttoast.success('Success', {\n\t\t\t\t\tdescription: `${message}`,\n\t\t\t\t\taction: {\n\t\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tnavigate({ to: '/sign-in', search: { me: email } });\n\t\t\t},\n\t\t});\n\t};\n\n\treturn (\n\t\t<div className=\"text-white w-xs\">\n\t\t\t<h2 className=\"text-2xl font-light\">Enter your account email</h2>\n\t\t\t<p className=\"text-sm pt-1\">If a matching account exists, we'll send you a password reset link.</p>\n\t\t\t<Form {...methods}>\n\t\t\t\t<form\n\t\t\t\t\tid=\"auth-forgot-password-form\"\n\t\t\t\t\tname=\"auth-forgot-password-form\"\n\t\t\t\t\tonSubmit={handleSubmit(submitForm)}\n\t\t\t\t\tclassName=\"my-4\"\n\t\t\t\t>\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"email\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem className=\"my-2\">\n\t\t\t\t\t\t\t\t<FormLabel>Email</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\tdisabled={isPending}\n\t\t\t\t\t\t\t\t\t\ttype=\"email\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t\t<Button type=\"submit\" variant=\"submit\" disabled={isPending} className=\"w-full my-2 rounded-full\">\n\t\t\t\t\t\tSend Password Reset Email\n\t\t\t\t\t</Button>\n\t\t\t\t</form>\n\t\t\t</Form>\n\t\t\t<div className=\"flex px-4 mt-4 underline place-content-between\">\n\t\t\t\t<Link className=\"text-sm hover:text-blue-300\" to=\"/sign-in\" search={{ me: email }}>\n\t\t\t\t\tSign in to your account\n\t\t\t\t</Link>\n\t\t\t\t<Link className=\"text-sm hover:text-blue-300\" to=\"/sign-up\" search={{ me: email }}>\n\t\t\t\t\tSign up for free\n\t\t\t\t</Link>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","import { apiClient } from '@/config/apiClient';\nimport { useMutation } from '@tanstack/react-query';\n\ntype ResetPasswordRequest = {\n\ttoken: string;\n\tpassword: string;\n};\n\ntype ResetPasswordResponse = {\n\tuserId: string;\n\temail: string;\n};\n\nconst onResetPasswordSubmit = async ({ token, password }: ResetPasswordRequest): Promise<ResetPasswordResponse> => {\n\t// TODO: The SchemaResetPassword is also not descriptive: Record<string, never> (which is really \"unknown\").\n\tconst { data } = await apiClient.put('/ResetPassword/', {\n\t\ttoken,\n\t\tnewPassword: password,\n\t});\n\t// TODO: The OpenAPI response for this endpoint isn't very good.\n\treturn data as ResetPasswordResponse;\n};\n\nexport function useResetPasswordMutation() {\n\treturn useMutation<ResetPasswordResponse, Error, ResetPasswordRequest>({\n\t\tmutationFn: (formData) => onResetPasswordSubmit(formData),\n\t});\n}\n","import { Button } from '@/components/ui/button';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { zodRequirePassword } from '@/lib/zod/password';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useNavigate, useSearch } from '@tanstack/react-router';\nimport { useCallback, useEffect } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useResetPasswordMutation } from './hooks/useResetPassword';\n\nconst ResetPasswordSchema = z\n\t.object({\n\t\tpassword: zodRequirePassword\n\t\t\t.min(8, { error: 'Password must be at least 8 characters long.' })\n\t\t\t.max(50, { error: 'Password cannot be longer than 50 characters.' }),\n\t\tconfirmPassword: z.string(),\n\t})\n\t.refine((data) => data.password === data.confirmPassword, {\n\t\terror: 'Passwords do not match.',\n\t\tpath: ['confirmPassword'],\n\t});\n\nexport function ResetPassword() {\n\tconst { token } = useSearch({ strict: false });\n\tconst navigate = useNavigate();\n\n\tuseEffect(() => {\n\t\tif (!token) {\n\t\t\tvoid navigate({ to: '/sign-in' });\n\t\t}\n\t}, [token, navigate]);\n\n\tconst methods = useForm({\n\t\tresolver: zodResolver(ResetPasswordSchema),\n\t\tdefaultValues: {\n\t\t\tpassword: '',\n\t\t\tconfirmPassword: '',\n\t\t},\n\t});\n\tconst { setFocus, control, handleSubmit } = methods;\n\n\tuseEffect(() => {\n\t\tsetFocus('password');\n\t}, [setFocus]);\n\n\tconst { mutate: submitResetPasswordData, isPending } = useResetPasswordMutation();\n\n\tconst submitForm = useCallback(async (formData: { password: string; confirmPassword: string }) => {\n\t\tsubmitResetPasswordData(\n\t\t\t{ token: token as string, password: formData.password },\n\t\t\t{\n\t\t\t\tonSuccess: () => {\n\t\t\t\t\ttoast.success('Success', {\n\t\t\t\t\t\tdescription: 'Your password has been reset successfully.',\n\t\t\t\t\t\taction: {\n\t\t\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tnavigate({ to: '/sign-in' });\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}, [navigate, submitResetPasswordData, token]);\n\n\treturn (\n\t\t<div className=\"text-white w-xs\">\n\t\t\t<h2 className=\"text-2xl font-light\">Reset Password</h2>\n\t\t\t<Form {...methods}>\n\t\t\t\t<form\n\t\t\t\t\tid=\"auth-reset-password-form\"\n\t\t\t\t\tname=\"auth-reset-password-form\"\n\t\t\t\t\tclassName=\"my-4\"\n\t\t\t\t\tonSubmit={handleSubmit(submitForm)}\n\t\t\t\t>\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"password\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem className=\"my-2\">\n\t\t\t\t\t\t\t\t<FormLabel>New Password</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\tdisabled={isPending}\n\t\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"confirmPassword\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem className=\"my-2\">\n\t\t\t\t\t\t\t\t<FormLabel>Confirm Password</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\tdisabled={isPending}\n\t\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t\t<Button variant=\"submit\" type=\"submit\" disabled={isPending} className=\"w-full my-2 rounded-full\">\n\t\t\t\t\t\tSubmit New Password\n\t\t\t\t\t</Button>\n\t\t\t\t</form>\n\t\t\t</Form>\n\t\t</div>\n\t);\n}\n","import './GitHubAuthenticationButton.css';\nimport { cx } from 'class-variance-authority';\nimport { MouseEventHandler } from 'react';\n\nexport function GitHubAuthenticationButton({\n\ttext,\n\tdisabled,\n\tonClick,\n}: {\n\ttext: 'Sign in with GitHub' | 'Sign up with GitHub';\n\tdisabled?: boolean;\n\tonClick?: MouseEventHandler<HTMLAnchorElement>;\n}) {\n\treturn (\n\t\t<a href=\"/oauth/github/login?redirect=%2F%23%2Fcheck-oauth\" onClick={onClick}>\n\t\t\t<button\n\t\t\t\tclassName={cx('github-signin-btn', disabled && 'opacity-50')}\n\t\t\t\ttype=\"button\"\n\t\t\t>\n\t\t\t\t<img src=\"/github/GitHub_Invertocat_White.svg\" alt=\"GitHub Logo\" className=\"github-icon\" />\n\t\t\t\t{text}\n\t\t\t</button>\n\t\t</a>\n\t);\n}\n","import './GoogleAuthenticationButton.css';\nimport { cx } from 'class-variance-authority';\nimport { MouseEventHandler } from 'react';\n\nexport function GoogleAuthenticationButton({\n\ttext,\n\tdisabled,\n\tonClick,\n}: {\n\ttext: 'Sign in with Google' | 'Sign up with Google';\n\tdisabled?: boolean;\n\tonClick?: MouseEventHandler<HTMLAnchorElement>;\n}) {\n\treturn (\n\t\t<a href=\"/oauth/google/login?redirect=%2F%23%2Fcheck-oauth\" onClick={onClick}>\n\t\t\t<button\n\t\t\t\tclassName={cx('gsi-material-button', disabled && 'opacity-50')}\n\t\t\t\ttype=\"button\"\n\t\t\t>\n\t\t\t\t<div className=\"gsi-material-button-state\"></div>\n\t\t\t\t<div className=\"gsi-material-button-content-wrapper\">\n\t\t\t\t\t<div className=\"gsi-material-button-icon\">\n\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\tversion=\"1.1\"\n\t\t\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\t\t\tviewBox=\"0 0 48 48\"\n\t\t\t\t\t\t\txmlnsXlink=\"http://www.w3.org/1999/xlink\"\n\t\t\t\t\t\t\tclassName=\"block\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t\tfill=\"#EA4335\"\n\t\t\t\t\t\t\t\td=\"M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t</path>\n\t\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t\tfill=\"#4285F4\"\n\t\t\t\t\t\t\t\td=\"M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t</path>\n\t\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t\tfill=\"#FBBC05\"\n\t\t\t\t\t\t\t\td=\"M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t</path>\n\t\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t\tfill=\"#34A853\"\n\t\t\t\t\t\t\t\td=\"M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t</path>\n\t\t\t\t\t\t\t<path fill=\"none\" d=\"M0 0h48v48H0z\"></path>\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t</div>\n\t\t\t\t\t<span className=\"gsi-material-button-contents\">{text}</span>\n\t\t\t\t\t<span className=\"hidden\">{text}</span>\n\t\t\t\t</div>\n\t\t\t</button>\n\t\t</a>\n\t);\n}\n","import { apiClient } from '@/config/apiClient';\nimport { currentUserQueryKey } from '@/features/auth/queries/getCurrentUser';\nimport { authStore, OverallAppSignIn } from '@/features/auth/store/authStore';\nimport { User } from '@/integrations/api/api.patch';\nimport { EmailSignInSchema } from '@/integrations/api/instance/auth/signInSchema';\nimport { loginSuccessDatadogAction } from '@/integrations/datadog/datadog';\nimport { reoClient } from '@/integrations/reo/reo';\nimport { parseCompanyFromEmail } from '@/lib/string/parseCompanyFromEmail';\nimport { getDefaultSignedInCloudRouteForUser } from '@/lib/urls/getDefaultSignedInCloudRouteForUser';\nimport { useMutation, useQueryClient } from '@tanstack/react-query';\nimport { useNavigate, useRouter, useSearch } from '@tanstack/react-router';\nimport { useCallback } from 'react';\nimport { z } from 'zod';\n\nexport function useCloudSignIn() {\n\tconst navigate = useNavigate();\n\tconst queryClient = useQueryClient();\n\tconst router = useRouter();\n\tconst { redirect } = useSearch({ strict: false });\n\n\tconst { mutate: submitLoginData, isPending } = useLoginMutation();\n\n\tconst submitForm = useCallback((formData: z.infer<typeof EmailSignInSchema>) => {\n\t\tsubmitLoginData(formData, {\n\t\t\tonSuccess: async (data) => {\n\t\t\t\tauthStore.setUserForEntity(OverallAppSignIn, data);\n\t\t\t\tconst defaultCloudRoute = getDefaultSignedInCloudRouteForUser(data);\n\n\t\t\t\tloginSuccessDatadogAction(data);\n\n\t\t\t\tconst company = parseCompanyFromEmail(data.email);\n\t\t\t\treoClient?.identify?.({\n\t\t\t\t\tusername: data.email,\n\t\t\t\t\ttype: 'email',\n\t\t\t\t\t...(company ? { company } : {}),\n\t\t\t\t});\n\t\t\t\tawait queryClient.invalidateQueries({ queryKey: currentUserQueryKey, refetchType: 'none' });\n\t\t\t\tvoid router.invalidate();\n\t\t\t\tawait navigate({ to: redirect?.startsWith('/') ? redirect : defaultCloudRoute });\n\t\t\t},\n\t\t});\n\t}, [navigate, queryClient, redirect, router, submitLoginData]);\n\n\treturn {\n\t\tisPending,\n\t\tsubmitForm,\n\t};\n}\n\nfunction useLoginMutation() {\n\treturn useMutation<User, Error, z.infer<typeof EmailSignInSchema>>({\n\t\tmutationFn: (loginData) => onLoginSubmit(loginData),\n\t});\n}\n\nasync function onLoginSubmit({ email, password }: z.infer<typeof EmailSignInSchema>) {\n\t// TODO: The OpenAPI request body for this endpoint isn't defined.\n\tconst { data } = await apiClient.post('/Login/', {\n\t\temail,\n\t\tpassword,\n\t});\n\tif (data) {\n\t\t// TODO: The OpenAPI response for this endpoint isn't defined.\n\t\treturn data as unknown as User;\n\t} else {\n\t\tthrow new Error('Something went wrong');\n\t}\n}\n","import { Button } from '@/components/ui/button';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { EmailSignInSchema } from '@/integrations/api/instance/auth/signInSchema';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { Link, useSearch } from '@tanstack/react-router';\nimport { useForm } from 'react-hook-form';\nimport { GitHubAuthenticationButton } from './components/GitHubAuthenticationButton';\nimport { GoogleAuthenticationButton } from './components/GoogleAuthenticationButton';\nimport { useCloudSignIn } from './hooks/useCloudSignIn';\n\nexport function SignIn() {\n\tconst { me: formPersistenceEmail } = useSearch({ strict: false });\n\n\tconst methods = useForm({\n\t\tresolver: zodResolver(EmailSignInSchema),\n\t\tdefaultValues: {\n\t\t\temail: formPersistenceEmail || '',\n\t\t\tpassword: '',\n\t\t},\n\t});\n\tconst { handleSubmit, control } = methods;\n\tconst email = methods.watch('email');\n\n\tconst { submitForm, isPending } = useCloudSignIn();\n\n\treturn (\n\t\t<div className=\"text-white w-xs\">\n\t\t\t<h2 className=\"text-2xl font-light\">Sign in to Harper Fabric</h2>\n\t\t\t<Form {...methods}>\n\t\t\t\t<form\n\t\t\t\t\tid=\"auth-signin-form\"\n\t\t\t\t\tname=\"auth-signin-form\"\n\t\t\t\t\tonSubmit={handleSubmit(submitForm)}\n\t\t\t\t\tclassName=\"my-4\"\n\t\t\t\t>\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"email\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem className=\"my-4\">\n\t\t\t\t\t\t\t\t<FormLabel>Email</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"email\"\n\t\t\t\t\t\t\t\t\t\tautoFocus={true}\n\t\t\t\t\t\t\t\t\t\tautoComplete=\"email\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"password\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem className=\"my-4\">\n\t\t\t\t\t\t\t\t<FormLabel>Password</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\t\tautoComplete=\"current-password\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t\t<Button type=\"submit\" variant=\"submit\" className=\"w-full my-2 rounded-full\" disabled={isPending}>\n\t\t\t\t\t\tSign In\n\t\t\t\t\t</Button>\n\t\t\t\t\t<div className=\"flex px-4 mt-4 underline place-content-between\">\n\t\t\t\t\t\t<Link className=\"text-sm hover:text-blue-300\" to=\"/sign-up\" search={{ me: email }}>\n\t\t\t\t\t\t\tSign up for free\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link className=\"text-sm hover:text-blue-300\" to=\"/forgot-password\" search={{ me: email }}>\n\t\t\t\t\t\t\tForgot password?\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t</div>\n\t\t\t\t</form>\n\t\t\t</Form>\n\n\t\t\t<hr className=\"border-gray-600 my-6\" />\n\n\t\t\t<div className=\"flex flex-col gap-2\">\n\t\t\t\t<GoogleAuthenticationButton text=\"Sign in with Google\" />\n\t\t\t\t<GitHubAuthenticationButton text=\"Sign in with GitHub\" />\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","export const personNameRegex =\n\t/^[a-zA-ZàáâäãåąčćęèéêëėįìíîïłńòóôöõøùúûüųūÿýżźñçčšžæÀÁÂÄÃÅĄĆČĖĘÈÉÊËÌÍÎÏĮŁŃÒÓÔÖÕØÙÚÛÜŲŪŸÝŻŹÑßÇŒÆČŠŽ∂ð ,'-]+$/u;\n","import { apiClient } from '@/config/apiClient';\nimport { SchemaUser } from '@/integrations/api/api.gen';\nimport { useMutation } from '@tanstack/react-query';\n\nexport interface SignUpCredentials extends Omit<SchemaUser, 'id'> {\n\temail: string;\n\tpassword: string;\n\tfirstname: string;\n\tlastname: string;\n}\n\nexport async function onSignUpSubmit(signUpCredentials: SignUpCredentials) {\n\t// TODO: The types in our OpenAPI for this endpoint aren't defined.\n\tconst { data } = await apiClient.post('/User/', signUpCredentials);\n\tif (data) {\n\t\treturn data;\n\t} else {\n\t\tthrow new Error('Something went wrong');\n\t}\n}\n\nexport function useSignUpMutation() {\n\treturn useMutation<SchemaUser, Error, SignUpCredentials>({\n\t\tmutationFn: (loginData) => onSignUpSubmit(loginData),\n\t});\n}\n","import { Button } from '@/components/ui/button';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { reoClient } from '@/integrations/reo/reo';\nimport { parseCompanyFromEmail } from '@/lib/string/parseCompanyFromEmail';\nimport { personNameRegex } from '@/lib/string/regex/personNameRegex';\nimport { zodRequireEmail } from '@/lib/zod/email';\nimport { zodRequirePassword } from '@/lib/zod/password';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { Link, useNavigate, useSearch } from '@tanstack/react-router';\nimport { MouseEvent, useCallback, useEffect, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { z } from 'zod';\nimport { GitHubAuthenticationButton } from './components/GitHubAuthenticationButton';\nimport { GoogleAuthenticationButton } from './components/GoogleAuthenticationButton';\nimport { useSignUpMutation } from './hooks/useSignUp';\n\nconst SignUpSchema = z.object({\n\temail: zodRequireEmail\n\t\t.max(80, { error: 'Email cannot be longer than 80 characters.' }),\n\tfirstname: z\n\t\t.string()\n\t\t.trim()\n\t\t.min(2, { error: 'Please enter your first name.' })\n\t\t.regex(\n\t\t\tpersonNameRegex,\n\t\t\t{ error: 'First name can only contain letters, spaces, and hyphens.' },\n\t\t)\n\t\t.max(40, { error: 'First name cannot be longer than 40 characters.' }),\n\tlastname: z\n\t\t.string()\n\t\t.trim()\n\t\t.min(2, { error: 'Please enter your last name.' })\n\t\t.regex(\n\t\t\tpersonNameRegex,\n\t\t\t{ error: 'Last name can only contain letters, spaces, and hyphens.' },\n\t\t)\n\t\t.max(80, { error: 'Last name cannot be longer than 80 characters.' }),\n\tpassword: zodRequirePassword\n\t\t.min(8, { error: 'Password must be at least 8 characters long.' }),\n\tconfirmPassword: z.string(),\n\tacceptTerms: z.boolean().refine(val => val === true, {\n\t\tmessage: 'You must accept the Privacy Policy and Terms of Service.',\n\t}),\n})\n\t.refine((data) => data.password === data.confirmPassword, {\n\t\terror: 'Passwords do not match.',\n\t\tpath: ['confirmPassword'],\n\t});\n\nexport function SignUp() {\n\tconst navigate = useNavigate();\n\tconst { email: searchEmail, me: formPersistenceEmail } = useSearch({ strict: false });\n\tconst [flashTerms, setFlashTerms] = useState(false);\n\n\tconst methods = useForm({\n\t\tresolver: zodResolver(SignUpSchema),\n\t\tdefaultValues: {\n\t\t\tfirstname: '',\n\t\t\tlastname: '',\n\t\t\temail: formPersistenceEmail || searchEmail || '',\n\t\t\tpassword: '',\n\t\t\tconfirmPassword: '',\n\t\t\tacceptTerms: false,\n\t\t},\n\t});\n\n\tconst email = methods.watch('email');\n\tconst acceptTerms = methods.watch('acceptTerms');\n\tconst { setFocus, control, handleSubmit } = methods;\n\n\tuseEffect(() => {\n\t\tsetFocus('firstname');\n\t}, [setFocus]);\n\n\tconst { mutate: submitSignUpData } = useSignUpMutation();\n\n\tconst submitForm = useCallback(async (formData: z.infer<typeof SignUpSchema>) => {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\t\tconst { confirmPassword, acceptTerms, ...userData } = formData;\n\t\tsubmitSignUpData(userData, {\n\t\t\tonSuccess: () => {\n\t\t\t\tconst company = parseCompanyFromEmail(userData.email);\n\t\t\t\treoClient?.identify?.({\n\t\t\t\t\tusername: userData.email,\n\t\t\t\t\ttype: 'email',\n\t\t\t\t\tfirstname: userData.firstname,\n\t\t\t\t\tlastname: userData.lastname,\n\t\t\t\t\t...(company ? { company } : {}),\n\t\t\t\t});\n\t\t\t\tvoid navigate({ to: '/verifying?email=' + encodeURIComponent(userData.email) });\n\t\t\t},\n\t\t});\n\t}, [navigate, submitSignUpData]);\n\n\tconst onOAuthClick = useCallback((e: MouseEvent) => {\n\t\tif (!acceptTerms) {\n\t\t\tsetFlashTerms(true);\n\t\t\tsetTimeout(() => setFlashTerms(false), 1000);\n\t\t\te.preventDefault();\n\t\t\treturn false;\n\t\t}\n\t}, [acceptTerms]);\n\n\tconst termsCheckbox = (\n\t\t<FormField\n\t\t\tcontrol={control}\n\t\t\tname=\"acceptTerms\"\n\t\t\trender={({ field }) => (\n\t\t\t\t<FormItem\n\t\t\t\t\tclassName={`flex flex-row items-start space-x-3 space-y-0 p-1 transition-colors duration-300 ${\n\t\t\t\t\t\tflashTerms ? 'bg-red-500/20 animate-pulse rounded' : ''\n\t\t\t\t\t}`}\n\t\t\t\t>\n\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\tclassName=\"size-4 rounded border-gray-300 bg-white text-purple-600 focus:ring-purple-500\"\n\t\t\t\t\t\t\tchecked={field.value}\n\t\t\t\t\t\t\tonChange={field.onChange}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</FormControl>\n\t\t\t\t\t<div className=\"space-y-1 leading-none\">\n\t\t\t\t\t\t<FormLabel className=\"text-xs font-normal\">\n\t\t\t\t\t\t\tI accept the{' '}\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\thref=\"https://www.harper.fast/resources/privacy-policy\"\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\t\t\tclassName=\"underline hover:text-blue-300\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tPrivacy Policy\n\t\t\t\t\t\t\t</a>{' '}\n\t\t\t\t\t\t\tand{' '}\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\thref=\"https://www.harper.fast/resources/paas-terms-of-service\"\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\t\t\tclassName=\"underline hover:text-blue-300\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tTerms of Service\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t</FormLabel>\n\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t</div>\n\t\t\t\t</FormItem>\n\t\t\t)}\n\t\t/>\n\t);\n\n\treturn (\n\t\t<div className=\"text-white w-xs\">\n\t\t\t<h2 className=\"text-2xl font-light\">Sign up for Harper Fabric</h2>\n\n\t\t\t<Form {...methods}>\n\t\t\t\t<div className=\"flex flex-col gap-2 my-6\">\n\t\t\t\t\t{termsCheckbox}\n\t\t\t\t\t<GoogleAuthenticationButton\n\t\t\t\t\t\ttext=\"Sign up with Google\"\n\t\t\t\t\t\tdisabled={!acceptTerms}\n\t\t\t\t\t\tonClick={onOAuthClick}\n\t\t\t\t\t/>\n\t\t\t\t\t<GitHubAuthenticationButton\n\t\t\t\t\t\ttext=\"Sign up with GitHub\"\n\t\t\t\t\t\tdisabled={!acceptTerms}\n\t\t\t\t\t\tonClick={onOAuthClick}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\n\t\t\t\t<hr className=\"border-gray-600\" />\n\n\t\t\t\t<form\n\t\t\t\t\tid=\"auth-signup-form\"\n\t\t\t\t\tname=\"auth-signup-form\"\n\t\t\t\t\tonSubmit={handleSubmit(submitForm)}\n\t\t\t\t\tclassName=\"grid gap-4 my-4\"\n\t\t\t\t>\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"firstname\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">First Name</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"words\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"lastname\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Last Name</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"words\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"email\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Email</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"email\"\n\t\t\t\t\t\t\t\t\t\treadOnly={!!searchEmail}\n\t\t\t\t\t\t\t\t\t\tdisabled={!!searchEmail}\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\tautoComplete=\"email\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"password\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Password</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\t\tautoComplete=\"new-password\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"confirmPassword\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Confirm Password</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\t\tautoComplete=\"new-password\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t\t{termsCheckbox}\n\n\t\t\t\t\t<Button type=\"submit\" variant=\"submit\" className=\"w-full rounded-full my-4\">\n\t\t\t\t\t\tSign Up For Free\n\t\t\t\t\t</Button>\n\t\t\t\t</form>\n\t\t\t</Form>\n\t\t\t<div className=\"flex px-4 mt-4 underline place-content-between\">\n\t\t\t\t<Link className=\"m-auto text-sm hover:text-blue-300\" to=\"/sign-in\" search={{ me: email }}>\n\t\t\t\t\tAlready have an account? Sign in instead.\n\t\t\t\t</Link>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","import { apiClient } from '@/config/apiClient';\nimport { useMutation } from '@tanstack/react-query';\n\nexport type ResendEmailVerificationRequest = {\n\temail: string;\n};\n\ntype ResendVerificationEmailResponse = {\n\temail: string;\n};\n\nconst onResendEmailVerificationSubmit = async ({\n\temail,\n}: ResendEmailVerificationRequest): Promise<ResendVerificationEmailResponse> => {\n\t// TODO: The OpenAPI request body for this endpoint isn't very descriptive.\n\tconst { data } = await apiClient.post<ResendEmailVerificationRequest>('/ResendVerificationEmail/', {\n\t\temail,\n\t});\n\treturn data;\n};\n\nexport function useResendEmailVerification() {\n\treturn useMutation<ResendVerificationEmailResponse, Error, ResendEmailVerificationRequest>({\n\t\tmutationFn: (loginData) => onResendEmailVerificationSubmit(loginData),\n\t});\n}\n","import { apiClient } from '@/config/apiClient';\nimport { useMutation } from '@tanstack/react-query';\n\ntype VerifyEmailToken = {\n\ttoken: string;\n};\n\ntype VerifyEmailResponse = {\n\tuseId: string;\n\temail: string;\n};\n\nconst onVerifyEmailTokenSubmit = async (token: VerifyEmailToken): Promise<VerifyEmailResponse> => {\n\t// TODO: The OpenAPI types don't describe the request body, either; Record<string, never>\n\tconst { data } = await apiClient.put<VerifyEmailToken>('/VerifyEmail/', {\n\t\ttoken: token.toString(),\n\t});\n\treturn data as VerifyEmailResponse;\n};\n\nfunction useVerifyEmailMutation() {\n\treturn useMutation<VerifyEmailResponse, Error, VerifyEmailToken>({\n\t\tmutationFn: (emailToken) => onVerifyEmailTokenSubmit(emailToken),\n\t});\n}\n\nexport type { VerifyEmailResponse, VerifyEmailToken };\nexport { useVerifyEmailMutation };\n","import { Button } from '@/components/ui/button';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { zodRequireEmail } from '@/lib/zod/email';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useNavigate, useSearch } from '@tanstack/react-router';\nimport { useCallback, useEffect } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useResendEmailVerification } from './hooks/useResendEmailVerification';\nimport { useVerifyEmailMutation, VerifyEmailToken } from './hooks/useVerifyEmail';\n\nconst VerifyEmailSchema = z.object({\n\temail: zodRequireEmail,\n});\n\nfunction SendEmailVerification() {\n\tconst navigate = useNavigate();\n\tconst { mutate: submitResendEmailVerification, isPending } = useResendEmailVerification();\n\tconst methods = useForm({\n\t\tresolver: zodResolver(VerifyEmailSchema),\n\t\tdefaultValues: {\n\t\t\temail: '',\n\t\t},\n\t});\n\tconst email = methods.watch('email');\n\tconst { setFocus, control, handleSubmit } = methods;\n\n\tuseEffect(() => {\n\t\tsetFocus('email');\n\t}, [setFocus]);\n\n\tconst submitForm = useCallback(async (formData: z.infer<typeof VerifyEmailSchema>) => {\n\t\tsubmitResendEmailVerification(formData, {\n\t\t\tonSuccess: (message) => {\n\t\t\t\ttoast.success('Success', {\n\t\t\t\t\tdescription: `${message}`,\n\t\t\t\t\taction: {\n\t\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tnavigate({ to: '/sign-in', search: { me: email } });\n\t\t\t},\n\t\t});\n\t}, [email, navigate, submitResendEmailVerification]);\n\n\treturn (\n\t\t<Form {...methods}>\n\t\t\t<p className=\"text-sm py-2\">Please Enter an Email</p>\n\t\t\t<form\n\t\t\t\tid=\"auth-verify-email-form\"\n\t\t\t\tname=\"auth-verify-email-form\"\n\t\t\t\tonSubmit={handleSubmit(submitForm)}\n\t\t\t\tclassName=\"my-4\"\n\t\t\t>\n\t\t\t\t<FormField\n\t\t\t\t\tcontrol={control}\n\t\t\t\t\tname=\"email\"\n\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t<FormItem className=\"my-2\">\n\t\t\t\t\t\t\t<FormLabel>Email</FormLabel>\n\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\tdisabled={isPending}\n\t\t\t\t\t\t\t\t\ttype=\"email\"\n\t\t\t\t\t\t\t\t\tclassName=\"bg-purple-400 border-purple-400 dark:bg-black dark:border-black\"\n\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t)}\n\t\t\t\t/>\n\t\t\t\t<Button type=\"submit\" variant=\"submit\" disabled={isPending} className=\"w-full my-2 rounded-full\">\n\t\t\t\t\tSend Verification Email\n\t\t\t\t</Button>\n\t\t\t</form>\n\t\t</Form>\n\t);\n}\n\nexport function VerifyEmail() {\n\tconst { token } = useSearch({ strict: false });\n\tconst navigate = useNavigate();\n\n\tconst { mutate: submitEmailVerificationToken, isPending } = useVerifyEmailMutation();\n\n\tconst submitEmailToken = useCallback(\n\t\t(emailToken: VerifyEmailToken) => {\n\t\t\tsubmitEmailVerificationToken(emailToken, {\n\t\t\t\tonSuccess: () => {\n\t\t\t\t\ttoast.success('Success', {\n\t\t\t\t\t\tdescription: 'Email verified successfully',\n\t\t\t\t\t\taction: {\n\t\t\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tvoid navigate({ to: '/sign-in' });\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t\t[submitEmailVerificationToken, navigate],\n\t);\n\n\tuseEffect(() => {\n\t\tif (token) {\n\t\t\tsubmitEmailToken(token);\n\t\t}\n\t}, [submitEmailToken, token]);\n\n\treturn (\n\t\t<div className=\"text-white w-xs\">\n\t\t\t<h1 className=\"text-3xl font-light\">Verify Email</h1>\n\t\t\t{!isPending ? <SendEmailVerification /> : <p className=\"text-sm pt-1\">Verifying email...</p>}\n\t\t</div>\n\t);\n}\n","import { Link, useSearch } from '@tanstack/react-router';\nimport { MouseEvent, useCallback } from 'react';\nimport { toast } from 'sonner';\nimport { useResendEmailVerification } from './hooks/useResendEmailVerification';\n\nexport function Verifying() {\n\tconst { email }: { email?: string } = useSearch({ strict: false });\n\n\tconst { mutate: resendEmailVerification, isPending } = useResendEmailVerification();\n\n\tconst resendCode = useCallback((e: MouseEvent) => {\n\t\te.preventDefault();\n\t\tif (email) {\n\t\t\tresendEmailVerification({ email }, {\n\t\t\t\tonSuccess: (message) => {\n\t\t\t\t\ttoast.success('Code Sent', {\n\t\t\t\t\t\tdescription: `${message}`,\n\t\t\t\t\t\taction: {\n\t\t\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t\treturn false;\n\t}, [email, resendEmailVerification]);\n\n\treturn (\n\t\t<div className=\"text-white w-lg flex flex-col gap-4\">\n\t\t\t<h1 className=\"text-3xl font-light\">\n\t\t\t\t<span\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\tclassName=\"text-2xl animate-flower-dance mr-4\"\n\t\t\t\t\ttitle=\"Loading\"\n\t\t\t\t>\n\t\t\t\t\t🌼\n\t\t\t\t</span>\n\t\t\t\tCheck your email!\n\t\t\t</h1>\n\t\t\t<p>\n\t\t\t\tYour account has been created! You should receive an email with a link to <strong>[Verify My Email]</strong>!\n\t\t\t</p>\n\t\t\t<p>\n\t\t\t\tFrom: <strong>harper@notifications.harperfabric.com</strong>\n\t\t\t</p>\n\t\t\t<p>\n\t\t\t\tTo: <strong>{email || 'your email'}</strong>\n\t\t\t</p>\n\t\t\t<p>Can you click it? Then we can carry on to more fun things!</p>\n\n\t\t\t<div className=\"underline flex gap-4\">\n\t\t\t\t<Link className=\"text-sm hover:text-blue-300\" to=\"/sign-in\" search={{ me: email }}>\n\t\t\t\t\tI did it, let me sign in!\n\t\t\t\t</Link>\n\t\t\t\t<Link\n\t\t\t\t\tclassName=\"text-sm opacity-50 hover:text-blue-300\"\n\t\t\t\t\tto={undefined}\n\t\t\t\t\tonClick={resendCode}\n\t\t\t\t\tdisabled={isPending}\n\t\t\t\t>\n\t\t\t\t\tSend me another code, please.\n\t\t\t\t</Link>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","import { defaultInstanceRoute } from '@/config/constants';\nimport { getDefaultSignedInCloudRouteForUser } from '@/lib/urls/getDefaultSignedInCloudRouteForUser';\nimport { rootRoute } from '@/router/rootRoute';\nimport { createRoute, redirect } from '@tanstack/react-router';\nimport { AuthLayout } from './AuthLayout';\nimport { CheckOAuth } from './CheckOAuth';\nimport { ClusterInstanceSignIn } from './ClusterInstanceSignIn';\nimport { ForgotPassword } from './ForgotPassword';\nimport { ResetPassword } from './ResetPassword';\nimport { SignIn } from './SignIn';\nimport { SignUp } from './SignUp';\nimport { OverallAppSignIn } from './store/authStore';\nimport { VerifyEmail } from './VerifyEmail';\nimport { Verifying } from './Verifying';\n\nconst authLayout = createRoute({\n\tgetParentRoute: () => rootRoute,\n\tid: '_authLayout',\n\tcomponent: AuthLayout,\n});\n\nconst signInRoute = createRoute({\n\tgetParentRoute: () => authLayout,\n\tpath: 'sign-in',\n\tcomponent: SignIn,\n\tbeforeLoad: ({ context, location }) => {\n\t\tconst user = context.authentication[OverallAppSignIn]?.user;\n\t\tif (user) {\n\t\t\tconst search: Record<string, string> = location?.search;\n\t\t\tconst defaultRoute = getDefaultSignedInCloudRouteForUser(user);\n\t\t\tthrow redirect({ to: search?.redirect?.startsWith('/') ? search.redirect : defaultRoute });\n\t\t}\n\t},\n});\n\nconst localSignInRoute = createRoute({\n\tgetParentRoute: () => rootRoute,\n\tpath: 'sign-in',\n\tcomponent: ClusterInstanceSignIn,\n\tbeforeLoad: ({ context, location }) => {\n\t\tif (context.authentication[OverallAppSignIn]?.user) {\n\t\t\tconst search: Record<string, string> = location?.search;\n\t\t\tthrow redirect({ to: search?.redirect?.startsWith('/') ? search.redirect : defaultInstanceRoute });\n\t\t}\n\t},\n});\n\nconst signUpRoute = createRoute({\n\tgetParentRoute: () => authLayout,\n\tpath: 'sign-up',\n\tcomponent: SignUp,\n});\nconst forgotPasswordRoute = createRoute({\n\tgetParentRoute: () => authLayout,\n\tpath: 'forgot-password',\n\tcomponent: ForgotPassword,\n});\n\nconst verifyEmailRoute = createRoute({\n\tgetParentRoute: () => authLayout,\n\tpath: 'verify-email',\n\tcomponent: VerifyEmail,\n});\n\nconst verifyingEmailRoute = createRoute({\n\tgetParentRoute: () => authLayout,\n\tpath: 'verifying',\n\tcomponent: Verifying,\n});\n\nconst checkOAuthRoute = createRoute({\n\tgetParentRoute: () => authLayout,\n\tpath: 'check-oauth',\n\tcomponent: CheckOAuth,\n});\n\nconst resetPasswordRoute = createRoute({\n\tgetParentRoute: () => authLayout,\n\tpath: 'reset-password',\n\tcomponent: ResetPassword,\n});\n\nexport const authRouteTree = authLayout.addChildren([\n\tsignInRoute,\n\tsignUpRoute,\n\tcheckOAuthRoute,\n\tforgotPasswordRoute,\n\tverifyEmailRoute,\n\tverifyingEmailRoute,\n\tresetPasswordRoute,\n]);\n\nexport const localAuthRoutes = [\n\tlocalSignInRoute,\n];\n","import { Breadcrumbs } from '@/components/Breadcrumbs';\nimport { ReactNode } from 'react';\n\nexport function SubNavMenu({ children }: { children?: ReactNode }) {\n\treturn (\n\t\t<nav className=\"fixed top-20 w-full h-12 z-39 py-2 px-4 md:px-12 bg-grey-700\">\n\t\t\t<div className=\"flex items-center h-full space-x-2\">\n\t\t\t\t<Breadcrumbs />\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</nav>\n\t);\n}\n","export type BadgeStatusVariant =\n\t| string\n\t| 'PROVISIONING'\n\t| 'CLONE_PENDING'\n\t| 'UPDATING_HDB_NODES'\n\t| 'UPDATING'\n\t| 'CLONE_READY'\n\t| 'RUNNING'\n\t| 'UPDATED'\n\t| 'STOPPED'\n\t| 'FAILED'\n\t| 'TERMINATED'\n\t| 'TERMINATING'\n\t| 'ERROR'\n\t| 'REMOVED';\n\nexport type BadgeStatusVariantValues = 'warning' | 'success' | 'secondary' | 'destructive' | 'outline' | 'default';\n\nexport function renderBadgeStatusVariant(value: BadgeStatusVariant): BadgeStatusVariantValues {\n\tif (isPendingUpdate(value) || isBeingUpdated(value)) {\n\t\treturn 'warning';\n\t}\n\tif (isRunning(value)) {\n\t\treturn 'success';\n\t}\n\tswitch (value) {\n\t\tcase 'STOPPED':\n\t\t\treturn 'secondary';\n\t\tcase 'TERMINATING':\n\t\tcase 'TERMINATED':\n\t\tcase 'FAILED':\n\t\tcase 'REMOVED':\n\t\tcase 'ERROR':\n\t\t\treturn 'destructive';\n\t\tdefault:\n\t\t\treturn 'default';\n\t}\n}\n\nexport function isRunning(value: string | undefined): value is 'RUNNING' | 'UPDATED' {\n\tswitch (value) {\n\t\tcase 'RUNNING':\n\t\tcase 'UPDATED':\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nexport function isFailed(value: string | undefined): value is 'FAILED' {\n\tswitch (value) {\n\t\tcase 'FAILED':\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nexport function isTerminated(value: string | undefined): value is 'TERMINATED' {\n\tswitch (value) {\n\t\tcase 'TERMINATED':\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nexport function isPendingUpdate(value: string | undefined): value is 'CLONE_PENDING' {\n\tswitch (value) {\n\t\tcase 'CLONE_PENDING':\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nexport function isBeingUpdated(\n\tvalue: string | undefined,\n): value is 'PROVISIONING' | 'CLONING' | 'CLONE_READY' | 'UPDATING_HDB_NODES' | 'UPDATING' {\n\tswitch (value) {\n\t\tcase 'PROVISIONING':\n\t\tcase 'CLONING':\n\t\tcase 'CLONE_READY':\n\t\tcase 'UPDATING_HDB_NODES':\n\t\tcase 'UPDATING':\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n","import * as DialogPrimitive from '@radix-ui/react-dialog';\nimport { XIcon } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn } from '@/lib/cn';\n\nfunction Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) {\n\treturn <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nfunction DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {\n\treturn <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />;\n}\n\nfunction DialogPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>) {\n\treturn <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />;\n}\n\nfunction DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) {\n\treturn <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />;\n}\n\nfunction DialogOverlay({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {\n\treturn (\n\t\t<DialogPrimitive.Overlay\n\t\t\tdata-slot=\"dialog-overlay\"\n\t\t\tclassName={cn(\n\t\t\t\t'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black-dark/90',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction DialogContent({ className, children, ...props }: React.ComponentProps<typeof DialogPrimitive.Content>) {\n\treturn (\n\t\t<DialogPortal data-slot=\"dialog-portal\">\n\t\t\t<DialogOverlay />\n\t\t\t<DialogPrimitive.Content\n\t\t\t\tdata-slot=\"dialog-content\"\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'bg-black '\n\t\t\t\t\t\t+ 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 '\n\t\t\t\t\t\t+ 'fixed top-[50%] left-[50%] z-50 grid '\n\t\t\t\t\t\t+ 'w-full max-w-[calc(100%-2rem)] lg:max-w-2xl '\n\t\t\t\t\t\t+ 'max-h-screen overflow-y-auto '\n\t\t\t\t\t\t+ 'translate-x-[-50%] translate-y-[-50%] '\n\t\t\t\t\t\t+ 'gap-4 rounded-md p-6 shadow-lg '\n\t\t\t\t\t\t+ 'duration-200',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t\t<DialogPrimitive.Close className=\"ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\">\n\t\t\t\t\t<XIcon className=\"text-white\" />\n\t\t\t\t\t<span className=\"sr-only\">Close</span>\n\t\t\t\t</DialogPrimitive.Close>\n\t\t\t</DialogPrimitive.Content>\n\t\t</DialogPortal>\n\t);\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<'div'>) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"dialog-header\"\n\t\t\tclassName={cn('flex flex-col gap-2 text-center sm:text-left', className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction DialogFooter({ className, ...props }: React.ComponentProps<'div'>) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"dialog-footer\"\n\t\t\tclassName={cn('flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {\n\treturn (\n\t\t<DialogPrimitive.Title\n\t\t\tdata-slot=\"dialog-title\"\n\t\t\tclassName={cn('text-lg leading-none text-white font-semibold', className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction DialogDescription({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Description>) {\n\treturn (\n\t\t<DialogPrimitive.Description\n\t\t\tdata-slot=\"dialog-description\"\n\t\t\tclassName={cn('text-muted-foreground text-sm', className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport {\n\tDialog,\n\tDialogClose,\n\tDialogContent,\n\tDialogDescription,\n\tDialogFooter,\n\tDialogHeader,\n\tDialogOverlay,\n\tDialogPortal,\n\tDialogTitle,\n\tDialogTrigger,\n};\n","import { Button } from '@/components/ui/button';\nimport {\n\tDialog,\n\tDialogContent,\n\tDialogDescription,\n\tDialogFooter,\n\tDialogHeader,\n\tDialogTitle,\n\tDialogTrigger,\n} from '@/components/ui/dialog';\nimport { ArrowLeft, Trash, TriangleAlert } from 'lucide-react';\nimport { ReactNode } from 'react';\n\nexport function ConfirmDeletionModal({\n\ttypeOfThingBeingDeleted,\n\tnameOfThingBeingDeleted,\n\tisModalOpen,\n\thideDataLossWarning,\n\tsetIsModalOpen,\n\tdeletionConfirmed,\n\tdeletionPending,\n\ttrigger,\n\tpresentParticiple = 'Deleting',\n\ttransitiveVerb = 'Delete',\n}: {\n\ttypeOfThingBeingDeleted: string;\n\tnameOfThingBeingDeleted?: string;\n\tisModalOpen: boolean;\n\thideDataLossWarning?: boolean;\n\tsetIsModalOpen: (isOpen: boolean) => void;\n\tdeletionConfirmed: () => void;\n\tdeletionPending: boolean;\n\ttrigger?: ReactNode;\n\tpresentParticiple?: 'Deleting' | 'Terminating' | string;\n\ttransitiveVerb?: 'Delete' | 'Terminate' | string;\n}) {\n\treturn (\n\t\t<Dialog open={isModalOpen} onOpenChange={setIsModalOpen}>\n\t\t\t{trigger && (\n\t\t\t\t<DialogTrigger asChild>\n\t\t\t\t\t{trigger}\n\t\t\t\t</DialogTrigger>\n\t\t\t)}\n\t\t\t<DialogContent className=\"sm:max-w-[750px]\">\n\t\t\t\t<DialogHeader>\n\t\t\t\t\t<DialogTitle>\n\t\t\t\t\t\tAre you sure you want to {transitiveVerb.toLowerCase()} this {typeOfThingBeingDeleted}?\n\t\t\t\t\t</DialogTitle>\n\t\t\t\t\t<DialogDescription>This action cannot be undone.</DialogDescription>\n\t\t\t\t</DialogHeader>\n\t\t\t\t{!hideDataLossWarning && (\n\t\t\t\t\t<div className=\"p-3 my-5 text-white rounded-md bg-amber-600\">\n\t\t\t\t\t\t<p className=\"flex space-x-1 font-semibold align-baseline\">\n\t\t\t\t\t\t\t<TriangleAlert className=\"inline-block size-5\" /> <span>Warning</span>\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p className=\"pt-2 text-base\">\n\t\t\t\t\t\t\tBy {presentParticiple.toLowerCase()} {typeOfThingBeingDeleted}{' '}\n\t\t\t\t\t\t\t<span className=\"font-semibold\">{nameOfThingBeingDeleted}</span>{' '}\n\t\t\t\t\t\t\tyou will lose the data stored in it permanently.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t<DialogFooter>\n\t\t\t\t\t<div className=\"flex justify-center space-x-5\">\n\t\t\t\t\t\t<Button type=\"button\" className=\"rounded-full\" onClick={() => setIsModalOpen(false)}>\n\t\t\t\t\t\t\t<ArrowLeft /> Cancel\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"destructive\"\n\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\tonClick={deletionConfirmed}\n\t\t\t\t\t\t\tdisabled={deletionPending}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Trash /> {transitiveVerb}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t</DialogFooter>\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { badgeVariants } from '@/components/ui/badgeVariants';\nimport { cn } from '@/lib/cn';\nimport { Slot } from '@radix-ui/react-slot';\nimport { type VariantProps } from 'class-variance-authority';\nimport * as React from 'react';\n\nexport function Badge({\n\tclassName,\n\tvariant,\n\tasChild = false,\n\t...props\n}: React.ComponentProps<'span'> & VariantProps<typeof badgeVariants> & { asChild?: boolean }) {\n\tconst Comp = asChild ? Slot : 'span';\n\n\treturn <Comp data-slot=\"badge\" className={cn(badgeVariants({ variant }), className)} {...props} />;\n}\n","import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\nimport { CheckIcon, ChevronRightIcon, CircleIcon } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn } from '@/lib/cn';\n\nfunction DropdownMenu({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {\n\treturn <DropdownMenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />;\n}\n\nfunction DropdownMenuPortal({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {\n\treturn <DropdownMenuPrimitive.Portal data-slot=\"dropdown-menu-portal\" {...props} />;\n}\n\nfunction DropdownMenuTrigger({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {\n\treturn <DropdownMenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />;\n}\n\nfunction DropdownMenuContent({\n\tclassName,\n\tsideOffset = 4,\n\t...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {\n\treturn (\n\t\t<DropdownMenuPrimitive.Portal>\n\t\t\t<DropdownMenuPrimitive.Content\n\t\t\t\tdata-slot=\"dropdown-menu-content\"\n\t\t\t\tsideOffset={sideOffset}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border border-grey-700 p-1 shadow-md',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t</DropdownMenuPrimitive.Portal>\n\t);\n}\n\nfunction DropdownMenuGroup({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {\n\treturn <DropdownMenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />;\n}\n\nfunction DropdownMenuItem({\n\tclassName,\n\tinset,\n\tvariant = 'default',\n\t...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {\n\tinset?: boolean;\n\tvariant?: 'default' | 'destructive';\n}) {\n\treturn (\n\t\t<DropdownMenuPrimitive.Item\n\t\t\tdata-slot=\"dropdown-menu-item\"\n\t\t\tdata-inset={inset}\n\t\t\tdata-variant={variant}\n\t\t\tclassName={cn(\n\t\t\t\t'focus:bg-accent focus:text-grey '\n\t\t\t\t\t+ 'data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 '\n\t\t\t\t\t+ 'dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive '\n\t\t\t\t\t+ \"data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground \"\n\t\t\t\t\t+ 'relative flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm '\n\t\t\t\t\t+ 'outline-hidden select-none '\n\t\t\t\t\t+ 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 '\n\t\t\t\t\t+ \"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction DropdownMenuCheckboxItem({\n\tclassName,\n\tchildren,\n\tchecked,\n\t...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {\n\treturn (\n\t\t<DropdownMenuPrimitive.CheckboxItem\n\t\t\tdata-slot=\"dropdown-menu-checkbox-item\"\n\t\t\tclassName={cn(\n\t\t\t\t'focus:bg-primary relative flex cursor-pointer items-center gap-2 rounded-sm'\n\t\t\t\t\t+ ' py-1.5 pr-2 pl-8'\n\t\t\t\t\t+ ' text-sm outline-hidden'\n\t\t\t\t\t+ ' select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50'\n\t\t\t\t\t+ \" [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tchecked={checked}\n\t\t\t{...props}\n\t\t>\n\t\t\t<span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n\t\t\t\t<DropdownMenuPrimitive.ItemIndicator>\n\t\t\t\t\t<CheckIcon className=\"size-4\" />\n\t\t\t\t</DropdownMenuPrimitive.ItemIndicator>\n\t\t\t</span>\n\t\t\t{children}\n\t\t</DropdownMenuPrimitive.CheckboxItem>\n\t);\n}\n\nfunction DropdownMenuRadioGroup({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {\n\treturn <DropdownMenuPrimitive.RadioGroup data-slot=\"dropdown-menu-radio-group\" {...props} />;\n}\n\nfunction DropdownMenuRadioItem({\n\tclassName,\n\tchildren,\n\t...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {\n\treturn (\n\t\t<DropdownMenuPrimitive.RadioItem\n\t\t\tdata-slot=\"dropdown-menu-radio-item\"\n\t\t\tclassName={cn(\n\t\t\t\t\"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n\t\t\t\t<DropdownMenuPrimitive.ItemIndicator>\n\t\t\t\t\t<CircleIcon className=\"size-2 fill-current\" />\n\t\t\t\t</DropdownMenuPrimitive.ItemIndicator>\n\t\t\t</span>\n\t\t\t{children}\n\t\t</DropdownMenuPrimitive.RadioItem>\n\t);\n}\n\nfunction DropdownMenuLabel({\n\tclassName,\n\tinset,\n\t...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {\n\tinset?: boolean;\n}) {\n\treturn (\n\t\t<DropdownMenuPrimitive.Label\n\t\t\tdata-slot=\"dropdown-menu-label\"\n\t\t\tdata-inset={inset}\n\t\t\tclassName={cn('px-2 py-1.5 text-sm font-medium data-[inset]:pl-8', className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction DropdownMenuSeparator({ className, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {\n\treturn (\n\t\t<DropdownMenuPrimitive.Separator\n\t\t\tdata-slot=\"dropdown-menu-separator\"\n\t\t\tclassName={cn('bg-grey-700 -mx-1 my-1 h-px', className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction DropdownMenuShortcut({ className, ...props }: React.ComponentProps<'span'>) {\n\treturn (\n\t\t<span\n\t\t\tdata-slot=\"dropdown-menu-shortcut\"\n\t\t\tclassName={cn('text-muted-foreground ml-auto text-xs tracking-widest', className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction DropdownMenuSub({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {\n\treturn <DropdownMenuPrimitive.Sub data-slot=\"dropdown-menu-sub\" {...props} />;\n}\n\nfunction DropdownMenuSubTrigger({\n\tclassName,\n\tinset,\n\tchildren,\n\t...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {\n\tinset?: boolean;\n}) {\n\treturn (\n\t\t<DropdownMenuPrimitive.SubTrigger\n\t\t\tdata-slot=\"dropdown-menu-sub-trigger\"\n\t\t\tdata-inset={inset}\n\t\t\tclassName={cn(\n\t\t\t\t'focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t\t<ChevronRightIcon className=\"ml-auto size-4\" />\n\t\t</DropdownMenuPrimitive.SubTrigger>\n\t);\n}\n\nfunction DropdownMenuSubContent({\n\tclassName,\n\t...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {\n\treturn (\n\t\t<DropdownMenuPrimitive.SubContent\n\t\t\tdata-slot=\"dropdown-menu-sub-content\"\n\t\t\tclassName={cn(\n\t\t\t\t'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport {\n\tDropdownMenu,\n\tDropdownMenuCheckboxItem,\n\tDropdownMenuContent,\n\tDropdownMenuGroup,\n\tDropdownMenuItem,\n\tDropdownMenuLabel,\n\tDropdownMenuPortal,\n\tDropdownMenuRadioGroup,\n\tDropdownMenuRadioItem,\n\tDropdownMenuSeparator,\n\tDropdownMenuShortcut,\n\tDropdownMenuSub,\n\tDropdownMenuSubContent,\n\tDropdownMenuSubTrigger,\n\tDropdownMenuTrigger,\n};\n","import { Cluster } from '@/integrations/api/api.patch';\n\nexport function clusterIsSelfManaged(cluster: Cluster | undefined): boolean {\n\treturn !!cluster?.plans?.[0]?.planId?.startsWith('self-hosted');\n}\n","import { Button } from '@/components/ui/button';\nimport { defaultInstanceRoute } from '@/config/constants';\nimport { authStore } from '@/features/auth/store/authStore';\nimport { useInstanceAuth } from '@/hooks/useAuth';\nimport { useOrganizationClusterPermissions } from '@/hooks/usePermissions';\nimport { Cluster } from '@/integrations/api/api.patch';\nimport { clusterIsSelfManaged } from '@/integrations/api/clusterIsSelfManaged';\nimport { Link } from '@tanstack/react-router';\nimport { ArrowRight } from 'lucide-react';\n\nexport function ClusterCardAction({ cluster }: { cluster: Cluster }) {\n\tconst auth = useInstanceAuth(cluster.id);\n\tconst { view, update } = useOrganizationClusterPermissions(cluster.organizationId, cluster.id);\n\tconst isFabricConnect = authStore.checkForFabricConnect(cluster.id);\n\tconst isDirectConnect = !isFabricConnect && !!auth.user;\n\n\tif (!view) {\n\t\treturn undefined;\n\t}\n\n\tif (!cluster.fqdn) {\n\t\treturn (\n\t\t\t<Link\n\t\t\t\tto={`/${cluster.organizationId}/${cluster.id}/instances`}\n\t\t\t\tclassName=\"text-sm text-nowrap\"\n\t\t\t\taria-label={`View ${cluster.name}`}\n\t\t\t\ttitle={`View ${cluster.name}`}\n\t\t\t>\n\t\t\t\t<span className=\"py-2 hover:border-b-2\">\n\t\t\t\t\tInstances <ArrowRight className=\"inline-block\" />\n\t\t\t\t</span>\n\t\t\t</Link>\n\t\t);\n\t}\n\n\tif (cluster.resetPassword) {\n\t\tif (update) {\n\t\t\treturn (\n\t\t\t\t<Link\n\t\t\t\t\tto={`/${cluster.organizationId}/${cluster.id}/finish-setup`}\n\t\t\t\t\tclassName=\"text-sm text-nowrap\"\n\t\t\t\t\taria-label={`Set Password on ${cluster.name}`}\n\t\t\t\t\ttitle={`Set Password on ${cluster.name}`}\n\t\t\t\t>\n\t\t\t\t\t<Button variant=\"positive\" className=\"py-2 hover:border-b-2 animate-glow-pulse\">\n\t\t\t\t\t\tFinish Setup <ArrowRight className=\"inline-block\" />\n\t\t\t\t\t</Button>\n\t\t\t\t</Link>\n\t\t\t);\n\t\t}\n\t\treturn (\n\t\t\t<span className=\"py-2 text-nowrap\">\n\t\t\t\tPending Owner Setup\n\t\t\t</span>\n\t\t);\n\t}\n\n\tif (auth.isLoading) {\n\t\treturn undefined;\n\t}\n\n\tif (isDirectConnect) {\n\t\treturn (\n\t\t\t<Link\n\t\t\t\tto={`/${cluster.organizationId}/${cluster.id}${defaultInstanceRoute}`}\n\t\t\t\tclassName=\"text-sm text-nowrap\"\n\t\t\t\taria-label={`View ${cluster.name}`}\n\t\t\t\ttitle={`View ${cluster.name}`}\n\t\t\t>\n\t\t\t\t<span className=\"py-2 hover:border-b-2\">\n\t\t\t\t\tDirect Connect <ArrowRight className=\"inline-block\" />\n\t\t\t\t</span>\n\t\t\t</Link>\n\t\t);\n\t}\n\n\tif (update && !clusterIsSelfManaged(cluster)) {\n\t\treturn (\n\t\t\t<Link\n\t\t\t\tto={`/${cluster.organizationId}/${cluster.id}${defaultInstanceRoute}`}\n\t\t\t\tclassName=\"text-sm text-nowrap\"\n\t\t\t\taria-label={`Connect to ${cluster.name}`}\n\t\t\t\ttitle={`Connect to ${cluster.name}`}\n\t\t\t>\n\t\t\t\t<span className=\"py-2 hover:border-b-2\">\n\t\t\t\t\tFabric Connect <ArrowRight className=\"inline-block\" />\n\t\t\t\t</span>\n\t\t\t</Link>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Link\n\t\t\tto={`/${cluster.organizationId}/${cluster.id}/sign-in`}\n\t\t\tclassName=\"text-sm text-nowrap\"\n\t\t\taria-label={`Sign In to ${cluster.name}`}\n\t\t\ttitle={`Sign In to ${cluster.name}`}\n\t\t>\n\t\t\t<span className=\"py-2 hover:border-b-2\">\n\t\t\t\tDirect Sign In <ArrowRight className=\"inline-block\" />\n\t\t\t</span>\n\t\t</Link>\n\t);\n}\n","export function mapBy<T, F extends keyof T>(array: T[], fieldName: F): T[F][] {\n\tconst values: T[F][] = [];\n\tif (array) {\n\t\tfor (const element of array) {\n\t\t\tvalues.push(element[fieldName]);\n\t\t}\n\t}\n\treturn values;\n}\n","import { isBeingUpdated, isFailed, isPendingUpdate, isRunning, isTerminated } from '@/components/ui/utils/badgeStatus';\nimport { getClusterInfoQueryOptions } from '@/features/cluster/queries/getClusterInfoQuery';\nimport { Cluster } from '@/integrations/api/api.patch';\nimport { mapBy } from '@/lib/arrays/mapBy';\nimport { capitalizeWords } from '@/lib/string/capitalizeWords';\nimport { useQuery } from '@tanstack/react-query';\nimport { useEffect, useMemo, useState } from 'react';\n\n/**\n * Displays a triple segment progress bar to the user which will let them watch their instance(s) progress through:\n * \t1. Pending (Clone Pending or Clone Ready)\n * \t2. Updating (Provisioning or Cloning)\n * \t3. Running (Running or Updated)\n */\nexport function ClusterProgress({ cluster, forceProgressBarVisible }: {\n\tcluster: Pick<Cluster, 'status' | 'id'>;\n\tforceProgressBarVisible?: boolean;\n}) {\n\tconst [showProgress, setShowProgress] = useState(forceProgressBarVisible || false);\n\n\tconst { data: clusterById } = useQuery(\n\t\tgetClusterInfoQueryOptions(showProgress && cluster.id, 2_000),\n\t);\n\n\tuseEffect(function showProgressIfPendingOrUpdating() {\n\t\tif (isPendingUpdate(cluster.status) || isBeingUpdated(cluster.status)) {\n\t\t\t// If the cluster is ever pending or updating, we want the progress bar to stick open for that card until they\n\t\t\t// navigate away or refresh. So we can setShowProgress to true safely.\n\t\t\t// eslint-disable-next-line react-hooks/set-state-in-effect\n\t\t\tsetShowProgress(true);\n\t\t}\n\t}, [showProgress, cluster.status, clusterById?.instances]);\n\n\tconst updating = useMemo(() => {\n\t\tconst activePlanIds = mapBy(clusterById?.plans ?? [], 'planId');\n\t\tconst instances = clusterById?.instances ?? [];\n\t\tlet pending = 0;\n\t\tconst pendingTexts: Record<string, string> = {};\n\t\tlet updating = 0;\n\t\tconst updatingTexts: Record<string, string> = {};\n\t\tlet running = 0;\n\t\tconst runningTexts: Record<string, string> = {};\n\t\tlet failed = 0;\n\t\tconst failedTexts: Record<string, string> = {};\n\t\tfor (const instance of instances) {\n\t\t\tconst status = instance.status;\n\t\t\tif (!status || isTerminated(status)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (isPendingUpdate(status)) {\n\t\t\t\tpending += 1;\n\t\t\t\tpendingTexts[status] = `${pending} ${capitalizeWords(status)}`;\n\t\t\t} else if (isBeingUpdated(status)) {\n\t\t\t\tupdating += 1;\n\t\t\t\tupdatingTexts[status] = `${updating} ${capitalizeWords(status)}`;\n\t\t\t} else if (isFailed(status)) {\n\t\t\t\tfailed += 1;\n\t\t\t\tfailedTexts[status] = `${failed} ${capitalizeWords(status)}`;\n\t\t\t} else if (!instance.planId || !activePlanIds.includes(instance.planId)) {\n\t\t\t\tupdating += 1;\n\t\t\t\tupdatingTexts['DRAINING_TRAFFIC'] = `${updating} ${capitalizeWords('Draining Traffic')}`;\n\t\t\t} else if (isRunning(status)) {\n\t\t\t\trunning += 1;\n\t\t\t\trunningTexts[status] = `${running} ${capitalizeWords(status)}`;\n\t\t\t}\n\t\t\t// We'll ignore terminated or non-updated instances from the totals.\n\t\t}\n\t\tconst total = pending + updating + running;\n\t\treturn {\n\t\t\tpendingWidth: `${total === 0 ? 100 : pending === 0 ? 0 : (pending / total * 100)}%`,\n\t\t\tupdatingWidth: `${updating === 0 ? 0 : (updating / total * 100)}%`,\n\t\t\tfailedWidth: `${failed === 0 ? 0 : (failed / total * 100)}%`,\n\t\t\trunningWidth: `${running === 0 ? 0 : (running / total * 100)}%`,\n\t\t\ttext: [\n\t\t\t\t...Object.values(runningTexts).sort(),\n\t\t\t\t...Object.values(failedTexts).sort(),\n\t\t\t\t...Object.values(updatingTexts).sort(),\n\t\t\t\t...Object.values(pendingTexts).sort(),\n\t\t\t].join(' · '),\n\t\t};\n\t}, [clusterById]);\n\n\tif (!showProgress) {\n\t\treturn null;\n\t}\n\treturn (\n\t\t<div className=\"w-full text-center\">\n\t\t\t<div className=\"w-full h-2.5 rounded-full overflow-clip flex shadow\">\n\t\t\t\t{/*Running*/}\n\t\t\t\t<div\n\t\t\t\t\tstyle={{ width: updating.runningWidth }}\n\t\t\t\t\tclassName=\"grow bg-green/80 transition-[width] duration-1000 ease-in-out motion-reduce:transition-none\"\n\t\t\t\t>\n\t\t\t\t</div>\n\t\t\t\t{/*Failed*/}\n\t\t\t\t<div\n\t\t\t\t\tstyle={{ width: updating.failedWidth }}\n\t\t\t\t\tclassName=\"grow bg-red/80 transition-[width] duration-1000 ease-in-out motion-reduce:transition-none\"\n\t\t\t\t>\n\t\t\t\t</div>\n\t\t\t\t{/*Updating*/}\n\t\t\t\t<div\n\t\t\t\t\tstyle={{ width: updating.updatingWidth }}\n\t\t\t\t\tclassName=\"grow animate-pulse bg-yellow/80 transition-[width] duration-1000 ease-in-out motion-reduce:transition-none\"\n\t\t\t\t>\n\t\t\t\t</div>\n\t\t\t\t{/*Pending*/}\n\t\t\t\t<div\n\t\t\t\t\tstyle={{ width: updating.pendingWidth }}\n\t\t\t\t\tclassName=\"grow bg-gray-600 transition-[width] duration-1000 ease-in-out motion-reduce:transition-none\"\n\t\t\t\t>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t{updating.text && <div className=\"text-xs text-muted-foreground font-light mt-2\">{updating.text}</div>}\n\t\t</div>\n\t);\n}\n","import { apiClient } from '@/config/apiClient';\nimport { useMutation } from '@tanstack/react-query';\n\nexport async function terminateCluster(clusterId: string) {\n\tconst { data } = await apiClient.delete(`/Cluster/${clusterId}` as '/Cluster/{id}', { timeout: 0 });\n\treturn data;\n}\n\nexport function useTerminateClusterMutation() {\n\treturn useMutation({\n\t\tmutationFn: (clusterId: string) => terminateCluster(clusterId),\n\t});\n}\n","import { ClipboardCheckIcon } from 'lucide-react';\nimport { useMemo } from 'react';\nimport { toast } from 'sonner';\n\nexport function useCopyToClipboard(...texts: string[]): Array<() => void> {\n\treturn useMemo(() => {\n\t\treturn texts.map(text => (() => {\n\t\t\tvoid navigator.clipboard.writeText(text);\n\t\t\ttoast.info('Copied to clipboard!', {\n\t\t\t\ticon: <ClipboardCheckIcon />,\n\t\t\t\tduration: 1000,\n\t\t\t});\n\t\t}));\n\t\t// We can override the linting here because we know we're providing an accurate list of dependencies that will only\n\t\t// change and trigger a re-render of the memo when the text contents change.\n\t\t// eslint-disable-next-line react-hooks/use-memo,react-hooks/exhaustive-deps\n\t}, texts);\n}\n","/**\n * Attempts to parse a string as JSON, and narrows the type down to the provided generic. Note that\n * no schema validation happens as a part of this, so the type might be inaccurate. But exceptions\n * won't be thrown by the actual parsing if invalid JSON is provided.\n * @param value\n */\nexport function safeParse<T>(value: string | null | undefined): T | null {\n\ttry {\n\t\tif (value === 'null' || value === 'undefined' || value === null || value === undefined) {\n\t\t\treturn null;\n\t\t}\n\t\treturn JSON.parse(value) as T;\n\t} catch (err) {\n\t\tconsole.error('safeParse failed to parse value, returning null instead', err);\n\t\treturn null;\n\t}\n}\n","import { LocalStorageKeys } from '@/lib/storage/localStorageKeys';\nimport { safeParse } from '@/lib/string/safeParse';\n\n/**\n * Retrieves a value from local storage.\n * @param key\n * @param defaultValue\n */\nexport function getLocalStorage<T>(key: LocalStorageKeys, defaultValue: T): T {\n\tconst lastSetValue = safeParse<T>(localStorage.getItem(key));\n\treturn lastSetValue ?? defaultValue;\n}\n","import { LocalStorageKeys } from '@/lib/storage/localStorageKeys';\n\n/**\n * Stores a value in local storage for later retrieval.\n * @param key\n * @param current\n */\nexport function setLocalStorage<T>(key: LocalStorageKeys, current: T): void {\n\tif (current === null || current === undefined) {\n\t\tlocalStorage.removeItem(key);\n\t} else {\n\t\tlocalStorage.setItem(key, JSON.stringify(current));\n\t}\n}\n","import { getLocalStorage } from '@/lib/storage/getLocalStorage';\nimport { LocalStorageKeys } from '@/lib/storage/localStorageKeys';\nimport { setLocalStorage } from '@/lib/storage/setLocalStorage';\nimport { useEffect, useState } from 'react';\n\n/**\n * Uses state that gets bootstrapped from and persists to local storage with the key you specify.\n * This does NOT pub-sub value changes in realtime across instances of this hook!\n * @param key\n * @param defaultValue\n */\nexport function useLocalStorage<T>(\n\tkey: LocalStorageKeys,\n\tdefaultValue: T,\n): [T, (value: ((prevState: T) => T) | T) => void] {\n\tconst state = useState<T>(getLocalStorage(key, defaultValue));\n\tconst [current] = state;\n\tuseEffect(() => setLocalStorage(key, current), [key, current]);\n\treturn state;\n}\n","export const enum LocalStorageKeys {\n\t'ApplicationChatPosition' = 'ApplicationChatPosition',\n\t'ApplicationChatWidth' = 'ApplicationChatWidth',\n\t'ChatAlwaysApprovedTools' = 'ChatAlwaysApprovedTools',\n\t'SavedClusterState' = 'SavedClusterState',\n}\n","import { ConfirmDeletionModal } from '@/components/ConfirmDeletionModal';\nimport { Badge } from '@/components/ui/badge';\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';\nimport {\n\tDropdownMenu,\n\tDropdownMenuContent,\n\tDropdownMenuItem,\n\tDropdownMenuSeparator,\n\tDropdownMenuTrigger,\n} from '@/components/ui/dropdownMenu';\nimport { isFailed, renderBadgeStatusVariant } from '@/components/ui/utils/badgeStatus';\nimport { activeClusterStatuses, deletedClusterStatuses } from '@/config/clusterStatuses';\nimport { isLocalStudio } from '@/config/constants';\nimport { useInstanceClient } from '@/config/useInstanceClient';\nimport { authStore } from '@/features/auth/store/authStore';\nimport { getClusterInfo } from '@/features/cluster/queries/getClusterInfoQuery';\nimport { ClusterCardAction } from '@/features/clusters/components/ClusterCardAction';\nimport { ClusterProgress } from '@/features/clusters/components/ClusterProgress';\nimport { useTerminateClusterMutation } from '@/features/clusters/mutations/terminateCluster';\nimport { useInstanceAuth } from '@/hooks/useAuth';\nimport { useCopyToClipboard } from '@/hooks/useCopyToClipboard';\nimport { useLocalStorage } from '@/hooks/useLocalStorage';\nimport { useOrganizationClusterPermissions } from '@/hooks/usePermissions';\nimport { Cluster } from '@/integrations/api/api.patch';\nimport { clusterIsSelfManaged } from '@/integrations/api/clusterIsSelfManaged';\nimport { onInstanceLogoutSubmit } from '@/integrations/api/instance/auth/onInstanceLogoutSubmit';\nimport { excludeFalsy } from '@/lib/arrays/excludeFalsy';\nimport { LocalStorageKeys } from '@/lib/storage/localStorageKeys';\nimport { capitalizeWords } from '@/lib/string/capitalizeWords';\nimport { getOperationsUrlForCluster } from '@/lib/urls/getOperationsUrlForCluster';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { Link, useRouter } from '@tanstack/react-router';\nimport {\n\tClipboardIcon,\n\tCopyIcon,\n\tEllipsis,\n\tGitGraphIcon,\n\tGlobeIcon,\n\tKeyIcon,\n\tScaleIcon,\n\tServerIcon,\n\tTrashIcon,\n} from 'lucide-react';\nimport { useCallback, useMemo, useState } from 'react';\nimport { toast } from 'sonner';\n\nexport function ClusterCard({ cluster }: { cluster: Cluster }) {\n\tconst router = useRouter();\n\tconst queryClient = useQueryClient();\n\tconst operationsUrl = useMemo(() => getOperationsUrlForCluster(cluster), [cluster]);\n\tconst instanceClient = useInstanceClient({ operationsUrl });\n\tconst auth = useInstanceAuth(cluster.id);\n\tconst [, setSavedClusterState] = useLocalStorage<unknown | null>(LocalStorageKeys.SavedClusterState, null);\n\n\tconst { view, update, remove, create } = useOrganizationClusterPermissions(cluster.organizationId, cluster.id);\n\tconst { mutate: terminateCluster, isPending: isTerminateClusterPending } = useTerminateClusterMutation();\n\n\tconst [signingOut, setSigningOut] = useState(false);\n\tconst [isTerminateClusterModalOpen, setIsTerminateClusterModalOpen] = useState(false);\n\n\tconst isActive = useMemo(() => cluster.status && activeClusterStatuses.includes(cluster.status), [cluster.status]);\n\tconst isSelfManaged = clusterIsSelfManaged(cluster);\n\tconst isFabricConnect = authStore.checkForFabricConnect(cluster.id);\n\tconst isDirectConnect = !isFabricConnect && !!auth.user;\n\tconst isTerminated = useMemo(\n\t\t() => cluster.status && deletedClusterStatuses.includes(cluster.status),\n\t\t[cluster.status],\n\t);\n\tconst clusterHasFailed = useMemo(\n\t\t() => cluster.status && isFailed(cluster.status),\n\t\t[cluster.status],\n\t);\n\n\tconst onSignOutClick = useCallback(async () => {\n\t\tsetSigningOut(true);\n\t\tconst fullCluster = await getClusterInfo(cluster.id).catch((err) => {\n\t\t\tconsole.error('Failed to lookup cluster details, proceeding without checking instances.', err);\n\t\t\treturn null;\n\t\t});\n\t\tawait onInstanceLogoutSubmit({ entityId: cluster.id, instanceClient });\n\t\tif (fullCluster?.instances?.length) {\n\t\t\t// Flag all cluster instances as signed out as well.\n\t\t\tfor (const instance of fullCluster.instances) {\n\t\t\t\tauthStore.setUserForEntity(instance, null);\n\t\t\t}\n\t\t}\n\t\tauthStore.setUserForEntity(cluster, null);\n\t}, [cluster, instanceClient]);\n\n\tconst onTryAgainClick = useCallback(() => {\n\t\tsetSavedClusterState(cluster);\n\t\tvoid router.navigate({ to: `/${cluster.organizationId}/new-cluster` });\n\t}, [cluster, router, setSavedClusterState]);\n\n\tconst onTerminateClick = useCallback(() => setIsTerminateClusterModalOpen(true), []);\n\n\tconst handleTerminatedCluster = useCallback(() => {\n\t\tconst organizationId = cluster.organizationId;\n\t\tterminateCluster(cluster.id, {\n\t\t\tonSuccess: async () => {\n\t\t\t\tawait queryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: [organizationId],\n\t\t\t\t\trefetchType: 'active',\n\t\t\t\t});\n\t\t\t\tawait router.invalidate();\n\t\t\t\ttoast.success('Success', {\n\t\t\t\t\tdescription: isSelfManaged\n\t\t\t\t\t\t? `Cluster successfully removed.`\n\t\t\t\t\t\t: `Cluster successfully terminated.`,\n\t\t\t\t\tduration: 5000,\n\t\t\t\t\taction: {\n\t\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tsetIsTerminateClusterModalOpen(false);\n\t\t\t},\n\t\t\tonError: () => {\n\t\t\t\ttoast.error('Error', {\n\t\t\t\t\tdescription: isSelfManaged\n\t\t\t\t\t\t? `Failed to remove cluster: ${cluster.name}`\n\t\t\t\t\t\t: `Failed to terminate cluster: ${cluster.name}.`,\n\t\t\t\t\tduration: 5000,\n\t\t\t\t\taction: {\n\t\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tsetIsTerminateClusterModalOpen(false);\n\t\t\t},\n\t\t});\n\t}, [router, cluster.organizationId, cluster.id, cluster.name, terminateCluster, isSelfManaged, queryClient]);\n\n\tconst clusterFQDN = cluster.domains?.[0]?.domain || cluster.fqdn;\n\tconst [onCopyFQDNClick, onCopyAPIClick] = useCopyToClipboard(\n\t\t`${clusterFQDN}`,\n\t\t`https://${clusterFQDN}`,\n\t);\n\n\tconst menuItems = [\n\t\tisActive && update && !auth.isLoading && (!isDirectConnect || isFabricConnect) && (\n\t\t\t<Link key=\"sign-in\" to={`${cluster.id}/sign-in`} disabled={signingOut}>\n\t\t\t\t<DropdownMenuItem>\n\t\t\t\t\t<KeyIcon className=\"text-green\" /> Direct Sign In\n\t\t\t\t</DropdownMenuItem>\n\t\t\t</Link>\n\t\t),\n\t\tisActive && update && (\n\t\t\t<Link key=\"edit\" to={`${cluster.id}/edit`} disabled={signingOut}>\n\t\t\t\t<DropdownMenuItem>\n\t\t\t\t\t<ScaleIcon className=\"text-purple-600\" /> {isSelfManaged ? 'Edit' : 'Edit Scaling'}\n\t\t\t\t</DropdownMenuItem>\n\t\t\t</Link>\n\t\t),\n\t\tisActive && update && !isSelfManaged && (\n\t\t\t<Link key=\"edit-version\" to={`${cluster.id}/edit/version`} disabled={signingOut}>\n\t\t\t\t<DropdownMenuItem>\n\t\t\t\t\t<GitGraphIcon className=\"text-fuchsia-300\" /> Edit Version\n\t\t\t\t</DropdownMenuItem>\n\t\t\t</Link>\n\t\t),\n\t\tisActive && update && !isLocalStudio && !clusterIsSelfManaged(cluster) && (\n\t\t\t<Link key=\"domains\" to={`${cluster.id}/domains`} disabled={signingOut}>\n\t\t\t\t<DropdownMenuItem>\n\t\t\t\t\t<GlobeIcon className=\"text-cyan-400\" /> Domains\n\t\t\t\t</DropdownMenuItem>\n\t\t\t</Link>\n\t\t),\n\t\tisActive && view && (\n\t\t\t<Link key=\"instances\" to={`${cluster.id}/instances`} disabled={signingOut}>\n\t\t\t\t<DropdownMenuItem>\n\t\t\t\t\t<ServerIcon className=\"text-orange-300\" /> Instances\n\t\t\t\t</DropdownMenuItem>\n\t\t\t</Link>\n\t\t),\n\n\t\tisActive && view && cluster.fqdn && <DropdownMenuSeparator key=\"copy-separator\" />,\n\t\tisActive && view && cluster.fqdn && (\n\t\t\t<DropdownMenuItem key=\"copy-host-name\" onClick={onCopyFQDNClick} disabled={signingOut}>\n\t\t\t\t<ClipboardIcon /> Copy Host Name\n\t\t\t</DropdownMenuItem>\n\t\t),\n\t\tisActive && view && cluster.fqdn && (\n\t\t\t<DropdownMenuItem key=\"copy-api-url\" onClick={onCopyAPIClick} disabled={signingOut}>\n\t\t\t\t<ClipboardIcon /> Copy API URL\n\t\t\t</DropdownMenuItem>\n\t\t),\n\n\t\tisActive && view && !!operationsUrl && !auth.isLoading && isDirectConnect && (\n\t\t\t<DropdownMenuItem key=\"direct-sign-out\" onClick={onSignOutClick} disabled={signingOut}>\n\t\t\t\tDirect Sign Out\n\t\t\t</DropdownMenuItem>\n\t\t),\n\t\tclusterHasFailed && create && (\n\t\t\t<DropdownMenuItem key=\"try-again\" className=\"focus:bg-green/70 focus:text-white\" onClick={onTryAgainClick}>\n\t\t\t\tTry Again\n\t\t\t</DropdownMenuItem>\n\t\t),\n\t\t!isTerminated && remove && isActive && <DropdownMenuSeparator key=\"remove-separator\" />,\n\t\t!isTerminated && remove && (\n\t\t\t<DropdownMenuItem key=\"remove\" className=\"focus:bg-red/70 focus:text-white\" onClick={onTerminateClick}>\n\t\t\t\t<TrashIcon className=\"text-red-300\" /> {isSelfManaged ? 'Remove' : 'Terminate'}\n\t\t\t</DropdownMenuItem>\n\t\t),\n\t].filter(excludeFalsy);\n\n\treturn (\n\t\t<Card className=\"relative h-full justify-between\">\n\t\t\t<CardHeader>\n\t\t\t\t<CardDescription className=\"flex items-center justify-between\">\n\t\t\t\t\t{clusterFQDN\n\t\t\t\t\t\t? (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<span className=\"truncate max-w-48\">{clusterFQDN}</span>\n\t\t\t\t\t\t\t\t<CopyIcon onClick={onCopyFQDNClick} size={16} className=\"cursor-pointer\" />\n\t\t\t\t\t\t\t\t<span className=\"grow\"></span>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)\n\t\t\t\t\t\t: <span>Self-Hosted</span>}\n\t\t\t\t\t{!isTerminated && (\n\t\t\t\t\t\t<DropdownMenu>\n\t\t\t\t\t\t\t<DropdownMenuTrigger>\n\t\t\t\t\t\t\t\t<Ellipsis aria-label=\"Cluster options\" />\n\t\t\t\t\t\t\t</DropdownMenuTrigger>\n\t\t\t\t\t\t\t<DropdownMenuContent>\n\t\t\t\t\t\t\t\t{...menuItems}\n\t\t\t\t\t\t\t</DropdownMenuContent>\n\t\t\t\t\t\t</DropdownMenu>\n\t\t\t\t\t)}\n\t\t\t\t</CardDescription>\n\t\t\t\t<CardTitle>\n\t\t\t\t\t<h2>{cluster.name}</h2>\n\t\t\t\t</CardTitle>\n\t\t\t</CardHeader>\n\t\t\t<CardContent className=\"flex items-center justify-between gap-2\">\n\t\t\t\t<ClusterProgress cluster={cluster} />\n\t\t\t\t{isActive && view && <ClusterCardAction cluster={cluster} />}\n\t\t\t\t{clusterHasFailed && cluster.status && (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<Badge variant={renderBadgeStatusVariant(cluster.status)}>{capitalizeWords(cluster.status)}</Badge>\n\t\t\t\t\t\t<span className=\"text-xs\">Click \"...\" to choose how to proceed.</span>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</CardContent>\n\n\t\t\t<ConfirmDeletionModal\n\t\t\t\ttypeOfThingBeingDeleted=\"cluster\"\n\t\t\t\ttransitiveVerb={isSelfManaged ? 'Remove' : 'Terminate'}\n\t\t\t\tpresentParticiple={isSelfManaged ? 'Removing' : 'Terminating'}\n\t\t\t\tnameOfThingBeingDeleted={cluster.name}\n\t\t\t\tisModalOpen={isTerminateClusterModalOpen}\n\t\t\t\thideDataLossWarning={isSelfManaged}\n\t\t\t\tsetIsModalOpen={(isOpen: boolean) => setIsTerminateClusterModalOpen(isOpen)}\n\t\t\t\tdeletionConfirmed={handleTerminatedCluster}\n\t\t\t\tdeletionPending={isTerminateClusterPending}\n\t\t\t/>\n\t\t</Card>\n\t);\n}\n","export function ContactUs({ overEmail }: { readonly overEmail?: boolean }) {\n\treturn (\n\t\t<a\n\t\t\thref={overEmail\n\t\t\t\t? 'mailto:support@harperdb.io'\n\t\t\t\t: 'https://discord.com/channels/1415002037439041710/1415002038286286994'}\n\t\t\ttarget=\"_blank\"\n\t\t\trel=\"noreferrer\"\n\t\t\tclassName=\"underline\"\n\t\t>\n\t\t\tContact us\n\t\t</a>\n\t);\n}\n","import { ComponentProps, ReactNode } from 'react';\n\ninterface LoadingProps extends ComponentProps<'div'> {\n\ttext?: ReactNode;\n\tcentered?: boolean;\n}\n\nexport function Loading({ className, text, centered, ...props }: LoadingProps) {\n\tconst additionalClassName = centered ? 'flex flex-col items-center justify-center' : '';\n\treturn (\n\t\t<div className={`text-white h-full w-full ${className || ''} ${additionalClassName}`} {...props}>\n\t\t\t<img src=\"/HDBDogOnly.svg\" width=\"100px\" height=\"100px\" alt=\"HDB Dog Logo Loading\" className=\"inline-block\" />\n\t\t\t<p className=\"pt-4\">{!text ? 'Loading...' : text}</p>\n\t\t</div>\n\t);\n}\n","import { SubNavMenu } from '@/components/SubNavMenu';\nimport { ReactNode } from 'react';\n\nexport function SubNavSimpleLayout({ children, className }: { children: ReactNode; className?: string }) {\n\treturn (\n\t\t<>\n\t\t\t<SubNavMenu />\n\t\t\t<div className={`mt-32 px-4 pt-4 md:px-12 min-h-[calc(100vh-(--spacing(32)))] relative ${className ?? ''}`}>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</>\n\t);\n}\n","import { apiClient } from '@/config/apiClient';\nimport { queryOptions } from '@tanstack/react-query';\n\nasync function getPlanTypes(organizationId: string) {\n\tconst { data } = await apiClient.get(`/Plan/`, {\n\t\tparams: {\n\t\t\torganizationId,\n\t\t},\n\t});\n\treturn data;\n}\n\nexport function getPlanTypesOptions(organizationId: string) {\n\treturn queryOptions({\n\t\tqueryKey: [organizationId, 'instancePlan'],\n\t\tqueryFn: () => getPlanTypes(organizationId),\n\t\tretry: false,\n\t});\n}\n","import { apiClient } from '@/config/apiClient';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport interface HarperVersionsResponse {\n\tname: string;\n\tdescription: string;\n\tvalue: HarperVersion[];\n}\n\ninterface HarperVersion {\n\tname: 'stable' | 'next' | 'current';\n\tversion: string;\n}\n\nasync function getHarperVersions() {\n\t// TODO: OpenAPI from CM is erroring, so this new endpoint isn't described.\n\tconst { data } = await apiClient.get(`/HarperVersions/` as any);\n\treturn data as HarperVersionsResponse;\n}\n\nexport function getHarperVersionsOptions() {\n\treturn queryOptions({\n\t\tqueryKey: ['HarperVersions'],\n\t\tqueryFn: getHarperVersions,\n\t\tstaleTime: 60_000,\n\t\tretry: false,\n\t});\n}\n","import { apiClient } from '@/config/apiClient';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport interface GetRegionLocationsParams {\n\torganizationId?: string;\n\tavailableHosts?: boolean;\n}\n\nasync function getRegionLocations({ organizationId, availableHosts }: GetRegionLocationsParams = {}) {\n\tconst { data } = await apiClient.get(`/Region/`, {\n\t\tparams: {\n\t\t\tavailableHosts,\n\t\t\torganizationId,\n\t\t},\n\t});\n\treturn data;\n}\n\nexport function getRegionLocationsOptions({ organizationId, availableHosts }: GetRegionLocationsParams = {}) {\n\treturn queryOptions({\n\t\tqueryKey: [organizationId, 'regionLocations', availableHosts],\n\t\tqueryFn: () => getRegionLocations({ organizationId, availableHosts }),\n\t\tretry: false,\n\t});\n}\n","export function sortByField<T>(fieldName: keyof T): (a: T, b: T) => number {\n\treturn (a: T, b: T): number => {\n\t\tif (a[fieldName] === b[fieldName]) {\n\t\t\treturn 0;\n\t\t}\n\t\treturn a[fieldName] > b[fieldName] ? 1 : -1;\n\t};\n}\n","export function ipAddressToNumber(ipAddress: string): number {\n\tconst parts = ipAddress.split('.').map(Number);\n\t// Coerce result to an unsigned 32-bit integer to avoid negative values for >= 128.0.0.0\n\treturn (((parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8) | parts[3]) >>> 0);\n}\n","export function isIpAddress(value: string | unknown): boolean {\n\tif (typeof value !== 'string') {\n\t\treturn false;\n\t}\n\t// Strict IPv4 check: exactly four octets, each 0–255; no extra chars\n\tconst ipv4 = /^(?:25[0-5]|2[0-4]\\d|1?\\d?\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1?\\d?\\d)){3}$/;\n\treturn ipv4.test(value);\n}\n","import { SchemaHdbInstance } from '@/integrations/api/api.gen';\nimport { ipAddressToNumber } from '@/lib/numbers/ipAddressToNumber';\nimport { isIpAddress } from '@/lib/string/isIpAddress';\n\nexport function byInstanceFqdnThenPort(\n\ta: Pick<SchemaHdbInstance, 'instanceFqdn' | 'operationsApiPort'>,\n\tb: Pick<SchemaHdbInstance, 'instanceFqdn' | 'operationsApiPort'>,\n) {\n\tif (a.instanceFqdn === b.instanceFqdn) {\n\t\treturn a.operationsApiPort - b.operationsApiPort;\n\t}\n\tif (isIpAddress(a.instanceFqdn) && isIpAddress(b.instanceFqdn)) {\n\t\treturn ipAddressToNumber(a.instanceFqdn) - ipAddressToNumber(b.instanceFqdn);\n\t}\n\treturn a.instanceFqdn > b.instanceFqdn ? 1 : -1;\n}\n","export function groupBy<T extends object>(items: T[], property: keyof T): Record<string, T[]> {\n\tconst retVal: Record<string, T[]> = {};\n\n\tfor (const item of items) {\n\t\tconst key = item[property] as string;\n\t\tif (key === undefined) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (Array.isArray(key)) {\n\t\t\tfor (const k of key) {\n\t\t\t\tif (!retVal[k]) {\n\t\t\t\t\tretVal[k] = [];\n\t\t\t\t}\n\t\t\t\tretVal[k].push(item);\n\t\t\t}\n\t\t} else {\n\t\t\tif (!retVal[key]) {\n\t\t\t\tretVal[key] = [];\n\t\t\t}\n\t\t\tretVal[key].push(item);\n\t\t}\n\t}\n\n\treturn retVal as Record<string, T[]>;\n}\n","export function keyBy<T extends object>(items: T[], property: keyof T): Record<string, T> {\n\tconst retVal: Record<string, T> = {};\n\n\tfor (const item of items) {\n\t\tconst key = item[property] as string;\n\t\tif (key === undefined) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (Array.isArray(key)) {\n\t\t\tfor (const k of key) {\n\t\t\t\tretVal[k] = item;\n\t\t\t}\n\t\t} else {\n\t\t\tretVal[key] = item;\n\t\t}\n\t}\n\n\treturn retVal;\n}\n","import { groupBy } from '@/lib/groupBy';\nimport { keyBy } from '@/lib/keyBy';\n\nexport function groupThenKeyBy<T extends object>(\n\titems: T[],\n\tgroupByKey: keyof T,\n\tkeyByKey: keyof T,\n): Record<string, Record<string, T>> {\n\tconst grouped = groupBy(items, groupByKey);\n\tconst keyed: Record<string, Record<string, T>> = {};\n\tfor (const groupName in grouped) {\n\t\tkeyed[groupName] = keyBy(grouped[groupName], keyByKey);\n\t}\n\treturn keyed;\n}\n","/**\n * Compare two semver strings according to SemVer 2.0.0 rules.\n * Returns true if \"b\" (second argument) is greater than or equal to \"a\" (first argument).\n * @param a The base version\n * @param b The potentially greater version\n * @example compareSemVer('4.7.0-beta.7', '4.7.0') => true\n * @example compareSemVer('4.7.0', '4.7.0-beta.7') => false\n */\nexport function wasAReleasedBeforeB(a: string, b: string): boolean {\n\tconst pa = parseSemVer(a);\n\tconst pb = parseSemVer(b);\n\n\tif (!pa || !pb) {\n\t\treturn false;\n\t}\n\n\treturn semverCompare(pb, pa) >= 0; // is b >= a ?\n}\n\n/**\n * Compare two semver strings according to SemVer 2.0.0 rules.\n * Returns -1 if a < b, 0 if a == b, 1 if a > b.\n */\nexport function compareVersions(a: string, b: string): number {\n\tconst pa = parseSemVer(a);\n\tconst pb = parseSemVer(b);\n\n\tif (!pa && !pb) { return 0; }\n\tif (!pa) { return -1; }\n\tif (!pb) { return 1; }\n\n\treturn semverCompare(pa, pb);\n}\n\n// Internal representation of a semver\ninterface SemVerParts {\n\tmajor: number;\n\tminor: number;\n\tpatch: number;\n\tpre: (number | string)[]; // numeric identifiers stay numbers, others as strings\n}\n\nfunction parseSemVer(input: string): SemVerParts | null {\n\tif (typeof input !== 'string') {\n\t\treturn null;\n\t}\n\n\t// Strip build metadata (+...) as it has no effect on precedence\n\tconst [versionAndPre] = input.split('+', 1).concat('');\n\n\t// Separate core and pre-release\n\tconst firstDash = versionAndPre.indexOf('-');\n\tconst core = firstDash === -1 ? versionAndPre : versionAndPre.slice(0, firstDash);\n\tconst pre = firstDash === -1 ? '' : versionAndPre.slice(firstDash + 1);\n\n\tconst coreParts = core.split('.');\n\tif (coreParts.length === 0) {\n\t\treturn null;\n\t}\n\n\tconst major = toInt(coreParts[0]);\n\tconst minor = toInt(coreParts[1] ?? '0');\n\tconst patch = toInt(coreParts[2] ?? '0');\n\n\tif (major == null || minor == null || patch == null) {\n\t\treturn null;\n\t}\n\n\tconst preParts: (number | string)[] = pre\n\t\t? pre.split('.').map((id) => (isNumeric(id) ? Number(id) : id))\n\t\t: [];\n\n\treturn { major, minor, patch, pre: preParts };\n}\n\nfunction toInt(s?: string): number | null {\n\tif (s == null || s === '') {\n\t\treturn null;\n\t}\n\tif (!/^\\d+$/.test(s)) {\n\t\treturn null;\n\t}\n\treturn Number(s);\n}\n\nfunction isNumeric(s: string): boolean {\n\treturn /^\\d+$/.test(s);\n}\n\n// Returns -1 if a<b, 0 if a==b, 1 if a>b\nfunction semverCompare(a: SemVerParts, b: SemVerParts): number {\n\tif (a.major !== b.major) {\n\t\treturn a.major < b.major ? -1 : 1;\n\t}\n\tif (a.minor !== b.minor) {\n\t\treturn a.minor < b.minor ? -1 : 1;\n\t}\n\tif (a.patch !== b.patch) {\n\t\treturn a.patch < b.patch ? -1 : 1;\n\t}\n\n\tconst aHasPre = a.pre.length > 0;\n\tconst bHasPre = b.pre.length > 0;\n\tif (!aHasPre && !bHasPre) {\n\t\treturn 0;\n\t}\n\t// A version without pre-release is greater than one with pre-release\n\tif (!aHasPre && bHasPre) {\n\t\treturn 1;\n\t}\n\tif (aHasPre && !bHasPre) {\n\t\treturn -1;\n\t}\n\n\tconst len = Math.min(a.pre.length, b.pre.length);\n\tfor (let i = 0; i < len; i++) {\n\t\tconst idA = a.pre[i];\n\t\tconst idB = b.pre[i];\n\t\tconst aNum = typeof idA === 'number';\n\t\tconst bNum = typeof idB === 'number';\n\n\t\tif (aNum && bNum) {\n\t\t\tif (idA !== (idB as number)) {\n\t\t\t\treturn (idA as number) < (idB as number) ? -1 : 1;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (aNum && !bNum) {\n\t\t\treturn -1; // numeric identifiers have lower precedence than non-numeric\n\t\t}\n\t\tif (!aNum && bNum) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// both strings: ASCII lexicographic compare\n\t\tif (idA !== idB) {\n\t\t\treturn String(idA) < String(idB) ? -1 : 1;\n\t\t}\n\t}\n\n\t// If all identifiers equal so far, longer set has higher precedence\n\tif (a.pre.length !== b.pre.length) {\n\t\treturn a.pre.length < b.pre.length ? -1 : 1;\n\t}\n\n\treturn 0;\n}\n","import { cx } from 'class-variance-authority';\n\nexport function ProgressBar({ width, className, animated, placeholder }: {\n\twidth: string | undefined;\n\tclassName?: string;\n\tanimated?: boolean;\n\tplaceholder?: string;\n}) {\n\treturn (\n\t\t<div className={cx('w-full bg-gray-200 rounded-full relative', placeholder ? 'h-6' : 'h-2.5')}>\n\t\t\t{placeholder && (\n\t\t\t\t<div className=\"absolute top-0 h-full w-full font-bold text-xs flex flex-col items-center justify-center text-black/60 text-shadow-2xs\">\n\t\t\t\t\t{placeholder}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<div\n\t\t\t\tclassName={cx(\n\t\t\t\t\t'rounded-full',\n\t\t\t\t\tplaceholder ? 'h-6' : 'h-2.5',\n\t\t\t\t\t!className?.includes('bg-') && 'bg-purple/40',\n\t\t\t\t\tanimated && 'transition-[width] duration-1000 ease-in-out motion-reduce:transition-none',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tstyle={{\n\t\t\t\t\twidth,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","import { ProgressBar } from '@/components/ProgressBar';\nimport { ReactNode, useCallback, useEffect, useRef, useState } from 'react';\n\nexport function EstimatedProgressBar({ duration, message, lateMessage }: {\n\tduration: number;\n\tmessage: ReactNode;\n\tlateMessage: ReactNode;\n}) {\n\tconst animationFrameId = useRef<number>(0);\n\tconst previousTimeRef = useRef<number>(0);\n\tconst [finished, setFinished] = useState(false);\n\tconst minPercentage = 5;\n\tconst [width, setWidth] = useState(`${minPercentage}%`);\n\n\tconst animate = useCallback(function animate(time: number) {\n\t\tif (!previousTimeRef.current) {\n\t\t\tpreviousTimeRef.current = time;\n\t\t}\n\t\tconst timeElapsed = time - previousTimeRef.current;\n\t\tconst percentage = Math.min(timeElapsed / duration, 1);\n\t\tsetWidth(Math.max(minPercentage, percentage * 100) + '%');\n\n\t\tif (percentage < 1) {\n\t\t\tanimationFrameId.current = requestAnimationFrame(animate);\n\t\t} else {\n\t\t\tsetFinished(true);\n\t\t}\n\t}, [duration]);\n\n\tuseEffect(() => {\n\t\tanimationFrameId.current = requestAnimationFrame(animate);\n\t\treturn () => cancelAnimationFrame(animationFrameId.current);\n\t}, [animate]);\n\n\treturn (\n\t\t<>\n\t\t\t{!finished ? message : lateMessage}\n\t\t\t<ProgressBar width={width} animated={false}></ProgressBar>\n\t\t</>\n\t);\n}\n","import { apiClient } from '@/config/apiClient';\nimport { SchemaCluster, SchemaClusterUpsert } from '@/integrations/api/api.gen';\nimport { useMutation } from '@tanstack/react-query';\n\nasync function onNewClusterSubmit(\n\tclusterInfo: SchemaClusterUpsert,\n): Promise<SchemaCluster> {\n\tconst { data } = await apiClient.post(\n\t\t'/Cluster/',\n\t\tclusterInfo,\n\t\t{ timeout: 0 },\n\t);\n\treturn data;\n}\n\nexport function useCreateNewClusterMutation() {\n\treturn useMutation<SchemaCluster, Error, SchemaClusterUpsert>({\n\t\tmutationFn: (clusterInfo) => onNewClusterSubmit(clusterInfo),\n\t});\n}\n","import { apiClient } from '@/config/apiClient';\nimport { SchemaCluster, SchemaClusterUpsert } from '@/integrations/api/api.gen';\nimport { useMutation } from '@tanstack/react-query';\n\ntype EditRegionPlan = Pick<SchemaCluster, 'id'> & Pick<SchemaClusterUpsert, 'regionPlans' | 'skipGtmWait'>;\ntype EditVersion = Pick<SchemaCluster, 'id'> & Pick<SchemaClusterUpsert, 'version' | 'skipGtmWait'>;\n\nasync function onEditClusterSubmit(\n\tclusterInfo: EditRegionPlan | EditVersion,\n): Promise<SchemaCluster> {\n\tconst { id, ...changes } = clusterInfo;\n\tconst { data } = await apiClient.put(\n\t\t`/Cluster/${id}` as '/Cluster/{id}',\n\t\tchanges,\n\t\t{ timeout: 0 },\n\t);\n\treturn data;\n}\n\nexport function useEditClusterMutation() {\n\treturn useMutation<SchemaCluster, Error, EditRegionPlan | EditVersion>({\n\t\tmutationFn: (clusterInfo) => onEditClusterSubmit(clusterInfo),\n\t});\n}\n","import { apiClient } from '@/config/apiClient';\nimport { Organization } from '@/integrations/api/api.patch';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport async function getOrganization(orgId: string): Promise<Organization> {\n\tconst { data } = await apiClient.get(`/Organization/${orgId}` as '/Organization/{id}');\n\treturn data;\n}\n\nexport function getOrganizationQueryOptions(orgId: string) {\n\treturn queryOptions({\n\t\tqueryKey: [orgId],\n\t\tqueryFn: () => getOrganization(orgId),\n\t\tretry: false,\n\t\trefetchInterval: 10000,\n\t});\n}\n","export const ENTERPRISE = 'ENTERPRISE';\nexport const SELF_SERVICE = 'SELF_SERVICE';\n","/**\n * Collapses a kebab-case string to meet a maximum length restriction.\n * It shortens segments one by one starting from the end, keeping the first character of each segment.\n *\n * @param str - The kebab-case string to collapse\n * @param maxLength - The maximum length the resulting string should have\n * @returns The collapsed string that meets the max length restriction\n *\n * @example\n * collapseKebabsToMaxLength('one-two-three', 8) // 'one-t-t'\n * collapseKebabsToMaxLength('hello-world', 7) // 'hello-w'\n * collapseKebabsToMaxLength('a-b-c-d', 5) // 'a-b-c'\n * collapseKebabsToMaxLength('short', 10) // 'short' (already within max length)\n */\nexport function collapseKebabsToMaxLength(str: string, maxLength: number): string {\n\t// Handle edge cases with zero or negative max length\n\tif (maxLength <= 0) {\n\t\treturn '';\n\t}\n\n\t// If the string is already within the max length, return it as is\n\tif (str.length <= maxLength) {\n\t\treturn str;\n\t}\n\n\t// Split the string by hyphens to get individual segments\n\tconst segments = str.split('-');\n\n\t// If there's only one segment, just truncate it\n\tif (segments.length === 1) {\n\t\treturn segments[0].slice(0, maxLength);\n\t}\n\n\t// First, collapse all segments except the first one to their first character\n\tconst collapsedSegments = [\n\t\tsegments[0],\n\t\t...segments.slice(1).map(segment => segment.charAt(0)),\n\t];\n\n\t// Check if the collapsed string now meets the max length\n\tconst result = collapsedSegments.join('-');\n\tif (result.length <= maxLength) {\n\t\treturn result;\n\t}\n\n\t// If we still exceed the max length, we need to truncate the first segment\n\t// Calculate how much space we have for the first segment\n\tconst otherSegmentsLength = collapsedSegments.slice(1).join('').length;\n\tconst hyphensLength = collapsedSegments.length - 1; // Number of hyphens\n\tconst maxFirstSegmentLength = maxLength - otherSegmentsLength - hyphensLength;\n\n\tif (maxFirstSegmentLength > 0) {\n\t\t// We have some space for the first segment\n\t\tcollapsedSegments[0] = collapsedSegments[0].slice(0, maxFirstSegmentLength);\n\t\treturn collapsedSegments.join('-');\n\t} else {\n\t\t// We don't have space for all segments, so we need to remove segments from the end\n\t\t// Keep as many segments as possible, starting from the beginning\n\t\tconst finalSegments = [];\n\t\tlet currentLength = 0;\n\n\t\t// Always include at least the first character of the first segment if possible\n\t\tif (maxLength > 0) {\n\t\t\tfinalSegments.push(segments[0].charAt(0));\n\t\t\tcurrentLength = 1;\n\t\t}\n\n\t\t// Add as many collapsed segments as we can fit\n\t\tfor (let i = 1; i < collapsedSegments.length; i++) {\n\t\t\t// +1 for the hyphen\n\t\t\tconst segmentLength = 1 + 1; // 1 for the collapsed segment, 1 for the hyphen\n\n\t\t\tif (currentLength + segmentLength <= maxLength) {\n\t\t\t\tfinalSegments.push(collapsedSegments[i]);\n\t\t\t\tcurrentLength += segmentLength;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn finalSegments.join('-');\n\t}\n}\n","export function stringsShareAPrefix(haystacks: string[], needle: string, delimiter = '-'): boolean {\n\tconst prefix = needle.split(delimiter)[0];\n\treturn -1 !== haystacks.findIndex(haystack => haystack.startsWith(prefix));\n}\n","/**\n * Converts a string to kebab-case.\n *\n * @param str - The string to convert\n * @returns The kebab-cased string\n *\n * @example\n * toKebabCase('Hello World') // 'hello-world'\n * toKebabCase('camelCase') // 'camel-case'\n * toKebabCase('PascalCase') // 'pascal-case'\n * toKebabCase('snake_case') // 'snake-case'\n * toKebabCase('with spaces and_underscores') // 'with-spaces-and-underscores'\n */\nexport function toKebabCase(str: string): string {\n\treturn str\n\t\t// Replace any non-alphanumeric characters with hyphens\n\t\t.replace(/[^a-zA-Z0-9]/g, '-')\n\t\t// Insert a hyphen before any uppercase letter that follows a lowercase letter\n\t\t.replace(/([a-z])([A-Z])/g, '$1-$2')\n\t\t// Convert to lowercase\n\t\t.toLowerCase()\n\t\t// Replace multiple consecutive hyphens with a single hyphen\n\t\t.replace(/-+/g, '-')\n\t\t// Remove leading and trailing hyphens\n\t\t.replace(/^-+|-+$/g, '');\n}\n\n// Easter egg: I know this file doesn't follow our convention (it should be toKebabCase.ts), but I thought it would\n// be funny if it was itself in kebab-case\n// - <3 Dawson\n","import { apiClient } from '@/config/apiClient';\nimport { useMutation } from '@tanstack/react-query';\n\ninterface Params {\n\torganizationId: string;\n\tpaymentMethodId: string;\n}\n\nexport async function onAttachPaymentMethodToOrganization(params: Params): Promise<void> {\n\t// TODO: PUT /Payment/ isn't describing itself from the API.\n\tawait apiClient.put(`/Payment/`, params);\n}\n\nexport function useAttachPaymentMethodToOrganization() {\n\treturn useMutation<void, Error, Params>({\n\t\tmutationFn: (params: Params) => onAttachPaymentMethodToOrganization(params),\n\t});\n}\n","import {\n\tuseAttachPaymentMethodToOrganization,\n} from '@/features/organization/mutations/payments/attachPaymentMethodToOrganization';\nimport { PaymentMethod } from '@stripe/stripe-js/dist/api/payment-methods';\nimport { useCallback } from 'react';\nimport { toast } from 'sonner';\n\nexport function useProcessStripePaymentMethod(organizationId: string) {\n\tconst { mutate: attachPaymentMethodToOrganization } = useAttachPaymentMethodToOrganization();\n\n\treturn useCallback((paymentMethod: string | PaymentMethod, onFinished: (added: boolean) => void) => {\n\t\tattachPaymentMethodToOrganization({\n\t\t\tpaymentMethodId: typeof paymentMethod === 'string' ? paymentMethod : paymentMethod.id,\n\t\t\torganizationId,\n\t\t}, {\n\t\t\tonSuccess: () => {\n\t\t\t\ttoast.success('Success! Your payment method has been saved.');\n\t\t\t\tonFinished(true);\n\t\t\t},\n\t\t\tonError: () => {\n\t\t\t\ttoast.error('Failed to process payment method details. Please try another payment method.');\n\t\t\t\tonFinished(false);\n\t\t\t},\n\t\t});\n\t}, [attachPaymentMethodToOrganization, organizationId]);\n}\n","import { StripeElementsOptions } from '@stripe/stripe-js';\nimport { createContext, useContext } from 'react';\n\nexport const StripeContext = createContext<StripeElementsOptions | null>(null);\n\nexport function useStripeOptions() {\n\treturn useContext(StripeContext) as StripeElementsOptions;\n}\n","import { Button } from '@/components/ui/button';\nimport { useProcessStripePaymentMethod } from '@/integrations/stripe/useProcessStripePaymentMethod';\n\nimport { useStripeOptions } from '@/integrations/stripe/useStripeOptions';\nimport { AddressElement, PaymentElement, useElements, useStripe } from '@stripe/react-stripe-js';\nimport { useParams } from '@tanstack/react-router';\nimport { Save } from 'lucide-react';\nimport { FormEvent, useCallback, useState } from 'react';\nimport { toast } from 'sonner';\n\ninterface AddNewPaymentMethodFormProps {\n\treadonly hasExistingBilling: boolean;\n\treadonly onPaymentAdded: (added: boolean) => void;\n\treadonly onSaveStateForBillingRedirect?: (redirecting: boolean) => void;\n}\n\nexport function AddNewPaymentMethodForm({\n\thasExistingBilling,\n\tonPaymentAdded,\n\tonSaveStateForBillingRedirect,\n}: AddNewPaymentMethodFormProps) {\n\tconst { organizationId } = useParams({ strict: false });\n\tconst stripe = useStripe();\n\tconst stripeOptions = useStripeOptions();\n\tconst elements = useElements();\n\tconst [loading, setLoading] = useState(false);\n\tconst processStripePaymentMethod = useProcessStripePaymentMethod(organizationId);\n\n\tconst onCancelClicked = useCallback(() => {\n\t\tonPaymentAdded(false);\n\t}, [onPaymentAdded]);\n\n\tconst onSubmitAddPaymentMethod = useCallback(async (evt: FormEvent) => {\n\t\tevt.preventDefault();\n\t\tif (!stripe || !elements) {\n\t\t\treturn;\n\t\t}\n\t\tsetLoading(true);\n\n\t\tawait elements.submit();\n\t\tonSaveStateForBillingRedirect?.(true);\n\t\tconst result = await stripe.confirmSetup({\n\t\t\tclientSecret: stripeOptions.clientSecret!,\n\t\t\telements,\n\t\t\tredirect: 'if_required',\n\t\t\t// If you want to test the redirect, this will force it to happen.\n\t\t\t// redirect: 'always' as 'if_required',\n\t\t\tconfirmParams: {\n\t\t\t\treturn_url: `${window.location.origin}/#/${organizationId}/billing/confirm`,\n\t\t\t},\n\t\t});\n\n\t\tif (result.error) {\n\t\t\tconsole.error(result.error.message);\n\t\t\ttoast.error(result.error.message);\n\t\t\tsetLoading(false);\n\t\t\tonSaveStateForBillingRedirect?.(false);\n\t\t} else if (result.setupIntent.payment_method) {\n\t\t\tprocessStripePaymentMethod(result.setupIntent.payment_method, onPaymentAdded);\n\t\t\tonSaveStateForBillingRedirect?.(false);\n\t\t} else {\n\t\t\t// For some payment methods, they will be redirected to an intermediate site first to authorize the\n\t\t\t// payment, then redirected to the `return_url`.\n\t\t}\n\t}, [\n\t\telements,\n\t\tonPaymentAdded,\n\t\tonSaveStateForBillingRedirect,\n\t\torganizationId,\n\t\tprocessStripePaymentMethod,\n\t\tstripe,\n\t\tstripeOptions.clientSecret,\n\t]);\n\n\treturn (\n\t\t<form\n\t\t\tid=\"billing-add-payment-method-form\"\n\t\t\tname=\"billing-add-payment-method-form\"\n\t\t\tonSubmit={onSubmitAddPaymentMethod}\n\t\t\tclassName=\"max-w-xl\"\n\t\t>\n\t\t\t<PaymentElement />\n\t\t\t<AddressElement options={{ mode: 'billing' }} />\n\n\t\t\t<div className=\"mt-4 flex gap-8 items-center\">\n\t\t\t\t<Button disabled={!stripe || !elements || loading} variant=\"submit\" className=\"rounded-full\">\n\t\t\t\t\t<Save /> Add Payment Method\n\t\t\t\t</Button>\n\t\t\t\t{hasExistingBilling && (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<div className=\"text-xs text-gray-600\">Your existing payment method will be overwritten.</div>\n\t\t\t\t\t\t<Button variant=\"defaultOutline\" type=\"button\" onClick={onCancelClicked}>Cancel</Button>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</form>\n\t);\n}\n","import { apiClient } from '@/config/apiClient';\nimport { SchemaStripeAccount } from '@/integrations/api/api.gen';\nimport { useMutation } from '@tanstack/react-query';\n\ninterface Params {\n\torganizationId: string;\n}\n\nexport async function addStripeToOrganizationAndGetIntent(params: Params): Promise<SchemaStripeAccount> {\n\tconst { data } = await apiClient.post(`/StripeAccount/`, params);\n\treturn data;\n}\n\nexport function useAddStripeToOrganizationAndGetIntent() {\n\treturn useMutation<SchemaStripeAccount, Error, Params>({\n\t\tmutationFn: (params: Params) => addStripeToOrganizationAndGetIntent(params),\n\t});\n}\n","import { apiClient } from '@/config/apiClient';\nimport { SchemaStripeAccount } from '@/integrations/api/api.gen';\nimport { useMutation } from '@tanstack/react-query';\n\ninterface Params {\n\torganizationId: string;\n}\n\nexport async function getNewStripeIntentForOrganization(params: Params): Promise<SchemaStripeAccount> {\n\t// TODO: POST /Payment/ isn't describing itself from the API.\n\tconst { data } = await apiClient.post(`/Payment/`, { organizationId: params.organizationId });\n\treturn data as SchemaStripeAccount;\n}\n\nexport function useGetNewStripeIntentForOrganization() {\n\treturn useMutation<SchemaStripeAccount, Error, Params>({\n\t\tmutationFn: (params: Params) => getNewStripeIntentForOrganization(params),\n\t});\n}\n","import { SchemaStripeAccount } from '@/integrations/api/api.gen';\nimport { useAddStripeToOrganizationAndGetIntent } from '@/integrations/stripe/addStripeToOrganizationAndGetIntent';\nimport { useGetNewStripeIntentForOrganization } from '@/integrations/stripe/getNewStripeIntentForOrganization';\nimport { useCallback, useEffect, useState } from 'react';\n\ninterface Params {\n\tenabled: boolean;\n\torganizationId: string;\n\texistingStripeId: string | undefined;\n}\n\nexport function useGetStripeClientSecret(params: Params) {\n\tconst { enabled, existingStripeId, organizationId } = params;\n\tconst { mutate: addStripeToOrganizationAndGetIntent } = useAddStripeToOrganizationAndGetIntent();\n\tconst { mutate: getNewStripeIntentForOrganization } = useGetNewStripeIntentForOrganization();\n\tconst [clientSecret, setClientSecret] = useState<string | undefined>(undefined);\n\n\tconst gotClientSecret = useCallback((data: SchemaStripeAccount) => {\n\t\tsetClientSecret(data.clientSecret);\n\t}, []);\n\n\tuseEffect(() => {\n\t\tif (enabled && import.meta.env.VITE_PUBLIC_STRIPE_KEY) {\n\t\t\tif (existingStripeId) {\n\t\t\t\tgetNewStripeIntentForOrganization({ organizationId }, { onSuccess: gotClientSecret });\n\t\t\t} else {\n\t\t\t\taddStripeToOrganizationAndGetIntent({ organizationId }, { onSuccess: gotClientSecret });\n\t\t\t}\n\t\t}\n\t}, [\n\t\taddStripeToOrganizationAndGetIntent,\n\t\tenabled,\n\t\texistingStripeId,\n\t\tgetNewStripeIntentForOrganization,\n\t\tgotClientSecret,\n\t\torganizationId,\n\t]);\n\n\treturn clientSecret;\n}\n","import { Loading } from '@/components/Loading';\nimport { getOrganizationQueryOptions } from '@/features/organization/queries/getOrganizationQuery';\nimport { stripePromise } from '@/integrations/stripe/stripePromise';\nimport { useGetStripeClientSecret } from '@/integrations/stripe/useGetStripeClientSecret';\nimport { StripeContext } from '@/integrations/stripe/useStripeOptions';\nimport { Elements } from '@stripe/react-stripe-js';\nimport { useQuery } from '@tanstack/react-query';\nimport { useParams } from '@tanstack/react-router';\nimport { ReactNode, useMemo } from 'react';\n\nexport function StripeWrapper({ children }: { children: ReactNode }) {\n\tconst { organizationId } = useParams({ strict: false });\n\tconst { data: organization } = useQuery(getOrganizationQueryOptions(organizationId));\n\tconst clientSecret = useGetStripeClientSecret({\n\t\torganizationId,\n\t\tenabled: !!organization,\n\t\texistingStripeId: organization?.stripeId,\n\t});\n\tconst options = useMemo(() => {\n\t\treturn {\n\t\t\tclientSecret: clientSecret || '',\n\t\t\tappearance: {\n\t\t\t\ttheme: 'night' as const,\n\t\t\t},\n\t\t};\n\t}, [clientSecret]);\n\n\tif (!import.meta.env.VITE_PUBLIC_STRIPE_KEY) {\n\t\tconsole.error('No VITE_PUBLIC_STRIPE_KEY is configured for this environment.');\n\t\treturn (\n\t\t\t<div className=\"mt-20 px-4 pt-4 md:px-12 min-h-[calc(100vh-theme(spacing.32))]\">\n\t\t\t\tSetting up your billing is currently disabled. Please check back again later.\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (!clientSecret || !organization) {\n\t\treturn <Loading centered />;\n\t}\n\n\treturn (\n\t\t<StripeContext value={options}>\n\t\t\t<Elements stripe={stripePromise()} options={options}>\n\t\t\t\t{children}\n\t\t\t</Elements>\n\t\t</StripeContext>\n\t);\n}\n","import { AddNewPaymentMethodForm } from '@/features/organization/billing/paymentMethod/AddNewPaymentMethodForm';\nimport { getOrganizationQueryOptions } from '@/features/organization/queries/getOrganizationQuery';\nimport { StripeWrapper } from '@/integrations/stripe/StripeContext';\nimport { useQuery } from '@tanstack/react-query';\nimport { useParams } from '@tanstack/react-router';\n\ninterface AddNewPaymentMethodProps {\n\treadonly onPaymentAdded: (added: boolean) => void;\n\treadonly onSaveStateForBillingRedirect?: (redirecting: boolean) => void;\n}\n\nexport function AddNewPaymentMethod({ onPaymentAdded, onSaveStateForBillingRedirect }: AddNewPaymentMethodProps) {\n\tconst { organizationId } = useParams({ strict: false });\n\tconst { data: organization } = useQuery(getOrganizationQueryOptions(organizationId));\n\tconst billing = organization?.billing;\n\tconst paymentMethod = billing?.paymentMethod;\n\n\treturn (\n\t\t<StripeWrapper>\n\t\t\t<div className=\"mt-2 mb-6\">\n\t\t\t\t{!paymentMethod && 'You currently have no payment method on file. Please fill out the secure form below.'}\n\t\t\t</div>\n\t\t\t<AddNewPaymentMethodForm\n\t\t\t\thasExistingBilling={!!billing}\n\t\t\t\tonSaveStateForBillingRedirect={onSaveStateForBillingRedirect}\n\t\t\t\tonPaymentAdded={onPaymentAdded}\n\t\t\t/>\n\t\t</StripeWrapper>\n\t);\n}\n","export const enum PaymentMethodStatus {\n\tPASS = 'pass',\n\tFAIL = 'fail',\n\tPENDING = 'pending',\n\tERROR = 'error',\n}\n","import { BadgeStatusVariantValues } from '@/components/ui/utils/badgeStatus';\nimport { PaymentMethodStatus } from '@/integrations/stripe/paymentMethodStatus';\n\nexport function translateStripePaymentMethodStatusToVariant(\n\tpaymentMethodStatus: PaymentMethodStatus | string,\n): BadgeStatusVariantValues {\n\tswitch (paymentMethodStatus) {\n\t\tcase PaymentMethodStatus.PASS:\n\t\t\treturn 'success';\n\t\tcase PaymentMethodStatus.FAIL:\n\t\tcase PaymentMethodStatus.ERROR:\n\t\t\treturn 'destructive';\n\t\tcase PaymentMethodStatus.PENDING:\n\t\tdefault:\n\t\t\treturn 'default';\n\t}\n}\n\nexport function translateStripePaymentMethodStatusToText(paymentMethodStatus: PaymentMethodStatus | string): string {\n\tswitch (paymentMethodStatus) {\n\t\tcase PaymentMethodStatus.PASS:\n\t\t\treturn 'READY';\n\t\tcase PaymentMethodStatus.FAIL:\n\t\tcase PaymentMethodStatus.ERROR:\n\t\tcase PaymentMethodStatus.PENDING:\n\t\tdefault:\n\t\t\treturn paymentMethodStatus.toUpperCase();\n\t}\n}\n","export function formatMonthAndYear(month: number, year: number): string {\n\tconst mm = String(month).padStart(2, '0');\n\t// Use two-digit year for typical card expiration display\n\tconst yy = String(year % 100).padStart(2, '0');\n\treturn `${mm}/${yy}`;\n}\n","import { ContactUs } from '@/components/ContactUs';\nimport { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport { AddNewPaymentMethod } from '@/features/organization/billing/paymentMethod/AddNewPaymentMethod';\nimport { getOrganizationQueryOptions } from '@/features/organization/queries/getOrganizationQuery';\nimport { useOrganizationPermissions } from '@/hooks/usePermissions';\nimport { ENTERPRISE } from '@/integrations/api/orgType';\nimport {\n\ttranslateStripePaymentMethodStatusToText,\n\ttranslateStripePaymentMethodStatusToVariant,\n} from '@/integrations/stripe/translateStripePaymentMethodStatus';\nimport { formatMonthAndYear } from '@/lib/formatMonthAndYear';\nimport { useQuery } from '@tanstack/react-query';\nimport { useParams } from '@tanstack/react-router';\nimport { useCallback, useState } from 'react';\n\ninterface PaymentMethodsDisplayProps {\n\tonSaveStateForBillingRedirect?: (redirecting: boolean) => void;\n\tonReplacingPaymentMethod?: (value: boolean) => void;\n}\n\nexport function PaymentMethodsDisplay(props?: PaymentMethodsDisplayProps) {\n\tconst { onSaveStateForBillingRedirect, onReplacingPaymentMethod } = props ?? {};\n\tconst { organizationId } = useParams({ strict: false });\n\tconst { update } = useOrganizationPermissions(organizationId);\n\tconst { data: organization, refetch } = useQuery(getOrganizationQueryOptions(organizationId));\n\tconst billing = organization?.billing;\n\tconst paymentMethod = billing?.paymentMethod;\n\tconst [replacingPaymentMethod, setReplacingPaymentMethod] = useState(false);\n\tconst onReplacePaymentMethodClicked = useCallback(\n\t\t() => {\n\t\t\tsetReplacingPaymentMethod(!replacingPaymentMethod);\n\t\t\tonReplacingPaymentMethod?.(!replacingPaymentMethod);\n\t\t},\n\t\t[onReplacingPaymentMethod, replacingPaymentMethod],\n\t);\n\tconst onPaymentAdded = useCallback((added: boolean) => {\n\t\tsetReplacingPaymentMethod(false);\n\t\tonReplacingPaymentMethod?.(false);\n\t\tif (added) {\n\t\t\tvoid refetch();\n\t\t}\n\t}, [onReplacingPaymentMethod, refetch]);\n\n\tif (organization?.type === ENTERPRISE) {\n\t\treturn (\n\t\t\t<span>\n\t\t\t\tYou are part of an enterprise organization! We don’t currently show your payment methods on this page.\n\t\t\t\tWant to explore your solution with Harper more? <ContactUs />, we would love to talk!\n\t\t\t</span>\n\t\t);\n\t}\n\n\tif (paymentMethod && !replacingPaymentMethod) {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<div className=\"mt-2\">\n\t\t\t\t\t{paymentMethod.brand?.toUpperCase() ?? 'Card'} ending in {paymentMethod.last4 ?? '••••'}\n\t\t\t\t\t{(paymentMethod.expMonth && paymentMethod.expYear)\n\t\t\t\t\t\t? <>(exp {formatMonthAndYear(paymentMethod.expMonth, paymentMethod.expYear)})</>\n\t\t\t\t\t\t: null}\n\t\t\t\t\t{paymentMethod.status\n\t\t\t\t\t\t? (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t—{' '}\n\t\t\t\t\t\t\t\t<Badge variant={translateStripePaymentMethodStatusToVariant(paymentMethod.status)}>\n\t\t\t\t\t\t\t\t\t{translateStripePaymentMethodStatusToText(paymentMethod.status)}\n\t\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)\n\t\t\t\t\t\t: null}\n\t\t\t\t</div>\n\t\t\t\t{update && (\n\t\t\t\t\t<div className=\"mt-2 mb-6\">\n\t\t\t\t\t\t<Button variant=\"defaultOutline\" type=\"button\" onClick={onReplacePaymentMethodClicked}>\n\t\t\t\t\t\t\tReplace Payment Method\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</>\n\t\t);\n\t}\n\n\tif (!update) {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\tThis org doesn't have a payment method, and you don't have access to add one. Please contact your administrator.\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<AddNewPaymentMethod\n\t\t\tonSaveStateForBillingRedirect={onSaveStateForBillingRedirect}\n\t\t\tonPaymentAdded={onPaymentAdded}\n\t\t/>\n\t);\n}\n","export function isPositive(value: number | undefined): value is number {\n\treturn value !== undefined && value > 0;\n}\n","import { ContactUs } from '@/components/ContactUs';\nimport { Button } from '@/components/ui/button';\nimport { PaymentMethodsDisplay } from '@/features/organization/billing/paymentMethod/PaymentMethodsDisplay';\nimport { getOrganizationQueryOptions } from '@/features/organization/queries/getOrganizationQuery';\nimport { SchemaPlan } from '@/integrations/api/api.gen';\nimport { ENTERPRISE } from '@/integrations/api/orgType';\nimport { PaymentMethodStatus } from '@/integrations/stripe/paymentMethodStatus';\nimport { pluralize } from '@/lib/pluralize';\nimport { isPositive } from '@/lib/types/isPositive';\nimport { useQuery } from '@tanstack/react-query';\nimport { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react';\nimport { useState } from 'react';\n\ninterface ClusterBillingProps {\n\treadonly clusterId?: string;\n\treadonly isPending: boolean;\n\treadonly onGoBackToDetails: () => void;\n\treadonly onSaveStateForBillingRedirect: (redirecting: boolean) => void;\n\treadonly onSubmit?: () => void;\n\treadonly organizationId: string;\n\treadonly selectedPlan: SchemaPlan | undefined;\n}\n\nexport function ClusterBilling({\n\tclusterId,\n\tisPending,\n\tonGoBackToDetails,\n\tonSaveStateForBillingRedirect,\n\tonSubmit,\n\torganizationId,\n\tselectedPlan,\n}: ClusterBillingProps) {\n\tconst { data: organization } = useQuery(getOrganizationQueryOptions(organizationId));\n\tconst billing = organization?.billing;\n\tconst allowBypass = import.meta.env.DEV && !import.meta.env.VITE_PUBLIC_STRIPE_KEY;\n\tconst isEnterprise = organization?.type === ENTERPRISE;\n\tconst hasValidPaymentMethod = allowBypass || isEnterprise\n\t\t|| billing?.paymentMethod?.status === PaymentMethodStatus.PASS;\n\tconst [replacingPaymentMethod, setReplacingPaymentMethod] = useState(false);\n\tconst expirationMonths = isPositive(selectedPlan?.planLimits?.expirationMonths)\n\t\t&& selectedPlan.planLimits.expirationMonths < 1000 && selectedPlan.planLimits.expirationMonths;\n\n\tconst footer = (\n\t\t<>\n\t\t\t<div className=\"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end mt-3 max-w-xl\">\n\t\t\t\t<Button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tvariant=\"defaultOutline\"\n\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\tdisabled={isPending}\n\t\t\t\t\tonClick={onGoBackToDetails}\n\t\t\t\t>\n\t\t\t\t\t<ArrowLeftIcon /> Back to Details\n\t\t\t\t</Button>\n\t\t\t\t<Button\n\t\t\t\t\tdisabled={isPending || !hasValidPaymentMethod || replacingPaymentMethod}\n\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\tvariant=\"submit\"\n\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\tonClick={onSubmit}\n\t\t\t\t>\n\t\t\t\t\t{clusterId ? 'Edit Cluster' : 'Create New Cluster'} <ArrowRightIcon />\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t</>\n\t);\n\n\tif (isEnterprise) {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<ul className=\"list-disc ml-6 max-w-lg\">\n\t\t\t\t\t<li>\n\t\t\t\t\t\tReminder: you will be billed at your contracted rate for any additional infrastructure.\n\t\t\t\t\t</li>\n\t\t\t\t\t<li>\n\t\t\t\t\t\tYour account representative can work with you to sort out more precise details, and to help accomplish your\n\t\t\t\t\t\tobjectives with this cluster. <ContactUs overEmail={true} />, we are here to help.\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\n\t\t\t\t{footer}\n\t\t\t</>\n\t\t);\n\t}\n\n\tif (allowBypass) {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<ul className=\"list-disc ml-6\">\n\t\t\t\t\t<li>\n\t\t\t\t\t\tStripe is not configured, and will be bypassed during cluster creation.\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\n\t\t\t\t{footer}\n\t\t\t</>\n\t\t);\n\t}\n\n\tconst orPossiblyExpires = expirationMonths && `, or ${pluralize(expirationMonths, 'month', 'months')} elapse`;\n\n\treturn (\n\t\t<>\n\t\t\t<ul className=\"list-disc ml-6 mb-6\">\n\t\t\t\t<li>\n\t\t\t\t\tYou will be billed for this cluster today, and will receive a license for the block of usage you've requested.\n\t\t\t\t</li>\n\t\t\t\t{clusterId && (\n\t\t\t\t\t<li>\n\t\t\t\t\t\tIf you scale up, you'll be charged for the additional blocks you've purchased now, and your next auto\n\t\t\t\t\t\trenewal will be for all purchased blocks.\n\t\t\t\t\t</li>\n\t\t\t\t)}\n\t\t\t\t{clusterId && (\n\t\t\t\t\t<li>\n\t\t\t\t\t\tIf you remove a region, that region's usage block will not be used anymore (because it is specific to that\n\t\t\t\t\t\tregion).\n\t\t\t\t\t</li>\n\t\t\t\t)}\n\t\t\t\t<li>When that block is used up{orPossiblyExpires}, you will be automatically renewed.</li>\n\t\t\t\t<li>While refunds are not available, we’d be happy to assist you with troubleshooting.</li>\n\t\t\t\t<li>\n\t\t\t\t\tWe would love to work with you to sort out more precise details, and to help accomplish your objectives with\n\t\t\t\t\tthis cluster. <ContactUs overEmail={true} />, we are here to help.\n\t\t\t\t</li>\n\t\t\t</ul>\n\n\t\t\t<p className=\"text-muted-foreground text-sm mb-6\">Payment method:</p>\n\n\t\t\t<PaymentMethodsDisplay\n\t\t\t\tonSaveStateForBillingRedirect={onSaveStateForBillingRedirect}\n\t\t\t\tonReplacingPaymentMethod={setReplacingPaymentMethod}\n\t\t\t/>\n\n\t\t\t{footer}\n\t\t</>\n\t);\n}\n","// Matches one of:\n// - \"localhost\"\n// - IPv4 address (four 0–255 octets, no leading zeros for multi-digit values)\n// - Domain with subdomains: labels 1–63 chars (alphanumeric and hyphen, not starting/ending with hyphen),\n// with a final TLD of 2+ letters. No ports, no paths, no IPv6.\nexport const hostNameRegex =\n\t/(^$|^(?:localhost|(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}|(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z]{2,})$)/i;\n","export const minPortNumber = 0;\nexport const maxPortNumber = 65535;\n","import { hostNameRegex } from '@/lib/string/regex/hostNameRegex';\nimport { maxPortNumber, minPortNumber } from '@/lib/types/portNumbers';\nimport { z } from 'zod';\n\nexport const specifiedAbbreviatedName = z\n\t.string()\n\t.max(20, 'Must be at most 20 characters long.')\n\t.regex(\n\t\t/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/,\n\t\t'Can only contain lowercase letters, numbers and dashes. Must not start or end with a dash.',\n\t);\n\nexport const UpsertClusterSchema = z.object({\n\tclusterName: z.string()\n\t\t.nonempty('Please enter a cluster name.')\n\t\t.max(255, 'Cluster name cannot be longer than 255 characters long.'),\n\tabbreviatedName: z.union([\n\t\tz.literal(''),\n\t\tz.undefined(),\n\t\tspecifiedAbbreviatedName,\n\t]),\n\tfqdn: z\n\t\t.string()\n\t\t.regex(hostNameRegex, 'Please enter a valid host name without the port or any path.')\n\t\t.optional(),\n\n\tversion: z.string().optional(),\n\tdeploymentDescription: z.string().nonempty('Please select a deployment tier.'),\n\tperformanceDescription: z.string().nonempty('Please select a performance tier.'),\n\n\tregionPlans: z.array(\n\t\tz.object({\n\t\t\tregionName: z.string().nonempty('Please select a region.'),\n\t\t\tlatencyDescription: z.string().nonempty('Please select a latency tier.'),\n\t\t}),\n\t).max(50, { error: 'A maximum of 50 regions can be selected for each cluster. ' }),\n\n\tinstances: z.array(\n\t\tz.object({\n\t\t\tsecure: z.enum(['true', 'false']),\n\t\t\tfqdn: z.string()\n\t\t\t\t.nonempty('Please enter the host name of your instance.')\n\t\t\t\t.regex(hostNameRegex, 'Please enter a valid host name without the port or any path.'),\n\t\t\tport: z.number()\n\t\t\t\t.min(minPortNumber, 'Positive thinking only, please.')\n\t\t\t\t.max(maxPortNumber, 'That port number is too high.')\n\t\t\t\t.optional(),\n\t\t}),\n\t).max(100, { error: 'A maximum of 100 instances can be added to each cluster.' }),\n\n\tskipToBilling: z.boolean().optional(),\n\tskipGtmWait: z.boolean().optional(),\n\tsourceClusterId: z.string().optional(),\n});\n\nexport type UpsertClusterSchemaType = z.infer<typeof UpsertClusterSchema>;\n","import { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { specifiedAbbreviatedName, UpsertClusterSchema } from '@/features/clusters/upsert/upsertClusterSchema';\nimport { UseFormReturn } from 'react-hook-form';\nimport { z } from 'zod';\n\nexport function ClusterAbbreviatedName({\n\tcalculatedNames,\n\tdisabled,\n\tform,\n}: {\n\tcalculatedNames: { suggestedAbbreviatedName: string; fullHostName: string };\n\tdisabled?: boolean | undefined;\n\tform: UseFormReturn<z.infer<typeof UpsertClusterSchema>>;\n}) {\n\treturn (\n\t\t<>\n\t\t\t<FormField\n\t\t\t\tcontrol={form.control}\n\t\t\t\tname=\"abbreviatedName\"\n\t\t\t\trender={({ field }) => (\n\t\t\t\t\t<FormItem className=\"col-span-3\">\n\t\t\t\t\t\t<FormLabel className=\"pb-1\">Host Name</FormLabel>\n\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\tmaxLength={specifiedAbbreviatedName.maxLength!}\n\t\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\tautoCorrect=\"off\"\n\t\t\t\t\t\t\t\tplaceholder={calculatedNames.suggestedAbbreviatedName}\n\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t</FormItem>\n\t\t\t\t)}\n\t\t\t/>\n\t\t\t<FormItem className=\"col-span-3 \">\n\t\t\t\t<FormLabel className=\"pb-1\">Full Host Name</FormLabel>\n\t\t\t\t<FormControl>\n\t\t\t\t\t<span>{calculatedNames.fullHostName}</span>\n\t\t\t\t</FormControl>\n\t\t\t\t<FormMessage />\n\t\t\t</FormItem>\n\t\t</>\n\t);\n}\n","import { cx } from 'class-variance-authority';\nimport { useMemo } from 'react';\n\nexport function TextLoadingSkeleton({ className }: { className?: string } = {}) {\n\tconst computedClassName = useMemo(() =>\n\t\tcx(\n\t\t\t`animate-pulse h-2.5 bg-gray-200 rounded-full dark:bg-gray-700`,\n\t\t\t!className?.includes('mb-') && 'mb-4 ',\n\t\t\t!className?.includes('w-') && 'w-48 ',\n\t\t\tclassName,\n\t\t), [className]);\n\treturn <div className={computedClassName}></div>;\n}\n","import * as SelectPrimitive from '@radix-ui/react-select';\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn } from '@/lib/cn';\n\nfunction Select({ ...props }: React.ComponentProps<typeof SelectPrimitive.Root>) {\n\treturn <SelectPrimitive.Root data-slot=\"select\" {...props} />;\n}\n\nfunction SelectGroup({ ...props }: React.ComponentProps<typeof SelectPrimitive.Group>) {\n\treturn <SelectPrimitive.Group data-slot=\"select-group\" {...props} />;\n}\n\nfunction SelectValue({ ...props }: React.ComponentProps<typeof SelectPrimitive.Value>) {\n\treturn <SelectPrimitive.Value data-slot=\"select-value\" {...props} />;\n}\n\nfunction SelectTrigger({ className, children, ...props }: React.ComponentProps<typeof SelectPrimitive.Trigger>) {\n\treturn (\n\t\t<SelectPrimitive.Trigger\n\t\t\tdata-slot=\"select-trigger\"\n\t\t\tclassName={cn(\n\t\t\t\t\"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive flex h-9 w-fit items-center justify-between gap-2 rounded-md border bg-grey-700 px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 *:data-[slot=select-value]:truncate *:data-[slot=select-value]:block *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t\t<SelectPrimitive.Icon asChild>\n\t\t\t\t<ChevronDownIcon className=\"opacity-50 size-4\" />\n\t\t\t</SelectPrimitive.Icon>\n\t\t</SelectPrimitive.Trigger>\n\t);\n}\n\nfunction SelectContent({\n\tclassName,\n\tchildren,\n\tposition = 'popper',\n\t...props\n}: React.ComponentProps<typeof SelectPrimitive.Content>) {\n\treturn (\n\t\t<SelectPrimitive.Portal>\n\t\t\t<SelectPrimitive.Content\n\t\t\t\tdata-slot=\"select-content\"\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border shadow-md',\n\t\t\t\t\tposition === 'popper'\n\t\t\t\t\t\t&& 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tposition={position}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t<SelectScrollUpButton />\n\t\t\t\t<SelectPrimitive.Viewport\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'p-1',\n\t\t\t\t\t\tposition === 'popper'\n\t\t\t\t\t\t\t&& 'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1',\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</SelectPrimitive.Viewport>\n\t\t\t\t<SelectScrollDownButton />\n\t\t\t</SelectPrimitive.Content>\n\t\t</SelectPrimitive.Portal>\n\t);\n}\n\nfunction SelectLabel({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Label>) {\n\treturn (\n\t\t<SelectPrimitive.Label\n\t\t\tdata-slot=\"select-label\"\n\t\t\tclassName={cn('px-2 py-1.5 text-sm font-medium', className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction SelectItem({ className, children, ...props }: React.ComponentProps<typeof SelectPrimitive.Item>) {\n\treturn (\n\t\t<SelectPrimitive.Item\n\t\t\tdata-slot=\"select-item\"\n\t\t\tclassName={cn(\n\t\t\t\t\"focus:bg-grey-200 focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n\t\t\t<span className=\"absolute right-2 flex size-3.5 items-center justify-center\">\n\t\t\t\t<SelectPrimitive.ItemIndicator>\n\t\t\t\t\t<CheckIcon className=\"size-4\" />\n\t\t\t\t</SelectPrimitive.ItemIndicator>\n\t\t\t</span>\n\t\t</SelectPrimitive.Item>\n\t);\n}\n\nfunction SelectSeparator({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Separator>) {\n\treturn (\n\t\t<SelectPrimitive.Separator\n\t\t\tdata-slot=\"select-separator\"\n\t\t\tclassName={cn('bg-border pointer-events-none -mx-1 my-1 h-px', className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction SelectScrollUpButton({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {\n\treturn (\n\t\t<SelectPrimitive.ScrollUpButton\n\t\t\tdata-slot=\"select-scroll-up-button\"\n\t\t\tclassName={cn('flex cursor-default items-center justify-center py-1', className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<ChevronUpIcon className=\"size-4\" />\n\t\t</SelectPrimitive.ScrollUpButton>\n\t);\n}\n\nfunction SelectScrollDownButton({\n\tclassName,\n\t...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {\n\treturn (\n\t\t<SelectPrimitive.ScrollDownButton\n\t\t\tdata-slot=\"select-scroll-down-button\"\n\t\t\tclassName={cn('flex cursor-default items-center justify-center py-1', className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<ChevronDownIcon className=\"size-4\" />\n\t\t</SelectPrimitive.ScrollDownButton>\n\t);\n}\n\nexport {\n\tSelect,\n\tSelectContent,\n\tSelectGroup,\n\tSelectItem,\n\tSelectLabel,\n\tSelectScrollDownButton,\n\tSelectScrollUpButton,\n\tSelectSeparator,\n\tSelectTrigger,\n\tSelectValue,\n};\n","import { TextLoadingSkeleton } from '@/components/TextLoadingSkeleton';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';\nimport { UpsertClusterSchema } from '@/features/clusters/upsert/upsertClusterSchema';\nimport { Suspense } from 'react';\nimport { UseFormReturn } from 'react-hook-form';\nimport { z } from 'zod';\n\nconst DEPLOYMENT_FULL_DESCRIPTION: { [key: string]: string } = {\n\t'Colocated': 'Shared infrastructure for optimized value',\n\t'Dedicated': 'Dedicated infrastructure for consistent performance',\n\t'Self-Hosted': 'Your own infrastructure',\n};\n\nexport function ClusterDeploymentDescription({\n\tavailableDeploymentTypes,\n\tdisabled,\n\tform,\n}: {\n\tavailableDeploymentTypes: string[];\n\tdisabled?: boolean | undefined;\n\tform: UseFormReturn<z.infer<typeof UpsertClusterSchema>>;\n}) {\n\treturn (\n\t\t<FormField\n\t\t\tcontrol={form.control}\n\t\t\tname=\"deploymentDescription\"\n\t\t\trender={({ field }) => (\n\t\t\t\t<FormItem className=\"col-span-3\">\n\t\t\t\t\t<FormLabel className=\"pb-1\">Harper Deployment</FormLabel>\n\n\t\t\t\t\t<Suspense fallback={<TextLoadingSkeleton />}>\n\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\tonValueChange={(deploymentDescription) => {\n\t\t\t\t\t\t\t\t\tfield.onChange(deploymentDescription);\n\t\t\t\t\t\t\t\t\tvoid form.trigger();\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<SelectTrigger className=\"w-full h-auto\">\n\t\t\t\t\t\t\t\t\t<SelectValue placeholder=\"Choose Tier\" />\n\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t\t<SelectGroup>\n\t\t\t\t\t\t\t\t\t\t{availableDeploymentTypes.map((deploymentDescription) => (\n\t\t\t\t\t\t\t\t\t\t\t<SelectItem\n\t\t\t\t\t\t\t\t\t\t\t\tkey={deploymentDescription}\n\t\t\t\t\t\t\t\t\t\t\t\tvalue={deploymentDescription}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<dt className=\"text-left font-bold text-sm/6\">{deploymentDescription}</dt>\n\t\t\t\t\t\t\t\t\t\t\t\t{DEPLOYMENT_FULL_DESCRIPTION[deploymentDescription] && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<dd className=\"font-light\">{DEPLOYMENT_FULL_DESCRIPTION[deploymentDescription]}</dd>\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</SelectGroup>\n\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t</Suspense>\n\n\t\t\t\t\t<FormMessage />\n\t\t\t\t</FormItem>\n\t\t\t)}\n\t\t/>\n\t);\n}\n","import { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { UpsertClusterSchema } from '@/features/clusters/upsert/upsertClusterSchema';\nimport { UseFormReturn } from 'react-hook-form';\nimport { z } from 'zod';\n\nexport function ClusterFQDN({\n\tdisabled,\n\tform,\n}: {\n\tdisabled?: boolean | undefined;\n\tform: UseFormReturn<z.infer<typeof UpsertClusterSchema>>;\n}) {\n\treturn (\n\t\t<FormField\n\t\t\tcontrol={form.control}\n\t\t\tname=\"fqdn\"\n\t\t\trender={({ field }) => (\n\t\t\t\t<FormItem className=\"md:col-span-6 col-span-3\">\n\t\t\t\t\t<FormLabel className=\"pb-1\">Optional Cluster Load Balancer Host Name</FormLabel>\n\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\tautoCorrect=\"off\"\n\t\t\t\t\t\t\tplaceholder=\"example.your-company.com\"\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</FormControl>\n\t\t\t\t\t<FormMessage />\n\t\t\t\t</FormItem>\n\t\t\t)}\n\t\t/>\n\t);\n}\n","import { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { UpsertClusterSchema } from '@/features/clusters/upsert/upsertClusterSchema';\nimport { UseFormReturn } from 'react-hook-form';\nimport { z } from 'zod';\n\nexport function ClusterName({\n\tclassName,\n\tdisabled,\n\tform,\n}: {\n\tclassName: string;\n\tdisabled?: boolean | undefined;\n\tform: UseFormReturn<z.infer<typeof UpsertClusterSchema>>;\n}) {\n\treturn (\n\t\t<FormField\n\t\t\tcontrol={form.control}\n\t\t\tname=\"clusterName\"\n\t\t\trender={({ field }) => (\n\t\t\t\t<FormItem className={className}>\n\t\t\t\t\t<FormLabel className=\"pb-1\">Cluster Name</FormLabel>\n\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\tautoFocus={true}\n\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\tmaxLength={UpsertClusterSchema.shape.clusterName.maxLength!}\n\t\t\t\t\t\t\tautoCapitalize=\"words\"\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</FormControl>\n\t\t\t\t\t<FormMessage />\n\t\t\t\t</FormItem>\n\t\t\t)}\n\t\t/>\n\t);\n}\n","import { TextLoadingSkeleton } from '@/components/TextLoadingSkeleton';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';\nimport { UpsertClusterSchema } from '@/features/clusters/upsert/upsertClusterSchema';\nimport { Suspense } from 'react';\nimport { UseFormReturn } from 'react-hook-form';\nimport { z } from 'zod';\n\nexport function ClusterPerformanceDescription({\n\tavailablePerformanceDescriptions,\n\tform,\n\tselectedDeployment,\n}: {\n\tavailablePerformanceDescriptions: { name: string; performanceTier: string; description?: string }[];\n\tform: UseFormReturn<z.infer<typeof UpsertClusterSchema>>;\n\tselectedDeployment: string;\n}) {\n\treturn (\n\t\t<FormField\n\t\t\tcontrol={form.control}\n\t\t\tname=\"performanceDescription\"\n\t\t\trender={({ field }) => (\n\t\t\t\t<FormItem className=\"col-span-3\">\n\t\t\t\t\t<FormLabel className=\"pb-1\">\n\t\t\t\t\t\t{selectedDeployment.startsWith('Self') ? 'Support' : 'Performance'} & Usage\n\t\t\t\t\t</FormLabel>\n\n\t\t\t\t\t<Suspense fallback={<TextLoadingSkeleton />}>\n\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\tonValueChange={(performanceDescription) => {\n\t\t\t\t\t\t\t\t\tfield.onChange(performanceDescription);\n\t\t\t\t\t\t\t\t\tvoid form.trigger();\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tdisabled={!availablePerformanceDescriptions?.length}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<SelectTrigger className=\"w-full h-auto\">\n\t\t\t\t\t\t\t\t\t<SelectValue placeholder=\"Choose Tier\" />\n\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t\t<SelectGroup>\n\t\t\t\t\t\t\t\t\t\t{availablePerformanceDescriptions.map((performanceDescription) => (\n\t\t\t\t\t\t\t\t\t\t\t<SelectItem\n\t\t\t\t\t\t\t\t\t\t\t\tkey={performanceDescription.name}\n\t\t\t\t\t\t\t\t\t\t\t\tvalue={performanceDescription.performanceTier}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<dt className=\"text-left font-bold text-sm/6\">{performanceDescription.name}</dt>\n\t\t\t\t\t\t\t\t\t\t\t\t{performanceDescription.description && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<dd className=\"font-light\">{performanceDescription.description}</dd>\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</SelectGroup>\n\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t</Suspense>\n\n\t\t\t\t\t<FormMessage />\n\t\t\t\t</FormItem>\n\t\t\t)}\n\t\t/>\n\t);\n}\n","import { useFormField } from '@/components/ui/form/useFormField';\nimport { cn } from '@/lib/cn';\nimport { ComponentProps } from 'react';\n\nexport function FormDescription({ className, ...props }: ComponentProps<'p'>) {\n\tconst { formDescriptionId } = useFormField();\n\n\treturn (\n\t\t<p\n\t\t\tdata-slot=\"form-description\"\n\t\t\tid={formDescriptionId}\n\t\t\tclassName={cn('text-muted-foreground text-sm', className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n","import { FormControl } from '@/components/ui/form/FormControl';\nimport { FormDescription } from '@/components/ui/form/FormDescription';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { Input } from '@/components/ui/input';\nimport { UpsertClusterSchema } from '@/features/clusters/upsert/upsertClusterSchema';\nimport { UseFormReturn } from 'react-hook-form';\nimport { z } from 'zod';\n\nexport function ClusterSkipGtmWait({\n\tclassName,\n\tform,\n}: {\n\tclassName?: string;\n\tform: UseFormReturn<z.infer<typeof UpsertClusterSchema>>;\n}) {\n\treturn (\n\t\t<FormField\n\t\t\tcontrol={form.control}\n\t\t\tname=\"skipGtmWait\"\n\t\t\trender={({ field }) => (\n\t\t\t\t<FormItem className={className}>\n\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\tclassName=\"w-4 h-4 cursor-pointer\"\n\t\t\t\t\t\t\t\tchecked={field.value || false}\n\t\t\t\t\t\t\t\tonChange={field.onChange}\n\t\t\t\t\t\t\t\tonBlur={field.onBlur}\n\t\t\t\t\t\t\t\tname={field.name}\n\t\t\t\t\t\t\t\tref={field.ref}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t<FormLabel className=\"cursor-pointer\">Immediate upgrade and restart</FormLabel>\n\t\t\t\t\t</div>\n\t\t\t\t\t<FormDescription>\n\t\t\t\t\t\tApply changes immediately without waiting for each instance to be taken out of the load balancer (faster,\n\t\t\t\t\t\tbut potentially less safe).\n\t\t\t\t\t</FormDescription>\n\t\t\t\t</FormItem>\n\t\t\t)}\n\t\t/>\n\t);\n}\n","import { TextLoadingSkeleton } from '@/components/TextLoadingSkeleton';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';\nimport { HarperVersionsResponse } from '@/features/clusters/queries/getHarperVersionsQuery';\nimport { UpsertClusterSchema } from '@/features/clusters/upsert/upsertClusterSchema';\nimport { Suspense } from 'react';\nimport { UseFormReturn } from 'react-hook-form';\nimport { z } from 'zod';\n\nexport function ClusterVersion({\n\tclassName,\n\tdisabled,\n\tform,\n\tharperVersions,\n}: {\n\tclassName: string;\n\tdisabled?: boolean | undefined;\n\tform: UseFormReturn<z.infer<typeof UpsertClusterSchema>>;\n\tharperVersions: HarperVersionsResponse | undefined;\n}) {\n\tif (!harperVersions?.value?.length) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<FormField\n\t\t\tcontrol={form.control}\n\t\t\tname=\"version\"\n\t\t\trender={({ field }) => (\n\t\t\t\t<FormItem className={className}>\n\t\t\t\t\t<FormLabel className=\"pb-1\">Harper Version</FormLabel>\n\n\t\t\t\t\t<Suspense fallback={<TextLoadingSkeleton />}>\n\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\tonValueChange={(version) => {\n\t\t\t\t\t\t\t\t\tfield.onChange(version);\n\t\t\t\t\t\t\t\t\tvoid form.trigger();\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<SelectTrigger className=\"w-full h-auto\">\n\t\t\t\t\t\t\t\t\t<SelectValue placeholder=\"Choose Version\" />\n\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t\t<SelectGroup>\n\t\t\t\t\t\t\t\t\t\t{harperVersions?.value.map((harperVersion) => (\n\t\t\t\t\t\t\t\t\t\t\t<SelectItem\n\t\t\t\t\t\t\t\t\t\t\t\tkey={harperVersion.version}\n\t\t\t\t\t\t\t\t\t\t\t\tvalue={harperVersion.version}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{harperVersion.version} <span className=\"font-light opacity-50\">{harperVersion.name}</span>\n\t\t\t\t\t\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</SelectGroup>\n\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t</Suspense>\n\n\t\t\t\t\t<FormMessage />\n\t\t\t\t</FormItem>\n\t\t\t)}\n\t\t/>\n\t);\n}\n","const numberPrefix = new RegExp(/^\\d+/);\n\nexport function sortByNumberPrefix(a: string, b: string): number {\n\tconst aPrefix = parseInt(a.match(numberPrefix)?.[0] || '0', 10);\n\tconst bPrefix = parseInt(b.match(numberPrefix)?.[0] || '0', 10);\n\tif (aPrefix === bPrefix) {\n\t\treturn 0;\n\t}\n\treturn aPrefix > bPrefix ? 1 : -1;\n}\n","export type Units = 'bytes' | 'secs';\n\nconst dataUnits = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];\nconst timeUnits = ['secs', 'mins', 'hrs'];\nconst unitsMultipliers = {\n\tbytes: 1000,\n\tsecs: 60,\n};\n\nexport function scaleValueToUnits(value: number, baseUnits: string, units: string) {\n\tlet availableUnits;\n\tlet scaleBase;\n\tswitch (baseUnits) {\n\t\tcase 'bytes': {\n\t\t\tavailableUnits = dataUnits;\n\t\t\tscaleBase = unitsMultipliers.bytes;\n\t\t\tbreak;\n\t\t}\n\t\tcase 'secs': {\n\t\t\tavailableUnits = timeUnits;\n\t\t\tscaleBase = unitsMultipliers.secs;\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t\treturn value;\n\t}\n\tconst scaleExponent = availableUnits.indexOf(units);\n\tif (scaleExponent === -1) {\n\t\treturn value;\n\t}\n\tconst scaleFactor = scaleBase ** scaleExponent;\n\treturn value / scaleFactor;\n}\n\nexport function determineUnits(baseUnits: string, value: number) {\n\tlet availableUnits;\n\tlet unitsMultiplier;\n\tswitch (baseUnits) {\n\t\tcase 'bytes':\n\t\t\tavailableUnits = dataUnits;\n\t\t\tunitsMultiplier = unitsMultipliers.bytes;\n\t\t\tbreak;\n\t\tcase 'secs':\n\t\t\tavailableUnits = timeUnits;\n\t\t\tunitsMultiplier = unitsMultipliers.secs;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn baseUnits;\n\t}\n\tlet i = 0;\n\twhile (value >= unitsMultiplier && i < availableUnits.length - 1) {\n\t\tvalue /= unitsMultiplier;\n\t\ti++;\n\t}\n\treturn availableUnits[i];\n}\n","import { determineUnits, scaleValueToUnits } from '@/lib/units.ts';\n\nexport function humanFileSize(input: number, multiplierFromBytes: number = 1) {\n\tconst initialValue = input * multiplierFromBytes;\n\tconst units = determineUnits('bytes', initialValue);\n\tconst scaled = scaleValueToUnits(initialValue, 'bytes', units);\n\n\tconst value = new Intl.NumberFormat().format(Math.round(scaled));\n\treturn `${value} ${units}`;\n}\n","export function addCommasToNumbers(input: number): string {\n\treturn new Intl.NumberFormat().format(input);\n}\n","import { addCommasToNumbers } from '@/lib/addCommasToNumbers';\n\nconst units = ['K', 'M', 'B', 'T', 'Qa', 'Qi', 'Sx', 'Sp', 'Oc', 'No', 'Dc'];\n\nexport function humanNumber(input: number): string {\n\tconst thresh = 1000;\n\tlet value = input;\n\n\tif (Math.abs(value) < thresh) {\n\t\treturn String(Math.round(value));\n\t}\n\n\tlet u = -1;\n\tconst r = 10;\n\n\tdo {\n\t\tvalue /= thresh;\n\t\t++u;\n\t} while (Math.round(Math.abs(value) * r) / r >= thresh && u < units.length - 1);\n\n\treturn `${addCommasToNumbers(Math.round(value))} ${units[u]}`;\n}\n","import { Button } from '@/components/ui/button';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { SchemaPlan, SchemaRegion } from '@/integrations/api/api.gen';\nimport { excludeFalsy } from '@/lib/arrays/excludeFalsy';\nimport { cn } from '@/lib/cn';\nimport { humanFileSize } from '@/lib/humanFileSize';\nimport { humanNumber } from '@/lib/humanNumber';\nimport { pluralize } from '@/lib/pluralize';\nimport { isPositive } from '@/lib/types/isPositive';\nimport { ArrowDownIcon, ArrowRightIcon } from 'lucide-react';\nimport { useCallback, useMemo, useState } from 'react';\n\nexport function ResourcesPerInstance({ selectedPlan, selectedRegion, isEnterprise }: {\n\treadonly selectedPlan: SchemaPlan | undefined;\n\treadonly selectedRegion: SchemaRegion | undefined;\n\treadonly isEnterprise: boolean;\n}) {\n\tconst [toggled, setToggled] = useState(false);\n\tconst onUsageLimitsClick = useCallback(() => {\n\t\tsetToggled(!toggled);\n\t}, [toggled, setToggled]);\n\tconst planLimits = selectedPlan?.planLimits;\n\tconst resourcesPerInstance = selectedPlan?.resourcesPerInstance;\n\n\tconst expirationMonths = isPositive(planLimits?.expirationMonths) && planLimits.expirationMonths < 1000\n\t\t&& planLimits.expirationMonths;\n\tconst multiplier = selectedRegion?.purchasedBlockMultiplier ?? 1;\n\tconst rows = useMemo<{ label: string; value: string }[]>(() => {\n\t\tif (!planLimits) {\n\t\t\treturn [];\n\t\t}\n\t\treturn ([\n\t\t\tisPositive(planLimits.totalReadCount) && {\n\t\t\t\tlabel: 'Total Reads',\n\t\t\t\tvalue: `${humanNumber(planLimits.totalReadCount * multiplier)} reads`,\n\t\t\t},\n\t\t\tisPositive(planLimits.totalReadsBytes) && {\n\t\t\t\tlabel: 'Total Read Transfer',\n\t\t\t\tvalue: `${humanFileSize(planLimits.totalReadsBytes * multiplier)}`,\n\t\t\t},\n\t\t\tisPositive(planLimits.readsPerMinuteCount) && {\n\t\t\t\tlabel: 'Read Rate',\n\t\t\t\tvalue: `${humanNumber(planLimits.readsPerMinuteCount * 60 * multiplier)}/min`,\n\t\t\t},\n\t\t\tisPositive(planLimits.readsPerMinuteBytes) && {\n\t\t\t\tlabel: 'Read Bandwidth',\n\t\t\t\tvalue: `${humanFileSize(planLimits.readsPerMinuteBytes * 60 * multiplier)}/min`,\n\t\t\t},\n\t\t\tisPositive(planLimits.totalWriteCount) && {\n\t\t\t\tlabel: 'Total Writes',\n\t\t\t\tvalue: `${humanNumber(planLimits.totalWriteCount)} reads`,\n\t\t\t},\n\t\t\tisPositive(planLimits.totalWritesBytes) && {\n\t\t\t\tlabel: 'Total Write Transfer',\n\t\t\t\tvalue: `${humanFileSize(planLimits.totalWritesBytes)}`,\n\t\t\t},\n\t\t\tisPositive(planLimits.writesPerMinuteCount) && {\n\t\t\t\tlabel: 'Write Rate',\n\t\t\t\tvalue: `${humanNumber(planLimits.writesPerMinuteCount * 60)}/min`,\n\t\t\t},\n\t\t\tisPositive(planLimits.writesPerMinuteBytes) && {\n\t\t\t\tlabel: 'Write Bandwidth',\n\t\t\t\tvalue: `${humanFileSize(planLimits.writesPerMinuteBytes * 60)}/min`,\n\t\t\t},\n\t\t\tisPositive(planLimits.totalRealTimeMessageDeliveries) && {\n\t\t\t\tlabel: 'Total Real-Time Messages',\n\t\t\t\tvalue: `${humanNumber(planLimits.totalRealTimeMessageDeliveries * multiplier)} messages`,\n\t\t\t},\n\t\t\tisPositive(planLimits.totalRealTimeMessageDeliveryBytes) && {\n\t\t\t\tlabel: 'Total Real-Time Message Transfer',\n\t\t\t\tvalue: `${humanFileSize(planLimits.totalRealTimeMessageDeliveryBytes * multiplier)}`,\n\t\t\t},\n\t\t\tisPositive(planLimits.realTimeMessageDeliveriesPerMinute) && {\n\t\t\t\tlabel: 'Real-Time Message Rate',\n\t\t\t\tvalue: `${humanNumber(planLimits.realTimeMessageDeliveriesPerMinute * 60 * multiplier)}/min`,\n\t\t\t},\n\t\t\tisPositive(planLimits.realTimeMessageDeliveryBytesPerMinute) && {\n\t\t\t\tlabel: 'Real-Time Message Bandwidth',\n\t\t\t\tvalue: `${humanFileSize(planLimits.realTimeMessageDeliveryBytesPerMinute * 60 * multiplier)}/min`,\n\t\t\t},\n\t\t\tisPositive(planLimits.tlsHandshakes) && {\n\t\t\t\tlabel: 'TLS Handshakes',\n\t\t\t\tvalue: `${humanNumber(planLimits.tlsHandshakes * 60 * multiplier)}`,\n\t\t\t},\n\t\t\tisPositive(planLimits.applicationComputeHours) && {\n\t\t\t\tlabel: 'Application Compute Hours',\n\t\t\t\tvalue: `${humanNumber(planLimits.applicationComputeHours * multiplier)}`,\n\t\t\t},\n\t\t\t!!resourcesPerInstance && isPositive(resourcesPerInstance.storageGb) && {\n\t\t\t\tlabel: 'Storage',\n\t\t\t\tvalue: `${humanFileSize(resourcesPerInstance.storageGb * 1000_000_000)}`,\n\t\t\t},\n\t\t\t!!expirationMonths && {\n\t\t\t\tlabel: 'Expiration',\n\t\t\t\tvalue: pluralize(expirationMonths, 'month', 'months'),\n\t\t\t},\n\t\t\t!!selectedRegion?.id && {\n\t\t\t\tlabel: 'Region ID',\n\t\t\t\tvalue: selectedRegion.id,\n\t\t\t},\n\t\t\t!!selectedPlan?.id && {\n\t\t\t\tlabel: 'Plan ID',\n\t\t\t\tvalue: selectedPlan.id,\n\t\t\t},\n\t\t] satisfies Array<boolean | { label: string; value: string }>).filter(excludeFalsy);\n\t}, [expirationMonths, selectedRegion, selectedPlan, multiplier]);\n\n\tif (!planLimits) {\n\t\t// The user hasn't selected a plan yet. so let's not show anything for the ResourcesPerInstance space yet.\n\t\treturn '';\n\t}\n\n\tif (!isPositive(planLimits.totalReadCount)) {\n\t\treturn 'This plan has no usage limits.';\n\t}\n\n\tconst pricingSubjectToTerms = isEnterprise\n\t\t? ' Pricing subject to contracted rate.'\n\t\t: ' Beta pricing subject to change.';\n\n\tconst maybeReadsPerMinute = isPositive(planLimits.readsPerMinuteCount)\n\t\t? `${humanNumber(planLimits.readsPerMinuteCount * multiplier)} reads/min & `\n\t\t: '';\n\tconst maybeWritesPerMinute = isPositive(planLimits.writesPerMinuteCount)\n\t\t? ` ${humanNumber(planLimits.writesPerMinuteCount)} writes/min & `\n\t\t: ' ';\n\tconst inRegionOrPerServer = isPositive(planLimits.readsPerMinuteCount)\n\t\t? `in ${selectedRegion?.region ?? ''} region${selectedRegion ? ` (${selectedRegion?.id})` : ''}`\n\t\t: 'per server';\n\tconst forMonths = expirationMonths ? `, for ${pluralize(expirationMonths, 'month', 'months')}` : '';\n\tconst forThePriceAbove = isEnterprise\n\t\t? 'for the contracted rate'\n\t\t: 'for the price listed above';\n\tconst expiresInMonths = expirationMonths ? ` in ${pluralize(expirationMonths, 'month', 'months')} or` : '';\n\n\treturn (\n\t\t<FormItem className=\"basis-full\">\n\t\t\t<FormLabel onClick={onUsageLimitsClick}>\n\t\t\t\t<em className=\"text-muted-foreground\">{selectedPlan?.id}</em> Purchasing usage block for {maybeReadsPerMinute}\n\t\t\t\t{humanNumber(planLimits.totalReadCount * multiplier)} total reads {inRegionOrPerServer},\n\t\t\t\t<br className=\"hidden sm:block\" />\n\t\t\t\t{maybeWritesPerMinute} {humanNumber(planLimits.totalWriteCount)} total writes{forMonths}.\n\t\t\t\t{pricingSubjectToTerms}\n\t\t\t\t<br className=\"block sm:hidden\" />\n\t\t\t\t<Button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tvariant=\"link\"\n\t\t\t\t\tclassName=\"text-white\"\n\t\t\t\t>\n\t\t\t\t\tLearn More {toggled ? <ArrowDownIcon /> : <ArrowRightIcon />}\n\t\t\t\t</Button>\n\t\t\t</FormLabel>\n\t\t\t<FormControl>\n\t\t\t\t<dl\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'divide-y divide-black overflow-hidden transition-[max-height] duration-200 ease-in',\n\t\t\t\t\t\ttoggled ? 'max-h-fit' : 'max-h-0',\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<div className=\"text-sm mb-3 max-w-lg\">\n\t\t\t\t\t\tThis plan licenses Harper for the usage limits below, {forThePriceAbove}. The usage license expires\n\t\t\t\t\t\t{expiresInMonths}{' '}\n\t\t\t\t\t\twhen any usage limit is reached. New usage blocks are automatically purchased/billed as blocks are consumed.\n\t\t\t\t\t</div>\n\t\t\t\t\t{rows.map((row, index) => (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tkey={row.label}\n\t\t\t\t\t\t\tclassName={cn('px-4 py-1 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-3', index % 2 === 0 && 'bg-gray-700')}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<dt className=\"text-sm/6 font-medium text-gray-300\">{row.label}</dt>\n\t\t\t\t\t\t\t<dd className=\"mt-1 text-sm/6 sm:col-span-2 sm:mt-0\">{row.value}</dd>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</dl>\n\t\t\t</FormControl>\n\t\t\t<FormMessage />\n\t\t</FormItem>\n\t);\n}\n","import { Button } from '@/components/ui/button';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';\nimport { UpsertClusterSchemaType } from '@/features/clusters/upsert/upsertClusterSchema';\nimport { SchemaPlan, SchemaRegion } from '@/integrations/api/api.gen';\nimport { sortByNumberPrefix } from '@/lib/arrays/sort/byNumberPrefix';\nimport { TrashIcon } from 'lucide-react';\nimport { useCallback, useEffect, useMemo } from 'react';\nimport { Control, UseFieldArrayReturn, UseFormReturn } from 'react-hook-form';\nimport { ResourcesPerInstance } from './ResourcesPerInstance';\n\ntype RegionFormInputsProps = {\n\tcontrol: Control<UpsertClusterSchemaType>;\n\tfieldArray: UseFieldArrayReturn<UpsertClusterSchemaType, 'regionPlans'>;\n\tform: UseFormReturn<UpsertClusterSchemaType>;\n\tindex: number;\n\tregionNameToLatencyToRegion: Record<string, Record<string, SchemaRegion>>;\n\tselectedPlan: SchemaPlan | undefined;\n\tisEnterprise: boolean;\n};\n\nexport function RegionFormInputs({\n\tcontrol,\n\tfieldArray,\n\tform,\n\tindex,\n\tregionNameToLatencyToRegion,\n\tselectedPlan,\n\tisEnterprise,\n}: RegionFormInputsProps) {\n\tconst availableRegionNames = useMemo(() => Object.keys(regionNameToLatencyToRegion).sort(), [\n\t\tregionNameToLatencyToRegion,\n\t]);\n\tconst isDedicated = form.watch('deploymentDescription')?.startsWith('Dedicated');\n\tconst selectedRegionName = form.watch(`regionPlans.${index}.regionName`);\n\tconst selectedLatencyDescription = form.watch(`regionPlans.${index}.latencyDescription`);\n\tconst availableLatencyDescriptions = useMemo(\n\t\t() => Object.keys(regionNameToLatencyToRegion[selectedRegionName] || {}).sort(sortByNumberPrefix).reverse(),\n\t\t[regionNameToLatencyToRegion, selectedRegionName],\n\t);\n\n\tuseEffect(function autoPickLatencyDescription() {\n\t\tif (\n\t\t\tselectedRegionName && availableLatencyDescriptions?.length\n\t\t\t&& !availableLatencyDescriptions?.includes(selectedLatencyDescription)\n\t\t) {\n\t\t\tconst oldValue = selectedLatencyDescription?.split(' ')[0].toLowerCase();\n\t\t\tconst newValue = availableLatencyDescriptions.find(description =>\n\t\t\t\t!oldValue ? true : description.split(' ')[0].toLowerCase() === oldValue\n\t\t\t) || availableLatencyDescriptions[0];\n\t\t\tform.setValue(`regionPlans.${index}.latencyDescription`, newValue);\n\t\t\tvoid form.trigger();\n\t\t}\n\t}, [availableLatencyDescriptions, form, index, selectedLatencyDescription, selectedRegionName]);\n\n\tconst onRemoveClicked = useCallback(() => {\n\t\tfieldArray?.remove(index);\n\t\tvoid form.trigger();\n\t}, [fieldArray, form, index]);\n\n\treturn (\n\t\t<div className=\"md:col-span-6 col-span-3 p-4 rounded-md bg-accent gap-6 flex flex-wrap items-start\">\n\t\t\t<FormField\n\t\t\t\tcontrol={control}\n\t\t\t\tname={`regionPlans.${index}.regionName`}\n\t\t\t\trender={({ field: regionField }) => (\n\t\t\t\t\t<FormItem className=\"flex-1\">\n\t\t\t\t\t\t<FormLabel>Region {fieldArray.fields.length > 1 ? index + 1 : ''}</FormLabel>\n\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\t\tonValueChange={value => {\n\t\t\t\t\t\t\t\t\tregionField.onChange(value);\n\t\t\t\t\t\t\t\t\tform.trigger();\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t{...regionField}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<SelectTrigger className=\"w-full\">\n\t\t\t\t\t\t\t\t\t<SelectValue placeholder=\"Choose Region\" />\n\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t\t<SelectGroup>\n\t\t\t\t\t\t\t\t\t\t{availableRegionNames.map((regionName) => (\n\t\t\t\t\t\t\t\t\t\t\t<SelectItem key={regionName} value={regionName}>{regionName}</SelectItem>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</SelectGroup>\n\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t</FormItem>\n\t\t\t\t)}\n\t\t\t/>\n\n\t\t\t<FormField\n\t\t\t\tcontrol={control}\n\t\t\t\tname={`regionPlans.${index}.latencyDescription`}\n\t\t\t\trender={({ field: regionField }) => (\n\t\t\t\t\t<FormItem className=\"flex-1\">\n\t\t\t\t\t\t<FormLabel>Estimated {isDedicated ? 'P95' : 'P90'} Latency, Distribution</FormLabel>\n\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\t\tonValueChange={value => {\n\t\t\t\t\t\t\t\t\tregionField.onChange(value);\n\t\t\t\t\t\t\t\t\tform.trigger();\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t{...regionField}\n\t\t\t\t\t\t\t\tdisabled={!availableLatencyDescriptions?.length}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<SelectTrigger className=\"w-full\">\n\t\t\t\t\t\t\t\t\t<SelectValue placeholder=\"Choose Latency Tier\" />\n\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t\t<SelectGroup>\n\t\t\t\t\t\t\t\t\t\t{availableLatencyDescriptions.map((latencyDescription) => (\n\t\t\t\t\t\t\t\t\t\t\t<SelectItem key={latencyDescription} value={latencyDescription}>{latencyDescription}</SelectItem>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</SelectGroup>\n\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t</FormItem>\n\t\t\t\t)}\n\t\t\t/>\n\n\t\t\t{fieldArray?.fields?.length && fieldArray?.fields?.length > 1 && (\n\t\t\t\t<div className=\"flex-none mt-6\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tvariant=\"destructiveOutline\"\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tonClick={onRemoveClicked}\n\t\t\t\t\t>\n\t\t\t\t\t\t<TrashIcon /> <span className=\"sr-only\">Remove</span>\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<ResourcesPerInstance\n\t\t\t\tselectedPlan={selectedPlan}\n\t\t\t\tselectedRegion={regionNameToLatencyToRegion[selectedRegionName]?.[selectedLatencyDescription]}\n\t\t\t\tisEnterprise={isEnterprise}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n","import { ContactUs } from '@/components/ContactUs';\nimport { ErrorComponent } from '@/components/ErrorComponent';\nimport { Button } from '@/components/ui/button';\nimport { SchemaPlan, SchemaRegion } from '@/integrations/api/api.gen';\nimport { PlusIcon } from 'lucide-react';\nimport { useCallback, useMemo } from 'react';\nimport { useFieldArray, UseFormReturn } from 'react-hook-form';\nimport { RegionFormInputs } from './components/RegionFormInputs';\nimport { UpsertClusterSchemaType } from './upsertClusterSchema';\n\ninterface ClusterRegionsProps {\n\tform: UseFormReturn<UpsertClusterSchemaType>;\n\tregionLocations: SchemaRegion[] | undefined;\n\tregionNameToLatencyToRegion: Record<string, Record<string, SchemaRegion>>;\n\tselectedPlan: SchemaPlan | undefined;\n\ttotalPrice: number | undefined;\n\tisEnterprise: boolean;\n}\n\nexport function ClusterRegions({\n\tform,\n\tregionLocations,\n\tregionNameToLatencyToRegion,\n\tselectedPlan,\n\ttotalPrice,\n\tisEnterprise,\n}: ClusterRegionsProps) {\n\tconst selectedRegionPlans = form.watch('regionPlans');\n\n\tconst regionPlansFieldArray = useFieldArray({\n\t\tcontrol: form.control,\n\t\tname: 'regionPlans',\n\t});\n\n\tconst nextAvailableRegionToAdd = useMemo(() => {\n\t\tconst selectedRegionNames = selectedRegionPlans.map(region =>\n\t\t\tregionNameToLatencyToRegion?.[region.regionName!]?.[region.latencyDescription!]?.region\n\t\t);\n\t\tif (!totalPrice) {\n\t\t\t// Free plans can only add a single region.\n\t\t\treturn null;\n\t\t}\n\t\treturn regionLocations?.find(r => !selectedRegionNames.includes(r.region));\n\t}, [regionLocations, regionNameToLatencyToRegion, selectedRegionPlans, totalPrice]);\n\n\tconst onAddARegionClick = useCallback(() => {\n\t\tif (nextAvailableRegionToAdd) {\n\t\t\tregionPlansFieldArray.append({\n\t\t\t\tregionName: nextAvailableRegionToAdd.region,\n\t\t\t\tlatencyDescription: nextAvailableRegionToAdd.latencyDescription,\n\t\t\t});\n\t\t\tvoid form.trigger();\n\t\t}\n\t}, [form, nextAvailableRegionToAdd, regionPlansFieldArray]);\n\n\tif (!regionLocations?.length) {\n\t\treturn (\n\t\t\t<div className=\"md:col-span-6 col-span-3\">\n\t\t\t\t<ErrorComponent\n\t\t\t\t\tclassName=\"mt-0 m-0\"\n\t\t\t\t\ttitle=\"No Regions Available\"\n\t\t\t\t\tshowReturnToHome={false}\n\t\t\t\t\terror={{\n\t\t\t\t\t\tmessage: (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\tThe deployment type you selected currently has no available regions. Please try a different deployment\n\t\t\t\t\t\t\t\ttype, try again later, or <ContactUs />.\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t),\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t{regionPlansFieldArray.fields.map((field, index) => (\n\t\t\t\t<RegionFormInputs\n\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\tfieldArray={regionPlansFieldArray}\n\t\t\t\t\tform={form}\n\t\t\t\t\tindex={index}\n\t\t\t\t\tkey={field.id}\n\t\t\t\t\tregionNameToLatencyToRegion={regionNameToLatencyToRegion}\n\t\t\t\t\tselectedPlan={selectedPlan}\n\t\t\t\t\tisEnterprise={isEnterprise}\n\t\t\t\t/>\n\t\t\t))}\n\n\t\t\t{nextAvailableRegionToAdd && (\n\t\t\t\t<div className=\"md:col-span-6 col-span-3\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tvariant=\"positiveOutline\"\n\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\tonClick={onAddARegionClick}\n\t\t\t\t\t>\n\t\t\t\t\t\t<PlusIcon />\n\t\t\t\t\t\tAdd Additional Region Usage\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</>\n\t);\n}\n","import { Button } from '@/components/ui/button';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';\nimport { defaultOperationsApiPort } from '@/config/constants';\nimport { UpsertClusterSchemaType } from '@/features/clusters/upsert/upsertClusterSchema';\nimport { maxPortNumber, minPortNumber } from '@/lib/types/portNumbers';\nimport { TrashIcon } from 'lucide-react';\nimport { useCallback } from 'react';\nimport { Control, UseFieldArrayReturn, UseFormReturn } from 'react-hook-form';\n\ntype InstanceFormInputsProps = {\n\tcontrol: Control<UpsertClusterSchemaType>;\n\tfieldArray: UseFieldArrayReturn<UpsertClusterSchemaType, 'instances'>;\n\tform: UseFormReturn<UpsertClusterSchemaType>;\n\tindex: number;\n};\n\nexport function InstanceFormInputs({\n\tcontrol,\n\tfieldArray,\n\tform,\n\tindex,\n}: InstanceFormInputsProps) {\n\tconst onRemoveClicked = useCallback(() => {\n\t\tfieldArray?.remove(index);\n\t}, [fieldArray, index]);\n\n\treturn (\n\t\t<div className=\"md:col-span-6 col-span-3 p-4 rounded-md bg-accent gap-6 flex flex-wrap items-start\">\n\t\t\t<FormField\n\t\t\t\tcontrol={control}\n\t\t\t\tname={`instances.${index}.secure`}\n\t\t\t\trender={({ field }) => (\n\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t<FormLabel>Instance {fieldArray.fields.length > 1 ? index + 1 : ''}</FormLabel>\n\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\tonValueChange={value => {\n\t\t\t\t\t\t\t\t\tfield.onChange(value);\n\t\t\t\t\t\t\t\t\tvoid form.trigger();\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<SelectTrigger className=\"w-full\">\n\t\t\t\t\t\t\t\t\t<SelectValue placeholder=\"https://\" />\n\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t\t<SelectGroup>\n\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"true\">https://</SelectItem>\n\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"false\">http://</SelectItem>\n\t\t\t\t\t\t\t\t\t</SelectGroup>\n\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t</FormItem>\n\t\t\t\t)}\n\t\t\t/>\n\n\t\t\t<FormField\n\t\t\t\tcontrol={control}\n\t\t\t\tname={`instances.${index}.fqdn`}\n\t\t\t\trender={({ field }) => (\n\t\t\t\t\t<FormItem className=\"flex-3\">\n\t\t\t\t\t\t<FormLabel>Host Name</FormLabel>\n\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\tautoCorrect=\"off\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t</FormItem>\n\t\t\t\t)}\n\t\t\t/>\n\n\t\t\t<FormField\n\t\t\t\tcontrol={control}\n\t\t\t\tname={`instances.${index}.port`}\n\t\t\t\trender={({ field }) => (\n\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t<FormLabel>Operations API Port</FormLabel>\n\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t\t\t\tmin={minPortNumber}\n\t\t\t\t\t\t\t\tmax={maxPortNumber}\n\t\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\tautoCorrect=\"off\"\n\t\t\t\t\t\t\t\tplaceholder={String(defaultOperationsApiPort)}\n\t\t\t\t\t\t\t\tonChange={e => {\n\t\t\t\t\t\t\t\t\tfield.onChange(e.target.value ? parseInt(e.target.value, 10) : undefined);\n\t\t\t\t\t\t\t\t\tvoid form.trigger();\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t</FormItem>\n\t\t\t\t)}\n\t\t\t/>\n\n\t\t\t{fieldArray?.fields?.length && fieldArray?.fields?.length > 1 && (\n\t\t\t\t<div className=\"flex-none mt-6\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tvariant=\"destructiveOutline\"\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tonClick={onRemoveClicked}\n\t\t\t\t\t>\n\t\t\t\t\t\t<TrashIcon /> <span className=\"sr-only\">Remove</span>\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import { Button } from '@/components/ui/button';\nimport { defaultOperationsApiPort } from '@/config/constants';\nimport { UpsertClusterSchemaType } from '@/features/clusters/upsert/upsertClusterSchema';\nimport { PlusIcon } from 'lucide-react';\nimport { useCallback } from 'react';\nimport { useFieldArray, UseFormReturn } from 'react-hook-form';\nimport { InstanceFormInputs } from './InstanceFormInputs';\n\ninterface ClusterInstancesProps {\n\tform: UseFormReturn<UpsertClusterSchemaType>;\n}\n\nexport function ClusterInstances({\n\tform,\n}: ClusterInstancesProps) {\n\tconst instancesFieldArray = useFieldArray({\n\t\tcontrol: form.control,\n\t\tname: 'instances',\n\t});\n\n\tconst onAddInstanceClick = useCallback(() => {\n\t\tinstancesFieldArray.append({\n\t\t\tsecure: 'true',\n\t\t\tfqdn: '',\n\t\t\tport: defaultOperationsApiPort,\n\t\t});\n\t}, [instancesFieldArray]);\n\n\treturn (\n\t\t<>\n\t\t\t{instancesFieldArray.fields.map((field, index) => (\n\t\t\t\t<InstanceFormInputs\n\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\tfieldArray={instancesFieldArray}\n\t\t\t\t\tform={form}\n\t\t\t\t\tindex={index}\n\t\t\t\t\tkey={field.id}\n\t\t\t\t/>\n\t\t\t))}\n\n\t\t\t<div className=\"md:col-span-6 col-span-3\">\n\t\t\t\t<Button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tvariant=\"positiveOutline\"\n\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\tonClick={onAddInstanceClick}\n\t\t\t\t>\n\t\t\t\t\t<PlusIcon />\n\t\t\t\t\tAdd Instance\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t</>\n\t);\n}\n","import { Button } from '@/components/ui/button';\nimport { DialogFooter } from '@/components/ui/dialog';\nimport { HarperVersionsResponse } from '@/features/clusters/queries/getHarperVersionsQuery';\nimport { ClusterAbbreviatedName } from '@/features/clusters/upsert/fields/ClusterAbbreviatedName';\nimport { ClusterDeploymentDescription } from '@/features/clusters/upsert/fields/ClusterDeploymentDescription';\nimport { ClusterFQDN } from '@/features/clusters/upsert/fields/ClusterFQDN';\nimport { ClusterName } from '@/features/clusters/upsert/fields/ClusterName';\nimport { ClusterPerformanceDescription } from '@/features/clusters/upsert/fields/ClusterPerformanceDescription';\nimport { ClusterSkipGtmWait } from '@/features/clusters/upsert/fields/ClusterSkipGtmWait';\nimport { ClusterVersion } from '@/features/clusters/upsert/fields/ClusterVersion';\nimport { SchemaPlan, SchemaRegion } from '@/integrations/api/api.gen';\nimport { ArrowRight } from 'lucide-react';\nimport { useEffect, useMemo } from 'react';\nimport { UseFormReturn, useFormState } from 'react-hook-form';\nimport { ClusterRegions } from './ClusterRegions';\nimport { ClusterInstances } from './components/ClusterInstances';\nimport { UpsertClusterSchemaType } from './upsertClusterSchema';\n\ninterface ClusterDetailsProps {\n\tcalculatedNames: { suggestedAbbreviatedName: string; fullHostName: string };\n\tclusterId?: string;\n\tdeploymentToPerformanceToPlan: Record<string, Record<string, SchemaPlan>>;\n\tform: UseFormReturn<UpsertClusterSchemaType>;\n\tharperVersions: HarperVersionsResponse | undefined;\n\tisEnterprise: boolean;\n\tisPending: boolean;\n\tmode: 'version' | undefined;\n\tregionLocations: SchemaRegion[] | undefined;\n\tregionNameToLatencyToRegion: Record<string, Record<string, SchemaRegion>>;\n\tselectedDeployment: string;\n\tselectedPerformance: string;\n\tselectedPlan: SchemaPlan | undefined;\n\ttotalPrice: number;\n}\n\nexport function ClusterDetails({\n\tcalculatedNames,\n\tclusterId,\n\tdeploymentToPerformanceToPlan,\n\tform,\n\tharperVersions,\n\tisEnterprise,\n\tisPending,\n\tmode,\n\tregionLocations,\n\tregionNameToLatencyToRegion,\n\tselectedDeployment,\n\tselectedPerformance,\n\tselectedPlan,\n\ttotalPrice,\n}: ClusterDetailsProps) {\n\tconst { isDirty, isValid } = useFormState();\n\tconst availablePerformanceDescriptions = useMemo(() => {\n\t\treturn Object.keys(deploymentToPerformanceToPlan[selectedDeployment] || {}).map(performanceTier => {\n\t\t\tconst splitByParens = performanceTier.slice(0, -1).split('(');\n\t\t\tif (splitByParens.length > 1) {\n\t\t\t\treturn {\n\t\t\t\t\tperformanceTier,\n\t\t\t\t\tname: splitByParens[0],\n\t\t\t\t\tdescription: splitByParens[1],\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst splitByFor = performanceTier.split(' for ');\n\t\t\tif (splitByFor.length > 1) {\n\t\t\t\treturn {\n\t\t\t\t\tperformanceTier,\n\t\t\t\t\tname: splitByFor[0],\n\t\t\t\t\tdescription: 'For ' + splitByFor[1],\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tperformanceTier,\n\t\t\t\tname: performanceTier,\n\t\t\t\tdescription: '',\n\t\t\t};\n\t\t});\n\t}, [deploymentToPerformanceToPlan, selectedDeployment]);\n\tconst availableDeploymentTypes = useMemo(() => Object.keys(deploymentToPerformanceToPlan).sort(), [\n\t\tdeploymentToPerformanceToPlan,\n\t]);\n\n\tuseEffect(function autoSelectFirstAvailablePerformanceDescription() {\n\t\tif (\n\t\t\tavailablePerformanceDescriptions?.length\n\t\t\t&& !availablePerformanceDescriptions.find(sp => sp.performanceTier === selectedPerformance)\n\t\t) {\n\t\t\tform.setValue('performanceDescription', availablePerformanceDescriptions[0].performanceTier);\n\t\t\tvoid form.trigger();\n\t\t}\n\t}, [selectedDeployment, selectedPerformance, availablePerformanceDescriptions, form]);\n\n\tconst isSelfManaged = selectedDeployment === 'Self-Hosted';\n\n\tconst footer = (\n\t\t<DialogFooter className=\"mt-3 mb-12\">\n\t\t\t<Button\n\t\t\t\ttype=\"submit\"\n\t\t\t\tvariant=\"submit\"\n\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\tdisabled={isPending || (clusterId && !isDirty) || !isValid}\n\t\t\t>\n\t\t\t\t{mode !== 'version' && totalPrice > 0\n\t\t\t\t\t? 'Confirm Payment Details'\n\t\t\t\t\t: clusterId\n\t\t\t\t\t? 'Edit Cluster'\n\t\t\t\t\t: 'Create New Cluster'}\n\t\t\t\t<ArrowRight />\n\t\t\t</Button>\n\t\t</DialogFooter>\n\t);\n\n\tif (mode === 'version') {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<div className=\"grid grid-cols-3 gap-6 text-white md:grid-cols-6\">\n\t\t\t\t\t<ClusterName\n\t\t\t\t\t\tclassName={harperVersions?.value?.length ? 'col-span-3' : 'md:col-span-6 col-span-3'}\n\t\t\t\t\t\tdisabled={true}\n\t\t\t\t\t\tform={form}\n\t\t\t\t\t/>\n\t\t\t\t\t<ClusterVersion\n\t\t\t\t\t\tclassName=\"col-span-3\"\n\t\t\t\t\t\tform={form}\n\t\t\t\t\t\tharperVersions={harperVersions}\n\t\t\t\t\t/>\n\t\t\t\t\t<ClusterSkipGtmWait className=\"col-span-3 md:col-span-6\" form={form} />\n\t\t\t\t</div>\n\t\t\t\t{footer}\n\t\t\t</>\n\t\t);\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t<div className=\"grid grid-cols-3 gap-6 text-white md:grid-cols-6\">\n\t\t\t\t<ClusterName\n\t\t\t\t\tclassName={harperVersions?.value?.length ? 'col-span-3' : 'md:col-span-6 col-span-3'}\n\t\t\t\t\tdisabled={!!clusterId}\n\t\t\t\t\tform={form}\n\t\t\t\t/>\n\t\t\t\t<ClusterVersion\n\t\t\t\t\tclassName=\"col-span-3\"\n\t\t\t\t\tdisabled={!!clusterId}\n\t\t\t\t\tform={form}\n\t\t\t\t\tharperVersions={harperVersions}\n\t\t\t\t/>\n\n\t\t\t\t{isSelfManaged\n\t\t\t\t\t? <ClusterFQDN form={form} disabled={!!clusterId} />\n\t\t\t\t\t: <ClusterAbbreviatedName form={form} calculatedNames={calculatedNames} disabled={!!clusterId} />}\n\n\t\t\t\t<ClusterDeploymentDescription form={form} availableDeploymentTypes={availableDeploymentTypes} />\n\n\t\t\t\t<ClusterPerformanceDescription\n\t\t\t\t\tavailablePerformanceDescriptions={availablePerformanceDescriptions}\n\t\t\t\t\tform={form}\n\t\t\t\t\tselectedDeployment={selectedDeployment}\n\t\t\t\t/>\n\n\t\t\t\t{isSelfManaged\n\t\t\t\t\t? <ClusterInstances form={form} />\n\t\t\t\t\t: (\n\t\t\t\t\t\t<ClusterRegions\n\t\t\t\t\t\t\tform={form}\n\t\t\t\t\t\t\tregionLocations={regionLocations}\n\t\t\t\t\t\t\tregionNameToLatencyToRegion={regionNameToLatencyToRegion}\n\t\t\t\t\t\t\tselectedPlan={selectedPlan}\n\t\t\t\t\t\t\ttotalPrice={totalPrice}\n\t\t\t\t\t\t\tisEnterprise={isEnterprise}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t{clusterId && !isSelfManaged && <ClusterSkipGtmWait className=\"col-span-3 md:col-span-6\" form={form} />}\n\t\t\t</div>\n\t\t\t{footer}\n\t\t</>\n\t);\n}\n","import { defaultOperationsApiPort } from '@/config/constants';\nimport { UpsertClusterSchema } from '@/features/clusters/upsert/upsertClusterSchema';\nimport { z } from 'zod';\n\nexport function calculateInstanceFQDN(instance: z.infer<typeof UpsertClusterSchema.shape.instances.element>) {\n\tconst { fqdn } = instance;\n\tlet { secure, port } = instance;\n\tif (!port) {\n\t\tport = defaultOperationsApiPort;\n\t}\n\tif (port === 443 && secure === 'false') {\n\t\tsecure = 'true';\n\t}\n\tif (port === 80 && secure === 'true') {\n\t\tsecure = 'false';\n\t}\n\treturn `${secure === 'true' ? 'https' : 'http'}://${fqdn}${port === 443 || port === 80 ? '' : (':' + port)}`\n\t\t.toLowerCase();\n}\n","import { UpsertClusterSchemaType } from '@/features/clusters/upsert/upsertClusterSchema';\nimport { SchemaPlan, SchemaRegion } from '@/integrations/api/api.gen';\n\nexport function calculateDefaultDeploymentPerformanceAndRegionPlans(\n\tplanTypes: SchemaPlan[],\n\tregionLocations: SchemaRegion[],\n\talreadyUsingFree?: boolean,\n): null | Pick<UpsertClusterSchemaType, 'deploymentDescription' | 'performanceDescription' | 'regionPlans'> {\n\tconst planToSelect =\n\t\tplanTypes.find(planType =>\n\t\t\t(alreadyUsingFree ? !!planType.priceUsd : !planType.priceUsd) && planType.deploymentType === 'colocated'\n\t\t)\n\t\t|| planTypes.find(planType => planType.deploymentType === 'colocated')\n\t\t|| planTypes[0];\n\tconst allowedRegionIds = planToSelect?.allowedRegionIds;\n\tif (planToSelect) {\n\t\tconst allowedRegions = allowedRegionIds\n\t\t\t? regionLocations.filter(regionLocation => allowedRegionIds.includes(regionLocation.id))\n\t\t\t: regionLocations;\n\t\tconst regionToSelect = allowedRegions.find(regionLocation => regionLocation.region === 'US') || allowedRegions[0];\n\t\tif (regionToSelect) {\n\t\t\treturn {\n\t\t\t\tdeploymentDescription: planToSelect.deploymentDescription,\n\t\t\t\tperformanceDescription: planToSelect.performanceDescription,\n\t\t\t\tregionPlans: [\n\t\t\t\t\t{\n\t\t\t\t\t\tregionName: regionToSelect.region,\n\t\t\t\t\t\tlatencyDescription: regionToSelect.latencyDescription,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t};\n\t\t}\n\t}\n\treturn null;\n}\n","import { UpsertClusterSchemaType } from '@/features/clusters/upsert/upsertClusterSchema';\nimport { SchemaPlan, SchemaRegion } from '@/integrations/api/api.gen';\nimport { UseFormReturn } from 'react-hook-form';\nimport {\n\tcalculateDefaultDeploymentPerformanceAndRegionPlans,\n} from './calculateDefaultDeploymentPerformanceAndRegionPlans';\n\nexport function pickDefaultDeploymentPerformanceAndRegionPlans(\n\tform: UseFormReturn<UpsertClusterSchemaType>,\n\tplanTypes: SchemaPlan[] | undefined,\n\tregionLocations: SchemaRegion[] | undefined,\n) {\n\tif (planTypes && regionLocations) {\n\t\tconst values = form.getValues();\n\t\tif (!values.deploymentDescription || !values.performanceDescription || !values.regionPlans.length) {\n\t\t\tconst defaults = calculateDefaultDeploymentPerformanceAndRegionPlans(planTypes, regionLocations);\n\t\t\tif (defaults) {\n\t\t\t\tif (!values.deploymentDescription && !values.performanceDescription) {\n\t\t\t\t\tform.setValue('deploymentDescription', defaults.deploymentDescription);\n\t\t\t\t\tform.setValue('performanceDescription', defaults.performanceDescription);\n\t\t\t\t}\n\t\t\t\tif (!values.regionPlans.length) {\n\t\t\t\t\tform.setValue('regionPlans', defaults.regionPlans);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n","export function PriceDisplay({ price }: { readonly price?: number }) {\n\tconst numberFormat = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' });\n\tconst parts = numberFormat.formatToParts(price || 0);\n\treturn (\n\t\t<span className=\"text-4xl\">\n\t\t\t{parts.map((part, index) => <PricePart key={index} type={part.type} value={part.value} />)}\n\t\t</span>\n\t);\n}\n\nfunction PricePart({ type, value }: ReturnType<Intl.NumberFormat['formatToParts']>[0]) {\n\tswitch (type) {\n\t\tcase 'currency':\n\t\tcase 'decimal':\n\t\tcase 'fraction':\n\t\t\treturn <sup className=\"font-light text-xl\">{value}</sup>;\n\t\tdefault:\n\t\t\treturn value;\n\t}\n}\n","import { EstimatedProgressBar } from '@/components/EstimatedProgressBar';\nimport { Form } from '@/components/ui/form/Form';\nimport { isFailed } from '@/components/ui/utils/badgeStatus';\nimport { defaultOperationsApiPort } from '@/config/constants';\nimport { useCreateNewClusterMutation } from '@/features/clusters/hooks/useCreateNewCluster';\nimport { useEditClusterMutation } from '@/features/clusters/hooks/useUpdateCluster';\nimport { terminateCluster } from '@/features/clusters/mutations/terminateCluster';\nimport { HarperVersionsResponse } from '@/features/clusters/queries/getHarperVersionsQuery';\nimport { getOrganization } from '@/features/organization/queries/getOrganizationQuery';\nimport { SchemaPlan, SchemaRegion, SchemaRegionPlan } from '@/integrations/api/api.gen';\nimport { Organization } from '@/integrations/api/api.patch';\nimport { ENTERPRISE } from '@/integrations/api/orgType';\nimport { sortByField } from '@/lib/arrays/sort/byField';\nimport { groupThenKeyBy } from '@/lib/groupThenKeyBy';\nimport { collapseKebabsToMaxLength } from '@/lib/string/collapseKebabsToMaxLength';\nimport { stringsShareAPrefix } from '@/lib/string/stringsShareAPrefix';\nimport { toKebabCase } from '@/lib/string/to-kebab-case';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useNavigate, useRouter } from '@tanstack/react-router';\nimport { cx } from 'class-variance-authority';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { ClusterBilling } from './ClusterBilling';\nimport { ClusterDetails } from './ClusterDetails';\nimport { calculateInstanceFQDN } from './lib/calculateInstanceFQDN';\nimport { pickDefaultDeploymentPerformanceAndRegionPlans } from './lib/pickDefaultDeploymentPerformanceAndRegionPlans';\nimport { PriceDisplay } from './PriceDisplay';\nimport { specifiedAbbreviatedName, UpsertClusterSchema, UpsertClusterSchemaType } from './upsertClusterSchema';\n\ninterface ClusterFormProps {\n\talreadyUsingFree: boolean;\n\tclusterId?: string;\n\tdefaultValues: UpsertClusterSchemaType;\n\tdeploymentToPerformanceToPlan: Record<string, Record<string, SchemaPlan>>;\n\tharperVersions: HarperVersionsResponse | undefined;\n\tmode: 'version' | undefined;\n\torganization: Organization;\n\torganizationId: string;\n\tplanTypes: SchemaPlan[];\n\tregionLocationsColocated: SchemaRegion[];\n\tregionLocationsDedicated: SchemaRegion[];\n\tsetSavedClusterState: (value: null | ({ clusterId?: string } & UpsertClusterSchemaType)) => void;\n\tstartOffOnBilling: boolean;\n}\n\nexport function ClusterForm({\n\talreadyUsingFree,\n\tclusterId,\n\tdefaultValues,\n\tdeploymentToPerformanceToPlan,\n\tharperVersions,\n\tmode,\n\torganization,\n\torganizationId,\n\tplanTypes,\n\tregionLocationsColocated,\n\tregionLocationsDedicated,\n\tsetSavedClusterState,\n\tstartOffOnBilling,\n}: ClusterFormProps) {\n\tconst navigate = useNavigate();\n\tconst router = useRouter();\n\tconst isEnterprise = organization?.type === ENTERPRISE;\n\n\tconst queryClient = useQueryClient();\n\tconst { mutate: submitNewClusterData, isPending: isCreatePending } = useCreateNewClusterMutation();\n\tconst { mutate: submitEditClusterData, isPending: isEditPending } = useEditClusterMutation();\n\n\tconst [confirmingPaymentDetails, setConfirmingPaymentDetails] = useState(startOffOnBilling);\n\n\tconst colocatedRegionNameToLatencyToRegion = useMemo<Record<string, Record<string, SchemaRegion>>>(\n\t\t() =>\n\t\t\tgroupThenKeyBy(\n\t\t\t\tregionLocationsColocated?.sort(sortByField('latencyDescription')) || [],\n\t\t\t\t'region',\n\t\t\t\t'latencyDescription',\n\t\t\t),\n\t\t[regionLocationsColocated],\n\t);\n\tconst dedicatedRegionNameToLatencyToRegion = useMemo<Record<string, Record<string, SchemaRegion>>>(\n\t\t() =>\n\t\t\tgroupThenKeyBy(\n\t\t\t\tregionLocationsDedicated?.sort(sortByField('latencyDescription')) || [],\n\t\t\t\t'region',\n\t\t\t\t'latencyDescription',\n\t\t\t),\n\t\t[regionLocationsDedicated],\n\t);\n\n\tconst refineZod = useCallback((data: UpsertClusterSchemaType, ctx: z.RefinementCtx) => {\n\t\tconst names = new Set();\n\t\tconst selectedPlan = deploymentToPerformanceToPlan?.[data.deploymentDescription]?.[data.performanceDescription];\n\t\tconst isSelfManaged = data.deploymentDescription === 'Self-Hosted';\n\t\tif (isSelfManaged) {\n\t\t\tfor (let i = 0; i < data.instances.length; i++) {\n\t\t\t\tconst fqdn = calculateInstanceFQDN(data.instances[i]);\n\t\t\t\tif (!names.has(fqdn)) {\n\t\t\t\t\tnames.add(fqdn);\n\t\t\t\t} else {\n\t\t\t\t\tctx.addIssue({\n\t\t\t\t\t\tcode: 'custom',\n\t\t\t\t\t\tpath: [`instances.${i}.fqdn`],\n\t\t\t\t\t\tmessage: 'Every instance url must be unique!',\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (selectedPlan?.priceUsd === 0 && alreadyUsingFree) {\n\t\t\t\tctx.addIssue({\n\t\t\t\t\tcode: 'custom',\n\t\t\t\t\tpath: [`performanceDescription`],\n\t\t\t\t\tmessage: 'Only one free cluster is allowed per organization.',\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst regionNameToLatencyToRegion = selectedPlan?.deploymentDescription !== 'Dedicated'\n\t\t\t\t? colocatedRegionNameToLatencyToRegion\n\t\t\t\t: dedicatedRegionNameToLatencyToRegion;\n\n\t\t\tfor (let i = 0; i < data.regionPlans.length; i++) {\n\t\t\t\tconst regionPlan = data.regionPlans[i];\n\t\t\t\tconst region = regionNameToLatencyToRegion[regionPlan.regionName]?.[regionPlan.latencyDescription];\n\t\t\t\tif (!names.has(regionPlan.regionName)) {\n\t\t\t\t\tnames.add(regionPlan.regionName);\n\t\t\t\t} else {\n\t\t\t\t\tctx.addIssue({\n\t\t\t\t\t\tcode: 'custom',\n\t\t\t\t\t\tpath: [`regionPlans.${i}.regionName`],\n\t\t\t\t\t\tmessage: 'You can only select a region once!',\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (selectedPlan?.allowedRegionIds?.length && region?.id) {\n\t\t\t\t\tif (!selectedPlan.allowedRegionIds.includes(region.id)) {\n\t\t\t\t\t\tconst prefixMatches = stringsShareAPrefix(selectedPlan.allowedRegionIds, region.id);\n\t\t\t\t\t\tif (!prefixMatches) {\n\t\t\t\t\t\t\tctx.addIssue({\n\t\t\t\t\t\t\t\tcode: 'custom',\n\t\t\t\t\t\t\t\tpath: [`regionPlans.${i}.regionName`],\n\t\t\t\t\t\t\t\tmessage: `This region is not available with the selected performance tier!`,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tctx.addIssue({\n\t\t\t\t\t\t\t\tcode: 'custom',\n\t\t\t\t\t\t\t\tpath: [`regionPlans.${i}.latencyDescription`],\n\t\t\t\t\t\t\t\tmessage: `This latency is not available with the selected performance tier!`,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (i >= 1) {\n\t\t\t\t\t\tctx.addIssue({\n\t\t\t\t\t\t\tcode: 'custom',\n\t\t\t\t\t\t\tpath: [`regionPlans.${i}.regionName`],\n\t\t\t\t\t\t\tmessage: `You can only select one region with this performance tier!`,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}, [\n\t\talreadyUsingFree,\n\t\tcolocatedRegionNameToLatencyToRegion,\n\t\tdedicatedRegionNameToLatencyToRegion,\n\t\tdeploymentToPerformanceToPlan,\n\t]);\n\n\tconst form = useForm({\n\t\tmode: 'onChange',\n\t\tresolver: zodResolver(UpsertClusterSchema.superRefine(refineZod)),\n\t\tdefaultValues,\n\t});\n\n\tconst [firstTime, setFirstTime] = useState(true);\n\tuseEffect(() => {\n\t\tif (firstTime && defaultValues) {\n\t\t\tsetSavedClusterState(null);\n\t\t\tsetFirstTime(false);\n\t\t}\n\t}, [defaultValues, firstTime, setSavedClusterState]);\n\n\tconst clusterName = form.watch('clusterName');\n\tconst abbreviatedName = form.watch('abbreviatedName');\n\tconst selectedDeployment = form.watch('deploymentDescription');\n\tconst selectedPerformance = form.watch('performanceDescription');\n\tconst selectedRegionPlans = form.watch('regionPlans');\n\tconst selectedInstances = form.watch('instances');\n\n\tconst regionNameToLatencyToRegion = selectedDeployment !== 'Dedicated'\n\t\t? colocatedRegionNameToLatencyToRegion\n\t\t: dedicatedRegionNameToLatencyToRegion;\n\tconst regionLocations = selectedDeployment !== 'Dedicated'\n\t\t? regionLocationsColocated\n\t\t: regionLocationsDedicated;\n\n\tuseEffect(function syncInstancesAndRegionsWithSelfManagedSelection() {\n\t\tconst values = form.getValues();\n\t\tconst isSelfManaged = selectedDeployment === 'Self-Hosted';\n\t\tif (!selectedDeployment) {\n\t\t\treturn;\n\t\t}\n\t\tif (isSelfManaged) {\n\t\t\tif (values.abbreviatedName) {\n\t\t\t\tform.setValue('abbreviatedName', '');\n\t\t\t}\n\t\t\tif (values.regionPlans.length) {\n\t\t\t\tform.setValue('regionPlans', []);\n\t\t\t}\n\t\t\tif (!values.instances.length) {\n\t\t\t\tform.setValue('instances', [\n\t\t\t\t\t{\n\t\t\t\t\t\tsecure: 'true',\n\t\t\t\t\t\tfqdn: '',\n\t\t\t\t\t\tport: defaultOperationsApiPort,\n\t\t\t\t\t},\n\t\t\t\t]);\n\t\t\t}\n\t\t} else {\n\t\t\tif (values.fqdn) {\n\t\t\t\tform.setValue('fqdn', '');\n\t\t\t}\n\t\t\tif (values.instances.length) {\n\t\t\t\tform.setValue('instances', []);\n\t\t\t}\n\t\t\tif (!values.regionPlans.length) {\n\t\t\t\tpickDefaultDeploymentPerformanceAndRegionPlans(form, planTypes, regionLocations);\n\t\t\t}\n\t\t}\n\t}, [form, planTypes, regionLocations, selectedDeployment]);\n\n\tconst calculatedNames = useMemo(() => {\n\t\tconst suggestedAbbreviatedName = collapseKebabsToMaxLength(\n\t\t\ttoKebabCase(clusterName),\n\t\t\tspecifiedAbbreviatedName.maxLength!,\n\t\t);\n\t\treturn {\n\t\t\tsuggestedAbbreviatedName,\n\t\t\tfullHostName: `${abbreviatedName || suggestedAbbreviatedName}.${\n\t\t\t\torganization.subdomain || 'your-org'\n\t\t\t}.harperfabric.com`,\n\t\t};\n\t}, [clusterName, abbreviatedName, organization]);\n\tconst selectedPlan = useMemo(() => deploymentToPerformanceToPlan?.[selectedDeployment]?.[selectedPerformance], [\n\t\tdeploymentToPerformanceToPlan,\n\t\tselectedDeployment,\n\t\tselectedPerformance,\n\t]);\n\n\tuseEffect(function autoSelectRegionBasedOnAllowedRegionIds() {\n\t\tconst allowedRegionIds = selectedPlan?.allowedRegionIds;\n\t\tif (allowedRegionIds?.length && selectedRegionPlans?.length === 1) {\n\t\t\tconst firstRegion = selectedRegionPlans[0];\n\t\t\tconst firstSelectedRegion = regionNameToLatencyToRegion?.[firstRegion.regionName]\n\t\t\t\t?.[firstRegion.latencyDescription];\n\t\t\tif (!allowedRegionIds.includes(firstSelectedRegion?.id)) {\n\t\t\t\tconst possibleRegions = regionLocations?.filter(r => allowedRegionIds.includes(r.id));\n\t\t\t\tconst regionToSelect = possibleRegions?.find(r => r.region === 'US') || possibleRegions?.[0];\n\t\t\t\tif (regionToSelect) {\n\t\t\t\t\tform.setValue('regionPlans.0.regionName', regionToSelect.region);\n\t\t\t\t\tform.setValue('regionPlans.0.latencyDescription', regionToSelect.latencyDescription);\n\t\t\t\t\tvoid form.trigger();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}, [selectedPlan, selectedRegionPlans, form, regionNameToLatencyToRegion, regionLocations]);\n\n\tuseEffect(function syncRegionSelectionsWithPossibleRegions() {\n\t\tconst isSelfManaged = selectedDeployment === 'Self-Hosted';\n\t\tif (!isSelfManaged && Object.keys(regionNameToLatencyToRegion).length && selectedRegionPlans.length) {\n\t\t\tfor (let i = 0; i < selectedRegionPlans.length; i++) {\n\t\t\t\tconst regionPlan = selectedRegionPlans[i];\n\t\t\t\tif (!regionNameToLatencyToRegion[regionPlan.regionName]) {\n\t\t\t\t\tform.setValue(`regionPlans.${i}.regionName`, '');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}, [form, regionNameToLatencyToRegion, selectedDeployment, selectedRegionPlans]);\n\n\tconst totalPrice = !selectedPlan?.priceUsd\n\t\t? 0\n\t\t: selectedDeployment === 'Self-Hosted'\n\t\t? selectedInstances.length * selectedPlan.priceUsd\n\t\t: selectedRegionPlans.reduce((total, region) => {\n\t\t\tconst regionPlan = regionNameToLatencyToRegion?.[region.regionName!]?.[region.latencyDescription!];\n\t\t\treturn total + (!regionPlan\n\t\t\t\t? 0\n\t\t\t\t: selectedPlan.priceUsd * regionPlan.instanceCount / 2);\n\t\t}, 0);\n\n\tconst onStartSaving = useCallback(({\n\t\tcreating,\n\t\tdeploymentDescription,\n\t}: {\n\t\tcreating: boolean;\n\t\tdeploymentDescription: string;\n\t}) =>\n\t\ttoast.message(creating ? 'Creating Cluster' : 'Updating Cluster', {\n\t\t\tdescription: (\n\t\t\t\t<EstimatedProgressBar\n\t\t\t\t\tmessage=\"This may take a little bit, hold tight!\"\n\t\t\t\t\tlateMessage=\"Still working on it... why don't you grab a coffee, and I'll let you know when it's done?\"\n\t\t\t\t\tduration={deploymentDescription === 'Dedicated' ? 60_000 : 5_000}\n\t\t\t\t/>\n\t\t\t),\n\t\t\tduration: 120_000,\n\t\t}), []);\n\n\tconst onClusterSavedCallback = useCallback(async ({\n\t\tclusterId,\n\t\tsourceClusterId,\n\t\tcreating,\n\t\ttoastId,\n\t\tisSelfManaged,\n\t}: {\n\t\tclusterId: string;\n\t\tsourceClusterId: string | undefined;\n\t\tcreating: boolean;\n\t\tisSelfManaged: boolean;\n\t\ttoastId: string | number;\n\t}) => {\n\t\tif (sourceClusterId) {\n\t\t\tconst existingOrg = await getOrganization(organizationId);\n\t\t\tconst sourceCluster = existingOrg.clusters?.find(c => c.id === sourceClusterId);\n\t\t\tif (isFailed(sourceCluster?.status)) {\n\t\t\t\tawait terminateCluster(sourceClusterId);\n\t\t\t}\n\t\t}\n\n\t\tvoid queryClient.invalidateQueries({ queryKey: [organizationId], refetchType: 'active' });\n\t\tif (!creating) {\n\t\t\tvoid queryClient.invalidateQueries({ queryKey: [clusterId], refetchType: 'active' });\n\t\t}\n\n\t\tvoid router.invalidate();\n\t\tif (isSelfManaged) {\n\t\t\tvoid navigate({ to: `/${organizationId}/${clusterId}/instances` });\n\t\t} else if (creating) {\n\t\t\tvoid navigate({ to: `/${organizationId}/${clusterId}/starting-up` });\n\t\t} else {\n\t\t\tvoid navigate({ to: `/${organizationId}/${clusterId}/scaling` });\n\t\t}\n\t\tform.reset();\n\t\ttoast.success(creating ? 'Cluster Created' : 'Cluster Updated', {\n\t\t\tid: toastId,\n\t\t\tdescription: isSelfManaged\n\t\t\t\t? undefined\n\t\t\t\t: creating\n\t\t\t\t? 'It is being provisioned now.'\n\t\t\t\t: 'The updates are being provisioned now.',\n\t\t\tduration: 5_000,\n\t\t});\n\t}, [queryClient, router, navigate, organizationId, form]);\n\n\tconst executeChangesToCluster = useCallback(async () => {\n\t\tconst formData = form.getValues();\n\t\tconst plans: SchemaRegionPlan[] = [];\n\t\tconst plan = deploymentToPerformanceToPlan[formData.deploymentDescription][formData.performanceDescription];\n\n\t\tconst isSelfManaged = formData.deploymentDescription === 'Self-Hosted';\n\t\tif (isSelfManaged) {\n\t\t\tfor (const instance of formData.instances) {\n\t\t\t\tplans.push({\n\t\t\t\t\tautoRenew: true,\n\t\t\t\t\tinstanceFqdn: instance.fqdn,\n\t\t\t\t\toperationsApiPort: instance.port || defaultOperationsApiPort,\n\t\t\t\t\toperationsApiSecure: instance.secure === 'true',\n\t\t\t\t\tplanId: plan.id,\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tfor (const regionPlan of formData.regionPlans) {\n\t\t\t\tconst region = regionNameToLatencyToRegion[regionPlan.regionName][regionPlan.latencyDescription];\n\t\t\t\tplans.push({\n\t\t\t\t\tautoRenew: true,\n\t\t\t\t\tplanId: plan.id,\n\t\t\t\t\tregionId: region.id,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tsetSavedClusterState(null);\n\t\tconst toastId = onStartSaving({ creating: !clusterId, deploymentDescription: formData.deploymentDescription });\n\t\tconst clearToast = () => toast.dismiss(toastId);\n\t\tif (clusterId) {\n\t\t\tsubmitEditClusterData(\n\t\t\t\tmode === 'version'\n\t\t\t\t\t? { id: clusterId, version: formData.version, skipGtmWait: formData.skipGtmWait }\n\t\t\t\t\t: { id: clusterId, regionPlans: plans, skipGtmWait: formData.skipGtmWait },\n\t\t\t\t{\n\t\t\t\t\tonSuccess: (data) =>\n\t\t\t\t\t\tonClusterSavedCallback({\n\t\t\t\t\t\t\tclusterId: data.id,\n\t\t\t\t\t\t\tsourceClusterId: formData.sourceClusterId,\n\t\t\t\t\t\t\tisSelfManaged,\n\t\t\t\t\t\t\tcreating: false,\n\t\t\t\t\t\t\ttoastId,\n\t\t\t\t\t\t}),\n\t\t\t\t\tonError: clearToast,\n\t\t\t\t},\n\t\t\t);\n\t\t} else {\n\t\t\tsubmitNewClusterData({\n\t\t\t\tabbreviatedName: isSelfManaged\n\t\t\t\t\t? undefined\n\t\t\t\t\t: (formData.abbreviatedName || calculatedNames.suggestedAbbreviatedName),\n\t\t\t\tautoRenew: true,\n\t\t\t\tfqdn: isSelfManaged && formData.fqdn || undefined,\n\t\t\t\tname: formData.clusterName,\n\t\t\t\tversion: formData.version,\n\t\t\t\torganizationId,\n\t\t\t\tregionPlans: plans,\n\t\t\t}, {\n\t\t\t\tonSuccess: (data) =>\n\t\t\t\t\tonClusterSavedCallback({\n\t\t\t\t\t\tclusterId: data.id,\n\t\t\t\t\t\tsourceClusterId: formData.sourceClusterId,\n\t\t\t\t\t\tisSelfManaged,\n\t\t\t\t\t\tcreating: true,\n\t\t\t\t\t\ttoastId,\n\t\t\t\t\t}),\n\t\t\t\tonError: clearToast,\n\t\t\t});\n\t\t}\n\t}, [\n\t\tcalculatedNames.suggestedAbbreviatedName,\n\t\tclusterId,\n\t\tdeploymentToPerformanceToPlan,\n\t\tform,\n\t\tonClusterSavedCallback,\n\t\tonStartSaving,\n\t\torganizationId,\n\t\tregionNameToLatencyToRegion,\n\t\tsetSavedClusterState,\n\t\tsubmitEditClusterData,\n\t\tsubmitNewClusterData,\n\t]);\n\n\tconst submitClusterDetailsForm = useCallback(() => {\n\t\tif (mode !== 'version' && totalPrice > 0) {\n\t\t\tsetConfirmingPaymentDetails(true);\n\t\t\treturn;\n\t\t}\n\t\treturn executeChangesToCluster();\n\t}, [mode, executeChangesToCluster, totalPrice]);\n\n\tconst onSaveStateForBillingRedirect = useCallback((redirecting: boolean) => {\n\t\tsetSavedClusterState(redirecting ? { clusterId, ...form.getValues(), skipToBilling: true } : null);\n\t}, [clusterId, form, setSavedClusterState]);\n\n\tconst onGoBackToDetails = useCallback(() => {\n\t\tsetConfirmingPaymentDetails(false);\n\t}, []);\n\n\tconst pricingMarginRight = !isEnterprise && 'mr-37.5';\n\treturn (\n\t\t<>\n\t\t\t{!isEnterprise && mode !== 'version' && (\n\t\t\t\t<div className=\"absolute top-3 right-4 md:right-12 text-right\">\n\t\t\t\t\t<dt className=\"font-light\">Total Price</dt>\n\t\t\t\t\t<dd className=\"font-bold\">\n\t\t\t\t\t\t<PriceDisplay price={totalPrice} />\n\t\t\t\t\t</dd>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<Form {...form}>\n\t\t\t\t{!confirmingPaymentDetails\n\t\t\t\t\t? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<h1 className={cx('text-lg leading-none text-white font-semibold mb-4', pricingMarginRight)}>\n\t\t\t\t\t\t\t\tCluster Configuration\n\t\t\t\t\t\t\t</h1>\n\t\t\t\t\t\t\t<p className={cx('text-muted-foreground text-sm mb-6', pricingMarginRight)}>\n\t\t\t\t\t\t\t\tConfigure your Harper cluster and define deployment plans.\n\t\t\t\t\t\t\t</p>\n\n\t\t\t\t\t\t\t<form\n\t\t\t\t\t\t\t\tid=\"cluster-upsert-form\"\n\t\t\t\t\t\t\t\tname=\"cluster-upsert-form\"\n\t\t\t\t\t\t\t\tonSubmit={form.handleSubmit(submitClusterDetailsForm)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<ClusterDetails\n\t\t\t\t\t\t\t\t\tcalculatedNames={calculatedNames}\n\t\t\t\t\t\t\t\t\tclusterId={clusterId}\n\t\t\t\t\t\t\t\t\tdeploymentToPerformanceToPlan={deploymentToPerformanceToPlan}\n\t\t\t\t\t\t\t\t\tform={form}\n\t\t\t\t\t\t\t\t\tisPending={isCreatePending || isEditPending}\n\t\t\t\t\t\t\t\t\tharperVersions={harperVersions}\n\t\t\t\t\t\t\t\t\tmode={mode}\n\t\t\t\t\t\t\t\t\tregionLocations={regionLocations}\n\t\t\t\t\t\t\t\t\tregionNameToLatencyToRegion={regionNameToLatencyToRegion}\n\t\t\t\t\t\t\t\t\tselectedDeployment={selectedDeployment}\n\t\t\t\t\t\t\t\t\tselectedPerformance={selectedPerformance}\n\t\t\t\t\t\t\t\t\tselectedPlan={selectedPlan}\n\t\t\t\t\t\t\t\t\ttotalPrice={totalPrice}\n\t\t\t\t\t\t\t\t\tisEnterprise={isEnterprise}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t</>\n\t\t\t\t\t)\n\t\t\t\t\t: (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<h1 className={cx('text-lg leading-none text-white font-semibold mb-4', pricingMarginRight)}>\n\t\t\t\t\t\t\t\tCluster Billing\n\t\t\t\t\t\t\t</h1>\n\t\t\t\t\t\t\t<p className={cx('text-muted-foreground text-sm mb-2', pricingMarginRight)}>\n\t\t\t\t\t\t\t\tPlease confirm the following billing details:\n\t\t\t\t\t\t\t</p>\n\n\t\t\t\t\t\t\t<ClusterBilling\n\t\t\t\t\t\t\t\tclusterId={clusterId}\n\t\t\t\t\t\t\t\tisPending={isCreatePending || isEditPending}\n\t\t\t\t\t\t\t\tonGoBackToDetails={onGoBackToDetails}\n\t\t\t\t\t\t\t\tonSaveStateForBillingRedirect={onSaveStateForBillingRedirect}\n\t\t\t\t\t\t\t\tonSubmit={executeChangesToCluster}\n\t\t\t\t\t\t\t\torganizationId={organizationId}\n\t\t\t\t\t\t\t\tselectedPlan={selectedPlan}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t</Form>\n\t\t</>\n\t);\n}\n","import { UpsertClusterSchemaType } from './upsertClusterSchema';\n\nexport function isUpsertClusterSchema(instance: unknown): instance is UpsertClusterSchemaType {\n\treturn (instance as UpsertClusterSchemaType)?.clusterName !== undefined;\n}\n","import { ContactUs } from '@/components/ContactUs';\nimport { ErrorComponent } from '@/components/ErrorComponent';\nimport { Loading } from '@/components/Loading';\nimport { SubNavSimpleLayout } from '@/components/SubNavSimpleLayout';\nimport { isFailed, isTerminated } from '@/components/ui/utils/badgeStatus';\nimport { deletedClusterStatuses } from '@/config/clusterStatuses';\nimport { getPlanTypesOptions } from '@/features/cluster/queries/getPlanTypesQuery';\nimport { getHarperVersionsOptions, HarperVersionsResponse } from '@/features/clusters/queries/getHarperVersionsQuery';\nimport { getRegionLocationsOptions } from '@/features/clusters/queries/getRegionLocationsQuery';\nimport { useLocalStorage } from '@/hooks/useLocalStorage';\nimport { useOrganizationClusterPermissions } from '@/hooks/usePermissions';\nimport { SchemaPlan } from '@/integrations/api/api.gen';\nimport { Cluster, Organization } from '@/integrations/api/api.patch';\nimport { excludeFalsy } from '@/lib/arrays/excludeFalsy';\nimport { sortByField } from '@/lib/arrays/sort/byField';\nimport { byInstanceFqdnThenPort } from '@/lib/arrays/sort/byInstanceFqdnThenPort';\nimport { groupThenKeyBy } from '@/lib/groupThenKeyBy';\nimport { LocalStorageKeys } from '@/lib/storage/localStorageKeys';\nimport { compareVersions, wasAReleasedBeforeB } from '@/lib/string/wasAReleasedBeforeB';\nimport { useQuery } from '@tanstack/react-query';\nimport { useParams, useRouteContext } from '@tanstack/react-router';\nimport { useMemo } from 'react';\nimport { z } from 'zod';\nimport { ClusterForm } from './ClusterForm';\nimport { isUpsertClusterSchema } from './isUpsertClusterSchema';\nimport {\n\tcalculateDefaultDeploymentPerformanceAndRegionPlans,\n} from './lib/calculateDefaultDeploymentPerformanceAndRegionPlans';\nimport { UpsertClusterSchema, UpsertClusterSchemaType } from './upsertClusterSchema';\n\nexport function UpsertCluster() {\n\tconst { organizationId, clusterId, mode }: { organizationId: string; clusterId?: string; mode?: 'version' } =\n\t\tuseParams({ strict: false });\n\tconst { create, update } = useOrganizationClusterPermissions(organizationId);\n\tconst { organization, cluster }: {\n\t\torganization: Organization;\n\t\tcluster?: Cluster;\n\t} = useRouteContext({ strict: false });\n\tconst [savedClusterState, setSavedClusterState] = useLocalStorage<\n\t\t| null\n\t\t| ({\n\t\t\tclusterId?: string;\n\t\t} & (UpsertClusterSchemaType | Cluster))\n\t>(LocalStorageKeys.SavedClusterState, null);\n\n\tconst { data: planTypes } = useQuery(getPlanTypesOptions(organizationId));\n\tconst { data: regionLocationsColocated } = useQuery(getRegionLocationsOptions({\n\t\tavailableHosts: true,\n\t\torganizationId,\n\t}));\n\tconst { data: regionLocationsDedicated } = useQuery(getRegionLocationsOptions({ organizationId }));\n\n\tconst { data: newHarperVersions } = useQuery(getHarperVersionsOptions());\n\tconst harperVersions = useMemo(() => {\n\t\tif (cluster) {\n\t\t\tconst clusterVersions = cluster.instances?.map(i => i.version).filter(excludeFalsy);\n\t\t\tif (newHarperVersions && clusterVersions) {\n\t\t\t\tconst latestClusterVersion = clusterVersions.sort(compareVersions).pop();\n\t\t\t\treturn {\n\t\t\t\t\t...newHarperVersions,\n\t\t\t\t\tvalue: [\n\t\t\t\t\t\t!!latestClusterVersion && {\n\t\t\t\t\t\t\tname: 'current',\n\t\t\t\t\t\t\tversion: latestClusterVersion,\n\t\t\t\t\t\t} as const,\n\t\t\t\t\t\t...(newHarperVersions?.value || []).filter(v => {\n\t\t\t\t\t\t\t// Is our version unique from the latest cluster version?\n\t\t\t\t\t\t\treturn latestClusterVersion !== v.version\n\t\t\t\t\t\t\t\t// Do we have a cluster version?\n\t\t\t\t\t\t\t\t&& (!latestClusterVersion\n\t\t\t\t\t\t\t\t\t// Or if we do, have we updated to a higher version already?\n\t\t\t\t\t\t\t\t\t// This can prevent upgrading to, say, \"next\" v5, and then downgrading to the \"latest\" v4.\n\t\t\t\t\t\t\t\t\t|| wasAReleasedBeforeB(latestClusterVersion, v.version));\n\t\t\t\t\t\t}),\n\t\t\t\t\t].filter(excludeFalsy),\n\t\t\t\t} satisfies HarperVersionsResponse;\n\t\t\t}\n\t\t}\n\t\treturn newHarperVersions;\n\t}, [newHarperVersions, cluster]);\n\n\tconst alreadyUsingFree = useMemo(() => {\n\t\tfor (const orgCluster of organization?.clusters ?? []) {\n\t\t\tif (\n\t\t\t\torgCluster.id !== cluster?.id\n\t\t\t\t&& planTypes\n\t\t\t\t&& !isTerminated(orgCluster.status)\n\t\t\t\t&& !isFailed(orgCluster.status)\n\t\t\t\t&& orgCluster.plans\n\t\t\t) {\n\t\t\t\tfor (const clusterPlan of orgCluster.plans) {\n\t\t\t\t\tconst foundPlan = planTypes.find(p => p.id === clusterPlan.planId);\n\t\t\t\t\tif (foundPlan?.priceUsd === 0 && !foundPlan.id.startsWith('self-hosted')) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}, [cluster?.id, organization?.clusters, planTypes]);\n\n\tconst deploymentToPerformanceToPlan = useMemo<Record<string, Record<string, SchemaPlan>>>(\n\t\t() =>\n\t\t\tgroupThenKeyBy(planTypes?.sort(sortByField('priceUsd')) || [], 'deploymentDescription', 'performanceDescription'),\n\t\t[planTypes],\n\t);\n\n\tconst defaultValues = useMemo<null | UpsertClusterSchemaType>(() => {\n\t\tif (\n\t\t\t!planTypes || !harperVersions || !regionLocationsColocated || !regionLocationsDedicated || (clusterId && !cluster)\n\t\t) {\n\t\t\treturn null;\n\t\t}\n\n\t\tlet clusterToLoad = cluster;\n\n\t\tif (savedClusterState) {\n\t\t\tif (isUpsertClusterSchema(savedClusterState)) {\n\t\t\t\treturn {\n\t\t\t\t\t...savedClusterState,\n\t\t\t\t\tclusterName: savedClusterState.clusterName || '',\n\t\t\t\t\tabbreviatedName: savedClusterState.abbreviatedName || '',\n\t\t\t\t\tversion: savedClusterState.version,\n\t\t\t\t\tdeploymentDescription: savedClusterState.deploymentDescription || '',\n\t\t\t\t\tperformanceDescription: savedClusterState.performanceDescription || '',\n\t\t\t\t\tfqdn: savedClusterState.fqdn || '',\n\t\t\t\t\tregionPlans: savedClusterState.regionPlans || [],\n\t\t\t\t\tinstances: savedClusterState.instances || [],\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tclusterToLoad = savedClusterState;\n\t\t\t}\n\t\t}\n\n\t\tconst selectedPlan = planTypes?.find(planType => planType.id === cluster?.plans?.[0].planId);\n\n\t\tconst regionPlans: z.infer<typeof UpsertClusterSchema.shape.regionPlans> = [];\n\t\tconst instances: z.infer<typeof UpsertClusterSchema.shape.instances> = [];\n\t\tconst regionLocations = selectedPlan?.deploymentDescription !== 'Dedicated'\n\t\t\t? regionLocationsColocated\n\t\t\t: regionLocationsDedicated;\n\t\tconst defaults = calculateDefaultDeploymentPerformanceAndRegionPlans(planTypes, regionLocations, alreadyUsingFree);\n\n\t\tlet isSelfManaged = false;\n\t\tif (clusterToLoad) {\n\t\t\tif (clusterToLoad.plans) {\n\t\t\t\tfor (const plan of clusterToLoad.plans) {\n\t\t\t\t\tif (plan.regionId) {\n\t\t\t\t\t\tconst selectedRegion = regionLocations.find(regionLocation => regionLocation.id === plan.regionId);\n\t\t\t\t\t\tif (selectedRegion) {\n\t\t\t\t\t\t\tregionPlans.push({\n\t\t\t\t\t\t\t\tregionName: selectedRegion.region,\n\t\t\t\t\t\t\t\tlatencyDescription: selectedRegion.latencyDescription,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!regionPlans.length && clusterToLoad.instances) {\n\t\t\t\tconst clusterInstances = clusterToLoad.instances\n\t\t\t\t\t.filter(instance => instance.status && !deletedClusterStatuses.includes(instance.status))\n\t\t\t\t\t.sort(byInstanceFqdnThenPort);\n\t\t\t\tfor (const instance of clusterInstances) {\n\t\t\t\t\tisSelfManaged = true;\n\t\t\t\t\tinstances.push({\n\t\t\t\t\t\tfqdn: instance.instanceFqdn,\n\t\t\t\t\t\tport: instance.operationsApiPort,\n\t\t\t\t\t\tsecure: instance.operationsApiSecure ? 'true' : 'false',\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (defaults) {\n\t\t\tregionPlans.push(...defaults.regionPlans);\n\t\t}\n\t\tif (!isSelfManaged && !regionPlans.length) {\n\t\t\tregionPlans.push({ regionName: '', latencyDescription: '' });\n\t\t}\n\n\t\tconst version = harperVersions.value?.find(v => v.name === 'current')?.version\n\t\t\t?? harperVersions.value?.find(v => v.name === 'stable')?.version;\n\n\t\treturn {\n\t\t\tsourceClusterId: clusterToLoad?.id,\n\t\t\tautoRenew: clusterToLoad?.plans?.[0]?.autoRenew ?? true,\n\t\t\tclusterName: clusterToLoad?.name ?? '',\n\t\t\tabbreviatedName: clusterToLoad?.abbreviatedName ?? '',\n\t\t\tversion,\n\t\t\tdeploymentDescription: selectedPlan?.deploymentDescription ?? defaults?.deploymentDescription ?? '',\n\t\t\tperformanceDescription: selectedPlan?.performanceDescription ?? defaults?.performanceDescription ?? '',\n\t\t\tfqdn: isSelfManaged ? clusterToLoad?.fqdn ?? '' : '',\n\t\t\tinstances,\n\t\t\tregionPlans,\n\t\t};\n\t}, [\n\t\talreadyUsingFree,\n\t\tcluster,\n\t\tclusterId,\n\t\tplanTypes,\n\t\tharperVersions,\n\t\tregionLocationsColocated,\n\t\tregionLocationsDedicated,\n\t\tsavedClusterState,\n\t]);\n\n\tconst isLoading = !defaultValues || !organization || !planTypes || !regionLocationsColocated\n\t\t|| !regionLocationsDedicated;\n\tif (isLoading) {\n\t\treturn (\n\t\t\t<SubNavSimpleLayout>\n\t\t\t\t<Loading centered={true} text=\"Loading...\" />\n\t\t\t</SubNavSimpleLayout>\n\t\t);\n\t}\n\n\tif (cluster?.id ? !update : !create) {\n\t\treturn (\n\t\t\t<SubNavSimpleLayout>\n\t\t\t\t<ErrorComponent\n\t\t\t\t\ttitle={`Not Allowed`}\n\t\t\t\t\terror={{\n\t\t\t\t\t\tmessage: (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\tYou do not have permission to {cluster?.id ? 'update' : 'create'} clusters in this org.\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t),\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</SubNavSimpleLayout>\n\t\t);\n\t}\n\n\tif (planTypes.length === 0) {\n\t\treturn (\n\t\t\t<SubNavSimpleLayout>\n\t\t\t\t<ErrorComponent\n\t\t\t\t\ttitle={`Cluster ${clusterId ? 'Modification' : 'Creation'} Not Currently Allowed`}\n\t\t\t\t\terror={{\n\t\t\t\t\t\tmessage: (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\tThere are no available deployment types right now! Please try again later, or <ContactUs />.\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t),\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</SubNavSimpleLayout>\n\t\t);\n\t}\n\n\treturn (\n\t\t<SubNavSimpleLayout className=\"max-w-4xl mx-auto\">\n\t\t\t<ClusterForm\n\t\t\t\talreadyUsingFree={alreadyUsingFree}\n\t\t\t\tclusterId={clusterId}\n\t\t\t\tdefaultValues={defaultValues}\n\t\t\t\tdeploymentToPerformanceToPlan={deploymentToPerformanceToPlan}\n\t\t\t\tharperVersions={harperVersions}\n\t\t\t\tmode={mode}\n\t\t\t\torganization={organization}\n\t\t\t\torganizationId={organizationId}\n\t\t\t\tplanTypes={planTypes}\n\t\t\t\tregionLocationsColocated={regionLocationsColocated}\n\t\t\t\tregionLocationsDedicated={regionLocationsDedicated}\n\t\t\t\tsetSavedClusterState={setSavedClusterState}\n\t\t\t\tstartOffOnBilling={isUpsertClusterSchema(savedClusterState) && savedClusterState.skipToBilling === true}\n\t\t\t/>\n\t\t</SubNavSimpleLayout>\n\t);\n}\n","import { Cluster } from '@/integrations/api/api.patch';\n\nconst statusPriority: Record<string, number> = {\n\t'FAILED': 0,\n\t'UPDATING': 1,\n\t'PROVISIONING': 2,\n\t'RUNNING': 3,\n\t'TERMINATED': 4,\n};\n\nconst DEFAULT_PRIORITY = statusPriority.RUNNING;\n\nexport function byClusterStatusThenName(a: Cluster, b: Cluster) {\n\tif (a.status === b.status) {\n\t\treturn a.name.localeCompare(b.name);\n\t}\n\n\tconst priorityA = a.status ? statusPriority[a.status] ?? DEFAULT_PRIORITY : DEFAULT_PRIORITY;\n\tconst priorityB = b.status ? statusPriority[b.status] ?? DEFAULT_PRIORITY : DEFAULT_PRIORITY;\n\treturn priorityA - priorityB;\n}\n","export function curryFilterByFuzzySearch<T>(fields: (keyof T)[], searchFor: string): (t: T) => boolean {\n\tconst searchForLower = searchFor.toLowerCase();\n\treturn (t: T) => {\n\t\tfor (const field of fields) {\n\t\t\tconst value = t[field];\n\t\t\tif (value === undefined || value === null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (typeof value === 'string') {\n\t\t\t\tif (value.toLowerCase().includes(searchForLower)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} else if (typeof value === 'boolean') {\n\t\t\t\tif (value && (searchForLower === 'yes' || searchForLower === 'true' || searchForLower === '1')) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (!value && (searchForLower === 'no' || searchForLower === 'false' || searchForLower === '0')) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new Error('curryFilterByFuzzySearch has not implemented support for ' + (typeof value) + ' fields yet!');\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t};\n}\n","import { SubNavMenu } from '@/components/SubNavMenu';\nimport { Button } from '@/components/ui/button';\nimport { Input } from '@/components/ui/input';\nimport { isTerminated } from '@/components/ui/utils/badgeStatus';\nimport { ClusterCard } from '@/features/clusters/components/ClusterCard';\nimport { UpsertCluster } from '@/features/clusters/upsert';\nimport { getOrganizationQueryOptions } from '@/features/organization/queries/getOrganizationQuery';\nimport { useLocalStorage } from '@/hooks/useLocalStorage';\nimport { useOrganizationClusterPermissions } from '@/hooks/usePermissions';\nimport { Cluster } from '@/integrations/api/api.patch';\nimport { byClusterStatusThenName } from '@/lib/arrays/sort/byClusterStatusThenName';\nimport { LocalStorageKeys } from '@/lib/storage/localStorageKeys';\nimport { curryFilterByFuzzySearch } from '@/lib/string/filterByFuzzySearch';\nimport { useSuspenseQuery } from '@tanstack/react-query';\nimport { Link, Navigate, useParams } from '@tanstack/react-router';\nimport { Plus } from 'lucide-react';\nimport { FormEvent, useCallback, useMemo, useState } from 'react';\n\nexport function ClustersList() {\n\tconst { organizationId }: { organizationId: string } = useParams({ strict: false });\n\tconst { create } = useOrganizationClusterPermissions(organizationId);\n\tconst { data: orgInfo, isSuccess } = useSuspenseQuery(getOrganizationQueryOptions(organizationId));\n\tconst [savedClusterState] = useLocalStorage<unknown | null>(LocalStorageKeys.SavedClusterState, null);\n\n\tconst [filterByNameValue, setFilterByNameValue] = useState('');\n\tconst clearFilterByNameValue = useCallback(() => setFilterByNameValue(''), []);\n\n\tconst onFilterByNameChanged = useCallback((e: FormEvent<HTMLInputElement>) => {\n\t\tsetFilterByNameValue(e.currentTarget.value?.toLowerCase() || '');\n\t}, []);\n\n\tconst runningClusters = useMemo(() =>\n\t\torgInfo?.clusters\n\t\t\t?.slice()\n\t\t\t.filter(cluster => !isTerminated(cluster.status))\n\t\t\t.sort(byClusterStatusThenName)\n\t\t|| [], [orgInfo?.clusters]);\n\n\tconst filteredClusters = useMemo(() =>\n\t\trunningClusters\n\t\t\t.filter(curryFilterByFuzzySearch<Cluster>(['id', 'name'], filterByNameValue))\n\t\t|| [], [filterByNameValue, runningClusters]);\n\n\tif (orgInfo && runningClusters.length === 0 && create) {\n\t\treturn <UpsertCluster />;\n\t}\n\tif (savedClusterState) {\n\t\treturn <Navigate to={`/${organizationId}/new-cluster`} />;\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t<SubNavMenu>\n\t\t\t\t{isSuccess\n\t\t\t\t\t? (\n\t\t\t\t\t\t<div className=\"flex w-full justify-end gap-2\">\n\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\tplaceholder=\"Filter by name\"\n\t\t\t\t\t\t\t\tclassName=\"inline-block w-full text-xs\"\n\t\t\t\t\t\t\t\tvalue={filterByNameValue}\n\t\t\t\t\t\t\t\tonChange={onFilterByNameChanged}\n\t\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t\t{create && (\n\t\t\t\t\t\t\t\t<Link to=\"new-cluster\">\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\tvariant=\"positive\"\n\t\t\t\t\t\t\t\t\t\taccessKey=\"n\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<Plus />{' '}\n\t\t\t\t\t\t\t\t\t\t<span className=\"hidden sm:inline-block\">\n\t\t\t\t\t\t\t\t\t\t\t<u>N</u>ew <span className=\"hidden md:inline-block\">Cluster</span>\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)\n\t\t\t\t\t: null}\n\t\t\t</SubNavMenu>\n\t\t\t<section className=\"mt-32 px-4 pt-4 md:px-12 min-h-[calc(100vh-(--spacing(32)))]\">\n\t\t\t\t<div className=\"grid grid-cols-1 gap-4 md:grid-cols-12 mb-4\">\n\t\t\t\t\t{filteredClusters.map((cluster) => (\n\t\t\t\t\t\t<div key={cluster.id} className=\"col-span-1 md:col-span-4 lg:col-span-3 2xl:col-span-2\">\n\t\t\t\t\t\t\t<ClusterCard cluster={cluster} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t\t{!filteredClusters.length && (\n\t\t\t\t\t\t<div className=\"col-span-1 md:col-span-12 text-center\">\n\t\t\t\t\t\t\t<h2 className=\"my-4 text-xl\">No matches found.</h2>\n\t\t\t\t\t\t\t<Button type=\"button\" variant=\"outline\" onClick={clearFilterByNameValue}>Clear Filters</Button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</section>\n\t\t</>\n\t);\n}\n","export function currentUrlAfterHash(): string {\n\tconst parsed = URL.parse(location.href);\n\tif (!parsed?.hash) {\n\t\treturn '/';\n\t}\n\treturn parsed.hash.startsWith('#/') ? parsed.hash.slice(1) : parsed.hash;\n}\n","import { currentUrlAfterHash } from '@/lib/urls/currentUrlAfterHash';\n\nexport function currentUrlIncludingHash(): string {\n\treturn '/#' + currentUrlAfterHash();\n}\n","import { Loading } from '@/components/Loading';\nimport { useLocalStorage } from '@/hooks/useLocalStorage';\nimport { useProcessStripePaymentMethod } from '@/integrations/stripe/useProcessStripePaymentMethod';\nimport { LocalStorageKeys } from '@/lib/storage/localStorageKeys';\nimport { currentUrlIncludingHash } from '@/lib/urls/currentUrlIncludingHash';\nimport { useStripe } from '@stripe/react-stripe-js';\nimport { useNavigate, useParams, useSearch } from '@tanstack/react-router';\nimport { useCallback, useEffect } from 'react';\nimport { toast } from 'sonner';\n\nexport function ProcessSetupIntent() {\n\tconst { organizationId } = useParams({ strict: false });\n\tconst navigate = useNavigate();\n\tconst urlParams = new URLSearchParams(window.location.search);\n\tconst clientSecretBeforeHash = urlParams.get('setup_intent_client_secret');\n\tconst { setup_intent_client_secret: clientSecretAfterHash }: {\n\t\tsetup_intent_client_secret?: string;\n\t} = useSearch({ strict: false });\n\tconst [savedClusterState] = useLocalStorage<\n\t\t{\n\t\t\tclusterId?: string;\n\t\t} & unknown | null\n\t>(LocalStorageKeys.SavedClusterState, null);\n\tconst clientSecret = clientSecretBeforeHash || clientSecretAfterHash;\n\n\tconst stripe = useStripe();\n\tconst processStripePaymentMethod = useProcessStripePaymentMethod(organizationId);\n\tconst navigateBack = useCallback(() => {\n\t\tconst to = savedClusterState\n\t\t\t? savedClusterState.clusterId\n\t\t\t\t? `../../${savedClusterState.clusterId}/edit`\n\t\t\t\t: '../../new-cluster'\n\t\t\t: '../';\n\t\twindow.history.replaceState(null, '', currentUrlIncludingHash());\n\t\tvoid navigate({ search: undefined, to });\n\t}, [navigate, savedClusterState]);\n\n\tuseEffect(() => {\n\t\tif (!stripe || !clientSecret || !processStripePaymentMethod || !organizationId || !navigateBack) {\n\t\t\treturn;\n\t\t}\n\n\t\t(async function() {\n\t\t\ttry {\n\t\t\t\tconst { setupIntent } = await stripe.retrieveSetupIntent(clientSecret);\n\t\t\t\tswitch (setupIntent?.status) {\n\t\t\t\t\tcase 'succeeded':\n\t\t\t\t\t\tif (setupIntent.payment_method !== null) {\n\t\t\t\t\t\t\tprocessStripePaymentMethod(setupIntent.payment_method, navigateBack);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttoast.error('Failed to process payment method details. Please try another payment method.');\n\t\t\t\t\t\t\tnavigateBack();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'processing':\n\t\t\t\t\t\ttoast.warning('Processing payment method. Please check back later.');\n\t\t\t\t\t\tnavigateBack();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'requires_payment_method':\n\t\t\t\t\t\ttoast.error('Failed to process payment method details. Please try another payment method.');\n\t\t\t\t\t\tnavigateBack();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\ttoast.error('Failed to process payment method details. Please try another payment method.');\n\t\t\t\t\t\tnavigateBack();\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(err);\n\t\t\t\ttoast.error('Failed to process payment method details. Please try another payment method.');\n\t\t\t\tnavigateBack();\n\t\t\t}\n\t\t})();\n\t}, [clientSecret, navigateBack, organizationId, processStripePaymentMethod, stripe]);\n\n\treturn <Loading centered />;\n}\n","import { ProcessSetupIntent } from '@/features/organization/billing/confirm/ProcessSetupIntent';\nimport { StripeWrapper } from '@/integrations/stripe/StripeContext';\n\nexport function ConfirmSetupIntent() {\n\treturn (\n\t\t<StripeWrapper>\n\t\t\t<ProcessSetupIntent />\n\t\t</StripeWrapper>\n\t);\n}\n","import { excludeFalsy } from '@/lib/arrays/excludeFalsy';\n\nexport function buildAbsoluteLinkToPage({\n\tclusterId,\n\tinstanceId,\n\torganizationId,\n}: {\n\tclusterId?: string;\n\tinstanceId?: string;\n\torganizationId?: string;\n}, page?: string): string {\n\treturn '/' + [\n\t\torganizationId,\n\t\tclusterId,\n\t\tinstanceId && 'instance',\n\t\tinstanceId,\n\t\tpage,\n\t].filter(excludeFalsy).join('/');\n}\n","import { SubNavMenu } from '@/components/SubNavMenu';\nimport { useOrganizationPermissions } from '@/hooks/usePermissions';\nimport { buildAbsoluteLinkToPage } from '@/lib/urls/buildAbsoluteLinkToPage';\nimport { Link, Outlet, useParams } from '@tanstack/react-router';\nimport { CreditCardIcon, ReceiptIcon, ReceiptTextIcon } from 'lucide-react';\n\nconst sharedClasses = 'flex items-center p-2 rounded-lg group';\nconst inactiveProps = { className: 'text-white hover:bg-gray-700' };\nconst activeProps = { className: 'text-black bg-white pointer-events-none cursor-default' };\n\nexport function OrgBillingIndex() {\n\tconst { organizationId } = useParams({ strict: false });\n\tconst { update } = useOrganizationPermissions(organizationId);\n\n\tif (!update) {\n\t\treturn (\n\t\t\t<div className=\"mt-32 px-4 pt-4 md:px-12 min-h-[calc(100vh-theme(spacing.32))]\">\n\t\t\t\tYou don't have access to manage payments for this organization. Please contact your administrator.\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t<SubNavMenu />\n\t\t\t<div className=\"mt-32 px-4 pt-4 md:px-12 min-h-[calc(100vh-theme(spacing.32))]\">\n\t\t\t\t<div className=\"md:grid gap-4 md:grid-cols-12 min-h-[calc(100vh-theme(spacing.36))] mb-12\">\n\t\t\t\t\t<section className=\"col-span-1 text-white md:col-span-4 lg:col-span-3 md:border-r-1 border-b md:border-b-0 md:pr-4 border-gray-700\">\n\t\t\t\t\t\t<DesktopBillingNavBar />\n\t\t\t\t\t\t<MobileBillingNavBar />\n\t\t\t\t\t</section>\n\t\t\t\t\t<section className=\"col-span-1 text-white md:col-span-8 lg:col-span-9\">\n\t\t\t\t\t\t<Outlet />\n\t\t\t\t\t</section>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</>\n\t);\n}\n\nfunction DesktopBillingNavBar() {\n\tconst params = useParams({ strict: false });\n\treturn (\n\t\t<div className=\"hidden md:block\">\n\t\t\t<span className={sharedClasses}>\n\t\t\t\t<ReceiptIcon className=\"inline-block\" />\n\t\t\t\t<h3 className=\"ms-3 text-2xl font-extrabold dark:text-white\">Billing</h3>\n\t\t\t</span>\n\n\t\t\t<ul className=\"border-t border-gray-700 pt-4 mt-4 space-y-2\">\n\t\t\t\t<li>\n\t\t\t\t\t<Link\n\t\t\t\t\t\tto={buildAbsoluteLinkToPage(params, 'billing')}\n\t\t\t\t\t\tclassName={sharedClasses}\n\t\t\t\t\t\tactiveOptions={{ exact: true }}\n\t\t\t\t\t\tinactiveProps={inactiveProps}\n\t\t\t\t\t\tactiveProps={activeProps}\n\t\t\t\t\t>\n\t\t\t\t\t\t<CreditCardIcon className=\"inline-block\" /> <span className=\"ms-3\">Payment Method</span>\n\t\t\t\t\t</Link>\n\t\t\t\t</li>\n\t\t\t\t<li>\n\t\t\t\t\t<Link\n\t\t\t\t\t\tto={buildAbsoluteLinkToPage(params, 'billing/invoices')}\n\t\t\t\t\t\tclassName={sharedClasses}\n\t\t\t\t\t\tinactiveProps={inactiveProps}\n\t\t\t\t\t\tactiveProps={activeProps}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ReceiptTextIcon className=\"inline-block\" />\n\t\t\t\t\t\t<span className=\"ms-3\">Invoices & Payments</span>\n\t\t\t\t\t</Link>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t</div>\n\t);\n}\n\nfunction MobileBillingNavBar() {\n\tconst params = useParams({ strict: false });\n\treturn (\n\t\t<ul className=\"flex space-x-4 md:hidden py-2\">\n\t\t\t<li>\n\t\t\t\t<Link\n\t\t\t\t\tto={buildAbsoluteLinkToPage(params, 'billing')}\n\t\t\t\t\tclassName={sharedClasses}\n\t\t\t\t\tactiveOptions={{ exact: true }}\n\t\t\t\t\tinactiveProps={inactiveProps}\n\t\t\t\t\tactiveProps={activeProps}\n\t\t\t\t>\n\t\t\t\t\t<CreditCardIcon className=\"inline-block\" /> <span className=\"ms-3\">Payment Method</span>\n\t\t\t\t</Link>\n\t\t\t</li>\n\t\t\t<li>\n\t\t\t\t<Link\n\t\t\t\t\tto={buildAbsoluteLinkToPage(params, 'billing/invoices')}\n\t\t\t\t\tclassName={sharedClasses}\n\t\t\t\t\tinactiveProps={inactiveProps}\n\t\t\t\t\tactiveProps={activeProps}\n\t\t\t\t>\n\t\t\t\t\t<ReceiptTextIcon className=\"inline-block\" /> <span className=\"ms-3\">Invoices & Payments</span>\n\t\t\t\t</Link>\n\t\t\t</li>\n\t\t</ul>\n\t);\n}\n","import { Button } from '@/components/ui/button';\nimport { cn } from '@/lib/cn';\nimport { flexRender, Header, RowData } from '@tanstack/react-table';\nimport { ArrowDown, ArrowUp, ArrowUpDown, GripVerticalIcon } from 'lucide-react';\nimport * as React from 'react';\nimport { useCallback } from 'react';\n\nexport interface TableProps extends React.ComponentProps<'table'> {\n\tcontainerClassName?: string;\n}\n\nexport function Table({ className, containerClassName, ...props }: TableProps) {\n\treturn (\n\t\t<div data-slot=\"table-container\" className={cn('relative w-full overflow-x-auto', containerClassName)}>\n\t\t\t<table data-slot=\"table\" className={cn('w-full caption-bottom text-sm', className)} {...props} />\n\t\t</div>\n\t);\n}\n\nexport function TableHeader({ className, ...props }: React.ComponentProps<'thead'>) {\n\treturn <thead data-slot=\"table-header\" className={cn('[&_tr]:border-b', className)} {...props} />;\n}\n\nexport function TableBody({ className, ...props }: React.ComponentProps<'tbody'>) {\n\treturn <tbody data-slot=\"table-body\" className={cn('[&_tr:last-child]:border-0', className)} {...props} />;\n}\n\nexport function TableFooter({ className, ...props }: React.ComponentProps<'tfoot'>) {\n\treturn (\n\t\t<tfoot\n\t\t\tdata-slot=\"table-footer\"\n\t\t\tclassName={cn('bg-muted/50 border-t font-medium [&>tr]:last:border-b-0', className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport function TableRow({ className, ...props }: React.ComponentProps<'tr'>) {\n\treturn (\n\t\t<tr\n\t\t\tdata-slot=\"table-row\"\n\t\t\tclassName={cn('border-b border-grey-700 transition-colors', className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport function TableHead({ className, ...props }: React.ComponentProps<'th'>) {\n\treturn (\n\t\t<th\n\t\t\tdata-slot=\"table-head\"\n\t\t\tclassName={cn(\n\t\t\t\t'h-10 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport function TableHeadSortable<TData extends RowData>({\n\theader,\n\tonColumnClick,\n\t...props\n}: React.ComponentProps<'th'> & {\n\theader: Header<TData, unknown>;\n\tonColumnClick?: (accessorKey: string, willSortByAscending: boolean) => void;\n}) {\n\tconst onClickSort = useCallback(() => {\n\t\theader.column.toggleSorting(header.column.getIsSorted() === 'asc');\n\t\tconst willSortByAscending = header.column.getIsSorted() === false || header.column.getIsSorted() !== 'asc';\n\t\t// @ts-expect-error The accessorKey isn't accessible.\n\t\tonColumnClick?.(header.column.columnDef.accessorKey, willSortByAscending);\n\t}, [header, onColumnClick]);\n\tconst enableSorting = header.column.columnDef.enableSorting;\n\tconst enableResizing = header.column.columnDef.enableResizing;\n\tconst content = header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext());\n\tconst resetSize = useCallback(() => {\n\t\theader.column.resetSize();\n\t}, [header]);\n\treturn (\n\t\t<TableHead\n\t\t\t{...props}\n\t\t\tstyle={{ width: `${header.getSize()}px` }}\n\t\t\tclassName={enableSorting ? 'px-0' : 'px-2'}\n\t\t>\n\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t{enableSorting\n\t\t\t\t\t? (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'rounded-none',\n\t\t\t\t\t\t\t\t!header.column.getIsSorted() || header.column.getIsSorted() === 'asc'\n\t\t\t\t\t\t\t\t\t? 'cursor-n-resize'\n\t\t\t\t\t\t\t\t\t: 'cursor-s-resize',\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tonClick={onClickSort}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{content}\n\t\t\t\t\t\t\t{header.column.getIsSorted() === 'asc'\n\t\t\t\t\t\t\t\t? <ArrowUp />\n\t\t\t\t\t\t\t\t: header.column.getIsSorted() === 'desc'\n\t\t\t\t\t\t\t\t? <ArrowDown />\n\t\t\t\t\t\t\t\t: <ArrowUpDown className=\"text-gray-600\" />}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)\n\t\t\t\t\t: content}\n\t\t\t\t{enableResizing && (\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\tclassName=\"cursor-col-resize\"\n\t\t\t\t\t\tonMouseDown={header.getResizeHandler()} // for desktop\n\t\t\t\t\t\tonTouchStart={header.getResizeHandler()} // for mobile\n\t\t\t\t\t\tonDoubleClick={resetSize}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\ttransform: header.column.getIsResizing()\n\t\t\t\t\t\t\t\t? `translateX(${header.getContext().table.getState().columnSizingInfo.deltaOffset}px)`\n\t\t\t\t\t\t\t\t: '',\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<GripVerticalIcon />\n\t\t\t\t\t</Button>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</TableHead>\n\t);\n}\n\nexport function TableCell({ className, ...props }: React.ComponentProps<'td'>) {\n\treturn (\n\t\t<td\n\t\t\tdata-slot=\"table-cell\"\n\t\t\tclassName={cn(\n\t\t\t\t'align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport function TableCaption({ className, ...props }: React.ComponentProps<'caption'>) {\n\treturn (\n\t\t<caption data-slot=\"table-caption\" className={cn('text-muted-foreground mt-4 text-sm', className)} {...props} />\n\t);\n}\n","'use client';\n\nimport { Loading } from '@/components/Loading';\n\nimport { Table, TableBody, TableCell, TableHeader, TableHeadSortable, TableRow } from '@/components/ui/table';\nimport { cn } from '@/lib/cn';\nimport {\n\tColumnDef,\n\tflexRender,\n\tgetCoreRowModel,\n\tgetSortedRowModel,\n\tPaginationState,\n\tRow,\n\tSortingState,\n\tuseReactTable,\n} from '@tanstack/react-table';\nimport React, { Dispatch, SetStateAction } from 'react';\n\ninterface BrowseDataTableProps<TData, TValue> {\n\tcolumns: ColumnDef<TData, TValue>[];\n\tdata: TData[];\n\tisFetching?: boolean;\n\ttotalPages?: number;\n\ttotalRecords?: number;\n\tonRowClick?: (row: Row<TData>) => void;\n\tonColumnClick?: (accessorKey: string, isDescending: boolean) => void;\n\tpaginationState?: {\n\t\tpageIndex: number;\n\t\tpageSize: number;\n\t};\n\tsortingState?: SortingState;\n\tsetPagination?: Dispatch<SetStateAction<PaginationState>>;\n\tchildren?: React.ReactNode;\n}\n\nexport function SimpleBrowseDataTable<TData, TValue>({\n\tcolumns,\n\tdata,\n\tisFetching,\n\tonRowClick,\n\tonColumnClick,\n\tsortingState,\n\tchildren,\n}: BrowseDataTableProps<TData, TValue>) {\n\tconst table = useReactTable({\n\t\tdata,\n\t\tcolumns,\n\t\tgetCoreRowModel: getCoreRowModel(),\n\t\tgetSortedRowModel: getSortedRowModel(),\n\t\tinitialState: {\n\t\t\tsorting: sortingState,\n\t\t},\n\t});\n\n\treturn (\n\t\t<>\n\t\t\t<div className=\"flex items-center justify-end space-x-2 pb-4\">\n\t\t\t\t<div className=\"grow lg:hidden\"></div>\n\t\t\t\t{children}\n\t\t\t\t<div className=\"grow hidden lg:visible\"></div>\n\t\t\t</div>\n\t\t\t<Table containerClassName=\"rounded-md bg-black-dark\">\n\t\t\t\t<TableHeader>\n\t\t\t\t\t{table.getHeaderGroups().map((headerGroup) => (\n\t\t\t\t\t\t<TableRow key={headerGroup.id} className=\"border-none\">\n\t\t\t\t\t\t\t{headerGroup.headers.map((header) => (\n\t\t\t\t\t\t\t\t<TableHeadSortable key={header.id} header={header} onColumnClick={onColumnClick} />\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t))}\n\t\t\t\t</TableHeader>\n\t\t\t\t<TableBody className=\"bg-black border border-grey-700\">\n\t\t\t\t\t{table.getRowModel().rows?.length\n\t\t\t\t\t\t? (table.getRowModel().rows.map((row) => (\n\t\t\t\t\t\t\t<TableRow\n\t\t\t\t\t\t\t\tkey={row.id}\n\t\t\t\t\t\t\t\tdata-state={row.getIsSelected() && 'selected'}\n\t\t\t\t\t\t\t\tonClick={() => onRowClick?.(row)}\n\t\t\t\t\t\t\t\tclassName={cn('hover:bg-muted/10 data-[state=selected]:bg-muted', onRowClick && 'cursor-pointer')}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{row.getVisibleCells().map((cell) => (\n\t\t\t\t\t\t\t\t\t<TableCell\n\t\t\t\t\t\t\t\t\t\tkey={cell.id}\n\t\t\t\t\t\t\t\t\t\tclassName=\"py-2 px-2 overflow-x-hidden max-w-32 text-ellipsis whitespace-nowrap\"\n\t\t\t\t\t\t\t\t\t\tstyle={{ width: `${cell.column.getSize()}px` }}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{flexRender(cell.column.columnDef.cell, cell.getContext())}\n\t\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t\t)))\n\t\t\t\t\t\t: (\n\t\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t\t<TableCell colSpan={columns.length} className=\"h-24 text-center\">\n\t\t\t\t\t\t\t\t\t{isFetching\n\t\t\t\t\t\t\t\t\t\t? (\n\t\t\t\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t\t\t\t<Loading className=\"p-12\" />\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t: <span>No results.</span>}\n\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t\t)}\n\t\t\t\t</TableBody>\n\t\t\t</Table>\n\t\t</>\n\t);\n}\n","import { BadgeStatusVariantValues } from '@/components/ui/utils/badgeStatus';\n\nexport function translateStripeStatusToVariant(status?: string): BadgeStatusVariantValues {\n\tswitch (status) {\n\t\tcase 'paid':\n\t\t\treturn 'success';\n\t\tcase 'void':\n\t\tcase 'uncollectible':\n\t\t\treturn 'destructive';\n\t\tcase 'draft':\n\t\tcase 'open':\n\t\tdefault:\n\t\t\treturn 'default';\n\t}\n}\n","export function toUSD(input: number): string {\n\treturn new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(input);\n}\n","export function translateSecondsToAgo(secondsElapsed: number, timeMs: number): string {\n\t// Note: I used the boundaries that moment.js uses.\n\tif (secondsElapsed < 45) {\n\t\treturn 'a few seconds ago';\n\t}\n\tif (secondsElapsed < 120) {\n\t\treturn 'a minute ago';\n\t}\n\tconst minutesElapsed = Math.floor(secondsElapsed / 60);\n\tif (minutesElapsed < 60) {\n\t\treturn `${minutesElapsed} minutes ago`;\n\t}\n\tif (minutesElapsed < 120) {\n\t\treturn 'an hour ago';\n\t}\n\tconst hoursElapsed = Math.floor(secondsElapsed / 3600);\n\tif (hoursElapsed > 48) {\n\t\treturn new Date(timeMs).toLocaleString();\n\t}\n\treturn `${hoursElapsed} hours ago`;\n}\n","import { Badge } from '@/components/ui/badge';\nimport { SchemaInvoice, SchemaInvoiceLine } from '@/integrations/api/api.gen';\nimport { translateStripeStatusToVariant } from '@/integrations/stripe/translateStripeStatusToVariant';\nimport { toUSD } from '@/lib/toUSD';\nimport { translateSecondsToAgo } from '@/lib/translateSecondsToAgo';\nimport { ColumnDef } from '@tanstack/react-table';\n\nexport const dataTableColumns: Array<ColumnDef<SchemaInvoice>> = [\n\t{\n\t\theader: 'Invoice Id',\n\t\taccessorKey: 'id',\n\t\tenableSorting: false,\n\t},\n\t{\n\t\theader: 'Status',\n\t\taccessorKey: 'status',\n\t\tenableSorting: false,\n\t\tcell: ({ cell }) => (\n\t\t\t<Badge variant={translateStripeStatusToVariant(cell.getValue<string>())}>{cell.getValue<string>()}</Badge>\n\t\t),\n\t},\n\t{\n\t\theader: 'Date',\n\t\taccessorKey: 'periodStart',\n\t\tenableSorting: false,\n\t\tcell: ({ cell }) => {\n\t\t\tconst periodStart = cell.row.original.periodStart * 1000;\n\t\t\tconst periodEnd = cell.row.original.periodEnd * 1000;\n\t\t\tconst secondsSinceStart = (Date.now() - periodStart) / 1000;\n\t\t\tconst secondsSinceEnd = (Date.now() - periodEnd) / 1000;\n\t\t\tif (Math.abs(secondsSinceStart - secondsSinceEnd) < 1000) {\n\t\t\t\treturn translateSecondsToAgo(secondsSinceStart, periodStart);\n\t\t\t}\n\t\t\treturn [\n\t\t\t\tperiodStart ? translateSecondsToAgo(secondsSinceStart, periodStart) : '-',\n\t\t\t\tperiodEnd ? translateSecondsToAgo(secondsSinceEnd, periodEnd) : '-',\n\t\t\t].join(' to ');\n\t\t},\n\t},\n\t{\n\t\theader: 'Amount Due',\n\t\taccessorKey: 'amountDue',\n\t\tenableSorting: false,\n\t\tcell: ({ cell }) => toUSD(cell.getValue<number>() ? cell.getValue<number>() / 100 : 0),\n\t},\n\t{\n\t\theader: 'Amount Paid',\n\t\taccessorKey: 'amountPaid',\n\t\tenableSorting: false,\n\t\tcell: ({ cell }) => toUSD(cell.getValue<number>() ? cell.getValue<number>() / 100 : 0),\n\t},\n\t{\n\t\theader: 'Lines',\n\t\taccessorKey: 'lines',\n\t\tenableSorting: false,\n\t\tcell: ({ cell }) => {\n\t\t\tconst invoiceLines = cell.getValue<SchemaInvoiceLine[]>();\n\t\t\tconst formattedLines: string[] = [];\n\t\t\tfor (const invoiceLine of invoiceLines) {\n\t\t\t\tformattedLines.push(`${invoiceLine.quantity}x ${invoiceLine.description} @ ${toUSD(invoiceLine.amount / 100)}`);\n\t\t\t}\n\t\t\treturn formattedLines.join('\\n');\n\t\t},\n\t},\n];\n","import { sleep } from '@/lib/sleep';\nimport { useCallback } from 'react';\nimport { toast } from 'sonner';\n\nexport function useRefreshClick(refetch: () => Promise<unknown>) {\n\treturn useCallback(async () => {\n\t\ttoast.loading('Refreshing...', { id: 'refreshing' });\n\t\tconst startedAt = Date.now();\n\t\tawait refetch();\n\t\tif (Date.now() - startedAt < 500) {\n\t\t\tawait sleep(500);\n\t\t}\n\t\ttoast.success('Refreshed!', { id: 'refreshing' });\n\t}, [refetch]);\n}\n","import { apiClient } from '@/config/apiClient';\nimport { SchemaInvoice } from '@/integrations/api/api.gen';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport async function getStripeInvoices(organizationId: string): Promise<SchemaInvoice[]> {\n\tconst { data } = await apiClient.get(`/Invoice/${organizationId}` as `/Invoice/{id}`);\n\t// TODO: The API isn't able to describe this array result accurately yet.\n\treturn data as unknown as SchemaInvoice[];\n}\n\nexport function getStripeInvoicesQueryOptions(organizationId: string | undefined | false, refetch?: boolean) {\n\treturn queryOptions({\n\t\tqueryKey: [organizationId, 'invoices'],\n\t\tqueryFn: () => getStripeInvoices(organizationId as string),\n\t\tretry: false,\n\t\tenabled: !!organizationId,\n\t\trefetchInterval: refetch ? 10000 : undefined,\n\t});\n}\n","import { ContactUs } from '@/components/ContactUs';\nimport { Loading } from '@/components/Loading';\nimport { SimpleBrowseDataTable } from '@/components/SimpleBrowseDataTable';\nimport { Button } from '@/components/ui/button';\nimport { dataTableColumns } from '@/features/organization/billing/invoices/constants/tableDefinition';\nimport { getOrganizationQueryOptions } from '@/features/organization/queries/getOrganizationQuery';\nimport { useRefreshClick } from '@/hooks/useRefreshClick';\nimport { ENTERPRISE } from '@/integrations/api/orgType';\nimport { getStripeInvoicesQueryOptions } from '@/integrations/stripe/useGetStripeInvoices';\nimport { useQuery } from '@tanstack/react-query';\nimport { useParams } from '@tanstack/react-router';\nimport { RefreshCwIcon } from 'lucide-react';\n\nexport function Invoices() {\n\tconst { organizationId } = useParams({ strict: false });\n\tconst { data: organization } = useQuery(getOrganizationQueryOptions(organizationId));\n\tconst {\n\t\tdata,\n\t\trefetch,\n\t\tisLoading,\n\t\tisFetching,\n\t\tisRefetching,\n\t} = useQuery(getStripeInvoicesQueryOptions(organization?.type !== ENTERPRISE && organization?.id, false));\n\n\tconst onRefreshClick = useRefreshClick(refetch);\n\n\tif (organization?.type === ENTERPRISE) {\n\t\treturn (\n\t\t\t<span>\n\t\t\t\tYou are part of an enterprise organization! We don’t currently show your invoices on this page. Want to\n\t\t\t\texplore your solution with Harper more? <ContactUs />, we would love to talk!\n\t\t\t</span>\n\t\t);\n\t}\n\tif (isLoading) {\n\t\treturn <Loading centered />;\n\t}\n\tif (!data || !data.length) {\n\t\treturn (\n\t\t\t<span>\n\t\t\t\tYour invoices will be shown here once one is available! Want to explore your solution with Harper more?{' '}\n\t\t\t\t<ContactUs overEmail={true} />, we would love to talk!\n\t\t\t</span>\n\t\t);\n\t}\n\treturn (\n\t\t<SimpleBrowseDataTable data={data} columns={dataTableColumns}>\n\t\t\t<Button variant=\"defaultOutline\" onClick={onRefreshClick} accessKey=\"r\" disabled={isFetching || isRefetching}>\n\t\t\t\t<RefreshCwIcon />\n\t\t\t\t<span className=\"hidden lg:inline-block\">\n\t\t\t\t\t<u>R</u>efresh\n\t\t\t\t</span>\n\t\t\t</Button>\n\t\t</SimpleBrowseDataTable>\n\t);\n}\n","import type { orgLayoutRoute } from '@/features/organization/routes';\nimport { createRoute } from '@tanstack/react-router';\nimport { ConfirmSetupIntent } from './confirm/ConfirmSetupIntent';\nimport { OrgBillingIndex } from './index';\nimport { Invoices } from './invoices/Invoices';\nimport { PaymentMethodsDisplay } from './paymentMethod/PaymentMethodsDisplay';\n\nexport function createBillingRouteTree(parentRoute: typeof orgLayoutRoute) {\n\tconst rootRoute = createRoute({\n\t\tgetParentRoute: () => parentRoute,\n\t\tpath: 'billing',\n\t\tcomponent: OrgBillingIndex,\n\t});\n\tconst paymentMethodsRoute = createRoute({\n\t\tgetParentRoute: () => rootRoute,\n\t\tpath: '/',\n\t\tcomponent: PaymentMethodsDisplay,\n\t});\n\tconst invoicesRoute = createRoute({\n\t\tgetParentRoute: () => rootRoute,\n\t\tpath: 'invoices',\n\t\tcomponent: Invoices,\n\t});\n\tconst confirmRoute = createRoute({\n\t\tgetParentRoute: () => rootRoute,\n\t\tpath: 'confirm',\n\t\tcomponent: ConfirmSetupIntent,\n\t});\n\n\treturn rootRoute.addChildren([\n\t\tpaymentMethodsRoute,\n\t\tinvoicesRoute,\n\t\tconfirmRoute,\n\t]);\n}\n","import { apiClient } from '@/config/apiClient';\nimport { SchemaOrganizationRole } from '@/integrations/api/api.gen';\nimport { queryOptions } from '@tanstack/react-query';\n\nasync function getOrganizationRoles(organizationId: string): Promise<SchemaOrganizationRole[]> {\n\tconst { data } = await apiClient.get(`/OrganizationRole/${organizationId}` as '/OrganizationRole/'); // TODO: The API is not describing itself accurately.\n\treturn data;\n}\n\nexport function getOrganizationRolesQueryOptions(organizationId: string) {\n\treturn queryOptions({\n\t\tqueryKey: [organizationId, 'roles'],\n\t\tqueryFn: () => getOrganizationRoles(organizationId),\n\t\tretry: false,\n\t\trefetchInterval: 10 * 1000, // 10 seconds\n\t});\n}\n","import { SchemaOrganizationRole } from '@/integrations/api/api.gen';\nimport { ColumnDef, createColumnHelper } from '@tanstack/react-table';\n\nconst columnHelper = createColumnHelper<SchemaOrganizationRole>();\n\nexport const dataTableColumns: Array<ColumnDef<SchemaOrganizationRole>> = [\n\t{\n\t\theader: 'Role Name',\n\t\taccessorKey: 'roleName',\n\t\tenableSorting: false,\n\t},\n\tcolumnHelper.display({\n\t\theader: 'Users Assigned',\n\t\tenableSorting: false,\n\t\tid: 'userIds',\n\t\tcell: (props) => {\n\t\t\tif (!props.row.original.userIds || props.row.original.userIds.length === 0) {\n\t\t\t\treturn 'No users assigned';\n\t\t\t}\n\t\t\treturn props.row.original.userIds.length;\n\t\t},\n\t}),\n];\n","import { apiClient } from '@/config/apiClient';\nimport { useMutation } from '@tanstack/react-query';\nimport { OrganizationRoleUpdatePayloadType } from './OrganizationRoleFormSchema';\n\nexport async function onAddOrganizationRoleSubmit(formData: OrganizationRoleUpdatePayloadType) {\n\tconst { data } = await apiClient.post('/Role/', formData);\n\treturn data;\n}\n\nexport function useAddOrganizationRole() {\n\treturn useMutation({\n\t\tmutationFn: onAddOrganizationRoleSubmit,\n\t});\n}\n","import { z } from 'zod';\n\nexport const OrganizationRoleOverviewSchema = z.object({\n\tname: z\n\t\t.string()\n\t\t.nonempty({\n\t\t\terror: 'Please enter a role name.',\n\t\t})\n\t\t.regex(/^[a-zA-Z_]*$/, {\n\t\t\terror: 'Role must contain only letters and underscores.',\n\t\t})\n\t\t.max(30, { error: 'Role name cannot be longer than 30 characters.' }),\n\tupdate: z.boolean(),\n\tdelete: z.boolean(),\n});\n\nexport const OrganizationRoleSpecificPermissionsSchema = z.object({\n\troles: z.object({\n\t\tcreate: z.boolean(),\n\t\tdelete: z.boolean(),\n\t\tupdate: z.boolean(),\n\t\tview: z.boolean(),\n\t}),\n\tclusters: z.object({\n\t\tcreate: z.boolean(),\n\t\tdelete: z.boolean(),\n\t\tupdate: z.boolean(),\n\t\tview: z.boolean(),\n\t\tresources: z.array(z.object({\n\t\t\tid: z.string(),\n\t\t\tdelete: z.boolean(),\n\t\t\tupdate: z.boolean(),\n\t\t\tview: z.boolean(),\n\t\t\tinstances: z.object({\n\t\t\t\tcreate: z.boolean(),\n\t\t\t\tdelete: z.boolean(),\n\t\t\t\tupdate: z.boolean(),\n\t\t\t\tview: z.boolean(),\n\t\t\t}),\n\t\t})),\n\t}),\n});\n\nexport type OrganizationRoleUpdatePayloadType =\n\t& z.infer<typeof OrganizationRoleOverviewSchema>\n\t& z.infer<typeof OrganizationRoleSpecificPermissionsSchema>\n\t& { organizationId: string };\n\nexport type OrganizationRoleOverviewType = z.infer<typeof OrganizationRoleOverviewSchema>;\nexport type OrganizationRoleSpecificPermissionsType = z.infer<typeof OrganizationRoleSpecificPermissionsSchema>;\n","import { Button } from '@/components/ui/button';\nimport { Dialog, DialogContent, DialogDescription, DialogFooter, DialogTitle } from '@/components/ui/dialog';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { useAddOrganizationRole } from '@/features/organization/mutations/addOrganizationRole';\nimport {\n\tOrganizationRoleOverviewSchema,\n\tOrganizationRoleOverviewType,\n\tOrganizationRoleSpecificPermissionsType,\n\tOrganizationRoleUpdatePayloadType,\n} from '@/features/organization/mutations/OrganizationRoleFormSchema';\nimport { safeParse } from '@/lib/string/safeParse';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { Editor } from '@monaco-editor/react';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useParams } from '@tanstack/react-router';\nimport { useCallback, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\n\nconst defaultPermissions: OrganizationRoleSpecificPermissionsType = {\n\troles: {\n\t\tcreate: true,\n\t\tview: true,\n\t\tupdate: true,\n\t\tdelete: true,\n\t},\n\tclusters: {\n\t\tcreate: true,\n\t\tview: true,\n\t\tupdate: true,\n\t\tdelete: true,\n\t\tresources: [],\n\t},\n};\n\nexport function AddOrganizationRoleModal({\n\tisModalOpen,\n\tsetIsModalOpen,\n}: {\n\tisModalOpen: boolean;\n\tsetIsModalOpen: (isOpen: boolean) => void;\n}) {\n\tconst queryClient = useQueryClient();\n\tconst { organizationId }: { organizationId: string } = useParams({ strict: false });\n\tconst [isValidJSON, setIsValidJSON] = useState(true);\n\tconst [updatedPermissions, setUpdatedPermissions] = useState<string>(JSON.stringify(defaultPermissions, null, 2));\n\n\tconst { mutate: addOrganizationRole, isPending } = useAddOrganizationRole();\n\n\tconst form = useForm({\n\t\tresolver: zodResolver(OrganizationRoleOverviewSchema),\n\t\tdefaultValues: {\n\t\t\tname: '',\n\t\t\tupdate: false,\n\t\t\tdelete: false,\n\t\t},\n\t});\n\n\tconst onValidate = useCallback(\n\t\t(markers: unknown[]) => {\n\t\t\tsetIsValidJSON(markers.length === 0);\n\t\t},\n\t\t[setIsValidJSON],\n\t);\n\n\tconst onSubmitRoleEdits = useCallback(\n\t\tasync (formData: OrganizationRoleOverviewType) => {\n\t\t\tconst parsedPermissions = safeParse<OrganizationRoleSpecificPermissionsType>(updatedPermissions);\n\t\t\tif (!parsedPermissions) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst updatedFormData: OrganizationRoleUpdatePayloadType = {\n\t\t\t\t...formData,\n\t\t\t\t...parsedPermissions,\n\t\t\t\torganizationId: organizationId,\n\t\t\t};\n\t\t\tif (formData && isValidJSON) {\n\t\t\t\taddOrganizationRole(updatedFormData, {\n\t\t\t\t\tonSuccess: () => {\n\t\t\t\t\t\ttoast.success('Organization role added successfully!');\n\t\t\t\t\t\tsetIsModalOpen(false);\n\t\t\t\t\t\tvoid queryClient.invalidateQueries({\n\t\t\t\t\t\t\tqueryKey: [organizationId, 'roles'],\n\t\t\t\t\t\t\trefetchType: 'active',\n\t\t\t\t\t\t});\n\t\t\t\t\t\tform.reset();\n\t\t\t\t\t},\n\t\t\t\t\tonError: (error: Error) => {\n\t\t\t\t\t\ttoast.error(`Failed to add organization role: ${error.message}`);\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\t[isValidJSON, updatedPermissions, addOrganizationRole, form, queryClient, setIsModalOpen, organizationId],\n\t);\n\n\treturn (\n\t\t<Dialog onOpenChange={setIsModalOpen} open={isModalOpen}>\n\t\t\t<DialogContent>\n\t\t\t\t<DialogTitle>Add New Organization Role</DialogTitle>\n\t\t\t\t<DialogDescription>Set the new organization role permissions.</DialogDescription>\n\t\t\t\t<Form {...form}>\n\t\t\t\t\t<form\n\t\t\t\t\t\tid=\"org-add-role-form\"\n\t\t\t\t\t\tname=\"org-add-role-form\"\n\t\t\t\t\t\tclassName=\"grid grid-cols-2 gap-4 my-4\"\n\t\t\t\t\t\tonSubmit={form.handleSubmit(onSubmitRoleEdits)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"name\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem className=\"col-span-2\">\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Role Name</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input type=\"text\" className=\"\" {...field} />\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"update\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Can Update Organization</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"w-6 ml-2\"\n\t\t\t\t\t\t\t\t\t\t\tchecked={field.value}\n\t\t\t\t\t\t\t\t\t\t\tonChange={(e) => field.onChange(e.target.checked)}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"delete\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Can Delete Organization</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"w-6 ml-2\"\n\t\t\t\t\t\t\t\t\t\t\tchecked={field.value}\n\t\t\t\t\t\t\t\t\t\t\tonChange={(e) => field.onChange(e.target.checked)}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<div className=\"col-span-2\">\n\t\t\t\t\t\t\t<Editor\n\t\t\t\t\t\t\t\ttheme=\"vs-dark\"\n\t\t\t\t\t\t\t\theight=\"300px\"\n\t\t\t\t\t\t\t\tdefaultLanguage=\"json\"\n\t\t\t\t\t\t\t\tonValidate={onValidate}\n\t\t\t\t\t\t\t\tonChange={(value) => {\n\t\t\t\t\t\t\t\t\tif (value) {\n\t\t\t\t\t\t\t\t\t\tsetUpdatedPermissions(value);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tdefaultValue={JSON.stringify(defaultPermissions, null, 2)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<DialogFooter className=\"col-span-2\">\n\t\t\t\t\t\t\t<div className=\"flex justify-between w-full\">\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tvariant=\"destructiveOutline\"\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tonClick={() => setIsModalOpen(false)}\n\t\t\t\t\t\t\t\t\tdisabled={isPending}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tvariant=\"submit\"\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\t\tdisabled={isPending || !isValidJSON || !form.formState.isValid}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tSave Changes\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</DialogFooter>\n\t\t\t\t\t</form>\n\t\t\t\t</Form>\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { apiClient } from '@/config/apiClient';\nimport { useMutation } from '@tanstack/react-query';\n\nexport async function onDeleteOrganizationRole({ roleId }: { roleId: string }) {\n\tconst { data } = await apiClient.delete(`/Role/${roleId}` as '/Role/{id}', {\n\t\t// @ts-expect-error would love to figure this out\n\t\tid: roleId,\n\t\tdeleted: true,\n\t});\n\treturn data;\n}\n\nexport function useDeleteOrganizationRole() {\n\treturn useMutation<unknown, Error, { roleId: string }>({\n\t\tmutationFn: ({ roleId }: { roleId: string }) => onDeleteOrganizationRole({ roleId }),\n\t});\n}\n","import { apiClient } from '@/config/apiClient';\nimport { SchemaRole } from '@/integrations/api/api.gen';\nimport { useMutation } from '@tanstack/react-query';\nimport { OrganizationRoleUpdatePayloadType } from './OrganizationRoleFormSchema';\n\ninterface UpdateOrganizationRoleParams {\n\troleId: string;\n\tupdatedRoleInfo: OrganizationRoleUpdatePayloadType;\n}\n\nexport async function onUpdateOrganizationRole({\n\troleId,\n\tupdatedRoleInfo,\n}: UpdateOrganizationRoleParams) {\n\tconst { data } = await apiClient.put(`/Role/${roleId}` as '/Role/{id}', updatedRoleInfo);\n\treturn data as SchemaRole;\n}\n\nexport function useUpdateOrganizationRole() {\n\treturn useMutation<\n\t\tSchemaRole,\n\t\tError,\n\t\tUpdateOrganizationRoleParams\n\t>({\n\t\tmutationFn: ({ roleId, updatedRoleInfo }: UpdateOrganizationRoleParams) =>\n\t\t\tonUpdateOrganizationRole({ roleId, updatedRoleInfo }),\n\t});\n}\n","import { apiClient } from '@/config/apiClient';\nimport { SchemaRole } from '@/integrations/api/api.gen';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport interface GetOrganizationRoleInfoResponse extends SchemaRole {\n\tname: string;\n\torganizationId: string;\n}\n\nexport function getOrganizationRoleInfoQueryOptions({\n\torganizationId,\n\troleId,\n}: {\n\torganizationId: string;\n\troleId: string;\n}) {\n\treturn queryOptions({\n\t\tqueryKey: [organizationId, 'roles', roleId] as const,\n\t\tqueryFn: () => getOrganizationRoleInfo(roleId),\n\t\trefetchInterval: 10 * 1000,\n\t});\n}\n\nexport async function getOrganizationRoleInfo(roleId?: string) {\n\tconst { data } = await apiClient.get(`/Role/${roleId}` as '/Role/{id}');\n\treturn data as GetOrganizationRoleInfoResponse;\n}\n","import { Button } from '@/components/ui/button';\nimport { DialogDescription, DialogFooter, DialogTitle } from '@/components/ui/dialog';\n\nexport function ConfirmDeletionContent({\n\tonRoleDeleteClick,\n\tsetIsConfirmingRoleDeletion,\n\tisRoleDeletionPending,\n}: {\n\tonRoleDeleteClick: () => void;\n\tsetIsConfirmingRoleDeletion: (isOpen: boolean) => void;\n\tisRoleDeletionPending: boolean;\n}) {\n\treturn (\n\t\t<>\n\t\t\t<DialogTitle>Confirm Role Deletion</DialogTitle>\n\t\t\t<DialogDescription>Are you sure you want to delete this role? This action cannot be undone.</DialogDescription>\n\t\t\t<DialogFooter>\n\t\t\t\t<Button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tvariant=\"defaultOutline\"\n\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\tonClick={() => setIsConfirmingRoleDeletion(false)}\n\t\t\t\t>\n\t\t\t\t\tCancel\n\t\t\t\t</Button>\n\t\t\t\t<Button\n\t\t\t\t\tvariant=\"destructiveOutline\"\n\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\tonClick={onRoleDeleteClick}\n\t\t\t\t\tdisabled={isRoleDeletionPending}\n\t\t\t\t>\n\t\t\t\t\t{isRoleDeletionPending ? 'Deleting...' : 'Delete Role'}\n\t\t\t\t</Button>\n\t\t\t</DialogFooter>\n\t\t</>\n\t);\n}\n","import { Button } from '@/components/ui/button';\nimport { Dialog, DialogContent, DialogFooter, DialogTitle } from '@/components/ui/dialog';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { useDeleteOrganizationRole } from '@/features/organization/mutations/deleteOrganizationRole';\nimport {\n\tOrganizationRoleOverviewSchema,\n\tOrganizationRoleOverviewType,\n\tOrganizationRoleSpecificPermissionsType,\n\tOrganizationRoleUpdatePayloadType,\n} from '@/features/organization/mutations/OrganizationRoleFormSchema';\nimport { useUpdateOrganizationRole } from '@/features/organization/mutations/updateOrganizationRole';\nimport { getOrganizationRoleInfoQueryOptions } from '@/features/organization/queries/getOrganizationRoleInfo';\nimport { useCloudAuth } from '@/hooks/useAuth';\nimport { useOrganizationRolePermissions } from '@/hooks/usePermissions';\nimport { SchemaOrganizationRole } from '@/integrations/api/api.gen';\nimport { safeParse } from '@/lib/string/safeParse';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { Editor } from '@monaco-editor/react';\nimport { useQueryClient, useSuspenseQuery } from '@tanstack/react-query';\nimport { useCallback, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { ConfirmDeletionContent } from './ConfirmDeletionContent';\n\nexport function EditOrganizationRoleModal({\n\tdata,\n\tisModalOpen,\n\tcloseModal,\n}: {\n\tdata: SchemaOrganizationRole;\n\tisModalOpen: boolean;\n\tcloseModal: (madeChanges: boolean) => void;\n}) {\n\tconst queryClient = useQueryClient();\n\tconst { data: roleInfo } = useSuspenseQuery(\n\t\tgetOrganizationRoleInfoQueryOptions({ roleId: data.id, organizationId: data.organizationId }),\n\t);\n\tconst auth = useCloudAuth();\n\tconst isSelf = auth.user && auth.user?.roles?.[data.organizationId]?.role === data.roleName;\n\tconst { update, remove } = useOrganizationRolePermissions(data.organizationId);\n\tconst { mutate: updateOrganizationRole, isPending: isRoleUpdatePending } = useUpdateOrganizationRole();\n\tconst { mutate: deleteOrganizationRole, isPending: isRoleDeletionPending } = useDeleteOrganizationRole();\n\n\tconst [isConfirmingRoleDeletion, setIsConfirmingRoleDeletion] = useState(false);\n\n\tconst form = useForm({\n\t\tresolver: zodResolver(OrganizationRoleOverviewSchema),\n\t\tdefaultValues: {\n\t\t\tname: data.roleName,\n\t\t\tupdate: roleInfo.organization.update || false,\n\t\t\tdelete: roleInfo.organization.delete || false,\n\t\t},\n\t});\n\n\tconst onRoleDeleteClick = useCallback(() => {\n\t\tdeleteOrganizationRole(\n\t\t\t{ roleId: data.id },\n\t\t\t{\n\t\t\t\tonSuccess: () => {\n\t\t\t\t\ttoast.success('Role deleted successfully!');\n\t\t\t\t\tcloseModal(true);\n\t\t\t\t\tform.reset();\n\t\t\t\t},\n\t\t\t\tonError: (error: Error | unknown) => {\n\t\t\t\t\ttoast.error('Error', {\n\t\t\t\t\t\tdescription: `Failed to delete role: ${error instanceof Error ? error.message : String(error)}.`,\n\t\t\t\t\t\taction: {\n\t\t\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}, [data.id, deleteOrganizationRole, form, closeModal]);\n\n\tconst [isValidJSON, setIsValidJSON] = useState(true);\n\tconst [updatedPermissions, setUpdatedPermissions] = useState<string>(\n\t\tJSON.stringify(\n\t\t\t{\n\t\t\t\troles: { ...roleInfo.organization.roles },\n\t\t\t\tclusters: { ...roleInfo.organization.clusters },\n\t\t\t} satisfies OrganizationRoleSpecificPermissionsType,\n\t\t\tnull,\n\t\t\t2,\n\t\t),\n\t);\n\n\tconst onValidate = useCallback(\n\t\t(markers: unknown[]) => {\n\t\t\tsetIsValidJSON(markers.length === 0);\n\t\t},\n\t\t[setIsValidJSON],\n\t);\n\n\tconst onSubmitRoleEdits = useCallback(\n\t\tasync (formData: OrganizationRoleOverviewType) => {\n\t\t\tif (!update) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst parsedPermissions = safeParse<OrganizationRoleSpecificPermissionsType>(updatedPermissions);\n\t\t\tif (!parsedPermissions) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst updatedFormData: OrganizationRoleUpdatePayloadType = {\n\t\t\t\t...formData,\n\t\t\t\t...parsedPermissions,\n\t\t\t\torganizationId: data.organizationId,\n\t\t\t};\n\n\t\t\tif (updatedPermissions && isValidJSON) {\n\t\t\t\tupdateOrganizationRole(\n\t\t\t\t\t{\n\t\t\t\t\t\troleId: data.id,\n\t\t\t\t\t\tupdatedRoleInfo: updatedFormData,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tonSuccess: async () => {\n\t\t\t\t\t\t\ttoast.success('Role updated successfully!');\n\t\t\t\t\t\t\tawait queryClient.invalidateQueries({\n\t\t\t\t\t\t\t\tqueryKey: [data.organizationId, 'roles', data.id],\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tcloseModal(false);\n\t\t\t\t\t\t\tform.reset();\n\t\t\t\t\t\t},\n\t\t\t\t\t\tonError: (error: Error | unknown) => {\n\t\t\t\t\t\t\ttoast.error('Error', {\n\t\t\t\t\t\t\t\tdescription: `Failed to update role: ${error instanceof Error ? error.message : String(error)}.`,\n\t\t\t\t\t\t\t\taction: {\n\t\t\t\t\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\tcloseModal,\n\t\t\tdata.id,\n\t\t\tdata.organizationId,\n\t\t\tform,\n\t\t\tisValidJSON,\n\t\t\tqueryClient,\n\t\t\troleInfo,\n\t\t\tupdate,\n\t\t\tupdatedPermissions,\n\t\t\tupdateOrganizationRole,\n\t\t],\n\t);\n\n\tconst onOpenChanges = useCallback(() => closeModal(false), [closeModal]);\n\n\treturn (\n\t\t<Dialog onOpenChange={onOpenChanges} open={isModalOpen}>\n\t\t\t<DialogContent>\n\t\t\t\t{isConfirmingRoleDeletion\n\t\t\t\t\t? (\n\t\t\t\t\t\t<ConfirmDeletionContent\n\t\t\t\t\t\t\tonRoleDeleteClick={onRoleDeleteClick}\n\t\t\t\t\t\t\tsetIsConfirmingRoleDeletion={setIsConfirmingRoleDeletion}\n\t\t\t\t\t\t\tisRoleDeletionPending={isRoleDeletionPending}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)\n\t\t\t\t\t: (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<DialogTitle>{isSelf || !update ? 'View' : 'Edit'} Organization Role \"{data.roleName}\"</DialogTitle>\n\t\t\t\t\t\t\t<Form {...form}>\n\t\t\t\t\t\t\t\t<form\n\t\t\t\t\t\t\t\t\tid=\"org-edit-role-form\"\n\t\t\t\t\t\t\t\t\tname=\"org-edit-role-form\"\n\t\t\t\t\t\t\t\t\tclassName=\"grid grid-cols-2 gap-4 my-4\"\n\t\t\t\t\t\t\t\t\tonSubmit={form.handleSubmit(onSubmitRoleEdits)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\t\t\t\tname=\"name\"\n\t\t\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t\t\t<FormItem className=\"col-span-2\">\n\t\t\t\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Role Name</FormLabel>\n\t\t\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={true}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treadOnly={true}\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\t\t\t\tname=\"update\"\n\t\t\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Can Update Organization</FormLabel>\n\t\t\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"w-6 ml-2\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={isSelf || !update}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treadOnly={isSelf || !update}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tchecked={field.value}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonChange={(e) => field.onChange(e.target.checked)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\t\t\t\tname=\"delete\"\n\t\t\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Can Delete Organization</FormLabel>\n\t\t\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"w-6 ml-2\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={isSelf || !update}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treadOnly={isSelf || !update}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tchecked={field.value}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonChange={(e) => field.onChange(e.target.checked)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t<div className=\"col-span-2\">\n\t\t\t\t\t\t\t\t\t\t<Editor\n\t\t\t\t\t\t\t\t\t\t\ttheme=\"vs-dark\"\n\t\t\t\t\t\t\t\t\t\t\theight=\"300px\"\n\t\t\t\t\t\t\t\t\t\t\tdefaultLanguage=\"json\"\n\t\t\t\t\t\t\t\t\t\t\tonValidate={onValidate}\n\t\t\t\t\t\t\t\t\t\t\tonChange={(value) => {\n\t\t\t\t\t\t\t\t\t\t\t\tif (value) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tsetUpdatedPermissions(value);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\toptions={isSelf || !update ? { readOnly: true } : undefined}\n\t\t\t\t\t\t\t\t\t\t\tdefaultValue={updatedPermissions}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t{(!isSelf && (remove || update)) && (\n\t\t\t\t\t\t\t\t\t\t<DialogFooter className=\"col-span-2\">\n\t\t\t\t\t\t\t\t\t\t\t<div className=\"flex justify-between w-full\">\n\t\t\t\t\t\t\t\t\t\t\t\t{remove && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"destructiveOutline\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => setIsConfirmingRoleDeletion(true)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={isRoleUpdatePending}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tDelete Role\n\t\t\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t{update && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"submit\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={!isValidJSON || isRoleUpdatePending || !form.formState.isValid\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t|| !form.formState.isDirty}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tSave Changes\n\t\t\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</DialogFooter>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t\t</Form>\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { Loading } from '@/components/Loading';\nimport { SimpleBrowseDataTable } from '@/components/SimpleBrowseDataTable';\nimport { SubNavMenu } from '@/components/SubNavMenu';\nimport { Button } from '@/components/ui/button';\nimport { getOrganizationRolesQueryOptions } from '@/features/organization/queries/getOrganizationRoles';\nimport { useOrganizationRolePermissions } from '@/hooks/usePermissions';\nimport { useRefreshClick } from '@/hooks/useRefreshClick';\nimport { SchemaOrganizationRole } from '@/integrations/api/api.gen';\nimport { useQueryClient, useSuspenseQuery } from '@tanstack/react-query';\nimport { useNavigate, useParams } from '@tanstack/react-router';\nimport { Row } from '@tanstack/react-table';\nimport { PlusIcon, RefreshCwIcon } from 'lucide-react';\nimport { Suspense, useCallback, useMemo, useState } from 'react';\nimport { dataTableColumns } from './constants/tableDefinition';\nimport { AddOrganizationRoleModal } from './modals/AddOrganizationRoleModal';\nimport { EditOrganizationRoleModal } from './modals/EditOrganizationRoleModal';\n\nexport function OrgConfigRolesIndex() {\n\tconst navigate = useNavigate();\n\tconst queryClient = useQueryClient();\n\n\tconst { organizationId, orgRoleId }: { organizationId: string; orgRoleId?: string } = useParams({ strict: false });\n\tconst { create } = useOrganizationRolePermissions(organizationId);\n\n\tconst {\n\t\tdata: orgRoles,\n\t\trefetch,\n\t\tisFetching,\n\t\tisRefetching,\n\t} = useSuspenseQuery(getOrganizationRolesQueryOptions(organizationId));\n\n\tconst selectedOrgRole = useMemo(\n\t\t() => orgRoles && orgRoles?.find((role) => role.id === orgRoleId),\n\t\t[orgRoles, orgRoleId],\n\t);\n\n\tconst isEditOrgRoleModalOpen = !!orgRoleId && !!selectedOrgRole;\n\n\tconst [isAddModalOpen, setIsAddModalOpen] = useState(false);\n\n\tconst onSelectOrgRole = useCallback(\n\t\tasync (newOrgRole: string | undefined, madeChanges: boolean) => {\n\t\t\tconst parts = [orgRoleId ? '..' : '', newOrgRole].filter(Boolean);\n\t\t\tawait navigate({ to: parts.join('/') });\n\t\t\tif (madeChanges) {\n\t\t\t\tawait queryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: [organizationId, 'roles'],\n\t\t\t\t\trefetchType: 'active',\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\t[orgRoleId, navigate, queryClient],\n\t);\n\n\tconst onAddClicked = useCallback(() => {\n\t\tsetIsAddModalOpen(true);\n\t}, [setIsAddModalOpen]);\n\n\tconst onRowClick = useCallback(\n\t\t(rowData: Row<SchemaOrganizationRole>) => {\n\t\t\treturn onSelectOrgRole(rowData.original.id, false);\n\t\t},\n\t\t[onSelectOrgRole],\n\t);\n\n\tconst closeEditModal = useCallback((madeChanges: boolean) => {\n\t\treturn onSelectOrgRole(undefined, madeChanges);\n\t}, [onSelectOrgRole]);\n\n\tconst onRefreshClick = useRefreshClick(refetch);\n\n\treturn (\n\t\t<>\n\t\t\t<SubNavMenu />\n\t\t\t<div className=\"mt-32 px-4 pt-4 md:px-12 min-h-[calc(100vh-(--spacing(32)))]\">\n\t\t\t\t<Suspense fallback={<Loading className=\"flex flex-col items-center justify-center h-full\" text=\"Loading...\" />}>\n\t\t\t\t\t<SimpleBrowseDataTable data={orgRoles} columns={dataTableColumns} onRowClick={onRowClick}>\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"defaultOutline\"\n\t\t\t\t\t\t\tonClick={onRefreshClick}\n\t\t\t\t\t\t\taccessKey=\"r\"\n\t\t\t\t\t\t\tdisabled={isFetching || isRefetching}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<RefreshCwIcon />\n\t\t\t\t\t\t\t<span className=\"hidden lg:inline-block\">\n\t\t\t\t\t\t\t\t<u>R</u>efresh\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t{create && (\n\t\t\t\t\t\t\t<Button variant=\"positiveOutline\" onClick={onAddClicked} accessKey=\"a\" disabled={isAddModalOpen}>\n\t\t\t\t\t\t\t\t<PlusIcon />\n\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t<u>A</u>dd\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</SimpleBrowseDataTable>\n\t\t\t\t\t{create && (\n\t\t\t\t\t\t<AddOrganizationRoleModal\n\t\t\t\t\t\t\tisModalOpen={isAddModalOpen}\n\t\t\t\t\t\t\tsetIsModalOpen={setIsAddModalOpen}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t\t{isEditOrgRoleModalOpen && (\n\t\t\t\t\t\t<EditOrganizationRoleModal\n\t\t\t\t\t\t\tdata={selectedOrgRole}\n\t\t\t\t\t\t\tisModalOpen={isEditOrgRoleModalOpen}\n\t\t\t\t\t\t\tcloseModal={closeEditModal}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</Suspense>\n\t\t\t</div>\n\t\t</>\n\t);\n}\n","import { SchemaUser } from '@/integrations/api/api.gen';\nimport { ColumnDef, createColumnHelper } from '@tanstack/react-table';\n\nconst columnHelper = createColumnHelper<SchemaUser>();\n\nexport const dataTableColumns: Array<ColumnDef<SchemaUser>> = [\n\t{\n\t\theader: 'User Id',\n\t\taccessorKey: 'id',\n\t\tenableSorting: false,\n\t},\n\t{\n\t\theader: 'Email',\n\t\taccessorKey: 'email',\n\t\tenableSorting: false,\n\t},\n\t{\n\t\theader: 'First Name',\n\t\taccessorKey: 'firstname',\n\t\tenableSorting: false,\n\t},\n\t{\n\t\theader: 'Last Name',\n\t\taccessorKey: 'lastname',\n\t\tenableSorting: false,\n\t},\n\tcolumnHelper.display({\n\t\theader: 'Roles',\n\t\tenableSorting: false,\n\t\tid: 'roles',\n\t\tcell: (props) => props.row.original.roles?.map(r => r.roleName)?.sort()?.join(', '),\n\t}),\n\t{\n\t\theader: 'Status',\n\t\taccessorKey: 'status',\n\t\tenableSorting: false,\n\t},\n\t{\n\t\theader: 'Verified',\n\t\taccessorKey: 'isVerified',\n\t\tenableSorting: false,\n\t},\n];\n","import { apiClient } from '@/config/apiClient';\nimport { zodRequireEmail } from '@/lib/zod/email';\nimport { useMutation } from '@tanstack/react-query';\nimport z from 'zod';\n\nexport const AddOrganizationRoleSchema = z.object({\n\temail: zodRequireEmail\n\t\t.max(80, { error: 'Email cannot be longer than 80 characters.' }),\n\troleId: z.string().nonempty({ error: 'Please select a role.' }),\n});\n\nexport async function onAddUserToOrganizationRoleSubmit(formData: z.infer<typeof AddOrganizationRoleSchema>) {\n\tconst { data } = await apiClient.post('/OrganizationRole/', formData);\n\treturn data;\n}\n\nexport function useAddUserToOrganizationRole() {\n\treturn useMutation({\n\t\tmutationFn: (formData: z.infer<typeof AddOrganizationRoleSchema>) => onAddUserToOrganizationRoleSubmit(formData),\n\t});\n}\n","import { apiClient } from '@/config/apiClient';\nimport { zodRequireEmail } from '@/lib/zod/email';\nimport { useMutation } from '@tanstack/react-query';\nimport z from 'zod';\n\nexport const InviteOrganizationRoleSchema = z.object({\n\temail: zodRequireEmail\n\t\t.max(80, { error: 'Email cannot be longer than 80 characters.' }),\n\troleId: z.string().nonempty({ error: 'Please select a role.' }),\n});\n\nexport async function onInviteUserToOrganizationRoleSubmit(formData: z.infer<typeof InviteOrganizationRoleSchema>) {\n\tconst { data } = await apiClient.post('/UserInvite/', formData);\n\treturn data;\n}\n\nexport function useInviteUserToOrganizationRole() {\n\treturn useMutation({\n\t\tmutationFn: (formData: z.infer<typeof InviteOrganizationRoleSchema>) =>\n\t\t\tonInviteUserToOrganizationRoleSubmit(formData),\n\t});\n}\n","import { TextLoadingSkeleton } from '@/components/TextLoadingSkeleton';\nimport { Button } from '@/components/ui/button';\nimport {\n\tDialog,\n\tDialogContent,\n\tDialogDescription,\n\tDialogFooter,\n\tDialogHeader,\n\tDialogTitle,\n} from '@/components/ui/dialog';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport {\n\tSelect,\n\tSelectContent,\n\tSelectGroup,\n\tSelectItem,\n\tSelectLabel,\n\tSelectTrigger,\n\tSelectValue,\n} from '@/components/ui/select';\nimport {\n\tAddOrganizationRoleSchema,\n\tuseAddUserToOrganizationRole,\n} from '@/features/organization/mutations/addUserToOrganizationRole';\nimport { useInviteUserToOrganizationRole } from '@/features/organization/mutations/inviteUserToOrganizationRole';\nimport { getOrganizationRolesQueryOptions } from '@/features/organization/queries/getOrganizationRoles';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useSuspenseQuery } from '@tanstack/react-query';\nimport { useParams } from '@tanstack/react-router';\nimport { AxiosError } from 'axios';\nimport { MailWarningIcon, Save } from 'lucide-react';\nimport { Suspense, useCallback, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\n\nexport function AddUserModal({\n\tisModalOpen,\n\tonChangesSaved,\n\tsetIsModalOpen,\n}: {\n\tisModalOpen: boolean;\n\tonChangesSaved: () => void;\n\tsetIsModalOpen: (open: boolean) => void;\n}) {\n\tconst { organizationId }: { organizationId: string } = useParams({ strict: false });\n\tconst { data: orgRoles } = useSuspenseQuery(getOrganizationRolesQueryOptions(organizationId));\n\tconst [shouldInvite, setShouldInvite] = useState(false);\n\n\tconst form = useForm({\n\t\tresolver: zodResolver(AddOrganizationRoleSchema),\n\t\tdefaultValues: {\n\t\t\temail: '',\n\t\t\troleId: '',\n\t\t},\n\t});\n\tconst { mutate: addUser, isPending: isAddPending } = useAddUserToOrganizationRole();\n\tconst { mutate: inviteUser, isPending: isInvitePending } = useInviteUserToOrganizationRole();\n\n\tconst onSubmitClick = useCallback(\n\t\tasync (formData: z.infer<typeof AddOrganizationRoleSchema>) => {\n\t\t\tif (formData) {\n\t\t\t\t(shouldInvite ? inviteUser : addUser)(formData, {\n\t\t\t\t\tonSuccess: () => {\n\t\t\t\t\t\tconst lastRole = formData.roleId;\n\t\t\t\t\t\tform.reset();\n\t\t\t\t\t\t// Persist the selected role if they open the form again.\n\t\t\t\t\t\tform.setValue('roleId', lastRole);\n\t\t\t\t\t\tonChangesSaved();\n\t\t\t\t\t\ttoast.success('User invited successfully!');\n\t\t\t\t\t\tsetIsModalOpen(false);\n\t\t\t\t\t\tsetShouldInvite(false);\n\t\t\t\t\t},\n\t\t\t\t\tonError: (error) => {\n\t\t\t\t\t\tif ((error as AxiosError)?.status === 404) {\n\t\t\t\t\t\t\tsetShouldInvite(true);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\t[addUser, form, inviteUser, onChangesSaved, setIsModalOpen, shouldInvite],\n\t);\n\n\treturn (\n\t\t<Dialog\n\t\t\tonOpenChange={() => {\n\t\t\t\tsetIsModalOpen(false);\n\t\t\t\tsetShouldInvite(false);\n\t\t\t\tform.reset();\n\t\t\t}}\n\t\t\topen={isModalOpen}\n\t\t>\n\t\t\t<DialogContent aria-describedby={undefined}>\n\t\t\t\t<Form {...form}>\n\t\t\t\t\t<form\n\t\t\t\t\t\tid=\"org-add-user-form\"\n\t\t\t\t\t\tname=\"org-add-user-form\"\n\t\t\t\t\t\tonSubmit={form.handleSubmit(onSubmitClick)}\n\t\t\t\t\t\tclassName=\"grid gap-4 my-4\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<DialogHeader>\n\t\t\t\t\t\t\t<DialogTitle>{shouldInvite ? 'Invite User' : 'Add User'}</DialogTitle>\n\t\t\t\t\t\t</DialogHeader>\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"email\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Email</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input type=\"email\" enterKeyHint=\"next\" autoComplete=\"email\" {...field} />\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"roleId\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Roles</FormLabel>\n\n\t\t\t\t\t\t\t\t\t<Suspense fallback={<TextLoadingSkeleton />}>\n\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t<Select {...field} onValueChange={(role) => field.onChange(role)}>\n\t\t\t\t\t\t\t\t\t\t\t\t<SelectTrigger className=\"w-full\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectValue placeholder=\"Choose Role\" />\n\t\t\t\t\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectGroup>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{/*TODO: Multi select*/}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectLabel>Role</SelectLabel>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{orgRoles?.map((role) => (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectItem key={role.id} value={role.id}>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{role.roleName}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</SelectGroup>\n\t\t\t\t\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t</Suspense>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t{shouldInvite && (\n\t\t\t\t\t\t\t<DialogDescription className=\"p-3 my-5 text-white rounded-md bg-amber-600 flex\">\n\t\t\t\t\t\t\t\t<MailWarningIcon className=\"inline-block size-12 pr-2\" />\n\t\t\t\t\t\t\t\t<span>This person doesn’t have a Fabric account. Do you want to invite them?</span>\n\t\t\t\t\t\t\t</DialogDescription>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t<DialogFooter>\n\t\t\t\t\t\t\t<div className=\"flex justify-between w-full\">\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\t\tvariant=\"submit\"\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\t\tdisabled={isAddPending || isInvitePending}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Save /> {shouldInvite ? 'Invite User' : 'Add User'}\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</DialogFooter>\n\t\t\t\t\t</form>\n\t\t\t\t</Form>\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { apiClient } from '@/config/apiClient';\nimport { useMutation } from '@tanstack/react-query';\n\nexport async function onRemoveUserFromOrganizationRole({ roleId, userId }: { roleId: string; userId: string }) {\n\t// TODO: The API doesn't describe this endpoint in its docs.\n\tconst { data } = await apiClient.delete(\n\t\t`/OrganizationRole/role/${roleId}/user/${userId}` as '/OrganizationRole/{id}',\n\t);\n\treturn data;\n}\n\nexport function useRemoveUserFromOrganizationRole() {\n\treturn useMutation<unknown, Error, { roleId: string; userId: string }>({\n\t\tmutationFn: ({ roleId, userId }: {\n\t\t\troleId: string;\n\t\t\tuserId: string;\n\t\t}) => onRemoveUserFromOrganizationRole({ roleId, userId }),\n\t});\n}\n","import { ChangeEvent, useCallback, useState } from 'react';\n\nexport function useCheckboxCallback(defaultValue?: boolean) {\n\tconst [state, setState] = useState<boolean>(defaultValue || false);\n\tconst onClick = useCallback((e: boolean | ChangeEvent<HTMLInputElement>) => {\n\t\tsetState(typeof e === 'boolean' ? e : e.target.checked);\n\t}, []);\n\treturn [state, onClick] as const;\n}\n","import { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\nimport { useAddUserToOrganizationRole } from '@/features/organization/mutations/addUserToOrganizationRole';\nimport { useRemoveUserFromOrganizationRole } from '@/features/organization/mutations/removeUserFromOrganizationRole';\nimport { useCheckboxCallback } from '@/hooks/useCheckboxCallback';\nimport { SchemaOrganizationRole, SchemaUser } from '@/integrations/api/api.gen';\nimport { useEffect, useState } from 'react';\nimport { toast } from 'sonner';\n\nexport function OrgUserRoleCheckbox({\n\tdata,\n\treadOnly,\n\tcanRemove,\n\torgRole,\n\tselectedRoles,\n\tsetChangesMade,\n}: {\n\tdata: SchemaUser;\n\treadOnly: boolean;\n\tcanRemove: boolean;\n\torgRole: SchemaOrganizationRole;\n\tselectedRoles: Record<string, SchemaOrganizationRole>;\n\tsetChangesMade: (value: boolean) => void;\n}) {\n\tconst { mutate: addUser, isPending: isAddPending } = useAddUserToOrganizationRole();\n\tconst { mutate: removeUser, isPending: isRemovePending } = useRemoveUserFromOrganizationRole();\n\tconst userIsInRole = !!selectedRoles[orgRole.roleName];\n\tconst [wasChecked, setWasChecked] = useState(userIsInRole);\n\tconst [isChecked, onCheckedChanged] = useCheckboxCallback(userIsInRole);\n\tuseEffect(() => {\n\t\tif (isChecked !== wasChecked) {\n\t\t\tif (isChecked) {\n\t\t\t\taddUser(\n\t\t\t\t\t{ email: data.email, roleId: orgRole.id },\n\t\t\t\t\t{\n\t\t\t\t\t\tonSuccess: () => {\n\t\t\t\t\t\t\tsetWasChecked(isChecked);\n\t\t\t\t\t\t\tsetChangesMade(true);\n\t\t\t\t\t\t\ttoast.success(`Role added successfully`);\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tremoveUser(\n\t\t\t\t\t{ userId: data.id, roleId: orgRole.id },\n\t\t\t\t\t{\n\t\t\t\t\t\tonSuccess: () => {\n\t\t\t\t\t\t\tsetWasChecked(isChecked);\n\t\t\t\t\t\t\tsetChangesMade(true);\n\t\t\t\t\t\t\ttoast.success(`Role removed successfully`);\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}, [addUser, data.email, data.id, isChecked, orgRole.id, removeUser, setChangesMade, wasChecked]);\n\n\treturn (\n\t\t<Label key={orgRole.id} className=\"flex\">\n\t\t\t<Input\n\t\t\t\ttype=\"checkbox\"\n\t\t\t\tclassName=\"w-6\"\n\t\t\t\tdisabled={readOnly || isAddPending || isRemovePending || (!canRemove && isChecked)}\n\t\t\t\tchecked={isChecked}\n\t\t\t\tonChange={onCheckedChanged}\n\t\t\t/>\n\t\t\t<span className=\"pl-4 pr-8 flex-1 py-2.5\">{orgRole.roleName}</span>\n\t\t</Label>\n\t);\n}\n","import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog';\nimport { getOrganizationRolesQueryOptions } from '@/features/organization/queries/getOrganizationRoles';\nimport { OrgUserRoleCheckbox } from '@/features/organization/users/components/OrgUserRoleCheckbox';\nimport { useCloudAuth } from '@/hooks/useAuth';\nimport { useOrganizationRolePermissions } from '@/hooks/usePermissions';\nimport { SchemaUser } from '@/integrations/api/api.gen';\nimport { keyBy } from '@/lib/keyBy';\nimport { useSuspenseQuery } from '@tanstack/react-query';\nimport { useParams } from '@tanstack/react-router';\nimport { useMemo, useState } from 'react';\n\nexport function EditUserModal({\n\tcloseModal,\n\tdata,\n\tisModalOpen,\n\tonUserUpdated,\n}: {\n\tcloseModal: () => void;\n\tdata: SchemaUser;\n\tisModalOpen: boolean;\n\tonUserUpdated: () => void;\n}) {\n\tconst { organizationId }: { organizationId: string } = useParams({ strict: false });\n\tconst auth = useCloudAuth();\n\tconst { update, remove } = useOrganizationRolePermissions(organizationId);\n\tconst isSelf = auth.user?.email === data.email;\n\tconst { data: orgRoles } = useSuspenseQuery(getOrganizationRolesQueryOptions(organizationId));\n\tconst selectedRoles = useMemo(() => data.roles ? keyBy(data.roles, 'roleName') : {}, [data]);\n\tconst [changesMade, setChangesMade] = useState<boolean>(false);\n\n\t// TODO: Cancel invite\n\treturn (\n\t\t<Dialog onOpenChange={changesMade ? onUserUpdated : closeModal} open={isModalOpen}>\n\t\t\t<DialogContent className=\"sm:max-w-[750px]\">\n\t\t\t\t<DialogHeader>\n\t\t\t\t\t<DialogTitle>{update ? 'Edit ' : 'View '} {data.email} {isSelf ? '(yourself)' : ''}</DialogTitle>\n\t\t\t\t</DialogHeader>\n\n\t\t\t\t{update && (\n\t\t\t\t\t<DialogDescription>\n\t\t\t\t\t\tTo remove {isSelf ? 'your self' : 'this user'} from the organization, uncheck all of the boxes below.\n\t\t\t\t\t</DialogDescription>\n\t\t\t\t)}\n\n\t\t\t\t{orgRoles.map((orgRole) => (\n\t\t\t\t\t<OrgUserRoleCheckbox\n\t\t\t\t\t\tkey={orgRole.id}\n\t\t\t\t\t\treadOnly={!update}\n\t\t\t\t\t\tcanRemove={remove}\n\t\t\t\t\t\tdata={data}\n\t\t\t\t\t\torgRole={orgRole}\n\t\t\t\t\t\tselectedRoles={selectedRoles}\n\t\t\t\t\t\tsetChangesMade={setChangesMade}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","export function sortByEmail(a: { email: string }, b: { email: string }) {\n\treturn a.email > b.email ? 1 : -1;\n}\n","import { Loading } from '@/components/Loading';\nimport { SimpleBrowseDataTable } from '@/components/SimpleBrowseDataTable';\nimport { SubNavMenu } from '@/components/SubNavMenu';\nimport { Button } from '@/components/ui/button';\nimport { getOrganizationRolesQueryOptions } from '@/features/organization/queries/getOrganizationRoles';\nimport { dataTableColumns } from '@/features/organization/users/constants/tableDefinition';\nimport { AddUserModal } from '@/features/organization/users/modals/AddUserModal';\nimport { EditUserModal } from '@/features/organization/users/modals/EditUserModal';\nimport { useOrganizationRolePermissions } from '@/hooks/usePermissions';\nimport { useRefreshClick } from '@/hooks/useRefreshClick';\nimport { SchemaUser } from '@/integrations/api/api.gen';\nimport { sortByEmail } from '@/lib/arrays/sort/byEmail';\nimport { useSuspenseQuery } from '@tanstack/react-query';\nimport { useNavigate, useParams } from '@tanstack/react-router';\nimport { Row } from '@tanstack/react-table';\nimport { PlusIcon, RefreshCwIcon } from 'lucide-react';\nimport { Suspense, useCallback, useMemo, useState } from 'react';\n\nexport function OrgConfigUsersIndex() {\n\tconst navigate = useNavigate();\n\tconst { organizationId, orgUserId }: { organizationId: string; orgUserId?: string } = useParams({ strict: false });\n\tconst { update } = useOrganizationRolePermissions(organizationId);\n\tconst {\n\t\tdata: organizationRoles,\n\t\trefetch,\n\t\tisFetching,\n\t\tisRefetching,\n\t} = useSuspenseQuery(getOrganizationRolesQueryOptions(organizationId));\n\tconst cloudUsers = useMemo(() => {\n\t\tconst users: Record<SchemaUser['id'], SchemaUser> = {};\n\t\tfor (const organizationRole of organizationRoles) {\n\t\t\tif (organizationRole.users) {\n\t\t\t\tfor (const user of organizationRole.users) {\n\t\t\t\t\tif (!users[user.id]) {\n\t\t\t\t\t\tusers[user.id] = { ...user, roles: [] };\n\t\t\t\t\t}\n\t\t\t\t\tusers[user.id].roles!.push(organizationRole);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn Object.values(users).sort(sortByEmail);\n\t}, [organizationRoles]);\n\n\tconst selectedUser = useMemo(() => cloudUsers?.find((user) => user.id === orgUserId), [cloudUsers, orgUserId]);\n\n\tconst onSelectUser = useCallback(\n\t\t(newUserId: string | undefined) => {\n\t\t\tconst parts = [orgUserId ? '..' : '', newUserId].filter(Boolean);\n\t\t\tvoid navigate({ to: parts.join('/') });\n\t\t},\n\t\t[orgUserId, navigate],\n\t);\n\n\tconst isEditModalOpen = !!orgUserId && !!selectedUser;\n\n\tconst [isAddModalOpen, setIsAddModalOpen] = useState(false);\n\tconst [sortTableDataParams] = useState({\n\t\tattribute: 'email',\n\t\tdescending: false,\n\t});\n\tconst sortingState = useMemo(\n\t\t() => [\n\t\t\t{\n\t\t\t\tdesc: sortTableDataParams.descending,\n\t\t\t\tid: sortTableDataParams.attribute,\n\t\t\t},\n\t\t],\n\t\t[sortTableDataParams],\n\t);\n\n\tconst onAddClicked = useCallback(() => {\n\t\tsetIsAddModalOpen(true);\n\t}, [setIsAddModalOpen]);\n\tconst onUsedAdded = useCallback(() => {\n\t\tvoid refetch();\n\t\tsetIsAddModalOpen(false);\n\t}, [refetch, setIsAddModalOpen]);\n\n\tconst onRowClick = useCallback(\n\t\t(rowData: Row<SchemaUser>) => {\n\t\t\tonSelectUser(rowData.original.id);\n\t\t},\n\t\t[onSelectUser],\n\t);\n\tconst closeEditModal = useCallback(() => {\n\t\tonSelectUser(undefined);\n\t}, [onSelectUser]);\n\n\tconst onUserUpdated = useCallback(() => {\n\t\tvoid refetch();\n\t\tonSelectUser(undefined);\n\t}, [onSelectUser, refetch]);\n\n\tconst onRefreshClick = useRefreshClick(refetch);\n\n\treturn (\n\t\t<>\n\t\t\t<SubNavMenu />\n\t\t\t<div className=\"mt-32 px-4 pt-4 md:px-12 min-h-[calc(100vh-theme(spacing.32))]\">\n\t\t\t\t<Suspense fallback={<Loading className=\"flex flex-col items-center justify-center h-full\" text=\"Loading...\" />}>\n\t\t\t\t\t<SimpleBrowseDataTable<SchemaUser, unknown>\n\t\t\t\t\t\tdata={cloudUsers}\n\t\t\t\t\t\tisFetching={isFetching || isRefetching}\n\t\t\t\t\t\tcolumns={dataTableColumns}\n\t\t\t\t\t\tonRowClick={onRowClick}\n\t\t\t\t\t\tsortingState={sortingState}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"defaultOutline\"\n\t\t\t\t\t\t\tonClick={onRefreshClick}\n\t\t\t\t\t\t\taccessKey=\"r\"\n\t\t\t\t\t\t\tdisabled={isFetching || isRefetching}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<RefreshCwIcon />{' '}\n\t\t\t\t\t\t\t<span className=\"hidden lg:inline-block\">\n\t\t\t\t\t\t\t\t<u>R</u>efresh\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t{update && (\n\t\t\t\t\t\t\t<Button variant=\"positiveOutline\" onClick={onAddClicked} accessKey=\"a\" disabled={isAddModalOpen}>\n\t\t\t\t\t\t\t\t<PlusIcon />{' '}\n\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t<u>A</u>dd\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</SimpleBrowseDataTable>\n\t\t\t\t\t{update && (\n\t\t\t\t\t\t<AddUserModal\n\t\t\t\t\t\t\tisModalOpen={isAddModalOpen}\n\t\t\t\t\t\t\tonChangesSaved={onUsedAdded}\n\t\t\t\t\t\t\tsetIsModalOpen={setIsAddModalOpen}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t\t{isEditModalOpen && (\n\t\t\t\t\t\t<EditUserModal\n\t\t\t\t\t\t\tcloseModal={closeEditModal}\n\t\t\t\t\t\t\tdata={selectedUser}\n\t\t\t\t\t\t\tisModalOpen={isEditModalOpen}\n\t\t\t\t\t\t\tonUserUpdated={onUserUpdated}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</Suspense>\n\t\t\t</div>\n\t\t</>\n\t);\n}\n","import { Badge } from '@/components/ui/badge';\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';\nimport {\n\tDropdownMenu,\n\tDropdownMenuContent,\n\tDropdownMenuItem,\n\tDropdownMenuLabel,\n\tDropdownMenuSeparator,\n\tDropdownMenuTrigger,\n} from '@/components/ui/dropdownMenu';\nimport { useOrganizationPermissions, useOrganizationRolePermissions } from '@/hooks/usePermissions';\nimport { capitalizeWords } from '@/lib/string/capitalizeWords';\nimport { Link } from '@tanstack/react-router';\nimport { ArrowRight, Ellipsis } from 'lucide-react';\nimport { useCallback } from 'react';\n\nexport function OrgCard({\n\torganizationRole,\n\tonDeleteOrgModal,\n}: {\n\torganizationRole: { organizationId: string; organizationName?: string; roleName: string };\n\tonDeleteOrgModal: (OrganizationRole: { organizationId: string; organizationName?: string }) => void;\n}) {\n\tconst { organizationId, organizationName, roleName } = organizationRole;\n\tconst { remove, update: canUpdateOrganization } = useOrganizationPermissions(organizationId);\n\tconst showBilling = canUpdateOrganization;\n\tconst { view: showOrgUsersAndRoles } = useOrganizationRolePermissions(organizationId);\n\n\tconst onDeleteClick = useCallback(() => {\n\t\tonDeleteOrgModal(organizationRole);\n\t}, [onDeleteOrgModal, organizationRole]);\n\n\treturn (\n\t\t<Card className=\"relative h-full justify-between\">\n\t\t\t<CardHeader>\n\t\t\t\t<CardDescription className=\"flex items-center justify-between\">\n\t\t\t\t\t<span className=\"truncate\">{organizationId}</span>\n\t\t\t\t\t{remove && (\n\t\t\t\t\t\t<DropdownMenu>\n\t\t\t\t\t\t\t<DropdownMenuTrigger className=\"p-4 -m-4 -mr-6 hover:text-white\">\n\t\t\t\t\t\t\t\t<Ellipsis aria-label=\"Options\" />\n\t\t\t\t\t\t\t</DropdownMenuTrigger>\n\t\t\t\t\t\t\t<DropdownMenuContent>\n\t\t\t\t\t\t\t\t<DropdownMenuLabel className=\"text-gray-600 text-xs\">Options</DropdownMenuLabel>\n\t\t\t\t\t\t\t\t<DropdownMenuSeparator />\n\t\t\t\t\t\t\t\t<Link to={`${organizationId}`}>\n\t\t\t\t\t\t\t\t\t<DropdownMenuItem>Clusters</DropdownMenuItem>\n\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t{showOrgUsersAndRoles && (\n\t\t\t\t\t\t\t\t\t<Link to={`${organizationId}/roles`}>\n\t\t\t\t\t\t\t\t\t\t<DropdownMenuItem>Roles</DropdownMenuItem>\n\t\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{showOrgUsersAndRoles && (\n\t\t\t\t\t\t\t\t\t<Link to={`${organizationId}/users`}>\n\t\t\t\t\t\t\t\t\t\t<DropdownMenuItem>Users</DropdownMenuItem>\n\t\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{showBilling && (\n\t\t\t\t\t\t\t\t\t<Link to={`${organizationId}/billing`}>\n\t\t\t\t\t\t\t\t\t\t<DropdownMenuItem>Billing</DropdownMenuItem>\n\t\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t<DropdownMenuSeparator />\n\t\t\t\t\t\t\t\t{remove && (\n\t\t\t\t\t\t\t\t\t<DropdownMenuItem\n\t\t\t\t\t\t\t\t\t\tclassName=\"focus:bg-red/70 focus:text-white\"\n\t\t\t\t\t\t\t\t\t\tonClick={onDeleteClick}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tDelete\n\t\t\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</DropdownMenuContent>\n\t\t\t\t\t\t</DropdownMenu>\n\t\t\t\t\t)}\n\t\t\t\t</CardDescription>\n\t\t\t\t<CardTitle>\n\t\t\t\t\t<h2>{organizationName}</h2>\n\t\t\t\t</CardTitle>\n\t\t\t</CardHeader>\n\t\t\t<CardContent className=\"flex justify-between\">\n\t\t\t\t<Badge>{capitalizeWords(roleName)}</Badge>\n\t\t\t\t<Link\n\t\t\t\t\tto={organizationId}\n\t\t\t\t\tclassName=\"text-sm\"\n\t\t\t\t\taria-label={`View ${organizationName}`}\n\t\t\t\t\ttitle={`View ${organizationName}`}\n\t\t\t\t>\n\t\t\t\t\t<span className=\"py-2 transition-all duration-100 ease-in-out border-0 hover:border-b-2\">\n\t\t\t\t\t\tView <ArrowRight className=\"inline-block\" />\n\t\t\t\t\t</span>\n\t\t\t\t</Link>\n\t\t\t</CardContent>\n\t\t</Card>\n\t);\n}\n","import { apiClient } from '@/config/apiClient';\nimport { useMutation } from '@tanstack/react-query';\n\nexport async function onDeleteOrganization(orgId: string) {\n\tconst { data } = await apiClient.delete(`/Organization/${orgId}` as '/Organization/{id}');\n\treturn data;\n}\n\nexport function useDeleteOrganizationMutation() {\n\treturn useMutation({\n\t\tmutationFn: (orgId: string) => onDeleteOrganization(orgId),\n\t});\n}\n","import { apiClient } from '@/config/apiClient';\nimport { SchemaOrganization } from '@/integrations/api/api.gen';\nimport { useMutation } from '@tanstack/react-query';\n\nasync function onNewOrganizationSubmit(newOrg: Omit<SchemaOrganization, 'id' | 'type'>): Promise<SchemaOrganization> {\n\tconst { data } = await apiClient.post('/Organization/', {\n\t\t...newOrg,\n\t});\n\treturn data;\n}\n\nexport function useCreateNewOrganizationMutation() {\n\treturn useMutation<SchemaOrganization, Error, Omit<SchemaOrganization, 'id' | 'type'>>({\n\t\tmutationFn: (clusterInfo) => onNewOrganizationSubmit(clusterInfo),\n\t});\n}\n","import { z } from 'zod';\n\nexport const specifiedSubdomain = z\n\t.string()\n\t.max(62, { error: 'Must be at most 62 characters long.' })\n\t.regex(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/, {\n\t\terror:\n\t\t\t'Please only use lowercase letters, digits and dashes (-) in the subdomain. Must not start or end with a dash.',\n\t});\n\nexport const NewOrganizationSchema = z.object({\n\tname: z\n\t\t.string()\n\t\t.max(255, {\n\t\t\terror: 'Name cannot be longer than 255 characters.',\n\t\t}),\n\tsubdomain: z.union([\n\t\tz.literal(''),\n\t\tz.undefined(),\n\t\tspecifiedSubdomain,\n\t]),\n});\n","import { Button } from '@/components/ui/button';\nimport { DialogFooter } from '@/components/ui/dialog';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { currentUserQueryKey } from '@/features/auth/queries/getCurrentUser';\nimport { authStore, OverallAppSignIn } from '@/features/auth/store/authStore';\nimport { useCreateNewOrganizationMutation } from '@/features/organizations/hooks/useCreateNewOrganization';\nimport { NewOrganizationSchema, specifiedSubdomain } from '@/features/organizations/mutations/newOrganizationSchema';\nimport { useCloudAuth } from '@/hooks/useAuth';\nimport { collapseKebabsToMaxLength } from '@/lib/string/collapseKebabsToMaxLength';\nimport { toKebabCase } from '@/lib/string/to-kebab-case';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useNavigate } from '@tanstack/react-router';\nimport { ArrowRight } from 'lucide-react';\nimport { useCallback, useEffect, useMemo } from 'react';\nimport { useForm } from 'react-hook-form';\nimport z from 'zod';\n\nexport function NewOrgForm() {\n\tconst { user } = useCloudAuth();\n\tconst navigate = useNavigate();\n\n\tconst form = useForm({\n\t\tresolver: zodResolver(NewOrganizationSchema),\n\t\tdefaultValues: {\n\t\t\tname: '',\n\t\t\tsubdomain: '',\n\t\t},\n\t});\n\tconst { setFocus, watch } = form;\n\n\tuseEffect(() => {\n\t\tsetFocus('name');\n\t}, [setFocus]);\n\n\tconst defaultName = `${user?.firstname} ${user?.lastname} Org`;\n\tconst name = watch('name') || defaultName;\n\tconst subdomain = watch('subdomain');\n\tconst calculatedNames = useMemo(() => {\n\t\tconst suggestedSubdomain = collapseKebabsToMaxLength(\n\t\t\ttoKebabCase(name),\n\t\t\tspecifiedSubdomain.maxLength!,\n\t\t);\n\t\treturn {\n\t\t\tsuggestedSubdomain,\n\t\t\tfullHostName: `future-cluster-names.${subdomain || suggestedSubdomain}.harperfabric.com`,\n\t\t};\n\t}, [name, subdomain]);\n\n\tconst { mutate: submitNewOrganizationData, isPending } = useCreateNewOrganizationMutation();\n\tconst queryClient = useQueryClient();\n\n\tconst submitForm = useCallback(async (formData: z.infer<typeof NewOrganizationSchema>) => {\n\t\tsubmitNewOrganizationData({\n\t\t\tname: formData.name || defaultName,\n\t\t\tsubdomain: formData.subdomain || calculatedNames.suggestedSubdomain,\n\t\t}, {\n\t\t\tonSuccess: (newOrg) => {\n\t\t\t\tqueryClient.invalidateQueries({ queryKey: currentUserQueryKey, refetchType: 'active' });\n\t\t\t\tauthStore.reloadUser(OverallAppSignIn);\n\t\t\t\tvoid navigate({ to: `/${newOrg.id}` });\n\t\t\t},\n\t\t});\n\t}, [calculatedNames.suggestedSubdomain, queryClient, submitNewOrganizationData, defaultName, navigate]);\n\n\treturn (\n\t\t<>\n\t\t\t<Form {...form}>\n\t\t\t\t<form\n\t\t\t\t\tid=\"org-add-form\"\n\t\t\t\t\tname=\"org-add-form\"\n\t\t\t\t\tonSubmit={form.handleSubmit(submitForm)}\n\t\t\t\t\tclassName=\"grid gap-6 text-white max-w-xl\"\n\t\t\t\t>\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\tname=\"name\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Name</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\tmaxLength={NewOrganizationSchema.shape.name.maxLength!}\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"words\"\n\t\t\t\t\t\t\t\t\t\tplaceholder={defaultName}\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\tname=\"subdomain\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Subdomain</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\tmaxLength={specifiedSubdomain.maxLength!}\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\t\t\t\tplaceholder={calculatedNames.suggestedSubdomain}\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t<FormLabel className=\"pb-1\">Full Host Name</FormLabel>\n\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t<span>{calculatedNames.fullHostName}</span>\n\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t</FormItem>\n\n\t\t\t\t\t<DialogFooter>\n\t\t\t\t\t\t<Button type=\"submit\" variant=\"submit\" className=\"rounded-full\" disabled={isPending}>\n\t\t\t\t\t\t\tCreate New Organization <ArrowRight />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</DialogFooter>\n\t\t\t\t</form>\n\t\t\t</Form>\n\t\t</>\n\t);\n}\n","import { SubNavMenu } from '@/components/SubNavMenu';\nimport { NewOrgForm } from '@/features/organizations/components/NewOrgForm';\n\nexport function NewOrg() {\n\treturn (\n\t\t<>\n\t\t\t<SubNavMenu />\n\t\t\t<section className=\"mt-32 px-4 pt-4 md:px-12 min-h-[calc(100vh-theme(spacing.32))]\">\n\t\t\t\t<NewOrgForm />\n\t\t\t</section>\n\t\t</>\n\t);\n}\n","import { ConfirmDeletionModal } from '@/components/ConfirmDeletionModal';\nimport { SubNavMenu } from '@/components/SubNavMenu';\nimport { Button } from '@/components/ui/button';\nimport { Input } from '@/components/ui/input';\nimport { getCurrentUserQueryOptions } from '@/features/auth/queries/getCurrentUser';\nimport { OrgCard } from '@/features/organizations/components/OrgCard';\nimport { useDeleteOrganizationMutation } from '@/features/organizations/mutations/deleteOrganization';\nimport { NewOrg } from '@/features/organizations/NewOrg';\nimport { curryFilterByFuzzySearch } from '@/lib/string/filterByFuzzySearch';\nimport { useQueryClient, useSuspenseQuery } from '@tanstack/react-query';\nimport { Link, Navigate, useSearch } from '@tanstack/react-router';\nimport { PlusIcon } from 'lucide-react';\nimport { FormEvent, useCallback, useMemo, useState } from 'react';\nimport { toast } from 'sonner';\n\nexport function OrganizationsIndex() {\n\tconst queryClient = useQueryClient();\n\tconst { data: user } = useSuspenseQuery(getCurrentUserQueryOptions());\n\tconst { mutate: deleteOrg, isPending: isDeletingOrgPending } = useDeleteOrganizationMutation();\n\n\tconst [isDeleteOrgModalOpen, setIsDeleteOrgModalOpen] = useState(false);\n\tconst [deleteOrgInfo, setDeleteOrgInfo] = useState<\n\t\tnull | {\n\t\t\torganizationId: string;\n\t\t\torganizationName?: string;\n\t\t}\n\t>(null);\n\n\tconst [filterByNameValue, setFilterByNameValue] = useState('');\n\tconst clearFilterByNameValue = useCallback(() => setFilterByNameValue(''), []);\n\n\tconst organizationRoles = useMemo(() => {\n\t\tconst roles = user?.roles || {};\n\t\tconst organizations = Object.values(roles);\n\t\tconst organizationIds = Object.keys(roles).map((organizationId, index) => ({\n\t\t\torganizationId,\n\t\t\torganizationName: organizations[index].organizationName,\n\t\t\troleName: organizations[index].role,\n\t\t}));\n\t\treturn (\n\t\t\torganizationIds\n\t\t\t\t.filter(curryFilterByFuzzySearch(['organizationId', 'organizationName'], filterByNameValue))\n\t\t\t\t.sort((a, b) => ((a.organizationName || '') > (b.organizationName || '') ? 1 : -1)) || []\n\t\t);\n\t}, [filterByNameValue, user?.roles]);\n\n\tconst onFilterByNameChanged = useCallback((e: FormEvent<HTMLInputElement>) => {\n\t\tsetFilterByNameValue(e.currentTarget.value?.toLowerCase() || '');\n\t}, []);\n\n\tconst handleDeleteOrg = useCallback(\n\t\t(org: { organizationId: string; organizationName?: string }) => {\n\t\t\tif (org?.organizationId) {\n\t\t\t\tdeleteOrg(org.organizationId, {\n\t\t\t\t\tonSuccess: () => {\n\t\t\t\t\t\ttoast.success('Success', {\n\t\t\t\t\t\t\tdescription: `Organization successfully deleted.`,\n\t\t\t\t\t\t\tduration: 5000,\n\t\t\t\t\t\t\taction: {\n\t\t\t\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t\tvoid queryClient.invalidateQueries({ queryKey: [] });\n\t\t\t\t\t\tsetIsDeleteOrgModalOpen(false);\n\t\t\t\t\t},\n\t\t\t\t\tonError: () => setIsDeleteOrgModalOpen(false),\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\t[deleteOrg, queryClient, setIsDeleteOrgModalOpen],\n\t);\n\n\tconst onDeleteOrgModal = useCallback((orgRole: { organizationId: string; organizationName?: string }) => {\n\t\tsetDeleteOrgInfo(orgRole);\n\t\tsetIsDeleteOrgModalOpen(true);\n\t}, []);\n\n\tconst { createCluster }: { createCluster?: string } = useSearch({ strict: false });\n\n\tif (organizationRoles.length === 1 && !filterByNameValue.length && createCluster) {\n\t\treturn <Navigate to={`/${organizationRoles[0].organizationId}/new-cluster`} replace={true} />;\n\t}\n\n\tif (!organizationRoles.length && !filterByNameValue.length) {\n\t\treturn <NewOrg />;\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t<SubNavMenu>\n\t\t\t\t<div className=\"flex w-full justify-end gap-2\">\n\t\t\t\t\t<Input\n\t\t\t\t\t\tplaceholder=\"Filter by name\"\n\t\t\t\t\t\tclassName=\"inline-block w-full text-xs\"\n\t\t\t\t\t\tvalue={filterByNameValue}\n\t\t\t\t\t\tonChange={onFilterByNameChanged}\n\t\t\t\t\t/>\n\t\t\t\t\t<Link to=\"/new-org\">\n\t\t\t\t\t\t<Button variant=\"positive\" accessKey=\"n\">\n\t\t\t\t\t\t\t<PlusIcon />\n\t\t\t\t\t\t\t<span className=\"hidden sm:inline-block\">\n\t\t\t\t\t\t\t\t<u>N</u>ew <span className=\"hidden md:inline-block\">Organization</span>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</Link>\n\t\t\t\t</div>\n\t\t\t</SubNavMenu>\n\t\t\t<section className=\"mt-32 px-4 pt-4 md:px-12 min-h-[calc(100vh-theme(spacing.32))]\">\n\t\t\t\t<div className=\"grid grid-cols-1 gap-4 md:grid-cols-12\">\n\t\t\t\t\t{organizationRoles.map((organizationRole) => (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tkey={organizationRole.organizationId}\n\t\t\t\t\t\t\tclassName=\"col-span-1 md:col-span-4 lg:col-span-3 2xl:col-span-2\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<OrgCard organizationRole={organizationRole} onDeleteOrgModal={onDeleteOrgModal} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t\t{!organizationRoles.length && (\n\t\t\t\t\t\t<div className=\"col-span-1 md:col-span-12 text-center\">\n\t\t\t\t\t\t\t<h2 className=\"my-4 text-xl\">No matches found.</h2>\n\t\t\t\t\t\t\t<Button variant=\"outline\" onClick={clearFilterByNameValue}>Clear Filters</Button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</section>\n\t\t\t{deleteOrgInfo && (\n\t\t\t\t<ConfirmDeletionModal\n\t\t\t\t\ttypeOfThingBeingDeleted=\"organization\"\n\t\t\t\t\tnameOfThingBeingDeleted={deleteOrgInfo.organizationName}\n\t\t\t\t\tisModalOpen={isDeleteOrgModalOpen}\n\t\t\t\t\tsetIsModalOpen={() => setIsDeleteOrgModalOpen(false)}\n\t\t\t\t\tdeletionConfirmed={() => handleDeleteOrg(deleteOrgInfo)}\n\t\t\t\t\tdeletionPending={isDeletingOrgPending}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t);\n}\n","import { Loading } from '@/components/Loading';\nimport { Navbar } from '@/components/Navbar';\nimport { useOverallAuth } from '@/hooks/useAuth';\nimport { useLocalStorage } from '@/hooks/useLocalStorage';\nimport { LocalStorageKeys } from '@/lib/storage/localStorageKeys';\nimport { Outlet, useSearch } from '@tanstack/react-router';\nimport { useEffect } from 'react';\n\nexport function Dashboard() {\n\tconst { isLoading: isUserLoading } = useOverallAuth();\n\tconst { createCluster }: { createCluster?: string } = useSearch({ strict: false });\n\tconst [, setSavedClusterState] = useLocalStorage<unknown | null>(LocalStorageKeys.SavedClusterState, null);\n\tuseEffect(() => {\n\t\tif (createCluster) {\n\t\t\tsetSavedClusterState(createCluster);\n\t\t}\n\t}, [createCluster, setSavedClusterState]);\n\n\tif (isUserLoading) {\n\t\treturn <Loading className=\"fixed z-50 translate-1/2\" />;\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t<header className=\"fixed top-0 z-40 w-full h-20 p-4 bg-black-dark dark:bg-black-dark dark:border-b dark:border-black md:px-12\">\n\t\t\t\t<Navbar />\n\t\t\t</header>\n\t\t\t<main>\n\t\t\t\t<Outlet />\n\t\t\t</main>\n\t\t</>\n\t);\n}\n","import { currentUrlAfterHash } from '@/lib/urls/currentUrlAfterHash';\n\nconst ignoredUrls = [\n\t'/',\n\t'/forgot-password',\n\t'/reset-password',\n\t'/sign-in',\n\t'/sign-up',\n\t'/verify-email',\n];\n\nexport function buildRedirectInSearch() {\n\tconst url = currentUrlAfterHash();\n\treturn !ignoredUrls.includes(url) && { redirect: url };\n}\n","import { OverallAppSignIn } from '@/features/auth/store/authStore';\nimport { Dashboard } from '@/features/layouts/Dashboard';\nimport { buildRedirectInSearch } from '@/lib/urls/buildRedirectInSearch';\nimport { rootRoute } from '@/router/rootRoute';\nimport { createRoute, redirect } from '@tanstack/react-router';\n\nexport const dashboardLayout = createRoute({\n\tgetParentRoute: () => rootRoute,\n\tid: '_dashboardLayout',\n\tcomponent: Dashboard,\n\tbeforeLoad: ({ context }) => {\n\t\tconst auth = context.authentication[OverallAppSignIn];\n\t\tif (auth && !auth.isLoading && !auth.user) {\n\t\t\tthrow redirect({\n\t\t\t\tto: '/sign-in',\n\t\t\t\tsearch: buildRedirectInSearch(),\n\t\t\t});\n\t\t}\n\t},\n});\n","import { OrganizationsIndex } from '@/features/organizations/index';\nimport { NewOrg } from '@/features/organizations/NewOrg';\nimport { dashboardLayout } from '@/router/dashboardRoute';\nimport { createRoute } from '@tanstack/react-router';\n\nexport const orgsLayoutRoute = createRoute({\n\tgetParentRoute: () => dashboardLayout,\n\tid: '_orgsLayout',\n});\n\nconst orgsIndexRoute = createRoute({\n\tgetParentRoute: () => orgsLayoutRoute,\n\tpath: '/',\n\tcomponent: OrganizationsIndex,\n});\n\nconst newOrgRoute = createRoute({\n\tgetParentRoute: () => orgsLayoutRoute,\n\tpath: '/new-org',\n\tcomponent: NewOrg,\n});\n\nexport const orgsRoutes = [\n\torgsIndexRoute,\n\tnewOrgRoute,\n];\n","import { createBillingRouteTree } from '@/features/organization/billing/routes';\nimport { getOrganizationQueryOptions } from '@/features/organization/queries/getOrganizationQuery';\nimport { OrgConfigRolesIndex } from '@/features/organization/roles';\nimport { OrgConfigUsersIndex } from '@/features/organization/users';\nimport { orgsLayoutRoute } from '@/features/organizations/routes';\nimport { createRoute } from '@tanstack/react-router';\n\nexport const orgLayoutRoute = createRoute({\n\tgetParentRoute: () => orgsLayoutRoute,\n\tpath: '$organizationId',\n\tbeforeLoad: async (opts) => {\n\t\treturn {\n\t\t\torganization: await opts.context.queryClient.ensureQueryData(\n\t\t\t\tgetOrganizationQueryOptions(opts.params.organizationId),\n\t\t\t),\n\t\t};\n\t},\n});\n\nconst orgRolesRoute = createRoute({\n\tgetParentRoute: () => orgLayoutRoute,\n\tpath: '/roles',\n\tcomponent: OrgConfigRolesIndex,\n});\nconst orgRoleRoute = createRoute({\n\tgetParentRoute: () => orgLayoutRoute,\n\tpath: '/roles/$orgRoleId',\n\tcomponent: OrgConfigRolesIndex,\n});\n\nconst orgUsersRoute = createRoute({\n\tgetParentRoute: () => orgLayoutRoute,\n\tpath: '/users',\n\tcomponent: OrgConfigUsersIndex,\n});\nconst orgUserRoute = createRoute({\n\tgetParentRoute: () => orgLayoutRoute,\n\tpath: '/users/$orgUserId',\n\tcomponent: OrgConfigUsersIndex,\n});\n\nexport const orgRoutes = [\n\tcreateBillingRouteTree(orgLayoutRoute),\n\torgRolesRoute,\n\torgRoleRoute,\n\torgUsersRoute,\n\torgUserRoute,\n];\n","import { clusterLayoutRoute } from '@/features/cluster/clusterLayoutRoute';\nimport { ClustersList as ClusterList } from '@/features/clusters/ClustersList';\nimport { UpsertCluster } from '@/features/clusters/upsert';\nimport { orgLayoutRoute } from '@/features/organization/routes';\nimport { createRoute } from '@tanstack/react-router';\n\nexport const clustersLayoutRoute = createRoute({\n\tgetParentRoute: () => orgLayoutRoute,\n\tid: '_clusterLayout',\n});\n\nconst clustersIndexRoute = createRoute({\n\tgetParentRoute: () => clustersLayoutRoute,\n\tpath: '/',\n\tcomponent: ClusterList,\n});\n\nconst newClusterRoute = createRoute({\n\tgetParentRoute: () => orgLayoutRoute,\n\tpath: '/new-cluster',\n\tcomponent: UpsertCluster,\n});\n\nconst editClusterRoute = createRoute({\n\tgetParentRoute: () => clusterLayoutRoute,\n\tpath: '/edit',\n\tcomponent: UpsertCluster,\n});\n\nconst editClusterVersionRoute = createRoute({\n\tgetParentRoute: () => clusterLayoutRoute,\n\tpath: '/edit/$mode',\n\tcomponent: UpsertCluster,\n});\n\nexport const clustersRoutes = [\n\tclustersIndexRoute,\n\tnewClusterRoute,\n\teditClusterRoute,\n\teditClusterVersionRoute,\n];\n","import { Outlet } from '@tanstack/react-router';\n\nexport function ClusterLayout() {\n\treturn <Outlet />;\n}\n","import { clustersLayoutRoute } from '@/features/clusters/routes';\nimport { createRoute } from '@tanstack/react-router';\nimport { ClusterLayout } from './ClusterLayout';\nimport { getClusterInfoQueryOptions } from './queries/getClusterInfoQuery';\n\nexport const clusterLayoutRoute = createRoute({\n\tgetParentRoute: () => clustersLayoutRoute,\n\tpath: '$clusterId',\n\tcomponent: ClusterLayout,\n\tbeforeLoad: async ({ context, params }) => {\n\t\treturn {\n\t\t\tcluster: await context.queryClient.ensureQueryData(getClusterInfoQueryOptions(params.clusterId)),\n\t\t};\n\t},\n});\n","import { SubNavMenu } from '@/components/SubNavMenu';\nimport { cx } from 'class-variance-authority';\nimport { ReactNode } from 'react';\n\nexport function NestedContentWithSubNavMenu({ children, className }: { children: ReactNode; className?: string }) {\n\treturn (\n\t\t<>\n\t\t\t<SubNavMenu />\n\t\t\t<div\n\t\t\t\tclassName={cx('mt-32 px-4 py-4 md:px-12 min-h-[calc(100vh-(--spacing(32)))] flex justify-center', className)}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</>\n\t);\n}\n","/**\n * A list of common second-level domains used in country-code TLDs (ccTLDs).\n * This helps identify if a domain like 'example.co.uk' should be treated\n * as a root domain (returning '@') or if 'co' is the subdomain.\n */\nconst COMMON_SLDS = new Set([\n\t'com',\n\t'co',\n\t'org',\n\t'net',\n\t'edu',\n\t'gov',\n\t'mil',\n\t'me',\n\t'biz',\n\t'info',\n\t'ac',\n\t'or',\n\t'ne',\n\t'go',\n\t'lg',\n\t'asn',\n\t'id',\n\t'nom',\n\t'sch',\n\t'ltd',\n\t'plc',\n]);\n\nexport function extractDomainFromTLD(domain: string): string | '@' {\n\tconst parts = domain.split('.');\n\tif (parts.length <= 2) {\n\t\treturn '@';\n\t}\n\n\tconst lastPart = parts[parts.length - 1];\n\tconst secondToLastPart = parts[parts.length - 2];\n\n\tconst isMultiPartTld = lastPart.length === 2 && COMMON_SLDS.has(secondToLastPart);\n\tconst rootPartCount = isMultiPartTld ? 3 : 2;\n\n\tif (parts.length <= rootPartCount) {\n\t\treturn '@';\n\t}\n\n\treturn parts.slice(0, -rootPartCount).join('.');\n}\n","import { Button } from '@/components/ui/button';\nimport { useCopyToClipboard } from '@/hooks/useCopyToClipboard';\nimport { Cluster, SchemaOrganizationDomain } from '@/integrations/api/api.patch';\nimport { extractDomainFromTLD } from '@/lib/string/extractDomainFromTLD';\nimport { CopyIcon } from 'lucide-react';\n\nexport function AssociateDomainWithCluster({ cluster: { fqdn }, domain: { domain, id } }: {\n\tcluster: Cluster;\n\tdomain: SchemaOrganizationDomain;\n}) {\n\tconst recordName = extractDomainFromTLD(domain);\n\tconst [onCopyName, onCopyTarget, onCopyId] = useCopyToClipboard(recordName, fqdn || '', id);\n\n\treturn (\n\t\t<div className=\"grid gap-4 grid-cols-1 md:grid-cols-[80px_1fr] pb-6\">\n\t\t\t<div className=\"text-muted-foreground md:col-span-2 text-wrap\">\n\t\t\t\tThis domain has been verified! Now to associate it with this cluster, add the following to your DNS registrar:\n\t\t\t</div>\n\n\t\t\t<div className=\"col-span-1\">Type:</div>\n\t\t\t<div className=\"col-span-1\">CNAME</div>\n\n\t\t\t<div className=\"col-span-1\">Name:</div>\n\t\t\t<div className=\"col-span-1 flex gap-2 items-center\">\n\t\t\t\t<div className=\"flex items-center gap-1 bg-gray-700 rounded-md px-3 py-1 flex-1 overflow-hidden\">\n\t\t\t\t\t<input\n\t\t\t\t\t\tclassName=\"bg-transparent border-none outline-none w-full cursor-text truncate\"\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\treadOnly={true}\n\t\t\t\t\t\tname=\"recordName\"\n\t\t\t\t\t\tvalue={recordName}\n\t\t\t\t\t\tonClick={onCopyName}\n\t\t\t\t\t/>\n\t\t\t\t\t<Button type=\"button\" variant=\"ghost\" className=\"h-6 w-6 p-0 shrink-0\" onClick={onCopyName}>\n\t\t\t\t\t\t<CopyIcon className=\"w-3.5 h-3.5\" />\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div className=\"col-span-1\">TTL:</div>\n\t\t\t<div className=\"col-span-1\">Auto</div>\n\n\t\t\t<div className=\"col-span-1\">Target:</div>\n\t\t\t<div className=\"col-span-1 flex gap-2 items-center\">\n\t\t\t\t<div className=\"flex items-center gap-1 bg-gray-700 rounded-md px-3 py-1 flex-1 overflow-hidden\">\n\t\t\t\t\t<input\n\t\t\t\t\t\tclassName=\"bg-transparent border-none outline-none w-full cursor-text truncate\"\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\treadOnly={true}\n\t\t\t\t\t\tname=\"recordTarget\"\n\t\t\t\t\t\tvalue={fqdn}\n\t\t\t\t\t\tonClick={onCopyTarget}\n\t\t\t\t\t/>\n\t\t\t\t\t<Button type=\"button\" variant=\"ghost\" className=\"h-6 w-6 p-0 shrink-0\" onClick={onCopyTarget}>\n\t\t\t\t\t\t<CopyIcon className=\"w-3.5 h-3.5\" />\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div className=\"col-span-1 text-xs\">Domain ID:</div>\n\t\t\t<div className=\"col-span-1 flex gap-2 items-center\">\n\t\t\t\t<div className=\"flex items-center gap-1 bg-gray-800 rounded-md px-3 py-0.5 text-xs text-muted-foreground italic flex-1 overflow-hidden\">\n\t\t\t\t\t<input\n\t\t\t\t\t\tclassName=\"bg-transparent border-none outline-none w-full cursor-text truncate\"\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\treadOnly={true}\n\t\t\t\t\t\tname=\"domainId\"\n\t\t\t\t\t\tvalue={id}\n\t\t\t\t\t\tonClick={onCopyId}\n\t\t\t\t\t/>\n\t\t\t\t\t<Button type=\"button\" variant=\"ghost\" className=\"h-5 w-5 p-0 shrink-0\" onClick={onCopyId}>\n\t\t\t\t\t\t<CopyIcon className=\"w-3 h-3\" />\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div className=\"text-muted-foreground md:col-span-2 text-wrap italic text-sm\">\n\t\t\t\tSelect this domain using the checkbox to the left, then click \"Bind\" in the top right to finish associating it\n\t\t\t\twith this cluster.\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","import { Button } from '@/components/ui/button';\nimport { ChallengeCertificate } from '@/features/cluster/domains/queries/getChallengeCertificates';\nimport { useCopyToClipboard } from '@/hooks/useCopyToClipboard';\nimport { Cluster, SchemaOrganizationDomain } from '@/integrations/api/api.patch';\nimport { extractDomainFromTLD } from '@/lib/string/extractDomainFromTLD';\nimport { CopyIcon } from 'lucide-react';\nimport { useMemo } from 'react';\n\nexport function CertificateProgress({\n\tcertificate,\n\tdomain,\n\tcluster,\n}: {\n\tcertificate: ChallengeCertificate;\n\tdomain: SchemaOrganizationDomain;\n\tcluster: Cluster;\n}) {\n\tconst recordName = extractDomainFromTLD(domain.domain);\n\tconst [onCopyName, onCopyTarget, onCopyId] = useCopyToClipboard(\n\t\trecordName,\n\t\tcluster.fqdn || '',\n\t\tdomain.id,\n\t);\n\n\tconst progress = useMemo(() => {\n\t\tif (certificate.issueDate && !certificate.inProgress) {\n\t\t\treturn {\n\t\t\t\twidth: '100%',\n\t\t\t\tcolor: 'bg-green/80',\n\t\t\t\tpulse: false,\n\t\t\t\ttext: 'Certificate Issued',\n\t\t\t};\n\t\t}\n\t\tif (certificate.inProgress) {\n\t\t\treturn {\n\t\t\t\twidth: '100%',\n\t\t\t\tcolor: 'bg-yellow/80',\n\t\t\t\tpulse: true,\n\t\t\t\ttext: 'Generating Certificate...',\n\t\t\t};\n\t\t}\n\t\t// If neither issueDate nor inProgress, it's pending\n\t\treturn {\n\t\t\twidth: '100%',\n\t\t\tcolor: 'bg-gray-600',\n\t\t\tpulse: false,\n\t\t\ttext: 'Pending Certificate Generation...',\n\t\t};\n\t}, [certificate]);\n\n\treturn (\n\t\t<div className=\"w-full max-w-2xl border border-border/50 rounded-md p-4 bg-gray-900/20\">\n\t\t\t<div className=\"mb-4\">\n\t\t\t\t<div className=\"w-full h-1.5 rounded-full overflow-clip flex shadow-sm bg-gray-800\">\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{ width: progress.width }}\n\t\t\t\t\t\tclassName={`grow transition-[width] duration-1000 ease-in-out motion-reduce:transition-none ${progress.color} ${\n\t\t\t\t\t\t\tprogress.pulse ? 'animate-pulse' : ''\n\t\t\t\t\t\t}`}\n\t\t\t\t\t>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<div className=\"text-[10px] text-muted-foreground font-light mt-1 italic\">{progress.text}</div>\n\t\t\t</div>\n\n\t\t\t<div className=\"grid gap-2 grid-cols-1 md:grid-cols-[80px_1fr] text-sm\">\n\t\t\t\t<div className=\"col-span-1 text-xs text-muted-foreground\">CNAME:</div>\n\t\t\t\t<div className=\"col-span-1 flex gap-2 items-center flex-wrap\">\n\t\t\t\t\t<div className=\"flex items-center gap-1 bg-gray-800 px-2 py-0.5 rounded text-xs\">\n\t\t\t\t\t\t<span className=\"truncate max-w-[150px]\" title={recordName}>\n\t\t\t\t\t\t\t{recordName}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\tclassName=\"h-4 w-4 p-0\"\n\t\t\t\t\t\t\tonClick={onCopyName}\n\t\t\t\t\t\t\ttitle=\"Copy Name\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<CopyIcon className=\"w-3 h-3\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t\t<ArrowIcon />\n\t\t\t\t\t<div className=\"flex items-center gap-1 bg-gray-800 px-2 py-0.5 rounded text-xs\">\n\t\t\t\t\t\t<span className=\"truncate max-w-[200px]\" title={cluster.fqdn || ''}>\n\t\t\t\t\t\t\t{cluster.fqdn}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\tclassName=\"h-4 w-4 p-0\"\n\t\t\t\t\t\t\tonClick={onCopyTarget}\n\t\t\t\t\t\t\ttitle=\"Copy Target\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<CopyIcon className=\"w-3 h-3\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t\t<div className=\"col-span-1 text-[10px] text-muted-foreground\">Domain ID:</div>\n\t\t\t\t<div className=\"col-span-1 flex gap-2 items-center\">\n\t\t\t\t\t<div className=\"flex items-center gap-1 bg-gray-800/50 px-2 py-0.5 rounded text-[10px] text-muted-foreground italic\">\n\t\t\t\t\t\t<span className=\"truncate max-w-[200px]\">{domain.id}</span>\n\t\t\t\t\t\t<Button type=\"button\" variant=\"ghost\" size=\"sm\" className=\"h-3 w-3 p-0\" onClick={onCopyId} title=\"Copy ID\">\n\t\t\t\t\t\t\t<CopyIcon className=\"w-2.5 h-2.5\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nfunction ArrowIcon() {\n\treturn (\n\t\t<svg\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tclassName=\"w-3 h-3 text-muted-foreground\"\n\t\t>\n\t\t\t<path d=\"M5 12h14\" />\n\t\t\t<path d=\"m12 5 7 7-7 7\" />\n\t\t</svg>\n\t);\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { queryOptions } from '@tanstack/react-query';\n\ninterface GetSearchByValueParams extends InstanceClientIdConfig {\n\tenabled: boolean;\n\tdatabaseName: string;\n\ttableName: string;\n\tsearchAttribute: string;\n\tsort: { attribute: string; descending: boolean };\n\tpageIndex: number;\n\tpageSize: number;\n\tonlyIfCached: boolean;\n\theaders?: Record<string, any>;\n}\n\ninterface SearchByValueRequest {\n\toperation: 'search_by_value';\n\tdatabase: string;\n\ttable: string;\n\tsearch_attribute: string;\n\tsearch_value: string;\n\tsort?: { attribute: string; descending: boolean };\n\toffset: number;\n\tlimit: number;\n\tget_attributes?: string[];\n\tonlyIfCached: boolean;\n\tnoCacheStore: boolean;\n}\n\nexport function getSearchByValueOptions(params: GetSearchByValueParams) {\n\tconst {\n\t\tenabled,\n\t\tentityId,\n\t\tdatabaseName,\n\t\ttableName,\n\t\tsearchAttribute,\n\t\tsort,\n\t\tpageIndex,\n\t\tpageSize,\n\t\tonlyIfCached,\n\t} = params;\n\treturn queryOptions({\n\t\tenabled,\n\t\tqueryKey: [\n\t\t\tentityId,\n\t\t\tdatabaseName,\n\t\t\ttableName,\n\t\t\t'search_by_value',\n\t\t\tsearchAttribute,\n\t\t\tsort.attribute || 'default',\n\t\t\tsort.descending || false,\n\t\t\tpageIndex || 0,\n\t\t\tpageSize || 0,\n\t\t\tonlyIfCached,\n\t\t] as const,\n\t\tretry: false,\n\t\tstaleTime: 60_000,\n\t\tgcTime: 5_000,\n\t\tqueryFn: () => getSearchByValue(params),\n\t});\n}\n\nexport async function getSearchByValue<T = Record<string, unknown>>({\n\tinstanceClient,\n\tdatabaseName,\n\ttableName,\n\tsearchAttribute,\n\tsort,\n\tpageIndex,\n\tpageSize,\n\tonlyIfCached,\n\theaders,\n}: Omit<GetSearchByValueParams, 'enabled'>) {\n\tconst customizedSort = sort.attribute.length && !(sort.attribute === searchAttribute && !sort.descending);\n\tconst response = await instanceClient.post<T[]>(\n\t\t'/',\n\t\t{\n\t\t\toperation: 'search_by_value',\n\t\t\tget_attributes: ['*'],\n\t\t\tdatabase: databaseName,\n\t\t\ttable: tableName,\n\t\t\tsearch_attribute: searchAttribute,\n\t\t\tsearch_value: '*',\n\t\t\tsort: customizedSort ? sort : undefined,\n\t\t\toffset: pageIndex * pageSize,\n\t\t\tlimit: pageSize,\n\t\t\tonlyIfCached: onlyIfCached,\n\t\t\tnoCacheStore: onlyIfCached,\n\t\t} satisfies SearchByValueRequest,\n\t\t{ timeout: 0, headers, validateStatus: (status) => status >= 200 && status < 400 || status === 404 },\n\t);\n\tif (response.status === 404) {\n\t\treturn { data: [] };\n\t}\n\treturn response;\n}\n","import { getInstanceClient } from '@/config/getInstanceClient';\nimport { getSearchByValue } from '@/integrations/api/instance/database/getSearchByValue';\nimport { queryOptions, useQuery } from '@tanstack/react-query';\n\nexport interface ChallengeCertificate {\n\tdomain: string;\n\tissueDate: string | null;\n\trenewalDate: string | null;\n\tchallengeToken: string;\n\tchallengeContent: string;\n\tinProgress: boolean;\n}\n\nexport function getChallengeCertificatesQueryOptions(clusterId?: string) {\n\treturn queryOptions({\n\t\tqueryKey: [clusterId, 'ChallengeCertificate'],\n\t\tqueryFn: async () => {\n\t\t\tif (!clusterId) { return []; }\n\t\t\tconst instanceClient = getInstanceClient({ id: clusterId, forceFabricConnect: true });\n\t\t\tconst { data } = await getSearchByValue<ChallengeCertificate>({\n\t\t\t\tsearchAttribute: 'domain',\n\t\t\t\tentityId: clusterId,\n\t\t\t\tdatabaseName: 'data',\n\t\t\t\ttableName: 'ChallengeCertificate',\n\t\t\t\tsort: { attribute: 'domain', descending: true },\n\t\t\t\tinstanceClient,\n\t\t\t\tonlyIfCached: false,\n\t\t\t\tpageIndex: 0,\n\t\t\t\tpageSize: 100,\n\t\t\t});\n\t\t\treturn data;\n\t\t},\n\t\tenabled: !!clusterId,\n\t\trefetchInterval: 5000,\n\t});\n}\n\nexport function useChallengeCertificates(clusterId?: string) {\n\treturn useQuery(getChallengeCertificatesQueryOptions(clusterId));\n}\n","import { Button } from '@/components/ui/button';\nimport { useCopyToClipboard } from '@/hooks/useCopyToClipboard';\nimport { Cluster, SchemaOrganizationDomain } from '@/integrations/api/api.patch';\nimport { extractDomainFromTLD } from '@/lib/string/extractDomainFromTLD';\nimport { CopyIcon } from 'lucide-react';\n\nexport function VerifyDomainOwnership(\n\t{ domain: { challengeToken, challengeTxtRecord, domain, id }, cluster: { fqdn } }: {\n\t\tdomain: SchemaOrganizationDomain;\n\t\tcluster: Cluster;\n\t},\n) {\n\tconst recordName = extractDomainFromTLD(domain);\n\tconst [onCopyTxtRecord, onCopyToken, onCopyName, onCopyTarget, onCopyId] = useCopyToClipboard(\n\t\tchallengeTxtRecord,\n\t\tchallengeToken,\n\t\trecordName,\n\t\tfqdn || '',\n\t\tid,\n\t);\n\n\treturn (\n\t\t<div className=\"grid gap-2 grid-cols-1 md:grid-cols-[80px_1fr] pb-6\">\n\t\t\t<div className=\"text-muted-foreground md:col-span-2 text-wrap\">\n\t\t\t\tProve that you own this domain by adding the following to your DNS registrar:\n\t\t\t</div>\n\n\t\t\t<div className=\"col-span-1\">Type:</div>\n\t\t\t<div className=\"col-span-1\">TXT</div>\n\n\t\t\t<div className=\"col-span-1\">Name:</div>\n\t\t\t<div className=\"col-span-1 flex gap-2 items-center\">\n\t\t\t\t<div className=\"flex items-center gap-1 bg-gray-700 rounded-md px-3 py-1 flex-1 overflow-hidden\">\n\t\t\t\t\t<input\n\t\t\t\t\t\tclassName=\"bg-transparent border-none outline-none w-full cursor-text truncate\"\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\treadOnly={true}\n\t\t\t\t\t\tname=\"challengeName\"\n\t\t\t\t\t\tvalue={challengeTxtRecord}\n\t\t\t\t\t\tonClick={onCopyTxtRecord}\n\t\t\t\t\t/>\n\t\t\t\t\t<Button type=\"button\" size=\"sm\" variant=\"ghost\" className=\"h-6 w-6 p-0 shrink-0\" onClick={onCopyTxtRecord}>\n\t\t\t\t\t\t<CopyIcon className=\"w-3.5 h-3.5\" />\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div className=\"col-span-1\">TTL:</div>\n\t\t\t<div className=\"col-span-1\">Auto</div>\n\n\t\t\t<div className=\"col-span-1\">Content:</div>\n\t\t\t<div className=\"col-span-1 flex gap-2 items-center\">\n\t\t\t\t<div className=\"flex items-center gap-1 bg-gray-700 rounded-md px-3 py-1 flex-1 overflow-hidden\">\n\t\t\t\t\t<input\n\t\t\t\t\t\tclassName=\"bg-transparent border-none outline-none w-full cursor-text truncate\"\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\treadOnly={true}\n\t\t\t\t\t\tname=\"challengeToken\"\n\t\t\t\t\t\tvalue={challengeToken}\n\t\t\t\t\t\tonClick={onCopyToken}\n\t\t\t\t\t/>\n\t\t\t\t\t<Button type=\"button\" size=\"sm\" variant=\"ghost\" className=\"h-6 w-6 p-0 shrink-0\" onClick={onCopyToken}>\n\t\t\t\t\t\t<CopyIcon className=\"w-3.5 h-3.5\" />\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div className=\"text-muted-foreground md:col-span-2 text-wrap mt-4\">\n\t\t\t\tWhile you're at it, you should also add the CNAME record to point to this cluster:\n\t\t\t</div>\n\n\t\t\t<div className=\"col-span-1\">Type:</div>\n\t\t\t<div className=\"col-span-1\">CNAME</div>\n\n\t\t\t<div className=\"col-span-1\">Name:</div>\n\t\t\t<div className=\"col-span-1 flex gap-2 items-center\">\n\t\t\t\t<div className=\"flex items-center gap-1 bg-gray-700 rounded-md px-3 py-1 flex-1 overflow-hidden\">\n\t\t\t\t\t<input\n\t\t\t\t\t\tclassName=\"bg-transparent border-none outline-none w-full cursor-text truncate\"\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\treadOnly={true}\n\t\t\t\t\t\tname=\"recordName\"\n\t\t\t\t\t\tvalue={recordName}\n\t\t\t\t\t\tonClick={onCopyName}\n\t\t\t\t\t/>\n\t\t\t\t\t<Button type=\"button\" size=\"sm\" variant=\"ghost\" className=\"h-6 w-6 p-0 shrink-0\" onClick={onCopyName}>\n\t\t\t\t\t\t<CopyIcon className=\"w-3.5 h-3.5\" />\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div className=\"col-span-1\">TTL:</div>\n\t\t\t<div className=\"col-span-1\">Auto</div>\n\n\t\t\t<div className=\"col-span-1\">Target:</div>\n\t\t\t<div className=\"col-span-1 flex gap-2 items-center\">\n\t\t\t\t<div className=\"flex items-center gap-1 bg-gray-700 rounded-md px-3 py-1 flex-1 overflow-hidden\">\n\t\t\t\t\t<input\n\t\t\t\t\t\tclassName=\"bg-transparent border-none outline-none w-full cursor-text truncate\"\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\treadOnly={true}\n\t\t\t\t\t\tname=\"recordTarget\"\n\t\t\t\t\t\tvalue={fqdn}\n\t\t\t\t\t\tonClick={onCopyTarget}\n\t\t\t\t\t/>\n\t\t\t\t\t<Button type=\"button\" size=\"sm\" variant=\"ghost\" className=\"h-6 w-6 p-0 shrink-0\" onClick={onCopyTarget}>\n\t\t\t\t\t\t<CopyIcon className=\"w-3.5 h-3.5\" />\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div className=\"col-span-1 text-xs\">Domain ID:</div>\n\t\t\t<div className=\"col-span-1 flex gap-2 items-center\">\n\t\t\t\t<div className=\"flex items-center gap-1 bg-gray-800 rounded-md px-3 py-0.5 text-xs text-muted-foreground italic flex-1 overflow-hidden\">\n\t\t\t\t\t<input\n\t\t\t\t\t\tclassName=\"bg-transparent border-none outline-none w-full cursor-text truncate\"\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\treadOnly={true}\n\t\t\t\t\t\tname=\"domainId\"\n\t\t\t\t\t\tvalue={id}\n\t\t\t\t\t\tonClick={onCopyId}\n\t\t\t\t\t/>\n\t\t\t\t\t<Button type=\"button\" size=\"sm\" variant=\"ghost\" className=\"h-5 w-5 p-0 shrink-0\" onClick={onCopyId}>\n\t\t\t\t\t\t<CopyIcon className=\"w-3 h-3\" />\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div className=\"text-muted-foreground md:col-span-2 text-wrap mt-2\">\n\t\t\t\tThen after your DNS TTL elapses, click the \"Validate\" button above.\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","import { apiClient } from '@/config/apiClient';\nimport { useMutation } from '@tanstack/react-query';\n\ninterface Params {\n\tclusterId: string;\n\tdomainIds: string[];\n\tgenerateDomainCerts: boolean;\n}\n\nasync function setDomainIdsOnCluster({ clusterId, domainIds, generateDomainCerts }: Params) {\n\t// TODO: API does not describe this endpoint permutation\n\tconst { data } = await apiClient.put(`/Cluster/${clusterId}` as '/Cluster/{id}', {\n\t\tdomainIds,\n\t\tgenerateDomainCerts,\n\t}, { timeout: 0 });\n\treturn data;\n}\n\nexport function useSetDomainIdsOnCluster() {\n\treturn useMutation({\n\t\tmutationFn: (params: Params) => setDomainIdsOnCluster(params),\n\t});\n}\n","import { apiClient } from '@/config/apiClient';\nimport { useMutation } from '@tanstack/react-query';\nimport z from 'zod';\n\nexport const DeleteDomainSchema = z.object({\n\tdomainId: z.string(),\n});\n\nasync function deleteDomainSubmit(formData: z.infer<typeof DeleteDomainSchema>) {\n\t// TODO: API does not describe this endpoint.\n\tconst { data } = await apiClient.delete(`/Domain/${formData.domainId}` as any);\n\treturn data;\n}\n\nexport function useDeleteDomain() {\n\treturn useMutation({\n\t\tmutationFn: (formData: z.infer<typeof DeleteDomainSchema>) => deleteDomainSubmit(formData),\n\t});\n}\n","export function unique<T>(arr: T[]): T[] {\n\treturn [...new Set(arr)];\n}\n","import { Button } from '@/components/ui/button';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';\nimport { isRunning } from '@/components/ui/utils/badgeStatus';\nimport { AssociateDomainWithCluster } from '@/features/cluster/domains/AssociateDomainWithCluster';\nimport { CertificateProgress } from '@/features/cluster/domains/components/CertificateProgress';\nimport { useChallengeCertificates } from '@/features/cluster/domains/queries/getChallengeCertificates';\nimport { VerifyDomainOwnership } from '@/features/cluster/domains/VerifyDomainOwnership';\nimport { useSetDomainIdsOnCluster } from '@/features/clusters/mutations/setDomainIdsOnCluster';\nimport { useDeleteDomain } from '@/features/organization/mutations/deleteDomain';\nimport { Cluster, SchemaOrganizationDomain } from '@/integrations/api/api.patch';\nimport { clusterIsSelfManaged } from '@/integrations/api/clusterIsSelfManaged';\nimport { unique } from '@/lib/arrays/unique';\nimport { queryClient } from '@/react-query/queryClient';\nimport { ColumnDef, createColumnHelper } from '@tanstack/react-table';\nimport { useCallback, useMemo } from 'react';\nimport { toast } from 'sonner';\n\nconst columnHelper = createColumnHelper<SchemaOrganizationDomain>();\n\nexport function useDataTableColumns(\n\tcluster: Cluster,\n\tselectedDomainIds: string[],\n\tonToggleDomainSelection: (domainId: string) => void,\n): Array<ColumnDef<SchemaOrganizationDomain>> {\n\tconst { data: challengeCertificates } = useChallengeCertificates(cluster.id);\n\tconst isGeneratingCert = useMemo(\n\t\t() => !!challengeCertificates?.some((cert) => !cert.issueDate || cert.inProgress),\n\t\t[challengeCertificates],\n\t);\n\n\tconst { mutate: setDomainIds, isPending: addPending } = useSetDomainIdsOnCluster();\n\tconst { mutate: deleteDomain, isPending: deletePending } = useDeleteDomain();\n\tconst isPending = addPending || deletePending;\n\n\tconst bindDomainToThisCluster = useCallback((domainId: string, generateDomainCerts: boolean) => {\n\t\tif (!isRunning(cluster.status)) {\n\t\t\ttoast.error('Cluster is currently ' + cluster.status, { description: 'To bind a domain, it must be running.' });\n\t\t\treturn;\n\t\t}\n\t\tsetDomainIds({\n\t\t\tclusterId: cluster.id,\n\t\t\tdomainIds: unique((cluster.domainIds?.slice() || []).concat([domainId])),\n\t\t\tgenerateDomainCerts,\n\t\t}, {\n\t\t\tonSuccess: () => {\n\t\t\t\tvoid queryClient.invalidateQueries({ queryKey: [cluster.organizationId], refetchType: 'active' });\n\t\t\t\ttoast.success(\n\t\t\t\t\t'Domain bound!' + (generateDomainCerts\n\t\t\t\t\t\t? ' Certificates are being generated in the background now.'\n\t\t\t\t\t\t: ''),\n\t\t\t\t);\n\t\t\t},\n\t\t});\n\t}, [setDomainIds, cluster]);\n\n\tconst deleteDomainById = useCallback((domainId: string) => {\n\t\tdeleteDomain({\n\t\t\tdomainId: domainId,\n\t\t}, {\n\t\t\tonSuccess: () => {\n\t\t\t\tvoid queryClient.invalidateQueries({ queryKey: [cluster.organizationId, 'domains'], refetchType: 'active' });\n\t\t\t\ttoast.success('Domain removed!');\n\t\t\t},\n\t\t});\n\t}, [deleteDomain]);\n\n\tconst unbindDomainById = useCallback((domainId: string) => {\n\t\tsetDomainIds({\n\t\t\tclusterId: cluster.id,\n\t\t\tdomainIds: (cluster.domainIds?.slice() || []).filter((id) => id !== domainId),\n\t\t\tgenerateDomainCerts: false,\n\t\t}, {\n\t\t\tonSuccess: () => {\n\t\t\t\tvoid queryClient.invalidateQueries({ queryKey: [cluster.organizationId], refetchType: 'active' });\n\t\t\t\ttoast.success('Domain unbound!');\n\t\t\t},\n\t\t});\n\t}, [deleteDomain]);\n\n\treturn useMemo(() => [\n\t\tcolumnHelper.display({\n\t\t\tid: 'select',\n\t\t\theader: 'Bind',\n\t\t\tsize: 50,\n\t\t\tcell: (props) => {\n\t\t\t\tconst domain = props.row.original;\n\t\t\t\tconst canBind = domain.status === 'ACTIVE' && !domain.clusterId && !clusterIsSelfManaged(cluster);\n\t\t\t\tif (!canBind) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\treturn (\n\t\t\t\t\t<label className=\"p-10 -m-10\">\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\tchecked={selectedDomainIds.includes(domain.id)}\n\t\t\t\t\t\t\tonChange={() => onToggleDomainSelection(domain.id)}\n\t\t\t\t\t\t\tdisabled={isPending || isGeneratingCert}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</label>\n\t\t\t\t);\n\t\t\t},\n\t\t}),\n\t\tcolumnHelper.display({\n\t\t\theader: 'Domains',\n\t\t\tid: 'domain',\n\t\t\tenableSorting: false,\n\t\t\tsize: 150,\n\t\t\tcell: (props) => {\n\t\t\t\tconst domain = props.row.original;\n\t\t\t\treturn (\n\t\t\t\t\t<Tooltip>\n\t\t\t\t\t\t<TooltipTrigger asChild>\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<div>{domain.domain}</div>\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tvariant=\"destructiveGhost\"\n\t\t\t\t\t\t\t\t\tclassName=\"text-muted-foreground text-xs\"\n\t\t\t\t\t\t\t\t\tdisabled={isPending || !!domain.clusterId}\n\t\t\t\t\t\t\t\t\tonClick={() => deleteDomainById(domain.id)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tRemove Domain\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t</TooltipTrigger>\n\t\t\t\t\t\t<TooltipContent\n\t\t\t\t\t\t\tside=\"bottom\"\n\t\t\t\t\t\t\talign=\"center\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{domain.clusterId\n\t\t\t\t\t\t\t\t? 'To delete this domain, please unbind it from all clusters first.'\n\t\t\t\t\t\t\t\t: 'Remember to clean up your DNS records!'}\n\t\t\t\t\t\t</TooltipContent>\n\t\t\t\t\t</Tooltip>\n\t\t\t\t);\n\t\t\t},\n\t\t}),\n\t\tcolumnHelper.display({\n\t\t\theader: 'Next Steps',\n\t\t\tenableSorting: false,\n\t\t\tsize: 500,\n\t\t\tid: 'nextSteps',\n\t\t\tcell: (props) => {\n\t\t\t\tconst domain = props.row.original;\n\n\t\t\t\tconst certForDomain = challengeCertificates?.find((c) => c.domain === domain.domain);\n\n\t\t\t\tif (domain.status === 'ACTIVE' && domain.clusterId) {\n\t\t\t\t\tif (cluster.id === domain.clusterId) {\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<div>Bound to this cluster</div>\n\t\t\t\t\t\t\t\t{certForDomain && (!certForDomain.issueDate || certForDomain.inProgress) && (\n\t\t\t\t\t\t\t\t\t<div className=\"py-2\">\n\t\t\t\t\t\t\t\t\t\t<CertificateProgress certificate={certForDomain} domain={domain} cluster={cluster} />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tvariant=\"destructiveGhost\"\n\t\t\t\t\t\t\t\t\tclassName=\"text-muted-foreground text-xs\"\n\t\t\t\t\t\t\t\t\tdisabled={isPending}\n\t\t\t\t\t\t\t\t\tonClick={() => unbindDomainById(domain.id)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tUnbind Domain\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn `Bound to cluster ${domain.clusterId}`;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (domain.status === 'PENDING_VALIDATION') {\n\t\t\t\t\treturn <VerifyDomainOwnership domain={domain} cluster={cluster} />;\n\t\t\t\t}\n\n\t\t\t\tif (clusterIsSelfManaged(cluster)) {\n\t\t\t\t\treturn `Cannot be associated with this self-managed cluster.`;\n\t\t\t\t}\n\n\t\t\t\tif (domain.status === 'ACTIVE' && !domain.clusterId) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<AssociateDomainWithCluster\n\t\t\t\t\t\t\tcluster={cluster}\n\t\t\t\t\t\t\tdomain={domain}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Otherwise... probably an unhandled status:\n\t\t\t\treturn domain.status;\n\t\t\t},\n\t\t}),\n\t], [\n\t\tcluster,\n\t\tbindDomainToThisCluster,\n\t\tisPending,\n\t\tchallengeCertificates,\n\t\tisGeneratingCert,\n\t\tselectedDomainIds,\n\t\tonToggleDomainSelection,\n\t]);\n}\n","import { apiClient } from '@/config/apiClient';\nimport { useMutation } from '@tanstack/react-query';\nimport z from 'zod';\n\nexport const AddOrganizationDomainSchema = z.object({\n\tdomain: z.string(),\n\torganizationId: z.string(),\n});\n\nexport async function onAddDomainToOrganizationSubmit(formData: z.infer<typeof AddOrganizationDomainSchema>) {\n\t// TODO: API does not describe this endpoint.\n\tconst { data } = await apiClient.post('/Domain/' as any, formData);\n\treturn data;\n}\n\nexport function useAddDomainToOrganization() {\n\treturn useMutation({\n\t\tmutationFn: (formData: z.infer<typeof AddOrganizationDomainSchema>) => onAddDomainToOrganizationSubmit(formData),\n\t});\n}\n","import { apiClient } from '@/config/apiClient';\n\nexport async function validateDomainInOrganization(domainId: string) {\n\t// TODO: API does not describe this endpoint.\n\tconst { data } = await apiClient.post(\n\t\t`/Domain/${domainId}/validate` as any,\n\t);\n\treturn data;\n}\n","import { apiClient } from '@/config/apiClient';\nimport { SchemaOrganizationDomain } from '@/integrations/api/api.patch';\nimport { queryOptions } from '@tanstack/react-query';\n\nasync function getOrganizationDomains(organizationId: string): Promise<SchemaOrganizationDomain[]> {\n\tconst { data } = await apiClient.get(`/Domain/?organizationId=${organizationId}` as any);\n\t// TODO: The API is not describing itself accurately.\n\treturn data;\n}\n\nexport function getOrganizationDomainsQueryOptions(organizationId: string) {\n\treturn queryOptions({\n\t\tqueryKey: [organizationId, 'domains'],\n\t\tqueryFn: () => getOrganizationDomains(organizationId),\n\t});\n}\n","import { SimpleBrowseDataTable } from '@/components/SimpleBrowseDataTable';\nimport { Button } from '@/components/ui/button';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { isRunning } from '@/components/ui/utils/badgeStatus';\nimport { useDataTableColumns } from '@/features/cluster/domains/constants/tableDefinition';\nimport { getClusterInfoQueryOptions } from '@/features/cluster/queries/getClusterInfoQuery';\nimport { useSetDomainIdsOnCluster } from '@/features/clusters/mutations/setDomainIdsOnCluster';\nimport {\n\tAddOrganizationDomainSchema,\n\tuseAddDomainToOrganization,\n} from '@/features/organization/mutations/addDomainToOrganization';\nimport { validateDomainInOrganization } from '@/features/organization/mutations/validateDomainInOrganization';\nimport { getOrganizationDomainsQueryOptions } from '@/features/organization/queries/getOrganizationDomains';\nimport { useOrganizationRolePermissions } from '@/hooks/usePermissions';\nimport { useRefreshClick } from '@/hooks/useRefreshClick';\nimport { SchemaOrganizationDomain } from '@/integrations/api/api.patch';\nimport { unique } from '@/lib/arrays/unique';\nimport { pluralize } from '@/lib/pluralize';\nimport { queryClient } from '@/react-query/queryClient';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useQuery, useSuspenseQuery } from '@tanstack/react-query';\nimport { useParams } from '@tanstack/react-router';\nimport { ListTodoIcon, PlusIcon, RefreshCwIcon, Save } from 'lucide-react';\nimport { useCallback, useMemo, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport z from 'zod';\n\nexport function DomainsManagement() {\n\tconst { organizationId, clusterId }: { organizationId: string; clusterId: string } = useParams({ strict: false });\n\tconst { data: cluster } = useSuspenseQuery(\n\t\tgetClusterInfoQueryOptions(clusterId, true),\n\t);\n\n\tconst { update } = useOrganizationRolePermissions(organizationId);\n\tconst {\n\t\tdata: organizationDomains,\n\t\trefetch,\n\t\tisFetching,\n\t\tisRefetching,\n\t} = useQuery(getOrganizationDomainsQueryOptions(organizationId));\n\n\tconst pendingDomains = useMemo(\n\t\t() => organizationDomains?.filter(o => o.status === 'PENDING_VALIDATION') || [],\n\t\t[organizationDomains],\n\t);\n\n\tconst [sortTableDataParams] = useState({\n\t\tattribute: 'domain',\n\t\tdescending: false,\n\t});\n\tconst sortingState = useMemo(\n\t\t() => [\n\t\t\t{\n\t\t\t\tdesc: sortTableDataParams.descending,\n\t\t\t\tid: sortTableDataParams.attribute,\n\t\t\t},\n\t\t],\n\t\t[sortTableDataParams],\n\t);\n\n\tconst onRefreshClick = useRefreshClick(refetch);\n\n\tconst [selectedDomainIds, setSelectedDomainIds] = useState<string[]>([]);\n\tconst onToggleDomainSelection = useCallback((domainId: string) => {\n\t\tsetSelectedDomainIds((prev) =>\n\t\t\tprev.includes(domainId) ? prev.filter((id) => id !== domainId) : [...prev, domainId]\n\t\t);\n\t}, []);\n\n\tconst { mutate: setDomainIds, isPending: isBindPending } = useSetDomainIdsOnCluster();\n\n\tconst onBindClick = useCallback(() => {\n\t\tif (!isRunning(cluster.status)) {\n\t\t\ttoast.error('Cluster is currently ' + cluster.status, { description: 'To bind a domain, it must be running.' });\n\t\t\treturn;\n\t\t}\n\n\t\tsetDomainIds({\n\t\t\tclusterId: cluster.id,\n\t\t\tdomainIds: unique((cluster.domainIds?.slice() || []).concat(selectedDomainIds)),\n\t\t\tgenerateDomainCerts: true,\n\t\t}, {\n\t\t\tonSuccess: () => {\n\t\t\t\tvoid queryClient.invalidateQueries({ queryKey: [cluster.organizationId], refetchType: 'active' });\n\t\t\t\ttoast.success('Domain(s) bound! Certificates are being generated in the background now.');\n\t\t\t\tsetSelectedDomainIds([]);\n\t\t\t},\n\t\t});\n\t}, [cluster, selectedDomainIds, setDomainIds]);\n\n\tconst { mutateAsync: addDomain, isPending: isAddPending } = useAddDomainToOrganization();\n\tconst form = useForm({\n\t\tresolver: zodResolver(AddOrganizationDomainSchema),\n\t\tdefaultValues: {\n\t\t\tdomain: '',\n\t\t\torganizationId,\n\t\t},\n\t});\n\n\tconst onSubmitClick = useCallback(\n\t\tasync (formData: z.infer<typeof AddOrganizationDomainSchema>) => {\n\t\t\tif (formData) {\n\t\t\t\tconst domains = formData.domain.split(/[,\\s]+/).map((d: string) => d.trim()).filter(Boolean);\n\t\t\t\tfor (const domain of domains) {\n\t\t\t\t\tawait addDomain({ ...formData, domain });\n\t\t\t\t}\n\t\t\t\tform.reset();\n\t\t\t\tawait refetch();\n\t\t\t\ttoast.success(\n\t\t\t\t\t`${\n\t\t\t\t\t\tpluralize(domains.length, 'Domain', 'Domains')\n\t\t\t\t\t} added! Please add the txt record above to your domain registrar.`,\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t\t[addDomain, form, refetch],\n\t);\n\n\tconst onValidateClick = useCallback(async () => {\n\t\tconst message = `Validating ${pluralize(pendingDomains.length, 'domain', 'domains')}...`;\n\t\tconst id = 'validatingDomains';\n\t\tlet checked = 0;\n\t\tlet failed = 0;\n\t\tfor (const pendingDomain of pendingDomains) {\n\t\t\ttry {\n\t\t\t\ttoast.loading(message, {\n\t\t\t\t\tdescription: `${checked++} of ${pendingDomains.length} checked`,\n\t\t\t\t\tid,\n\t\t\t\t});\n\t\t\t\tawait validateDomainInOrganization(pendingDomain.id);\n\t\t\t} catch {\n\t\t\t\tfailed += 1;\n\t\t\t}\n\t\t}\n\t\tif (failed > 0) {\n\t\t\ttoast.error('Validation failed!', {\n\t\t\t\tdescription:\n\t\t\t\t\t`Please make sure the TXT record has been put in place. You may need to wait a bit for the DNS change to propagate.`,\n\t\t\t\tid,\n\t\t\t});\n\t\t} else {\n\t\t\tawait refetch();\n\t\t\ttoast.success('Validation succeeded!', {\n\t\t\t\tdescription: `Please take a look at the next steps for newly verified domains.`,\n\t\t\t\tid,\n\t\t\t});\n\t\t}\n\t}, [pendingDomains]);\n\n\tconst dataTableColumns = useDataTableColumns(cluster, selectedDomainIds, onToggleDomainSelection);\n\n\tconst domainValue = form.watch('domain');\n\tconst isApex = useMemo(() => {\n\t\tif (typeof domainValue !== 'string') { return false; }\n\t\tconst parts = domainValue.trim().split('.');\n\t\treturn parts.length === 2;\n\t}, [domainValue]);\n\n\tconst suggestWww = useCallback(() => {\n\t\tif (typeof domainValue === 'string') {\n\t\t\tform.setValue('domain', `${domainValue.trim()}, www.${domainValue.trim()}`);\n\t\t}\n\t}, [domainValue, form]);\n\n\treturn (\n\t\t<SimpleBrowseDataTable<SchemaOrganizationDomain, unknown>\n\t\t\tdata={organizationDomains || []}\n\t\t\tisFetching={isFetching || isRefetching}\n\t\t\tcolumns={dataTableColumns}\n\t\t\tsortingState={sortingState}\n\t\t>\n\t\t\t<div className=\"w-full flex flex-col md:flex-row items-center md:justify-between md:space-x-2 space-y-2 md:space-y-0\">\n\t\t\t\t{update && (\n\t\t\t\t\t<Form {...form}>\n\t\t\t\t\t\t<form\n\t\t\t\t\t\t\tid=\"cluster-add-domain-form\"\n\t\t\t\t\t\t\tname=\"cluster-add-domain-form\"\n\t\t\t\t\t\t\tonSubmit={form.handleSubmit(onSubmitClick)}\n\t\t\t\t\t\t\tclassName=\"flex gap-1 flex-col md:flex-row\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\t\tname=\"domain\"\n\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t<FormItem className=\"flex-1\">\n\t\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">New Domain Name</FormLabel>\n\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t<Input type=\"text\" enterKeyHint=\"done\" autoComplete=\"off\" {...field} />\n\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t{isApex && (\n\t\t\t\t\t\t\t\t\t\t\t<div className=\"mt-1 flex gap-4\">\n\t\t\t\t\t\t\t\t\t\t\t\tAdding an apex domain?\n\t\t\t\t\t\t\t\t\t\t\t\t<Button variant=\"positiveOutline\" type=\"button\" onClick={suggestWww}>\n\t\t\t\t\t\t\t\t\t\t\t\t\tAdd www as well\n\t\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t<FormMessage>\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-muted-foreground italic\">\n\t\t\t\t\t\t\t\t\t\t\t\tType in a domain like example.com or your.example.com, and you'll be guided through validating\n\t\t\t\t\t\t\t\t\t\t\t\tand binding your cluster to it.\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t</FormMessage>\n\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<div className=\"flex-0 self-start flex gap-1 md:pt-6.5\">\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\t\tvariant=\"submit\"\n\t\t\t\t\t\t\t\t\tdisabled={isAddPending}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<PlusIcon /> Add\n\t\t\t\t\t\t\t\t</Button>\n\n\t\t\t\t\t\t\t\t{pendingDomains.length > 0 && (\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\tvariant=\"positiveOutline\"\n\t\t\t\t\t\t\t\t\t\tonClick={onValidateClick}\n\t\t\t\t\t\t\t\t\t\taccessKey=\"r\"\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdisabled={isFetching || isRefetching}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<ListTodoIcon />{' '}\n\t\t\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t\t\t<u>V</u>alidate\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tvariant=\"defaultOutline\"\n\t\t\t\t\t\t\t\t\tonClick={onRefreshClick}\n\t\t\t\t\t\t\t\t\taccessKey=\"r\"\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tdisabled={isFetching || isRefetching}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<RefreshCwIcon />{' '}\n\t\t\t\t\t\t\t\t\t<span className=\"hidden lg:inline-block\">\n\t\t\t\t\t\t\t\t\t\t<u>R</u>efresh\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</form>\n\t\t\t\t\t</Form>\n\t\t\t\t)}\n\n\t\t\t\t{selectedDomainIds.length > 0 && (\n\t\t\t\t\t<div className=\"flex-0 self-start md:pt-6.5\">\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"submit\"\n\t\t\t\t\t\t\tonClick={onBindClick}\n\t\t\t\t\t\t\tdisabled={isBindPending}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Save /> Bind {pluralize(selectedDomainIds.length, 'Domain', 'Domains')}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</SimpleBrowseDataTable>\n\t);\n}\n","import { NestedContentWithSubNavMenu } from '@/components/NestedContentWithSubNavMenu';\nimport { DomainsManagement } from './Management';\n\nexport function DomainsPage() {\n\treturn (\n\t\t<NestedContentWithSubNavMenu className=\"flex flex-col justify-start max-w-4xl\">\n\t\t\t<DomainsManagement />\n\t\t</NestedContentWithSubNavMenu>\n\t);\n}\n","import { zodRequirePassword } from '@/lib/zod/password';\nimport { zodRequireUsername } from '@/lib/zod/username';\nimport { z } from 'zod';\n\nexport const AddUserFormSchema = z\n\t.object({\n\t\tusername: zodRequireUsername,\n\t\trole: z\n\t\t\t.string()\n\t\t\t.nonempty({\n\t\t\t\terror: 'Please select a role.',\n\t\t\t}),\n\t\tpassword: zodRequirePassword\n\t\t\t.min(8, { error: 'Password must be at least 8 characters long.' }),\n\t\tconfirmPassword: z.string(),\n\t})\n\t.refine((data) => data.password === data.confirmPassword, {\n\t\terror: 'Passwords do not match.',\n\t\tpath: ['confirmPassword'],\n\t});\n","import { apiClient } from '@/config/apiClient';\n\nexport async function resetPasswordUpdater(clusterId: string) {\n\tawait apiClient.patch(`/ResetPasswordUpdater/${clusterId}` as '/ResetPasswordUpdater/{id}');\n}\n","import { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { useMutation } from '@tanstack/react-query';\n\ninterface AddUserFormData extends InstanceClientConfig {\n\tactive: boolean;\n\tpassword: string;\n\trole: string;\n\tusername: string;\n}\n\nexport async function onAddUserSubmit(formData: AddUserFormData) {\n\tconst { instanceClient, ...userData } = formData;\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation: 'add_user',\n\t\t...userData,\n\t});\n\treturn data;\n}\n\nexport function useAddUserMutation() {\n\treturn useMutation({\n\t\tmutationFn: onAddUserSubmit,\n\t});\n}\n","import { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { useMutation } from '@tanstack/react-query';\n\nexport interface AlterUserRequestBody extends InstanceClientConfig {\n\tusername?: string;\n\tpassword?: string;\n\trole?: string;\n\tactive?: boolean;\n}\n\ninterface AlterUserResponse {\n\tmessage: string;\n\tskipped_hashes: string[];\n\ttxn_time: number;\n\tupdate_hashes: string[];\n}\n\nexport async function onAlterUser({\n\tusername,\n\tpassword,\n\trole,\n\tactive,\n\tinstanceClient,\n}: AlterUserRequestBody): Promise<AlterUserResponse> {\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation: 'alter_user',\n\t\tusername,\n\t\tpassword,\n\t\trole,\n\t\tactive,\n\t});\n\treturn data as AlterUserResponse;\n}\n\nexport function useAlterUser() {\n\treturn useMutation({\n\t\tmutationFn: onAlterUser,\n\t});\n}\n","import { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { useMutation } from '@tanstack/react-query';\n\ninterface DeleteUserData extends InstanceClientConfig {\n\tusername: string;\n}\n\ninterface DeleteUserResponse {\n\tmessage: string;\n}\n\nexport async function onDeleteUser({ username, instanceClient }: DeleteUserData) {\n\tconst { data } = await instanceClient.post<DeleteUserResponse>('/', {\n\t\toperation: 'drop_user',\n\t\tusername,\n\t});\n\treturn data;\n}\n\nexport function useDeleteUserMutation() {\n\treturn useMutation({\n\t\tmutationFn: onDeleteUser,\n\t});\n}\n","import { defaultClusterUsername } from '@/config/constants';\nimport { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { resetPasswordUpdater } from '@/features/cluster/queries/resetPasswordUpdater';\nimport { useMutation } from '@tanstack/react-query';\nimport { onAddUserSubmit } from './addUser';\nimport { onAlterUser } from './alterUser';\nimport { onDeleteUser } from './deleteUser';\nimport { onInstanceLogoutSubmit } from './onInstanceLogoutSubmit';\nimport { LoginInfoResponse, onInstanceLoginSubmit } from './useInstanceLoginMutation';\n\ninterface InstanceResetPasswordParams extends InstanceClientConfig {\n\tclusterId: string;\n\tinitialUsername: string;\n\tdesiredUsername: string;\n\tnewPassword: string;\n\ttempPassword: string | undefined;\n}\n\nasync function onInstanceResetPassword({\n\tclusterId,\n\tinitialUsername,\n\tdesiredUsername,\n\tnewPassword,\n\ttempPassword,\n\tinstanceClient: initialInstanceClient,\n}: InstanceResetPasswordParams): Promise<LoginInfoResponse> {\n\t// Do we have a temporary password?\n\tif (!tempPassword) {\n\t\tthrow new Error('You may not have permission to set the password on this cluster.');\n\t}\n\tlet instanceClient = initialInstanceClient;\n\ttry {\n\t\t// Sign in with the temporary password,\n\t\tconst loginResponse = await onInstanceLoginSubmit({\n\t\t\tusername: initialUsername,\n\t\t\tpassword: tempPassword,\n\t\t\tinstanceClient,\n\t\t\tentityId: clusterId,\n\t\t});\n\t\tif (loginResponse.instanceClient) {\n\t\t\tinstanceClient = loginResponse.instanceClient;\n\t\t}\n\t\t// if the usernames match, we need to alter the user...\n\t\tif (desiredUsername === defaultClusterUsername) {\n\t\t\tawait onAlterUser({\n\t\t\t\tusername: desiredUsername,\n\t\t\t\tpassword: newPassword,\n\t\t\t\tinstanceClient,\n\t\t\t});\n\t\t} else {\n\t\t\t// ... or create a new user!\n\t\t\tawait onAddUserSubmit({\n\t\t\t\tusername: desiredUsername,\n\t\t\t\tpassword: newPassword,\n\t\t\t\trole: 'super_user',\n\t\t\t\tactive: true,\n\t\t\t\tinstanceClient,\n\t\t\t});\n\t\t\t// since we created a new user, we should log in with the new one\n\t\t\tawait onInstanceLoginSubmit({\n\t\t\t\tusername: desiredUsername,\n\t\t\t\tpassword: newPassword,\n\t\t\t\tinstanceClient,\n\t\t\t\tentityId: clusterId,\n\t\t\t});\n\t\t\t// clean up the old one\n\t\t\tawait onDeleteUser({\n\t\t\t\tusername: defaultClusterUsername,\n\t\t\t\tinstanceClient,\n\t\t\t});\n\t\t}\n\t\t// and finally, tell the central manager that we changed their password.\n\t\tawait resetPasswordUpdater(clusterId);\n\t\treturn loginResponse;\n\t} catch (err) {\n\t\t// If something went wrong, logout as well.\n\t\tawait onInstanceLogoutSubmit({\n\t\t\tentityId: clusterId,\n\t\t\tinstanceClient,\n\t\t});\n\t\tthrow err;\n\t}\n}\n\nexport function useInstanceResetPasswordMutation() {\n\treturn useMutation<LoginInfoResponse, Error, InstanceResetPasswordParams>({\n\t\tmutationFn: onInstanceResetPassword,\n\t});\n}\n","import { Breadcrumbs } from '@/components/Breadcrumbs';\nimport { Button } from '@/components/ui/button';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { defaultClusterUsername, defaultInstanceRouteUpOne } from '@/config/constants';\nimport { useInstanceClient } from '@/config/useInstanceClient';\nimport { authStore } from '@/features/auth/store/authStore';\nimport { useCloudAuth } from '@/hooks/useAuth';\nimport { AddUserFormSchema } from '@/integrations/api/instance/auth/addUserFormSchema';\nimport { useInstanceResetPasswordMutation } from '@/integrations/api/instance/auth/useInstanceResetPasswordMutation';\nimport { getOperationsUrlForCluster } from '@/lib/urls/getOperationsUrlForCluster';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useQuery } from '@tanstack/react-query';\nimport { Navigate, useNavigate, useParams, useRouter, useSearch } from '@tanstack/react-router';\nimport { ActivityIcon } from 'lucide-react';\nimport { useCallback, useEffect, useMemo } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { getClusterInfoQueryOptions } from './queries/getClusterInfoQuery';\n\nexport function FinishSetup() {\n\tconst { user } = useCloudAuth();\n\tconst { clusterId }: { clusterId: string } = useParams({ strict: false });\n\tconst { data: cluster } = useQuery(\n\t\tgetClusterInfoQueryOptions(clusterId, true),\n\t);\n\n\tconst navigate = useNavigate();\n\tconst operationsUrl = useMemo(() => getOperationsUrlForCluster(cluster), [cluster]);\n\tconst instanceClient = useInstanceClient({ operationsUrl });\n\n\tconst { redirect } = useSearch({ strict: false });\n\tconst router = useRouter();\n\n\tconst methods = useForm({\n\t\tresolver: zodResolver(AddUserFormSchema),\n\t\tdefaultValues: {\n\t\t\tconfirmPassword: '',\n\t\t\tpassword: '',\n\t\t\trole: 'super_user',\n\t\t\tusername: user?.email ?? '',\n\t\t},\n\t});\n\tconst { setFocus, control, handleSubmit } = methods;\n\n\tuseEffect(() => {\n\t\tsetFocus('password');\n\t}, [setFocus]);\n\n\tconst tempPassword = cluster?.instances?.find(i => i.tempPassword)?.tempPassword;\n\n\tconst { mutate: submitInstanceResetPassword, isPending } = useInstanceResetPasswordMutation();\n\n\tconst submitForm = useCallback(async (formData: z.infer<typeof AddUserFormSchema>) => {\n\t\tif (!operationsUrl) {\n\t\t\ttoast.error('Cluster is not yet fully loaded, please wait a moment before trying to sign in.');\n\t\t\treturn;\n\t\t}\n\t\tsubmitInstanceResetPassword({\n\t\t\tinstanceClient,\n\t\t\tclusterId,\n\t\t\tnewPassword: formData.password,\n\t\t\ttempPassword,\n\t\t\tinitialUsername: defaultClusterUsername,\n\t\t\tdesiredUsername: formData.username,\n\t\t}, {\n\t\t\tonSuccess: async ({ message, user }) => {\n\t\t\t\ttoast.success(message);\n\t\t\t\tauthStore.setUserForEntity(cluster!, user);\n\t\t\t\tvoid router.invalidate();\n\t\t\t\tawait navigate({ to: redirect?.startsWith('/') ? redirect : defaultInstanceRouteUpOne });\n\t\t\t},\n\t\t});\n\t}, [\n\t\tcluster,\n\t\tclusterId,\n\t\tinstanceClient,\n\t\tnavigate,\n\t\toperationsUrl,\n\t\tredirect,\n\t\trouter,\n\t\tsubmitInstanceResetPassword,\n\t\ttempPassword,\n\t]);\n\n\tif (cluster && !cluster.resetPassword) {\n\t\treturn <Navigate to=\"../sign-in\" replace={true} />;\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t<nav className=\"fixed top-20 w-full h-12 z-39 px-4 md:px-12 bg-grey-700 flex items-center\">\n\t\t\t\t<Breadcrumbs />\n\t\t\t</nav>\n\t\t\t<div className=\"items-center justify-center flex mt-32 py-4 min-h-[calc(100vh-(--spacing(32)))]\">\n\t\t\t\t<div className=\"text-white w-xs\">\n\t\t\t\t\t<h2 className=\"text-2xl font-light\">Create Admin User</h2>\n\t\t\t\t\t<p className=\"text-muted-foreground\">\n\t\t\t\t\t\tYou are ready to create your first user in your new cluster. These credentials belong to you alone, and you\n\t\t\t\t\t\tcan create more users and roles once you create this first one.\n\t\t\t\t\t</p>\n\t\t\t\t\t<Form {...methods}>\n\t\t\t\t\t\t<form\n\t\t\t\t\t\t\tid=\"cluster-create-admin-form\"\n\t\t\t\t\t\t\tname=\"cluster-create-admin-form\"\n\t\t\t\t\t\t\tonSubmit={handleSubmit(submitForm)}\n\t\t\t\t\t\t\tclassName=\"my-4\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\t\t\tname=\"username\"\n\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t<FormItem className=\"my-4\">\n\t\t\t\t\t\t\t\t\t\t<FormLabel>Username</FormLabel>\n\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"username\"\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\t\t\tname=\"password\"\n\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t<FormItem className=\"my-4\">\n\t\t\t\t\t\t\t\t\t\t<FormLabel>Password</FormLabel>\n\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\t\t\tname=\"confirmPassword\"\n\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t<FormItem className=\"my-4\">\n\t\t\t\t\t\t\t\t\t\t<FormLabel>Confirm Password</FormLabel>\n\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t\t<Button disabled={isPending} type=\"submit\" variant=\"submit\" className=\"w-full my-2 rounded-full\">\n\t\t\t\t\t\t\t\tCreate Admin User\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</form>\n\t\t\t\t\t</Form>\n\n\t\t\t\t\t<p className=\"text-muted-foreground flex gap-2 align-middle\">\n\t\t\t\t\t\t<ActivityIcon size={36} className=\"flex-none\" />\n\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\tThese credentials will be used to sign into your cluster directly, providing you a secure connection from\n\t\t\t\t\t\t\tyour browser to your cluster.\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</>\n\t);\n}\n","'use client';\n\nimport { ColumnDef, flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table';\n\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';\n\ninterface DataTableProps<TData, TValue> {\n\tcolumns: ColumnDef<TData, TValue>[];\n\tdata: TData[];\n}\n\nexport function DataTable<TData, TValue>({ columns, data }: DataTableProps<TData, TValue>) {\n\tconst table = useReactTable({\n\t\tdata,\n\t\tcolumns,\n\t\tgetCoreRowModel: getCoreRowModel(),\n\t});\n\n\treturn (\n\t\t<div className=\"bg-black-dark rounded-md\">\n\t\t\t<Table>\n\t\t\t\t<TableHeader>\n\t\t\t\t\t{table.getHeaderGroups().map((headerGroup) => (\n\t\t\t\t\t\t<TableRow key={headerGroup.id} className=\"border-none\">\n\t\t\t\t\t\t\t{headerGroup.headers.map((header) => {\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<TableHead key={header.id} className=\"p-4\" style={{ width: `${header.getSize()}%` }}>\n\t\t\t\t\t\t\t\t\t\t{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}\n\t\t\t\t\t\t\t\t\t</TableHead>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t))}\n\t\t\t\t</TableHeader>\n\t\t\t\t<TableBody className=\"bg-black\">\n\t\t\t\t\t{table.getRowModel().rows?.length\n\t\t\t\t\t\t? (\n\t\t\t\t\t\t\ttable.getRowModel().rows.map((row) => (\n\t\t\t\t\t\t\t\t<TableRow\n\t\t\t\t\t\t\t\t\tkey={row.id}\n\t\t\t\t\t\t\t\t\tdata-state={row.getIsSelected() && 'selected'}\n\t\t\t\t\t\t\t\t\tclassName=\"hover:bg-muted/10 data-[state=selected]:bg-muted\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{row.getVisibleCells().map((cell) => (\n\t\t\t\t\t\t\t\t\t\t<TableCell key={cell.id} className=\"p-4\" style={{ width: `${cell.column.getSize()}%` }}>\n\t\t\t\t\t\t\t\t\t\t\t{flexRender(cell.column.columnDef.cell, cell.getContext())}\n\t\t\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t\t\t))\n\t\t\t\t\t\t)\n\t\t\t\t\t\t: (\n\t\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t\t<TableCell colSpan={columns.length} className=\"h-24 text-center\">\n\t\t\t\t\t\t\t\t\tNo results.\n\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t\t)}\n\t\t\t\t</TableBody>\n\t\t\t</Table>\n\t\t</div>\n\t);\n}\n","export function EmptyCluster() {\n\treturn (\n\t\t<div className=\"flex-col items-center justify-center px-16 space-y-3 text-center pt-30\">\n\t\t\t<p>No instances found.</p>\n\t\t</div>\n\t);\n}\n","import { Button } from '@/components/ui/button';\nimport { defaultInstanceRoute } from '@/config/constants';\nimport { useInstanceClient } from '@/config/useInstanceClient';\nimport { authStore } from '@/features/auth/store/authStore';\nimport { useInstanceAuth } from '@/hooks/useAuth';\nimport { useOrganizationClusterInstancePermissions } from '@/hooks/usePermissions';\nimport { Instance } from '@/integrations/api/api.patch';\nimport { onInstanceLogoutSubmit } from '@/integrations/api/instance/auth/onInstanceLogoutSubmit';\nimport { getOperationsUrlForInstance } from '@/lib/urls/getOperationsUrlForInstance';\nimport { Link } from '@tanstack/react-router';\nimport { LoaderCircleIcon } from 'lucide-react';\nimport { useCallback, useMemo } from 'react';\n\nexport function InstanceLogInCell(\n\t{ isSelfManaged, instance }: { readonly isSelfManaged: boolean; readonly instance: Instance },\n) {\n\tconst { user: instanceUser, isLoading: instanceAuthIsLoading } = useInstanceAuth(instance.id);\n\tconst operationsUrl = useMemo(() => getOperationsUrlForInstance(instance), [instance]);\n\tconst instanceClient = useInstanceClient({ operationsUrl });\n\tconst { update } = useOrganizationClusterInstancePermissions();\n\tconst isFabricConnect = authStore.checkForFabricConnect(instance.id);\n\n\tconst onSignOutClick = useCallback(async () => {\n\t\tawait onInstanceLogoutSubmit({ instanceClient, entityId: instance.id });\n\t\tauthStore.setUserForEntity(instance, null);\n\t}, [instance, instanceClient]);\n\n\tif (instanceAuthIsLoading || !['CLONE_READY', 'RUNNING', 'UPDATED'].includes(instance.status)) {\n\t\treturn <LoaderCircleIcon className=\"animate-spin\" color=\"gray\" />;\n\t}\n\n\tif (!instanceUser || isFabricConnect) {\n\t\treturn (\n\t\t\t<span className=\"flex gap-4\">\n\t\t\t\t{update && !isSelfManaged && (\n\t\t\t\t\t<Link\n\t\t\t\t\t\tto={`../instance/${instance.id}${defaultInstanceRoute}`}\n\t\t\t\t\t\tclassName=\"text-sm\"\n\t\t\t\t\t\taria-label={`Connect to ${instance.name} instance`}\n\t\t\t\t\t\ttitle={`Connect to ${instance.name} instance`}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Button variant=\"positiveOutline\">Fabric Connect</Button>\n\t\t\t\t\t</Link>\n\t\t\t\t)}\n\t\t\t\t<Link\n\t\t\t\t\tto={`../instance/${instance.id}/sign-in`}\n\t\t\t\t\tclassName=\"text-sm\"\n\t\t\t\t\taria-label={`Sign in to ${instance.name} instance`}\n\t\t\t\t\ttitle={`Sign in to ${instance.name} instance`}\n\t\t\t\t>\n\t\t\t\t\t<Button variant={update ? 'defaultOutline' : 'positiveOutline'}>Direct Sign In</Button>\n\t\t\t\t</Link>\n\t\t\t</span>\n\t\t);\n\t}\n\n\treturn (\n\t\t<span className=\"flex gap-4\">\n\t\t\t<Link\n\t\t\t\tto={`../instance/${instance.id}${defaultInstanceRoute}`}\n\t\t\t\tclassName=\"text-sm\"\n\t\t\t\taria-label={`Go to ${instance.name} instance`}\n\t\t\t\ttitle={`Go to ${instance.name} instance`}\n\t\t\t>\n\t\t\t\t<Button variant=\"positiveOutline\">Direct Connect</Button>\n\t\t\t</Link>\n\t\t\t<Button\n\t\t\t\tvariant=\"destructiveOutline\"\n\t\t\t\tclassName=\"text-sm\"\n\t\t\t\taria-label={`Sign out from ${instance.name} instance`}\n\t\t\t\ttitle={`Sign out from ${instance.name} instance`}\n\t\t\t\tonClick={onSignOutClick}\n\t\t\t>\n\t\t\t\tDirect Sign Out\n\t\t\t</Button>\n\t\t</span>\n\t);\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport interface SystemStatus {\n\tid: 'availability' | 'maintenance' | 'primary' | string;\n\tstatus: 'Available' | 'Unavailable' | string;\n\t__updatedtime__: number;\n\t__createdtime__: number;\n}\n\nconst enum ComponentStatusName {\n\t'hdb.http' = 'hdb.http',\n\t'hdb.authentication' = 'hdb.authentication',\n\t'hdb.replication' = 'hdb.replication',\n\t'hdb.logging' = 'hdb.logging',\n\t'hdb.mqtt' = 'hdb.mqtt',\n\t'hdb.operationsApi' = 'hdb.operationsApi',\n\t'status-check.rest' = 'status-check.rest',\n\t'status-check.jsResource' = 'status-check.jsResource',\n}\n\ninterface ComponentStatus {\n\tname: ComponentStatusName | string;\n\tcomponentName: ComponentStatusName | string;\n\tstatus: 'healthy' | string;\n\tlastChecked: {\n\t\tworkers: Record<string, number>;\n\t\tmain: number;\n\t};\n}\n\ninterface StatusResponse {\n\tsystemStatus: SystemStatus[];\n\trestartRequired: boolean;\n\tcomponentStatus: ComponentStatus[];\n\n\t[key: string]: unknown;\n}\n\nexport function getStatusQueryOptions({ entityId, instanceClient }: InstanceClientIdConfig, enabled?: boolean) {\n\treturn queryOptions({\n\t\tqueryKey: [entityId, 'get_status'] as const,\n\t\tstaleTime: 9_000,\n\t\trefetchInterval: 10_000,\n\t\tretryDelay: 10_000,\n\t\tthrowOnError: false,\n\t\tenabled,\n\t\tqueryFn: async () => {\n\t\t\tconst { data } = await instanceClient.post<StatusResponse>('/', {\n\t\t\t\toperation: 'get_status',\n\t\t\t});\n\t\t\treturn data;\n\t\t},\n\t});\n}\n\nexport function getSystemStatusById(\n\tstatusResponse: StatusResponse | undefined,\n\tid: SystemStatus['id'],\n): SystemStatus['status'] | undefined {\n\tconst systemStatus = statusResponse?.systemStatus?.find(s => s.id === id);\n\treturn systemStatus?.status;\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { SystemStatus } from '@/integrations/api/instance/status/getStatus';\nimport { ReplicatedResponse } from '@/integrations/api/replication';\nimport { queryClient } from '@/react-query/queryClient';\nimport { useMutation } from '@tanstack/react-query';\n\ninterface SetConfigurationParams extends Pick<SystemStatus, 'id' | 'status'>, InstanceClientIdConfig {\n}\n\nasync function setStatus({\n\tinstanceClient,\n\tid,\n\tstatus,\n}: SetConfigurationParams): Promise<ReplicatedResponse> {\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation: 'set_status',\n\t\tid,\n\t\tstatus,\n\t});\n\treturn data;\n}\n\nexport function useSetStatus() {\n\treturn useMutation({\n\t\tmutationFn: setStatus,\n\t\tonSuccess: (_data, variables) => queryClient.invalidateQueries({ queryKey: [variables.entityId, 'get_status'] }),\n\t});\n}\n","import { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { useOrganizationClusterInstancePermissions } from '@/hooks/usePermissions';\nimport { Instance } from '@/integrations/api/api.patch';\nimport { getStatusQueryOptions, getSystemStatusById } from '@/integrations/api/instance/status/getStatus';\nimport { useSetStatus } from '@/integrations/api/instance/status/setStatus';\nimport { getOperationsUrlForInstance } from '@/lib/urls/getOperationsUrlForInstance';\nimport { useQuery } from '@tanstack/react-query';\nimport { LoaderCircleIcon, ShieldCheckIcon, ShieldXIcon } from 'lucide-react';\nimport { useEffect, useMemo, useState } from 'react';\n\nexport function InstanceStatusCell(\n\t{ instance, index }: { readonly instance: Instance; index: number },\n) {\n\tconst { update: canManage } = useOrganizationClusterInstancePermissions();\n\tconst operationsUrl = useMemo(() => getOperationsUrlForInstance(instance), [instance]);\n\tconst instanceParams = useInstanceClientIdParams({\n\t\toperationsUrl,\n\t\tinstanceId: instance.id,\n\t\tforceFabricConnect: true,\n\t});\n\tconst { mutate: setStatus, isPending: isSettingStatus } = useSetStatus();\n\n\tconst [ready, setReady] = useState(false);\n\n\t// Spread the status requests out.\n\tuseEffect(() => {\n\t\tconst timer = setTimeout(() => setReady(true), index * 500);\n\t\treturn () => clearTimeout(timer);\n\t}, [index]);\n\n\tconst { data: statusResponse, isLoading, isFetching } = useQuery(\n\t\tgetStatusQueryOptions(instanceParams, ready && canManage),\n\t);\n\n\tconst systemStatus = getSystemStatusById(statusResponse, 'availability') || 'Unknown';\n\tconst isAvailable = systemStatus === 'Available';\n\tconst isUnavailable = systemStatus === 'Unavailable';\n\n\tif (!canManage) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<div className=\"flex items-center gap-2\">\n\t\t\t<Tooltip>\n\t\t\t\t<TooltipTrigger asChild>\n\t\t\t\t\t<div className=\"flex items-center\">\n\t\t\t\t\t\t{isLoading || !ready || (isFetching && !statusResponse)\n\t\t\t\t\t\t\t? <LoaderCircleIcon className=\"animate-spin size-5 text-muted-foreground\" />\n\t\t\t\t\t\t\t: (\n\t\t\t\t\t\t\t\t<Badge\n\t\t\t\t\t\t\t\t\tvariant={isAvailable ? 'success' : isUnavailable ? 'destructive' : 'default'}\n\t\t\t\t\t\t\t\t\tclassName=\"size-4 rounded-full p-0\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span className=\"sr-only\">{isAvailable ? 'Online' : 'Offline'}</span>\n\t\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t</TooltipTrigger>\n\t\t\t\t<TooltipContent>\n\t\t\t\t\t{isFetching && statusResponse ? 'Refreshing... ' : ''}\n\t\t\t\t\t{systemStatus}\n\t\t\t\t</TooltipContent>\n\t\t\t</Tooltip>\n\n\t\t\t{canManage && (\n\t\t\t\t<div className=\"flex gap-1\">\n\t\t\t\t\t{isAvailable && (\n\t\t\t\t\t\t<Tooltip>\n\t\t\t\t\t\t\t<TooltipTrigger asChild>\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tvariant=\"destructiveGhost\"\n\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\tonClick={() => setStatus({ ...instanceParams, id: 'availability', status: 'Unavailable' })}\n\t\t\t\t\t\t\t\t\tdisabled={isSettingStatus}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{isSettingStatus\n\t\t\t\t\t\t\t\t\t\t? <LoaderCircleIcon className=\"animate-spin size-4\" />\n\t\t\t\t\t\t\t\t\t\t: <ShieldXIcon className=\"size-4\" />}\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</TooltipTrigger>\n\t\t\t\t\t\t\t<TooltipContent>Bring out of rotation</TooltipContent>\n\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t)}\n\t\t\t\t\t{isUnavailable && (\n\t\t\t\t\t\t<Tooltip>\n\t\t\t\t\t\t\t<TooltipTrigger asChild>\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\tonClick={() => setStatus({ ...instanceParams, id: 'availability', status: 'Available' })}\n\t\t\t\t\t\t\t\t\tdisabled={isSettingStatus}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{isSettingStatus\n\t\t\t\t\t\t\t\t\t\t? <LoaderCircleIcon className=\"animate-spin size-4\" />\n\t\t\t\t\t\t\t\t\t\t: <ShieldCheckIcon className=\"size-4\" />}\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</TooltipTrigger>\n\t\t\t\t\t\t\t<TooltipContent>Bring back into rotation</TooltipContent>\n\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import { DataTable } from '@/components/DataTable';\nimport { SubNavMenu } from '@/components/SubNavMenu';\nimport { TextLoadingSkeleton } from '@/components/TextLoadingSkeleton';\nimport { Badge } from '@/components/ui/badge';\nimport { Card, CardContent } from '@/components/ui/card';\nimport { renderBadgeStatusVariant } from '@/components/ui/utils/badgeStatus';\nimport { deletedClusterStatuses } from '@/config/clusterStatuses';\nimport { calculateInstanceFQDN } from '@/features/clusters/upsert/lib/calculateInstanceFQDN';\nimport { Instance } from '@/integrations/api/api.patch';\nimport { clusterIsSelfManaged } from '@/integrations/api/clusterIsSelfManaged';\nimport { excludeFalsy } from '@/lib/arrays/excludeFalsy';\nimport { byInstanceFqdnThenPort } from '@/lib/arrays/sort/byInstanceFqdnThenPort';\nimport { capitalizeWords } from '@/lib/string/capitalizeWords';\nimport { useQuery } from '@tanstack/react-query';\nimport { useParams } from '@tanstack/react-router';\nimport { ColumnDef } from '@tanstack/react-table';\nimport { useMemo } from 'react';\nimport { EmptyCluster } from './EmptyCluster';\nimport { InstanceLogInCell } from './InstanceLogInCell';\nimport { InstanceStatusCell } from './InstanceStatusCell';\nimport { getClusterInfoQueryOptions } from './queries/getClusterInfoQuery';\n\nexport function Instances() {\n\tconst { clusterId }: { clusterId: string } = useParams({ strict: false });\n\tconst { data: cluster, isLoading: clusterIsLoading } = useQuery(\n\t\tgetClusterInfoQueryOptions(clusterId, true),\n\t);\n\tconst isSelfManaged = clusterIsSelfManaged(cluster);\n\n\tconst columns: ColumnDef<Instance>[] = useMemo(\n\t\t() =>\n\t\t\t([\n\t\t\t\t{\n\t\t\t\t\tid: 'instanceActions',\n\t\t\t\t\tsize: 1,\n\t\t\t\t\tminSize: 1,\n\t\t\t\t\tcell: (cell) => (\n\t\t\t\t\t\t<div className=\"flex justify-end gap-2 items-center\">\n\t\t\t\t\t\t\t<InstanceLogInCell isSelfManaged={isSelfManaged} instance={cell.row.original} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t\tisSelfManaged && {\n\t\t\t\t\taccessorKey: 'instanceFqdn',\n\t\t\t\t\tsize: 90,\n\t\t\t\t\theader: 'URL',\n\t\t\t\t\tcell: (cell) => {\n\t\t\t\t\t\treturn calculateInstanceFQDN({\n\t\t\t\t\t\t\tsecure: cell.row.original.operationsApiSecure ? 'true' : 'false',\n\t\t\t\t\t\t\tport: cell.row.original.operationsApiPort,\n\t\t\t\t\t\t\tfqdn: cell.row.original.instanceFqdn,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t!isSelfManaged && {\n\t\t\t\t\taccessorKey: 'name',\n\t\t\t\t\tsize: 90,\n\t\t\t\t\theader: 'Name',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\taccessorKey: 'status',\n\t\t\t\t\theader: 'Status',\n\t\t\t\t\tsize: 1,\n\t\t\t\t\tminSize: 1,\n\t\t\t\t\tcell: (cell) => {\n\t\t\t\t\t\tconst status = cell.getValue() as string;\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t\t<InstanceStatusCell instance={cell.row.original} index={cell.row.index} />\n\t\t\t\t\t\t\t\t{status ? <Badge variant={renderBadgeStatusVariant(status)}>{capitalizeWords(status)}</Badge> : null}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t!isSelfManaged && {\n\t\t\t\t\taccessorKey: 'version',\n\t\t\t\t\tsize: 1,\n\t\t\t\t\tminSize: 1,\n\t\t\t\t\theader: 'Version',\n\t\t\t\t},\n\t\t\t\t!isSelfManaged && {\n\t\t\t\t\taccessorKey: 'storageGb',\n\t\t\t\t\tsize: 1,\n\t\t\t\t\tminSize: 1,\n\t\t\t\t\theader: 'Storage',\n\t\t\t\t\tcell: (cell) => {\n\t\t\t\t\t\tconst value = cell.getValue() as number;\n\t\t\t\t\t\treturn `${value} GB`; // This is already in GB\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t!isSelfManaged && {\n\t\t\t\t\taccessorKey: 'usedStorageGb',\n\t\t\t\t\tsize: 1,\n\t\t\t\t\tminSize: 1,\n\t\t\t\t\theader: 'Used Storage',\n\t\t\t\t\tcell: (cell) => {\n\t\t\t\t\t\tconst value = cell.getValue();\n\t\t\t\t\t\treturn value === undefined ? '-' : `${value} GB`;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t!isSelfManaged && {\n\t\t\t\t\taccessorKey: 'cpuCores',\n\t\t\t\t\tsize: 1,\n\t\t\t\t\tminSize: 1,\n\t\t\t\t\theader: 'Cores/Threads',\n\t\t\t\t\tcell: (cell) => {\n\t\t\t\t\t\treturn <>{cell.row.original.cpuCores} / {cell.row.original.threads}</>;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t!isSelfManaged && {\n\t\t\t\t\taccessorKey: 'memoryMb',\n\t\t\t\t\tsize: 1,\n\t\t\t\t\tminSize: 1,\n\t\t\t\t\theader: 'Memory',\n\t\t\t\t\tcell: (cell) => {\n\t\t\t\t\t\tconst value = cell.getValue() as number;\n\t\t\t\t\t\treturn `${value / 1024} GB`; // The value is in MiB since that's how memory is sold, but alwayas says MB or GB instead of MiB or GiB\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t] satisfies Array<ColumnDef<Instance> | false>).filter(excludeFalsy),\n\t\t[isSelfManaged],\n\t);\n\tconst instances = useMemo(\n\t\t() => {\n\t\t\tif (!cluster?.instances) {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t\treturn cluster.instances\n\t\t\t\t.filter(instance => instance.status && !deletedClusterStatuses.includes(instance.status))\n\t\t\t\t.sort(byInstanceFqdnThenPort);\n\t\t},\n\t\t[cluster],\n\t);\n\treturn (\n\t\t<>\n\t\t\t<SubNavMenu />\n\t\t\t<div className=\"mt-32 px-4 pt-4 md:px-12 min-h-[calc(100vh-(--spacing(32)))]\">\n\t\t\t\t<Card className=\"p-0 mt-4 min-h-96\">\n\t\t\t\t\t<CardContent className=\"p-0 min-h-96\">\n\t\t\t\t\t\t{clusterIsLoading\n\t\t\t\t\t\t\t? <TextLoadingSkeleton />\n\t\t\t\t\t\t\t: instances.length\n\t\t\t\t\t\t\t? <DataTable data={instances} columns={columns} />\n\t\t\t\t\t\t\t: <EmptyCluster />}\n\t\t\t\t\t</CardContent>\n\t\t\t\t</Card>\n\t\t\t</div>\n\t\t</>\n\t);\n}\n","import { NestedContentWithSubNavMenu } from '@/components/NestedContentWithSubNavMenu';\nimport { TextLoadingSkeleton } from '@/components/TextLoadingSkeleton';\nimport { activeClusterStatuses } from '@/config/clusterStatuses';\nimport { ClusterCardAction } from '@/features/clusters/components/ClusterCardAction';\nimport { ClusterProgress } from '@/features/clusters/components/ClusterProgress';\nimport { useQuery } from '@tanstack/react-query';\nimport { useParams } from '@tanstack/react-router';\nimport { useMemo } from 'react';\nimport { getClusterInfoQueryOptions } from './queries/getClusterInfoQuery';\n\nexport function Scaling() {\n\tconst { clusterId }: { organizationId: string; clusterId: string } = useParams({ strict: false });\n\tconst { data: cluster, isLoading: clusterIsLoading } = useQuery(\n\t\tgetClusterInfoQueryOptions(clusterId, 2_000),\n\t);\n\tconst status = cluster?.status;\n\tconst clusterIsActive = useMemo(() => {\n\t\treturn status && activeClusterStatuses.includes(status);\n\t}, [status]);\n\n\tif (clusterIsLoading || !cluster) {\n\t\treturn (\n\t\t\t<NestedContentWithSubNavMenu className=\"flex justify-center\">\n\t\t\t\t<TextLoadingSkeleton />\n\t\t\t</NestedContentWithSubNavMenu>\n\t\t);\n\t}\n\n\tif (clusterIsActive) {\n\t\treturn (\n\t\t\t<NestedContentWithSubNavMenu className=\"flex justify-center\">\n\t\t\t\t<div className=\"center w-2xl flex flex-col gap-4\">\n\t\t\t\t\t<h1 className=\"text-xl text-center\">All done!</h1>\n\t\t\t\t\t<ClusterProgress cluster={cluster} forceProgressBarVisible={true} />\n\t\t\t\t\t<p>Your cluster finished updating, and is ready for interaction.</p>\n\t\t\t\t\t<div className=\"text-center\">\n\t\t\t\t\t\t<ClusterCardAction cluster={cluster} />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</NestedContentWithSubNavMenu>\n\t\t);\n\t}\n\n\treturn (\n\t\t<NestedContentWithSubNavMenu className=\"flex justify-center\">\n\t\t\t<div className=\"center w-2xl flex flex-col gap-4\">\n\t\t\t\t<h1 className=\"text-xl text-center\">Here we go!</h1>\n\t\t\t\t<ClusterProgress cluster={cluster} forceProgressBarVisible={true} />\n\t\t\t\t<p>\n\t\t\t\t\tYour cluster is updating with the latest changes. This includes waiting several minutes to let traffic drain\n\t\t\t\t\tsafely.{' '}\n\t\t\t\t\t<span className=\"text-muted-foreground\">\n\t\t\t\t\t\tWe will let you know when we are ready for you to connect! In the meantime, join us on{' '}\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\thref=\"https://discord.gg/VzZuaw3Xay\"\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\t\tclassName=\"underline hover:text-blue-300\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tDiscord\n\t\t\t\t\t\t</a>! Get real-time help from our engineers, see feature drops early, and connect with others building on\n\t\t\t\t\t\tFabric.\n\t\t\t\t\t</span>\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</NestedContentWithSubNavMenu>\n\t);\n}\n","import { ContactUs } from '@/components/ContactUs';\nimport { NestedContentWithSubNavMenu } from '@/components/NestedContentWithSubNavMenu';\nimport { TextLoadingSkeleton } from '@/components/TextLoadingSkeleton';\nimport { Button } from '@/components/ui/button';\nimport { isFailed } from '@/components/ui/utils/badgeStatus';\nimport { activeClusterStatuses } from '@/config/clusterStatuses';\nimport { ClusterCardAction } from '@/features/clusters/components/ClusterCardAction';\nimport { ClusterProgress } from '@/features/clusters/components/ClusterProgress';\nimport { useLocalStorage } from '@/hooks/useLocalStorage';\nimport { LocalStorageKeys } from '@/lib/storage/localStorageKeys';\nimport { useQuery } from '@tanstack/react-query';\nimport { useParams, useRouter } from '@tanstack/react-router';\nimport { CloudAlertIcon } from 'lucide-react';\nimport { useCallback, useMemo } from 'react';\nimport { getClusterInfoQueryOptions } from './queries/getClusterInfoQuery';\n\nexport function StartingUp() {\n\tconst router = useRouter();\n\tconst { clusterId }: { organizationId: string; clusterId: string } = useParams({ strict: false });\n\tconst { data: cluster, isLoading: clusterIsLoading } = useQuery(\n\t\tgetClusterInfoQueryOptions(clusterId, 2_000),\n\t);\n\n\tconst status = cluster?.status;\n\n\tconst clusterIsActive = useMemo(() => {\n\t\treturn status && activeClusterStatuses.includes(status);\n\t}, [status]);\n\tconst clusterHasFailed = isFailed(status);\n\tconst [, setSavedClusterState] = useLocalStorage<unknown | null>(LocalStorageKeys.SavedClusterState, null);\n\n\tconst onTryAgainClick = useCallback(() => {\n\t\tsetSavedClusterState(cluster);\n\t\tvoid router.navigate({ to: `/${cluster!.organizationId}/new-cluster` });\n\t}, [cluster, router, setSavedClusterState]);\n\n\tif (clusterIsLoading || !cluster) {\n\t\treturn (\n\t\t\t<NestedContentWithSubNavMenu className=\"flex justify-center\">\n\t\t\t\t<TextLoadingSkeleton />\n\t\t\t</NestedContentWithSubNavMenu>\n\t\t);\n\t}\n\n\tif (clusterHasFailed) {\n\t\treturn (\n\t\t\t<NestedContentWithSubNavMenu className=\"flex justify-center\">\n\t\t\t\t<div className=\"center max-w-2xl flex flex-col gap-4 items-center\">\n\t\t\t\t\t<CloudAlertIcon className=\"w-24 h-24\" />\n\t\t\t\t\t<span>\n\t\t\t\t\t\tYour cluster failed to successfully start. This is usually caused by temporary communication problems. Would\n\t\t\t\t\t\tyou like to try again? We also get notified about these failures. <ContactUs /> if you want more help.\n\t\t\t\t\t</span>\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tvariant=\"positiveOutline\"\n\t\t\t\t\t\tonClick={onTryAgainClick}\n\t\t\t\t\t>\n\t\t\t\t\t\tTry Again\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</NestedContentWithSubNavMenu>\n\t\t);\n\t}\n\n\tif (clusterIsActive) {\n\t\treturn (\n\t\t\t<NestedContentWithSubNavMenu className=\"flex justify-center\">\n\t\t\t\t<div className=\"center max-w-2xl flex flex-col gap-4\">\n\t\t\t\t\t<h1 className=\"text-xl text-center\">It's ready!</h1>\n\t\t\t\t\t<ClusterProgress cluster={cluster} forceProgressBarVisible={true} />\n\t\t\t\t\t<p>\n\t\t\t\t\t\tLet's set up your secure, browser-to-cluster connection now.{' '}\n\t\t\t\t\t\t<span className=\"text-muted-foreground\">\n\t\t\t\t\t\t\tDid you know during this step, you connect straight to your cluster, providing a private secure\n\t\t\t\t\t\t\tconnection? That's <em>Direct Connect</em>! Once you create your user, you will have the option to{' '}\n\t\t\t\t\t\t\t<em>Fabric Connect</em> from your Fabric account without having to sign in again.\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</p>\n\t\t\t\t\t<div className=\"text-center\">\n\t\t\t\t\t\t<ClusterCardAction cluster={cluster} />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</NestedContentWithSubNavMenu>\n\t\t);\n\t}\n\n\treturn (\n\t\t<NestedContentWithSubNavMenu className=\"flex justify-center\">\n\t\t\t<div className=\"center max-w-2xl flex flex-col gap-4\">\n\t\t\t\t<h1 className=\"text-xl text-center\">Here we go!</h1>\n\t\t\t\t<ClusterProgress cluster={cluster} forceProgressBarVisible={true} />\n\t\t\t\t<p>\n\t\t\t\t\tYour cluster is spinning up with the latest changes, including your own DNS records and private connections.\n\t\t\t\t\tPlease wait while we get everything going.{' '}\n\t\t\t\t\t<span className=\"text-muted-foreground\">\n\t\t\t\t\t\tWe will let you know when we are ready for you to connect! In the meantime, join us on{' '}\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\thref=\"https://discord.gg/VzZuaw3Xay\"\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\t\tclassName=\"underline hover:text-blue-300\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tDiscord\n\t\t\t\t\t\t</a>! Get real-time help from our engineers, see feature drops early, and connect with others building on\n\t\t\t\t\t\tFabric.\n\t\t\t\t\t</span>\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</NestedContentWithSubNavMenu>\n\t);\n}\n","import { defaultInstanceRouteUpOne } from '@/config/constants';\nimport { ClusterInstanceSignIn } from '@/features/auth/ClusterInstanceSignIn';\nimport { authStore } from '@/features/auth/store/authStore';\nimport { createRoute, redirect } from '@tanstack/react-router';\nimport { clusterLayoutRoute } from './clusterLayoutRoute';\nimport { DomainsPage } from './domains/Page';\nimport { FinishSetup } from './FinishSetup';\nimport { Instances } from './Instances';\nimport { Scaling } from './Scaling';\nimport { StartingUp } from './StartingUp';\n\nconst clusterInstancesRoute = createRoute({\n\tgetParentRoute: () => clusterLayoutRoute,\n\tpath: 'instances',\n\tcomponent: Instances,\n});\n\nconst clusterStartingUpRoute = createRoute({\n\tgetParentRoute: () => clusterLayoutRoute,\n\tpath: 'starting-up',\n\tcomponent: StartingUp,\n});\n\nconst clusterScalingRoute = createRoute({\n\tgetParentRoute: () => clusterLayoutRoute,\n\tpath: 'scaling',\n\tcomponent: Scaling,\n});\n\nconst clusterDomainsRoute = createRoute({\n\tgetParentRoute: () => clusterLayoutRoute,\n\tpath: 'domains',\n\tcomponent: DomainsPage,\n});\n\nconst clusterSignInRoute = createRoute({\n\tgetParentRoute: () => clusterLayoutRoute,\n\tpath: 'sign-in',\n\tcomponent: ClusterInstanceSignIn,\n\tbeforeLoad: ({ context, location, params }) => {\n\t\tconst isFabricConnect = authStore.checkForFabricConnect(params.clusterId);\n\t\tif (context.authentication[params.clusterId]?.user && !isFabricConnect) {\n\t\t\tconst search: Record<string, string> = location?.search;\n\t\t\tthrow redirect({\n\t\t\t\tto: search?.redirect?.startsWith('/')\n\t\t\t\t\t? search.redirect\n\t\t\t\t\t: defaultInstanceRouteUpOne,\n\t\t\t});\n\t\t}\n\t},\n});\n\nconst instanceSignInRoute = createRoute({\n\tgetParentRoute: () => clusterLayoutRoute,\n\tpath: 'instance/$instanceId/sign-in',\n\tcomponent: ClusterInstanceSignIn,\n\tbeforeLoad: ({ context, location, params }) => {\n\t\tconst isFabricConnect = authStore.checkForFabricConnect(params.clusterId)\n\t\t\t|| authStore.checkForFabricConnect(params.instanceId);\n\t\tif (isFabricConnect) {\n\t\t\treturn;\n\t\t}\n\t\tif (context.authentication[params.instanceId]?.user) {\n\t\t\tconst search: Record<string, string> = location?.search;\n\t\t\tthrow redirect({\n\t\t\t\tto: search?.redirect?.startsWith('/')\n\t\t\t\t\t? search.redirect\n\t\t\t\t\t: defaultInstanceRouteUpOne,\n\t\t\t});\n\t\t}\n\t},\n});\n\nconst clusterFinishSetupRoute = createRoute({\n\tgetParentRoute: () => clusterLayoutRoute,\n\tpath: 'finish-setup',\n\tcomponent: FinishSetup,\n});\n\nexport const clusterRoutes = [\n\tclusterInstancesRoute,\n\tclusterStartingUpRoute,\n\tclusterScalingRoute,\n\tclusterDomainsRoute,\n\tclusterFinishSetupRoute,\n\tclusterSignInRoute,\n\tinstanceSignInRoute,\n];\n","import { createInstanceLayoutRoute } from '@/features/instance/instanceLayoutRoute';\nimport { createRoute } from '@tanstack/react-router';\n\nexport function createAPIsRouteTree(instanceLayoutRoute: ReturnType<typeof createInstanceLayoutRoute>) {\n\treturn createRoute({\n\t\tgetParentRoute: () => instanceLayoutRoute,\n\t\tpath: 'apis',\n\t}).lazy(() => import('./index.lazy').then((d) => d.route));\n}\n","// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function shallowCompareObjects(a: any, b: any): boolean {\n\t// Handle edge cases\n\tif (a === b) { return true; }\n\tif (!a || !b) { return false; }\n\n\tconst aKeys = Object.keys(a);\n\tconst bKeys = Object.keys(b);\n\n\tif (aKeys.length !== bKeys.length) {\n\t\treturn false;\n\t}\n\n\t// Check if every key in a exists in b and has the same value\n\tfor (const key of aKeys) {\n\t\tif (!bKeys.includes(key) || a[key] !== b[key]) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n","import { shallowCompareObjects } from '@/lib/arrays/shallowCompareObjects';\nimport { Dispatch, SetStateAction, useEffect, useState } from 'react';\n\nexport function useEffectedState<S>(initialState: S, deps: unknown): [S, Dispatch<SetStateAction<S>>] {\n\tconst [currentDeps, setDeps] = useState(deps);\n\tconst [currentState, setCurrentState] = useState<S>(initialState);\n\n\t// Use the proper React hook so we can update the state more permanently.\n\tuseEffect(() => {\n\t\tif (!shallowCompareObjects(currentDeps, deps)) {\n\t\t\t// We watch and decide if the deps change on our own, which lets us wipe out the old state at the same time.\n\t\t\t// eslint-disable-next-line react-hooks/set-state-in-effect\n\t\t\tsetDeps(deps);\n\t\t\tsetCurrentState(initialState);\n\t\t}\n\t}, [currentDeps, deps, initialState]);\n\n\t// But also watch it so we can immediately patch the state.\n\tif (!shallowCompareObjects(currentDeps, deps)) {\n\t\treturn [initialState, setCurrentState];\n\t}\n\n\treturn [currentState, setCurrentState];\n}\n","import { WatchedValueKeys, WatchedValuesTypeMap } from '@/lib/storage/watchedValueKeys';\nimport { useCallback, useEffect } from 'react';\n\nconst listenersMap: Record<string, Array<(newValue: unknown, trigger?: unknown) => void>> = {};\n\nexport function useListener<K extends keyof WatchedValuesTypeMap, T extends WatchedValuesTypeMap[K]>(\n\tname: K,\n\tlistener: (newValue: T, trigger?: unknown) => void,\n\tdeps: unknown,\n) {\n\t// eslint-disable-next-line react-hooks/preserve-manual-memoization,react-hooks/exhaustive-deps\n\tconst callback = useCallback((newValue: T, trigger?: unknown) => listener(newValue, trigger), [deps]);\n\tuseEffect(() => {\n\t\tif (!listenersMap[name]) {\n\t\t\tlistenersMap[name] = [];\n\t\t}\n\t\tlistenersMap[name].push(callback as (newValue: unknown, trigger?: unknown) => void);\n\n\t\treturn function cleanUp() {\n\t\t\tconst index = listenersMap[name].indexOf(callback as (newValue: unknown, trigger?: unknown) => void);\n\t\t\tif (index >= 0) {\n\t\t\t\tlistenersMap[name].splice(index, 1);\n\t\t\t}\n\t\t};\n\t}, [name, listener, callback]);\n}\n\nexport function emitToListeners<K extends keyof WatchedValuesTypeMap, T extends WatchedValuesTypeMap[K]>(\n\tname: K,\n\tvalue: T,\n\ttrigger?: unknown,\n): void {\n\tconst listeners = listenersMap[name];\n\tif (listeners) {\n\t\tfor (const listener of listeners) {\n\t\t\tlistener(value, trigger);\n\t\t}\n\t}\n}\n\nexport function curryEmitToListeners<K extends keyof WatchedValuesTypeMap, T extends WatchedValuesTypeMap[K]>(\n\tname: K,\n\tvalue: T,\n\ttrigger?: unknown,\n): (e?: unknown) => void {\n\treturn (e?: unknown) => emitToListeners(name, value, trigger ?? e);\n}\n\nexport function useEmitToListeners<K extends keyof WatchedValuesTypeMap, T extends WatchedValuesTypeMap[K]>(\n\tname: WatchedValueKeys,\n\tvalue: T,\n\ttrigger?: unknown,\n): () => void {\n\treturn useCallback((e?: unknown) => emitToListeners(name, value, trigger ?? e), [name, value, trigger]);\n}\n","import { SessionStorageKeys } from '@/lib/storage/sessionStorageKeys';\nimport { safeParse } from '@/lib/string/safeParse';\n\n/**\n * Retrieves a value from session storage.\n * @param key\n * @param defaultValue\n */\nexport function getSessionStorage<T, K extends keyof SessionStorageKeys>(key: K, defaultValue: T): T {\n\tconst lastSetValue = safeParse<T>(sessionStorage.getItem(String(key)));\n\treturn lastSetValue ?? defaultValue;\n}\n","import { SessionStorageKeys } from '@/lib/storage/sessionStorageKeys';\n\n/**\n * Stores a value in session storage for later retrieval.\n * @param key\n * @param current\n */\nexport function setSessionStorage<T, K extends keyof SessionStorageKeys>(key: K, current: T): void {\n\tif (current === null || current === undefined) {\n\t\tsessionStorage.removeItem(String(key));\n\t} else {\n\t\tsessionStorage.setItem(String(key), JSON.stringify(current));\n\t}\n}\n","import { useEffectedState } from '@/hooks/useEffectedState';\nimport { emitToListeners, useListener } from '@/lib/events/listener';\nimport { getSessionStorage } from '@/lib/storage/getSessionStorage';\nimport { SessionStorageKeys } from '@/lib/storage/sessionStorageKeys';\nimport { setSessionStorage } from '@/lib/storage/setSessionStorage';\nimport { useEffect } from 'react';\n\n/**\n * Uses state that gets bootstrapped from and persists to session storage with the key you specify.\n * @param key\n * @param defaultValue\n */\nexport function useSessionStorage<T, K extends keyof SessionStorageKeys>(\n\tkey: K,\n\tdefaultValue: T,\n): [T, (value: ((prevState: T) => T) | T) => void] {\n\tconst state = useEffectedState<T>(getSessionStorage(key, defaultValue), [key]);\n\tconst [current, setCurrent] = state;\n\n\tuseEffect(() => {\n\t\tsetSessionStorage(key, current);\n\t\temitToListeners(`Session:${key}` as 'Session:{key}', current);\n\t}, [key, current]);\n\n\tuseListener(`Session:${key}` as 'Session:{key}', function watchForInternalStorageChanges(newValue: T) {\n\t\tif (current !== newValue) {\n\t\t\tsetCurrent(newValue);\n\t\t}\n\t}, [current, key, defaultValue]);\n\n\tuseEffect(function watchForExternalStorageChanges() {\n\t\tconst storageListener = (event: StorageEvent) => {\n\t\t\tif (event.key === key) {\n\t\t\t\tsetCurrent(getSessionStorage(key, defaultValue));\n\t\t\t}\n\t\t};\n\t\twindow.addEventListener('storage', storageListener);\n\t\treturn () => {\n\t\t\twindow.removeEventListener('storage', storageListener);\n\t\t};\n\t}, [key, setCurrent, defaultValue]);\n\n\treturn state;\n}\n","import { useSessionStorage } from '@/hooks/useSessionStorage';\nimport { useToggler } from '@/hooks/useToggler';\nimport { SessionStorageKeys } from '@/lib/storage/sessionStorageKeys';\nimport { MouseEvent, useCallback, useMemo } from 'react';\n\nexport function useSessionToggler<K extends keyof SessionStorageKeys>(\n\tkey: K,\n\tdefaultValue: boolean = false,\n): ReturnType<typeof useToggler> {\n\tconst [toggled, setToggled] = useSessionStorage(key, defaultValue);\n\n\tconst toggle = useCallback((e?: MouseEvent | unknown) => {\n\t\t(e as MouseEvent)?.preventDefault?.();\n\t\tsetToggled((checked: boolean) => {\n\t\t\treturn !checked;\n\t\t});\n\t}, [setToggled]);\n\tconst toggleOn = useCallback((e?: MouseEvent | unknown) => {\n\t\t(e as MouseEvent)?.preventDefault?.();\n\t\tsetToggled(true);\n\t}, [setToggled]);\n\tconst toggleOff = useCallback((e?: MouseEvent | unknown) => {\n\t\t(e as MouseEvent)?.preventDefault?.();\n\t\tsetToggled(false);\n\t}, [setToggled]);\n\n\treturn useMemo(() => {\n\t\treturn {\n\t\t\ttoggled,\n\t\t\tsetToggled,\n\t\t\ttoggle,\n\t\t\ttoggleOn,\n\t\t\ttoggleOff,\n\t\t};\n\t}, [toggle, setToggled, toggleOff, toggleOn, toggled]);\n}\n","import { APIDirectoryEntry } from '@/integrations/api/instance/applications/getComponents';\nimport { SetComponentFileRequest } from '@/integrations/api/instance/applications/setComponentFile';\nimport { createContext } from 'react';\nimport { TreeItemIndex } from 'react-complex-tree/src/types';\nimport { DirectoryEntry } from './directoryEntry';\nimport { FileEntry } from './fileEntry';\n\nexport type EditorViewContextValue = {\n\trootEntries: Array<DirectoryEntry | FileEntry>;\n\treloadRootEntries: () => Promise<APIDirectoryEntry>;\n\tentryExists: (path: string) => boolean;\n\n\topenedEntry: DirectoryEntry | FileEntry | undefined;\n\tsetOpenedEntry: (entry: DirectoryEntry | FileEntry | undefined) => void;\n\n\trestrictPackageModification: boolean;\n\topenedEntryContents: string | undefined;\n\tsetOpenedEntryContents: (\n\t\tcontents: (string | undefined) | ((existingContents: string | undefined) => string | undefined),\n\t) => void;\n\n\tfocusedItem: TreeItemIndex | undefined;\n\tsetFocusedItem: (\n\t\tentry: TreeItemIndex | undefined | ((prevState: TreeItemIndex | undefined) => TreeItemIndex | undefined),\n\t) => void;\n\texpandedItems: TreeItemIndex[];\n\tsetExpandedItems: (entries: TreeItemIndex[] | ((prevState: TreeItemIndex[]) => TreeItemIndex[])) => void;\n\tselectedItems: TreeItemIndex[];\n\tsetSelectedItems: (entries: TreeItemIndex[] | ((prevState: TreeItemIndex[]) => TreeItemIndex[])) => void;\n\n\tsaveFile: (data: SetComponentFileRequest, filePath: string) => void;\n\tisSavingFile: boolean;\n};\n\nexport const EditorViewContext = createContext<EditorViewContextValue | null>(null);\n","import { EditorViewContext, EditorViewContextValue } from '@/features/instance/applications/context/EditorViewContext';\nimport { useContext } from 'react';\n\nexport function useEditorView() {\n\treturn useContext(EditorViewContext) as EditorViewContextValue;\n}\n","import { InstanceClientConfig, InstanceTypeConfig } from '@/config/instanceClientConfig';\nimport { ReplicatedResponse } from '@/integrations/api/replication';\nimport { useMutation } from '@tanstack/react-query';\n\ninterface DropComponentRequest extends InstanceClientConfig, InstanceTypeConfig {\n\tproject: string;\n\tfile: string | undefined;\n}\n\nexport async function dropComponent({\n\tfile,\n\tproject,\n\tentityType,\n\tinstanceClient,\n}: DropComponentRequest): Promise<ReplicatedResponse> {\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation: 'drop_component',\n\t\tfile: file || undefined,\n\t\tproject,\n\t\treplicated: entityType === 'cluster',\n\t});\n\treturn data;\n}\n\nexport function useDropComponent() {\n\treturn useMutation({\n\t\tmutationFn: dropComponent,\n\t});\n}\n","export function parseFileExtension(filename: string | undefined) {\n\tconst parts = (filename || '')?.split('.');\n\treturn parts.length > 1 ? parts.slice(-1)[0] : '';\n}\n","import { parseFileExtension } from '@/lib/string/parseFileExtension';\n\nexport function hasImageFileExtension(filename: string | undefined): boolean {\n\tconst extension = parseFileExtension(filename).toLowerCase();\n\tswitch (extension) {\n\t\tcase 'jpg':\n\t\tcase 'jpeg':\n\t\tcase 'gif':\n\t\tcase 'png':\n\t\tcase 'pneg':\n\t\tcase 'webp':\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { hasImageFileExtension } from '@/lib/string/hasImageFileExtension';\nimport { queryOptions } from '@tanstack/react-query';\n\ninterface GetComponentFileRequest extends InstanceClientIdConfig {\n\tproject: string | undefined;\n\tfile: string | undefined;\n\tencoding?: 'utf8' | 'ASCII' | 'binary' | 'hex' | 'base64' | 'utf16le' | 'latin1' | 'ucs2';\n}\n\nexport interface GetComponentFileResponse {\n\tproject: string;\n\tfile: string;\n\tbirthtime: string;\n\tmessage: string;\n\tmtime: string;\n\tsize: number;\n}\n\nexport async function getComponentFile({\n\tinstanceClient,\n\tfile,\n\tproject,\n\tencoding,\n}: GetComponentFileRequest): Promise<GetComponentFileResponse> {\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation: 'get_component_file',\n\t\tproject,\n\t\tfile,\n\t\tencoding: encoding ?? (hasImageFileExtension(file) ? 'base64' : 'utf8'),\n\t});\n\treturn {\n\t\tproject,\n\t\tfile,\n\t\t...data,\n\t};\n}\n\nexport function getComponentFileQueryOptions(params: GetComponentFileRequest) {\n\treturn queryOptions({\n\t\tqueryKey: getComponentFileQueryKey(params),\n\t\tqueryFn: () => getComponentFile(params),\n\t\tenabled: !!params.file && !!params.project,\n\t\tretry: false,\n\t});\n}\n\nexport function getComponentFileQueryKey(params: GetComponentFileRequest) {\n\treturn [\n\t\tparams.entityId,\n\t\t'get_component_file',\n\t\tparams.project,\n\t\tparams.file,\n\t\tparams.encoding,\n\t] as const;\n}\n","import { InstanceClientConfig, InstanceTypeConfig } from '@/config/instanceClientConfig';\nimport { useMutation } from '@tanstack/react-query';\n\nexport interface SetComponentFileRequest extends InstanceClientConfig, InstanceTypeConfig {\n\tfile: string;\n\tpayload?: string;\n\tproject: string;\n\tencoding?: 'utf8' | 'ASCII' | 'binary' | 'hex' | 'base64' | 'utf16le' | 'latin1' | 'ucs2';\n}\n\nexport async function setComponentFile({\n\tfile,\n\tpayload,\n\tproject,\n\tentityType,\n\tinstanceClient,\n\tencoding,\n}: SetComponentFileRequest) {\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation: 'set_component_file',\n\t\tfile,\n\t\tpayload,\n\t\tproject,\n\t\tencoding,\n\t\treplicated: entityType === 'cluster',\n\t}, { timeout: 300_000 });\n\treturn data;\n}\n\nexport function useSetComponentFile() {\n\treturn useMutation({\n\t\tmutationFn: setComponentFile,\n\t});\n}\n","import { ProgressBar } from '@/components/ProgressBar';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { useEditorView } from '@/features/instance/applications/hooks/useEditorView';\nimport { dropComponent } from '@/integrations/api/instance/applications/dropComponent';\nimport { getComponentFile } from '@/integrations/api/instance/applications/getComponentFile';\nimport { setComponentFile } from '@/integrations/api/instance/applications/setComponentFile';\nimport { pluralize } from '@/lib/pluralize';\nimport { useCallback } from 'react';\nimport { ExternalToast, toast } from 'sonner';\n\nexport function useRenameFiles() {\n\tconst {\n\t\treloadRootEntries,\n\t\tsetFocusedItem,\n\t\tsetSelectedItems,\n\t} = useEditorView();\n\n\tconst instanceParams = useInstanceClientIdParams();\n\n\treturn useCallback(async (changes: { from: string; to: string }[]) => {\n\t\tlet canceled = false;\n\t\tconst actualChanges = changes.filter(change => change.from !== change.to);\n\n\t\tif (actualChanges.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst toastTitle = `Renaming ${pluralize(actualChanges.length, 'File', 'Files')}`;\n\t\tconst toastConfig: ExternalToast = {\n\t\t\tduration: 60_000,\n\t\t\taction: {\n\t\t\t\tlabel: 'Cancel',\n\t\t\t\tonClick: () => {\n\t\t\t\t\tcanceled = true;\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\n\t\ttoastConfig.id = toast.loading(toastTitle, {\n\t\t\t...toastConfig,\n\t\t\tdescription: <ProgressBar animated={true} width=\"0%\" />,\n\t\t});\n\n\t\tconst stepsPerFile = 3;\n\t\tconst totalSteps = actualChanges.length * stepsPerFile;\n\t\tlet currentStep = 0;\n\n\t\tfunction stepForward() {\n\t\t\tcurrentStep += 1;\n\t\t\ttoast.loading(toastTitle, {\n\t\t\t\t...toastConfig,\n\t\t\t\tdescription: (\n\t\t\t\t\t<ProgressBar animated={true} width={(currentStep === 0 ? 0 : (currentStep / totalSteps * 100)) + '%'} />\n\t\t\t\t),\n\t\t\t});\n\t\t}\n\n\t\tfor (const change of actualChanges) {\n\t\t\tconst oldParts = change.from.split('/');\n\t\t\tconst oldProject = oldParts.shift()!;\n\t\t\tconst oldFile = oldParts.join('/');\n\t\t\tconst newParts = change.to.split('/');\n\t\t\tconst newProject = newParts.shift()!;\n\t\t\tconst newFile = newParts.join('/');\n\n\t\t\tconst fileContents = await getComponentFile({\n\t\t\t\t...instanceParams,\n\t\t\t\tfile: oldFile,\n\t\t\t\tproject: oldProject,\n\t\t\t\tencoding: 'base64',\n\t\t\t});\n\t\t\tif (canceled) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tstepForward();\n\n\t\t\tawait setComponentFile({\n\t\t\t\t...instanceParams,\n\t\t\t\tfile: newFile,\n\t\t\t\tproject: newProject,\n\t\t\t\tencoding: 'base64',\n\t\t\t\tpayload: fileContents.message,\n\t\t\t});\n\t\t\tif (canceled) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tstepForward();\n\n\t\t\tawait dropComponent({\n\t\t\t\t...instanceParams,\n\t\t\t\tfile: oldFile,\n\t\t\t\tproject: oldProject,\n\t\t\t});\n\t\t\tif (canceled) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tstepForward();\n\t\t}\n\n\t\tif (currentStep >= totalSteps) {\n\t\t\ttoast.success(`Renamed ${pluralize(actualChanges.length, 'File', 'Files')}`, {\n\t\t\t\tid: toastConfig.id,\n\t\t\t\tdescription: 'All done!',\n\t\t\t\tduration: 3000,\n\t\t\t\taction: {\n\t\t\t\t\tlabel: 'OK',\n\t\t\t\t\tonClick: () => {\n\t\t\t\t\t\t// ;D\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\t\t} else {\n\t\t\ttoast.warning(`Rename Cancelled`, {\n\t\t\t\tid: toastConfig.id,\n\t\t\t\tdescription: `${currentStep} of ${totalSteps} steps completed.`,\n\t\t\t\tduration: 10000,\n\t\t\t\taction: {\n\t\t\t\t\tlabel: 'OK',\n\t\t\t\t\tonClick: () => {\n\t\t\t\t\t\t// >_<\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\tvoid reloadRootEntries();\n\n\t\tsetSelectedItems(selectedItems => {\n\t\t\tconst updatedSelectedItems = selectedItems.slice();\n\t\t\tfor (const change of actualChanges) {\n\t\t\t\tconst existingIndex = updatedSelectedItems.indexOf(change.from);\n\t\t\t\tif (existingIndex >= 0) {\n\t\t\t\t\tupdatedSelectedItems.splice(existingIndex, 1, change.to);\n\t\t\t\t} else {\n\t\t\t\t\tupdatedSelectedItems.push(change.to);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn updatedSelectedItems;\n\t\t});\n\n\t\tsetFocusedItem(focusedItem => {\n\t\t\tfor (const change of actualChanges) {\n\t\t\t\tif (focusedItem === change.from) {\n\t\t\t\t\treturn change.to;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn focusedItem;\n\t\t});\n\t}, [instanceParams, reloadRootEntries, setFocusedItem, setSelectedItems]);\n}\n","export function itemKeyIsDefined<T, K extends keyof T>(item: T, key: K): item is T & Required<Pick<T, K>> {\n\treturn item[key] !== undefined;\n}\n","import { itemKeyIsDefined } from '@/lib/types/itemKeyIsDefined';\n\nexport function excludePropertyFalsy<T, K extends keyof T>(key: K) {\n\treturn (item: T) => itemKeyIsDefined(item, key);\n}\n","import { emitToListeners, useListener } from '@/lib/events/listener';\nimport { WatchedValueKeys, WatchedValuesTypeMap } from '@/lib/storage/watchedValueKeys';\nimport { useCallback, useState } from 'react';\n\ninterface ValueWrapper<T> {\n\tvalue: T;\n\ttrigger?: unknown;\n}\n\nexport function useWatchedValue<K extends keyof WatchedValuesTypeMap, T extends WatchedValuesTypeMap[K], D extends T>(\n\tname: K,\n\tdefaultValue: D,\n): ValueWrapper<T> {\n\tconst [value, setValue] = useState<{ value: T; trigger?: unknown }>({ value: defaultValue });\n\tuseListener(\n\t\tname,\n\t\t(newValue: T, trigger) => setValue({ value: newValue, trigger }),\n\t\t[setValue],\n\t);\n\treturn value;\n}\n\nexport function setWatchedValue<K extends keyof WatchedValuesTypeMap, T extends WatchedValuesTypeMap[K]>(\n\tname: WatchedValueKeys,\n\tvalue: T,\n\ttrigger?: unknown,\n): void {\n\temitToListeners(name, value, trigger);\n}\n\nexport function currySetWatchedValue<K extends keyof WatchedValuesTypeMap, T extends WatchedValuesTypeMap[K]>(\n\tname: WatchedValueKeys,\n\tvalue: T,\n\ttrigger?: unknown,\n): (e?: unknown) => void {\n\treturn (e) => setWatchedValue(name, value, trigger ?? e);\n}\n\nexport function useSetWatchedValue<K extends keyof WatchedValuesTypeMap, T extends WatchedValuesTypeMap[K]>(\n\tname: WatchedValueKeys,\n\tvalue: T,\n\ttrigger?: unknown,\n): () => void {\n\treturn useCallback((e?: unknown) => {\n\t\tsetWatchedValue(name, value, trigger ?? e);\n\t}, [name, value, trigger]);\n}\n","import { excludePropertyFalsy } from '@/lib/arrays/excludePropertyFalsy';\nimport { OnMount } from '@monaco-editor/react';\nimport { useEffect } from 'react';\nimport { Contract } from './contract';\nimport { deleteShortcut } from './deleteShortcut';\nimport { newDirectoryShortcut } from './newDirectoryShortcut';\nimport { newFileShortcut } from './newFileShortcut';\nimport { renameFileShortcut } from './renameFileShortcut';\nimport { revertFileShortcut } from './revertFileShortcut';\nimport { saveChangesShortcut } from './saveChangesShortcut';\n\nconst shortcuts: Contract[] = [\n\tdeleteShortcut,\n\tnewDirectoryShortcut,\n\tnewFileShortcut,\n\trenameFileShortcut,\n\trevertFileShortcut,\n\tsaveChangesShortcut,\n];\n\nconst editorShortcuts = shortcuts.filter(excludePropertyFalsy('addEditorAction'));\nconst globalShortcuts = shortcuts.filter(excludePropertyFalsy('handleGlobal'));\n\nexport function registerWithEditor(mounted: Parameters<OnMount>) {\n\tconst [editor, monaco] = mounted;\n\tconst disposables = editorShortcuts\n\t\t.map(shortcut => editor.addAction(shortcut.addEditorAction(monaco)));\n\treturn () => {\n\t\tfor (const disposable of disposables) {\n\t\t\tdisposable?.dispose();\n\t\t}\n\t};\n}\n\nexport function useGlobalShortcutKeys() {\n\tuseEffect(() => {\n\t\tdocument.addEventListener('keydown', keyDownHandler);\n\n\t\treturn () => {\n\t\t\tdocument.removeEventListener('keydown', keyDownHandler);\n\t\t};\n\t}, []);\n}\n\nfunction keyDownHandler(e: KeyboardEvent) {\n\tconst cmd = e.getModifierState('Meta');\n\tconst alt = e.getModifierState('Alt');\n\tconst shift = e.getModifierState('Shift');\n\tconst ctrl = e.getModifierState('Control');\n\tconst modifiers = { cmd, alt, shift, ctrl };\n\n\tfor (const globalShortcut of globalShortcuts) {\n\t\tif (globalShortcut.handleGlobal(e.key, modifiers)) {\n\t\t\te.preventDefault();\n\t\t\treturn;\n\t\t}\n\t}\n\t// console.log('unhandled key press', e.key, modifiers);\n}\n","import { currySetWatchedValue, setWatchedValue } from '@/lib/events/watcher';\nimport { Contract } from './contract';\n\nexport const deleteShortcut = {\n\thandleGlobal(key, modifiers) {\n\t\tif ((modifiers.cmd || modifiers.ctrl) && key === 'Delete') {\n\t\t\tsetWatchedValue('ShowDeleteDirectoryOrFileModal', true);\n\t\t\treturn true;\n\t\t}\n\t},\n\taddEditorAction(monaco) {\n\t\treturn {\n\t\t\tid: 'delete-file',\n\t\t\tlabel: 'Delete File',\n\t\t\tkeybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.Delete],\n\t\t\trun: currySetWatchedValue('ShowDeleteDirectoryOrFileModal', true),\n\t\t};\n\t},\n} satisfies Contract;\n","import { currySetWatchedValue, setWatchedValue } from '@/lib/events/watcher';\nimport { Contract } from './contract';\n\nexport const newDirectoryShortcut = {\n\thandleGlobal(key, modifiers) {\n\t\tif (modifiers.ctrl && modifiers.alt && modifiers.shift && key === '˜' /*n*/) {\n\t\t\tsetWatchedValue('ShowAddDirectoryOrFileModalType', 'directory');\n\t\t\treturn true;\n\t\t}\n\t},\n\taddEditorAction(monaco) {\n\t\treturn {\n\t\t\tid: 'new-directory',\n\t\t\tlabel: 'New Directory',\n\t\t\tkeybindings: [monaco.KeyMod.WinCtrl | monaco.KeyMod.Alt | monaco.KeyMod.Shift | monaco.KeyCode.KeyN],\n\t\t\trun: currySetWatchedValue('ShowAddDirectoryOrFileModalType', 'directory'),\n\t\t};\n\t},\n} satisfies Contract;\n","import { currySetWatchedValue, setWatchedValue } from '@/lib/events/watcher';\nimport { Contract } from './contract';\n\nexport const newFileShortcut = {\n\thandleGlobal(key, modifiers) {\n\t\tif (modifiers.ctrl && key === 'n') {\n\t\t\tsetWatchedValue('ShowAddDirectoryOrFileModalType', 'file');\n\t\t\treturn true;\n\t\t}\n\t},\n\taddEditorAction(monaco) {\n\t\treturn {\n\t\t\tid: 'new-file',\n\t\t\tlabel: 'New File',\n\t\t\tkeybindings: [monaco.KeyMod.WinCtrl | monaco.KeyCode.KeyN],\n\t\t\trun: currySetWatchedValue('ShowAddDirectoryOrFileModalType', 'file'),\n\t\t};\n\t},\n} satisfies Contract;\n","import { currySetWatchedValue, setWatchedValue } from '@/lib/events/watcher';\nimport { Contract } from './contract';\n\nexport const renameFileShortcut = {\n\thandleGlobal(key) {\n\t\tif (key === 'F2') {\n\t\t\tsetWatchedValue('ShowRenameFileModal', 'file');\n\t\t\treturn true;\n\t\t}\n\t},\n\taddEditorAction(monaco) {\n\t\treturn {\n\t\t\tid: 'rename-file',\n\t\t\tlabel: 'Rename File',\n\t\t\tkeybindings: [\n\t\t\t\tmonaco.KeyMod.WinCtrl | monaco.KeyMod.Alt | monaco.KeyCode.KeyR,\n\t\t\t\tmonaco.KeyCode.F2,\n\t\t\t],\n\t\t\trun: currySetWatchedValue('ShowRenameFileModal', true),\n\t\t};\n\t},\n} satisfies Contract;\n","import { curryEmitToListeners } from '@/lib/events/listener';\nimport { Contract } from './contract';\n\nexport const revertFileShortcut = {\n\taddEditorAction() {\n\t\treturn {\n\t\t\tid: 'revert-file',\n\t\t\tlabel: 'Revert File',\n\t\t\trun: curryEmitToListeners('RevertChanges', true),\n\t\t};\n\t},\n} satisfies Contract;\n","import { curryEmitToListeners, emitToListeners } from '@/lib/events/listener';\nimport { Contract } from './contract';\n\nexport const saveChangesShortcut = {\n\thandleGlobal(key, modifiers) {\n\t\tif (modifiers.cmd && key === 's') {\n\t\t\temitToListeners('SaveFile', true);\n\t\t\treturn true;\n\t\t}\n\t},\n\taddEditorAction(monaco) {\n\t\treturn {\n\t\t\tid: 'save-file',\n\t\t\tlabel: 'Save Changes',\n\t\t\tkeybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS],\n\t\t\trun: curryEmitToListeners('SaveFile', true),\n\t\t};\n\t},\n} satisfies Contract;\n","export function extractFileNameFromPath(path: string): string {\n\treturn path.split('/').pop()!;\n}\n","export function joinPath(...parts: (string | string[])[]): string {\n\tconst flattened = parts.flat(1);\n\treturn flattened\n\t\t.map((p, i) =>\n\t\t\ttypeof p !== 'string'\n\t\t\t\t? p\n\t\t\t\t: trimSlashes(p, i !== 0, i !== flattened.length - 1)\n\t\t)\n\t\t.join('/');\n}\n\nfunction trimSlashes(str: string, start: boolean = true, end: boolean = true) {\n\tconst trimStart = start && str[0] === '/';\n\tconst trimEnd = end && str[str.length - 1] === '/';\n\tif (trimStart && trimEnd) {\n\t\treturn str.slice(1, -1);\n\t}\n\tif (trimStart) {\n\t\treturn str.slice(1);\n\t}\n\tif (trimEnd) {\n\t\treturn str.slice(0, -1);\n\t}\n\treturn str;\n}\n","import { DirectoryEntry } from '@/features/instance/applications/context/directoryEntry';\nimport { FileEntry } from '@/features/instance/applications/context/fileEntry';\nimport { APIDirectoryEntry, APIFileEntry } from '@/integrations/api/instance/applications/getComponents';\n\nexport function isDirectory(entry: DirectoryEntry | FileEntry | undefined): entry is DirectoryEntry;\nexport function isDirectory(entry: APIDirectoryEntry | APIFileEntry | undefined): entry is APIDirectoryEntry;\nexport function isDirectory(entry: DirectoryEntry | FileEntry | APIDirectoryEntry | APIFileEntry | undefined) {\n\treturn Boolean((entry as DirectoryEntry)?.entries);\n}\n","export const rootId = '__root__';\nexport const importedApplications = 'importedApplications';\nexport const newApplication = 'newApplication';\n","import type { DirectoryEntry } from '@/features/instance/applications/context/directoryEntry';\nimport type { FileEntry } from '@/features/instance/applications/context/fileEntry';\nimport { isDirectory } from '@/features/instance/applications/context/isDirectory';\nimport { excludeFalsy } from '@/lib/arrays/excludeFalsy';\nimport type { TreeItem } from 'react-complex-tree';\nimport { importedApplications, newApplication, rootId } from './specialItems';\n\nexport function buildItems(rootEntries: Array<DirectoryEntry | FileEntry>): {\n\titems: Record<string, TreeItem<DirectoryEntry | FileEntry | undefined>>;\n\trootId: string;\n} {\n\tconst items: Record<string, TreeItem<DirectoryEntry | FileEntry | undefined>> = {};\n\n\tconst directoryIds: string[] = [];\n\tconst applicationIds: string[] = [];\n\tconst fileIds: string[] = [];\n\tfor (const entry of rootEntries) {\n\t\tif (isDirectory(entry)) {\n\t\t\tif (entry.package) {\n\t\t\t\tapplicationIds.push(entry.path);\n\t\t\t} else {\n\t\t\t\tdirectoryIds.push(entry.path);\n\t\t\t}\n\t\t} else {\n\t\t\tfileIds.push(entry.path);\n\t\t}\n\t\taddEntry(items, entry);\n\t}\n\n\titems[rootId] = {\n\t\tindex: rootId,\n\t\tisFolder: true,\n\t\tchildren: [\n\t\t\tnewApplication,\n\t\t\timportedApplications,\n\t\t\t...directoryIds,\n\t\t\t...fileIds,\n\t\t].filter(\n\t\t\texcludeFalsy,\n\t\t),\n\t\tdata: undefined,\n\t\tcanMove: false,\n\t\tcanRename: false,\n\t} satisfies TreeItem<undefined>;\n\n\titems[importedApplications] = {\n\t\tindex: importedApplications,\n\t\tisFolder: true,\n\t\tchildren: applicationIds,\n\t\tdata: {\n\t\t\tname: 'Imported Applications',\n\t\t\tpath: importedApplications,\n\t\t\tpackage: importedApplications,\n\t\t\tproject: '',\n\t\t\tentries: [],\n\t\t},\n\t\tcanMove: false,\n\t\tcanRename: false,\n\t} satisfies TreeItem<DirectoryEntry>;\n\n\titems[newApplication] = {\n\t\tindex: newApplication,\n\t\tisFolder: false,\n\t\tdata: {\n\t\t\tname: 'New Application',\n\t\t\tpath: newApplication,\n\t\t\tproject: '',\n\t\t},\n\t\tcanMove: false,\n\t\tcanRename: false,\n\t} satisfies TreeItem<FileEntry>;\n\n\treturn { items, rootId };\n}\n\nfunction addEntry(\n\titems: Record<string, TreeItem<DirectoryEntry | FileEntry | undefined>>,\n\tentry: DirectoryEntry | FileEntry,\n) {\n\tconst index = entry.path;\n\tif (isDirectory(entry)) {\n\t\tconst dir = entry as DirectoryEntry;\n\t\tconst childDirectoryIds: string[] = [];\n\t\tconst childFileIds: string[] = [];\n\t\tfor (const childEntry of dir.entries) {\n\t\t\tif (isDirectory(childEntry)) {\n\t\t\t\tchildDirectoryIds.push(childEntry.path);\n\t\t\t} else {\n\t\t\t\tchildFileIds.push(childEntry.path);\n\t\t\t}\n\t\t}\n\t\titems[index] = {\n\t\t\tindex,\n\t\t\tisFolder: true,\n\t\t\tchildren: [...childDirectoryIds, ...childFileIds],\n\t\t\tdata: entry,\n\t\t\tcanMove: false,\n\t\t\tcanRename: false,\n\t\t} satisfies TreeItem<DirectoryEntry>;\n\t\tfor (const child of dir.entries) {\n\t\t\taddEntry(items, child);\n\t\t}\n\t} else {\n\t\titems[index] = {\n\t\t\tindex,\n\t\t\tisFolder: false,\n\t\t\tdata: entry,\n\t\t\tcanMove: !entry.package,\n\t\t\tcanRename: !entry.package,\n\t\t} satisfies TreeItem<FileEntry>;\n\t}\n}\n","import { useCallback, useEffect, useMemo, useState } from 'react';\nimport { importedApplications, newApplication } from './specialItems';\n\nexport function useDraggingHook() {\n\tconst [dragging, setDragging] = useState(false);\n\tconst [dragTarget, setDragTarget] = useState<Element | undefined>(undefined);\n\tconst startDragging = useCallback((e: DragEvent) => {\n\t\tconst foundFiles = e.dataTransfer?.types?.includes('Files');\n\t\tif (!foundFiles) {\n\t\t\treturn;\n\t\t}\n\t\tconst newTarget = e.target;\n\t\tif (\n\t\t\tnewTarget instanceof Element\n\t\t\t&& newTarget.classList.contains('rct-tree-item-button-isFolder')\n\t\t) {\n\t\t\tconst itemId = newTarget.getAttribute('data-rct-item-id');\n\t\t\tconst isLocked = newTarget.querySelector('.packageIsLocked');\n\t\t\tif (\n\t\t\t\t!isLocked && itemId && itemId !== importedApplications && itemId !== newApplication\n\t\t\t) {\n\t\t\t\tsetDragTarget(currentTarget => {\n\t\t\t\t\tif (currentTarget !== newTarget) {\n\t\t\t\t\t\tcurrentTarget?.classList?.remove?.('rct-tree-item-title-container-dragging-over');\n\t\t\t\t\t\tnewTarget.classList.add('rct-tree-item-title-container-dragging-over');\n\t\t\t\t\t\treturn newTarget;\n\t\t\t\t\t}\n\t\t\t\t\treturn currentTarget;\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tsetDragging(true);\n\t}, []);\n\n\tconst dragLeave = useCallback(() => {\n\t\tsetDragging(false);\n\t\tsetDragTarget(currentTarget => {\n\t\t\tif (currentTarget) {\n\t\t\t\tcurrentTarget.classList.remove('rct-tree-item-title-container-dragging-over');\n\t\t\t}\n\t\t\treturn undefined;\n\t\t});\n\t}, []);\n\n\tconst dropped = useCallback((e: DragEvent) => {\n\t\tconst foundFiles = e.dataTransfer?.types?.includes('Files');\n\t\tif (!foundFiles) {\n\t\t\treturn;\n\t\t}\n\t\tif (e.detail === 1337) {\n\t\t\t// Prevent a recursive dispatch.\n\t\t\treturn;\n\t\t}\n\t\tsetDragging(false);\n\t\tif (dragTarget) {\n\t\t\tdragTarget.classList.remove('rct-tree-item-title-container-dragging-over');\n\t\t\tsetDragTarget(undefined);\n\t\t}\n\t\tconst dropTarget = document.getElementById('dropTarget');\n\t\tif (dropTarget) {\n\t\t\treturn dropTarget.dispatchEvent(\n\t\t\t\tnew DragEvent('drop', {\n\t\t\t\t\tbubbles: true,\n\t\t\t\t\tdetail: 1337, // Prevent a recursive dispatch.\n\t\t\t\t\tcancelable: true,\n\t\t\t\t\tdataTransfer: e.dataTransfer,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn false;\n\t}, [dragTarget]);\n\n\tuseEffect(() => {\n\t\tdocument.addEventListener('dragenter', startDragging);\n\t\tdocument.addEventListener('dragover', startDragging);\n\t\tdocument.addEventListener('dragleave', dragLeave);\n\t\tdocument.addEventListener('drop', dropped);\n\n\t\treturn () => {\n\t\t\tdocument.removeEventListener('dragenter', startDragging);\n\t\t\tdocument.removeEventListener('dragover', startDragging);\n\t\t\tdocument.removeEventListener('dragleave', dragLeave);\n\t\t\tdocument.removeEventListener('drop', dropped);\n\t\t};\n\t}, [startDragging, dropped, dragLeave]);\n\n\treturn useMemo(() => ({ dragging, dragTarget }), [dragging, dragTarget]);\n}\n","export function readAsDataURL(file: File): Promise<ProgressEvent<FileReader>> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst reader = new FileReader();\n\t\treader.onabort = reject;\n\t\treader.onerror = reject;\n\t\treader.onload = resolve;\n\t\treader.readAsDataURL(file);\n\t});\n}\n","import { maxFabricConnectUploadFileSize, maxUploadFileSize } from '@/config/constants';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { authStore } from '@/features/auth/store/authStore';\nimport { useDraggingHook } from '@/features/instance/applications/components/ApplicationsSidebar/useDraggingHook';\nimport { isDirectory } from '@/features/instance/applications/context/isDirectory';\nimport { useEditorView } from '@/features/instance/applications/hooks/useEditorView';\nimport { setComponentFile } from '@/integrations/api/instance/applications/setComponentFile';\nimport { humanFileSize } from '@/lib/humanFileSize';\nimport { pluralize } from '@/lib/pluralize';\nimport { readAsDataURL } from '@/lib/storage/readAsDataURL';\nimport { useParams } from '@tanstack/react-router';\nimport { cx } from 'class-variance-authority';\nimport { useCallback, useState } from 'react';\nimport { FileRejection, FileWithPath, useDropzone } from 'react-dropzone';\nimport { toast } from 'sonner';\n\nexport function DropTarget() {\n\tconst [uploading, setUploading] = useState('');\n\tconst { clusterId }: { clusterId?: string } = useParams({ strict: false });\n\tconst { openedEntry, restrictPackageModification, reloadRootEntries, entryExists } = useEditorView();\n\tconst canUpload = !!openedEntry && !openedEntry.package && !restrictPackageModification;\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst { dragging: isDraggingAnywhere, dragTarget } = useDraggingHook();\n\tconst dragTargetId = dragTarget?.getAttribute?.('data-rct-item-id');\n\tconst dragTargetDirectory = dragTargetId?.split?.('/')?.pop?.();\n\n\tconst currentProject = openedEntry?.project;\n\tlet currentPath: string | false = false;\n\tlet currentDirectory: string | undefined = undefined;\n\tif (openedEntry?.path) {\n\t\tconst parts = openedEntry.path.split('/');\n\t\tconst currentPathIsDirectory = isDirectory(openedEntry);\n\t\tcurrentPath = canUpload && ((\n\t\t\tcurrentPathIsDirectory\n\t\t\t\t? parts.slice(1)\n\t\t\t\t: parts.slice(1, -1)\n\t\t).join('/'));\n\t\tcurrentDirectory = parts[parts.length - (currentPathIsDirectory ? 1 : 2)];\n\t}\n\n\tconst onUploadDrop = useCallback(async (\n\t\trawAcceptedFiles: FileWithPath[],\n\t\trawRejectedFiles: FileRejection[],\n\t) => {\n\t\tconst dragItemId = dragTarget?.getAttribute?.('data-rct-item-id')?.split?.('/');\n\t\tconst targetProject = dragItemId?.length ? dragItemId[0] : canUpload ? currentProject : false;\n\t\tconst targetPath = dragItemId?.length ? dragItemId.slice(1).join('/') : canUpload ? currentPath : false;\n\t\tif (targetProject === false || targetProject === undefined || targetPath === false || targetPath === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst filesToUpload: FileWithPath[] = [];\n\t\tconst filesRejected: FileRejection[] = rawRejectedFiles.slice();\n\n\t\tfor (const file of rawAcceptedFiles) {\n\t\t\tconst filePath = getFilePath(targetPath, file);\n\t\t\tif (file.name.startsWith('.') || file.relativePath?.includes('/.')) {\n\t\t\t\tfilesRejected.push({\n\t\t\t\t\tfile,\n\t\t\t\t\terrors: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmessage: 'Sensitive files and folders starting with . are skipped.',\n\t\t\t\t\t\t\tcode: 'dot-ignored',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t} else if (entryExists(`${targetProject}/${filePath}`)) {\n\t\t\t\tfilesRejected.push({\n\t\t\t\t\tfile,\n\t\t\t\t\terrors: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmessage: `${filePath} already exists`,\n\t\t\t\t\t\t\tcode: 'duplicate',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tfilesToUpload.push(file);\n\t\t\t}\n\t\t}\n\n\t\tlet canceled = false;\n\n\t\tconst id = 'uploading-files';\n\t\tconst toastCancelAction = {\n\t\t\tlabel: 'Cancel',\n\t\t\tonClick: () => {\n\t\t\t\tcanceled = true;\n\t\t\t},\n\t\t};\n\t\tconst toastOKAction = {\n\t\t\tlabel: 'OK',\n\t\t\tonClick: () => undefined,\n\t\t};\n\n\t\tsetUploading(`Uploading ${pluralize(filesToUpload.length, 'file', 'files')}...`);\n\n\t\tconst totalBytes = filesToUpload.reduce((sum, f) => sum + f.size, 0);\n\t\tlet uploadedBytes = 0;\n\t\tlet counter = 0;\n\t\tfor (const file of filesToUpload) {\n\t\t\tcounter += 1;\n\n\t\t\ttoast.loading(`Upload in progress...`, {\n\t\t\t\tid,\n\t\t\t\tdescriptionClassName: 'whitespace-pre',\n\t\t\t\tdescription: `${counter} of ${pluralize(filesToUpload.length, 'file', 'files')}\n${file.name}\n${humanFileSize(uploadedBytes)} of ${humanFileSize(totalBytes)}`,\n\t\t\t\taction: toastCancelAction,\n\t\t\t});\n\n\t\t\tconst filePath = getFilePath(targetPath, file);\n\t\t\tconst dataURLResponse = await readAsDataURL(file);\n\t\t\tconst dataURLResult = dataURLResponse.target!.result as string;\n\t\t\tconst demarcation = 'base64,';\n\t\t\tconst encodingIndex = dataURLResult.indexOf(demarcation);\n\t\t\tif (!canceled) {\n\t\t\t\tawait setComponentFile({\n\t\t\t\t\t...instanceParams,\n\t\t\t\t\tfile: filePath,\n\t\t\t\t\tproject: targetProject,\n\t\t\t\t\tencoding: 'base64',\n\t\t\t\t\tpayload: dataURLResult.slice(encodingIndex + demarcation.length),\n\t\t\t\t});\n\t\t\t\tuploadedBytes += file.size;\n\t\t\t} else {\n\t\t\t\tfilesRejected.push({\n\t\t\t\t\tfile,\n\t\t\t\t\terrors: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmessage: `${filePath} cancelled`,\n\t\t\t\t\t\t\tcode: 'cancelled',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\ttoast.loading(`Reloading sidebar...`, {\n\t\t\tid: canceled ? undefined : id,\n\t\t\taction: toastOKAction,\n\t\t\tdescription: '',\n\t\t});\n\t\tawait reloadRootEntries();\n\n\t\tif (filesRejected.length === 0) {\n\t\t\tif (rawAcceptedFiles.length > 0) {\n\t\t\t\ttoast.success(`Uploaded ${pluralize(filesToUpload.length, 'file', 'files')}!`, {\n\t\t\t\t\tid,\n\t\t\t\t\taction: toastOKAction,\n\t\t\t\t\tdescription: '',\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\t// Note: this console.log is deliberate. It lets developers know all the files that were rejected.\n\t\t\tconsole.log(filesRejected);\n\t\t\ttoast.error(canceled ? 'Cancelled uploads' : 'Rejected uploads', {\n\t\t\t\tid: canceled ? undefined : id,\n\t\t\t\taction: toastOKAction,\n\t\t\t\tdescriptionClassName: 'whitespace-pre overflow-y-auto',\n\t\t\t\tdescription: filesRejected\n\t\t\t\t\t.slice(0, 5)\n\t\t\t\t\t.map(r => r.errors.map(e => e.message).join('\\n'))\n\t\t\t\t\t.join('\\n')\n\t\t\t\t\t+ (filesRejected?.length > 5 ? '\\nCheck the console for the full list.' : ''),\n\t\t\t});\n\t\t}\n\t\tsetUploading('');\n\t}, [dragTarget, canUpload, currentProject, currentPath, entryExists, instanceParams, reloadRootEntries]);\n\n\tconst isFabricConnect = !!clusterId && authStore.checkForFabricConnect(clusterId);\n\tconst { getRootProps, getInputProps } = useDropzone({\n\t\tmultiple: true,\n\t\tmaxSize: isFabricConnect ? maxFabricConnectUploadFileSize : maxUploadFileSize,\n\t\tonDrop: onUploadDrop,\n\t});\n\n\tif (!canUpload && !dragTarget) {\n\t\tif (!isDraggingAnywhere) {\n\t\t\treturn null;\n\t\t}\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={cx(\n\t\t\t\t\t'border-3 border-dashed',\n\t\t\t\t\t'pointer-events-auto',\n\t\t\t\t\t'cursor-copy text-sm text-center',\n\t\t\t\t\t'p-2 w-full fixed bottom-0 h-16',\n\t\t\t\t\t'flex flex-col items-center justify-center',\n\t\t\t\t\t'bg-red-950 border-red-600',\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\tYou cannot upload into<br />\n\t\t\t\t<strong>{currentDirectory}</strong>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div\n\t\t\t{...getRootProps()}\n\t\t\tclassName={isDraggingAnywhere\n\t\t\t\t? 'fixed top-0 bottom-0 w-full'\n\t\t\t\t\t+ ' pointer-events-none'\n\t\t\t\t: ''}\n\t\t>\n\t\t\t<input id=\"dropTarget\" {...getInputProps()} />\n\t\t\t<div\n\t\t\t\tclassName={cx(\n\t\t\t\t\t'border-3 border-dashed',\n\t\t\t\t\t'pointer-events-auto',\n\t\t\t\t\t'cursor-copy text-sm text-center',\n\t\t\t\t\t'p-2 w-full fixed bottom-0 h-16',\n\t\t\t\t\t'flex flex-col items-center justify-center',\n\t\t\t\t\tisDraggingAnywhere\n\t\t\t\t\t\t? 'animate-glow-pulse bg-green-950 border-green-600'\n\t\t\t\t\t\t: 'bg-purple-950 border-purple-600',\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{uploading\n\t\t\t\t\t? uploading\n\t\t\t\t\t: dragTarget\n\t\t\t\t\t? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\tDrop to upload into<br />\n\t\t\t\t\t\t\t<strong>{dragTargetDirectory}</strong>\n\t\t\t\t\t\t</>\n\t\t\t\t\t)\n\t\t\t\t\t: isDraggingAnywhere\n\t\t\t\t\t? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\tDrop to upload into<br />\n\t\t\t\t\t\t\t<strong>{currentDirectory}</strong>\n\t\t\t\t\t\t</>\n\t\t\t\t\t)\n\t\t\t\t\t: (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\tDrag and drop to upload<br />or click to select files.\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nfunction getFilePath(intoPath: string, file: FileWithPath): string {\n\tconst relativePath = file.relativePath ?? file.name;\n\tconst firstSlashIndex = relativePath.indexOf('/');\n\tconst trimmedRelativePath = firstSlashIndex === 0 || firstSlashIndex === 1\n\t\t? relativePath.slice(firstSlashIndex + 1)\n\t\t: relativePath;\n\treturn intoPath ? `${intoPath}/${trimmedRelativePath}` : trimmedRelativePath;\n}\n","import type { DirectoryEntry } from '@/features/instance/applications/context/directoryEntry';\nimport type { FileEntry } from '@/features/instance/applications/context/fileEntry';\nimport type { TreeItem } from 'react-complex-tree';\n\nexport function getItemTitle(item: TreeItem<DirectoryEntry | FileEntry | undefined>): string {\n\tconst data = item.data;\n\tif (data && 'name' in data) {\n\t\treturn data.name;\n\t}\n\treturn 'root';\n}\n","import { isLocalStudio } from '@/config/constants';\nimport { OverallAppSignIn } from '@/features/auth/store/authStore';\nimport { useSessionStorage } from '@/hooks/useSessionStorage';\nimport { useParams } from '@tanstack/react-router';\nimport { useMemo } from 'react';\n\nexport function useEditorFileContent(path: string | undefined | false) {\n\tconst { instanceId, clusterId }: { instanceId?: string; clusterId?: string } = useParams({ strict: false });\n\tconst id = isLocalStudio ? OverallAppSignIn : instanceId ?? clusterId;\n\tconst [updatedContent, setUpdatedContent] = useSessionStorage(\n\t\t`EditorFileContent/${id}}/${path}` as 'EditorFileContent/{entityId}/{path}',\n\t\tundefined as string | undefined,\n\t);\n\n\treturn useMemo(() => ({\n\t\tcontent: path ? updatedContent : undefined,\n\t\tsetContent: setUpdatedContent,\n\t}), [path, updatedContent, setUpdatedContent]);\n}\n","export const iconSharedClassName = 'w-6 pointer-events-none ';\n","import { FolderIcon, FolderOpenIcon, PackageIcon, PackageOpenIcon } from 'lucide-react';\nimport { iconSharedClassName } from './constants';\n\nexport function DirectoryIcon({ opened, pkg }: { readonly opened?: boolean; readonly pkg?: boolean }) {\n\tconst iconClassName = iconSharedClassName + 'w-4 h-4 shrink-0';\n\n\tif (pkg) {\n\t\treturn opened\n\t\t\t? <PackageOpenIcon className={`${iconClassName} text-orange-600`} />\n\t\t\t: <PackageIcon className={`${iconClassName} text-orange-600`} />;\n\t}\n\treturn opened\n\t\t? <FolderOpenIcon className={`${iconClassName} text-orange-400`} />\n\t\t: <FolderIcon className={`${iconClassName} text-orange-400`} />;\n}\n","import {\n\tCodeIcon,\n\tFileCode2Icon,\n\tFileIcon,\n\tFileImageIcon,\n\tFileJsonIcon,\n\tFileTypeIcon as LucideFileTypeIcon,\n} from 'lucide-react';\n\nexport function FileTypeIcon({ extension }: { readonly extension: string | null }) {\n\tconst iconClassName = 'w-4 h-4 mr-2 shrink-0';\n\n\tswitch (extension) {\n\t\tcase 'js':\n\t\tcase 'jsx':\n\t\tcase 'cjs':\n\t\t\treturn <FileCode2Icon className={`${iconClassName} text-yellow-500`} />;\n\t\tcase 'ts':\n\t\tcase 'tsx':\n\t\t\treturn <FileCode2Icon className={`${iconClassName} text-blue-500`} />;\n\t\tcase 'yaml':\n\t\tcase 'yml':\n\t\t\treturn <FileIcon className={iconClassName} />;\n\t\tcase 'css':\n\t\t\treturn <FileIcon className={`${iconClassName} text-blue-500`} />;\n\t\tcase 'html':\n\t\t\treturn <CodeIcon className={iconClassName} />;\n\t\tcase 'json':\n\t\t\treturn <FileJsonIcon className={iconClassName} />;\n\t\tcase 'png':\n\t\tcase 'jpg':\n\t\tcase 'jpeg':\n\t\tcase 'gif':\n\t\t\treturn <FileImageIcon className={iconClassName} />;\n\t\tcase 'svg':\n\t\t\treturn <LucideFileTypeIcon className={iconClassName} />;\n\t\tcase 'vue':\n\t\t\treturn <FileCode2Icon className={`${iconClassName} text-green-500`} />;\n\t\tdefault:\n\t\t\treturn <FileIcon className={iconClassName} />;\n\t}\n}\n","import { LockIcon } from 'lucide-react';\nimport { iconSharedClassName } from './constants';\n\nexport function LockedIcon() {\n\treturn (\n\t\t<LockIcon\n\t\t\tclassName={iconSharedClassName + 'w-4 h-4 shrink-0 text-gray-400 ml-2 packageIsLocked'}\n\t\t/>\n\t);\n}\n","import { PlusIcon } from 'lucide-react';\nimport { iconSharedClassName } from './constants';\n\nexport function NewApplicationIcon() {\n\treturn <PlusIcon className={iconSharedClassName + 'w-4 h-4 shrink-0 text-green-500'} />;\n}\n","import type { DirectoryEntry } from '@/features/instance/applications/context/directoryEntry';\nimport { useEditorFileContent } from '@/features/instance/applications/context/editorFileContent';\nimport type { FileEntry } from '@/features/instance/applications/context/fileEntry';\nimport { isDirectory } from '@/features/instance/applications/context/isDirectory';\nimport { parseFileExtension } from '@/lib/string/parseFileExtension';\nimport { TreeItem } from 'react-complex-tree';\nimport { TreeItemRenderContext } from 'react-complex-tree/src/types';\nimport { DirectoryIcon } from './DirectoryIcon';\nimport { FileTypeIcon } from './FileTypeIcon';\nimport { LockedIcon } from './LockedIcon';\nimport { NewApplicationIcon } from './NewApplicationIcon';\nimport { importedApplications, newApplication } from './specialItems';\n\nexport function ItemTitle({ title, item, context }: {\n\ttitle: string;\n\titem: TreeItem<DirectoryEntry | FileEntry | undefined>;\n\tcontext: TreeItemRenderContext;\n}) {\n\tconst { content } = useEditorFileContent(item.data?.path);\n\treturn (\n\t\t<>\n\t\t\t{item.data?.path === newApplication\n\t\t\t\t? <NewApplicationIcon />\n\t\t\t\t: isDirectory(item.data)\n\t\t\t\t? (\n\t\t\t\t\t<DirectoryIcon\n\t\t\t\t\t\topened={context.isExpanded}\n\t\t\t\t\t\tpkg={!!item.data?.package || item.data.path === importedApplications}\n\t\t\t\t\t/>\n\t\t\t\t)\n\t\t\t\t: <FileTypeIcon extension={parseFileExtension(title)} />}\n\t\t\t<span className=\"text-nowrap pointer-events-none\">{title}{content ? '*' : ''}</span>\n\t\t\t{item.data?.package && <LockedIcon />}\n\t\t</>\n\t);\n}\n","import type { DirectoryEntry } from '@/features/instance/applications/context/directoryEntry';\nimport type { FileEntry } from '@/features/instance/applications/context/fileEntry';\nimport { useEditorView } from '@/features/instance/applications/hooks/useEditorView';\nimport { useRenameFiles } from '@/features/instance/applications/hooks/useRenameFiles';\nimport { useGlobalShortcutKeys } from '@/features/instance/applications/shortcuts';\nimport { extractFileNameFromPath } from '@/lib/string/paths/extractFileNameFromPath';\nimport { joinPath } from '@/lib/string/paths/joinPath';\nimport { useCallback, useEffect, useMemo } from 'react';\nimport { ControlledTreeEnvironment, Tree, TreeItem } from 'react-complex-tree';\nimport './file-explorer-modern.css';\nimport { DraggingPosition } from 'react-complex-tree/src/types';\nimport { toast } from 'sonner';\nimport { buildItems } from './buildItems';\nimport { DropTarget } from './DropTarget';\nimport { getItemTitle } from './getItemTitle';\nimport { ItemTitle } from './ItemTitle';\n\nexport function ApplicationsSidebar() {\n\tconst {\n\t\trootEntries,\n\t\topenedEntry,\n\t\tsetOpenedEntry,\n\t\tfocusedItem,\n\t\tsetFocusedItem,\n\t\texpandedItems,\n\t\tsetExpandedItems,\n\t\tselectedItems,\n\t\tsetSelectedItems,\n\t} = useEditorView();\n\tconst { items, rootId } = useMemo(() => buildItems(rootEntries), [rootEntries]);\n\n\tuseGlobalShortcutKeys();\n\n\tuseEffect(function setOpenedEntryFromFocusedItem() {\n\t\tif (openedEntry?.path !== focusedItem && focusedItem) {\n\t\t\tconst item = items[focusedItem];\n\t\t\tconst entry = item?.data as DirectoryEntry | FileEntry | undefined;\n\t\t\tif (entry) {\n\t\t\t\tsetOpenedEntry(entry);\n\t\t\t}\n\t\t}\n\t}, [focusedItem, items, openedEntry?.path, setOpenedEntry]);\n\n\tconst renameFiles = useRenameFiles();\n\tconst onInternalDrop = useCallback(\n\t\t(droppedItems: TreeItem<FileEntry | DirectoryEntry | undefined>[], target: DraggingPosition) => {\n\t\t\tswitch (target.targetType) {\n\t\t\t\tcase 'item':\n\t\t\t\t\tif (items[target.targetItem]?.data?.package) {\n\t\t\t\t\t\ttoast.error('Read-Only Imported Application', {\n\t\t\t\t\t\t\tdescription: 'To make changes to an application, please click the \"Redeploy\" button and update the'\n\t\t\t\t\t\t\t\t+ ' reference.',\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn renameFiles(droppedItems.map(item => ({\n\t\t\t\t\t\t\tfrom: item.index as string,\n\t\t\t\t\t\t\tto: joinPath(target.targetItem as string, extractFileNameFromPath(item.index as string)),\n\t\t\t\t\t\t})));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\ttoast.error(`${target.targetType} drop not yet supported`);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\t\t[items, renameFiles],\n\t);\n\n\treturn (\n\t\t<div className=\"h-full overflow-auto pr-1.5 pb-18\">\n\t\t\t<ControlledTreeEnvironment\n\t\t\t\tcanDragAndDrop={true}\n\t\t\t\tcanDropOnFolder={true}\n\t\t\t\tcanDropOnNonFolder={false}\n\t\t\t\tcanReorderItems={false}\n\t\t\t\tcanSearch={true}\n\t\t\t\tcanRename={false}\n\t\t\t\tgetItemTitle={getItemTitle}\n\t\t\t\titems={items}\n\t\t\t\tonDrop={onInternalDrop}\n\t\t\t\trenderItemTitle={ItemTitle}\n\t\t\t\tviewState={{ applicationsTree: { focusedItem, expandedItems, selectedItems } }}\n\t\t\t\tonFocusItem={item => setFocusedItem(item.index)}\n\t\t\t\tonExpandItem={item => setExpandedItems([...expandedItems, item.index])}\n\t\t\t\tonCollapseItem={item =>\n\t\t\t\t\tsetExpandedItems(expandedItems.filter(expandedItemIndex => expandedItemIndex !== item.index))}\n\t\t\t\tonSelectItems={items => setSelectedItems(items)}\n\t\t\t>\n\t\t\t\t<Tree treeId=\"applicationsTree\" rootItem={rootId} treeLabel=\"Applications file tree\" />\n\t\t\t</ControlledTreeEnvironment>\n\n\t\t\t<DropTarget />\n\t\t</div>\n\t);\n}\n","import { sleep } from '@/lib/sleep';\nimport { AxiosResponse } from 'axios';\n\nexport async function axiosRetry<T = unknown, R = AxiosResponse<T>>(\n\trequestPromise: () => Promise<R>,\n\tretries = 3,\n\tmsDelayBetweenAttempts = 1000,\n): Promise<R> {\n\tlet attempt = 0;\n\tif (retries <= 0) {\n\t\tthrow new Error('retries must be greater than 0');\n\t}\n\tlet lastError: unknown;\n\t// use for loop to retry 3 times at most\n\twhile (attempt < retries) {\n\t\ttry {\n\t\t\treturn await requestPromise();\n\t\t} catch (error) {\n\t\t\tattempt++;\n\t\t\tlastError = error;\n\t\t\tif (attempt === retries) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait sleep(msDelayBetweenAttempts);\n\t\t}\n\t}\n\tthrow lastError;\n}\n","import { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { getInstanceUserInfo } from '@/integrations/api/instance/status/getInstanceUserInfo';\nimport { ReplicatedResponse } from '@/integrations/api/replication';\nimport { axiosRetry } from '@/lib/axiosRetry';\nimport { sleep } from '@/lib/sleep';\nimport { useMutation } from '@tanstack/react-query';\n\ninterface RestartInstanceParams {\n\toperation: 'restart_service' | 'restart';\n\treplicated: boolean;\n}\n\nexport async function restartInstance(\n\t{ operation, replicated, instanceClient }: RestartInstanceParams & InstanceClientConfig,\n): Promise<ReplicatedResponse> {\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation,\n\t\tservice: operation === 'restart_service' ? 'http' : undefined,\n\t\treplicated,\n\t});\n\tawait sleep(10_000);\n\tawait axiosRetry(() => getInstanceUserInfo({ instanceClient, timeout: 3_000 }), 12, 15_000);\n\treturn data;\n}\n\nexport function useRestartInstance() {\n\treturn useMutation({\n\t\tmutationFn: restartInstance,\n\t});\n}\n","import { ProgressBar } from '@/components/ProgressBar';\nimport { getInstanceClient } from '@/config/getInstanceClient';\nimport { authStore } from '@/features/auth/store/authStore';\nimport { getClusterInfo } from '@/features/cluster/queries/getClusterInfoQuery';\nimport { getInstanceUserInfo } from '@/integrations/api/instance/status/getInstanceUserInfo';\nimport { restartInstance } from '@/integrations/api/instance/status/restartInstance';\nimport { excludeFalsy } from '@/lib/arrays/excludeFalsy';\nimport { pluralize } from '@/lib/pluralize';\nimport { sleep } from '@/lib/sleep';\nimport { getOperationsUrlForInstance } from '@/lib/urls/getOperationsUrlForInstance';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useParams } from '@tanstack/react-router';\nimport { useCallback, useState } from 'react';\nimport { toast } from 'sonner';\n\ninterface RestartClusterClickParams {\n\tonRestartedSuccessfully?: () => void;\n}\n\ninterface RestartClusterClickResponse {\n\tonRestartClick: () => void;\n\tisRestartPending: boolean;\n}\n\nexport function useRestartClusterClick(\n\t{ onRestartedSuccessfully }: RestartClusterClickParams = {},\n): RestartClusterClickResponse {\n\tconst { clusterId }: { clusterId?: string } = useParams({ strict: false });\n\tconst queryClient = useQueryClient();\n\tconst [isRestartPending, setIsRestartPending] = useState(false);\n\tconst onRestartClick = useCallback(async () => {\n\t\tif (!clusterId) {\n\t\t\tthrow new Error('clusterId must be set in the route to invoke useRestartClusterClick');\n\t\t}\n\t\tsetIsRestartPending(true);\n\n\t\tlet canceled = false;\n\t\tconst toastConfig = {\n\t\t\tduration: 60_000,\n\t\t\taction: {\n\t\t\t\tlabel: 'Cancel',\n\t\t\t\tonClick: () => {\n\t\t\t\t\tcanceled = true;\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\n\t\tconst toastId = toast.loading('Restarting', {\n\t\t\t...toastConfig,\n\t\t\tdescription: (\n\t\t\t\t<ProgressBar\n\t\t\t\t\tanimated={true}\n\t\t\t\t\twidth=\"0%\"\n\t\t\t\t/>\n\t\t\t),\n\t\t});\n\n\t\tconst cluster = await getClusterInfo(clusterId);\n\t\tconst clusterUsesFabricConnect = authStore.checkForFabricConnect(cluster.id);\n\t\tconst allInstances = cluster?.instances ?? [];\n\t\tconst instanceClients = allInstances\n\t\t\t.filter(instance => instance.status === 'RUNNING')\n\t\t\t.map(instance =>\n\t\t\t\tgetInstanceClient({\n\t\t\t\t\tid: instance.id,\n\t\t\t\t\tforceFabricConnect: clusterUsesFabricConnect,\n\t\t\t\t\toperationsUrl: getOperationsUrlForInstance(instance),\n\t\t\t\t})\n\t\t\t)\n\t\t\t.reverse();\n\t\tlet instancesRestarted = 0;\n\n\t\tif (instanceClients.length) {\n\t\t\tfor (let i = 0; i < instanceClients.length; i++) {\n\t\t\t\tconst instanceClient = instanceClients[i];\n\t\t\t\tif (!canceled) {\n\t\t\t\t\ttoast.loading(`Restarting Instance ${i + 1} of ${instanceClients.length}`, {\n\t\t\t\t\t\t...toastConfig,\n\t\t\t\t\t\tid: toastId,\n\t\t\t\t\t\tdescription: (\n\t\t\t\t\t\t\t<ProgressBar\n\t\t\t\t\t\t\t\tanimated={true}\n\t\t\t\t\t\t\t\twidth={(i === 0 ? 0 : (i / instanceClients.length * 100)) + '%'}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t});\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Make sure the instance is responding.\n\t\t\t\t\t\tawait getInstanceUserInfo({\n\t\t\t\t\t\t\tinstanceClient,\n\t\t\t\t\t\t});\n\t\t\t\t\t\t// Then restart it.\n\t\t\t\t\t\tawait restartInstance({\n\t\t\t\t\t\t\toperation: 'restart',\n\t\t\t\t\t\t\treplicated: false,\n\t\t\t\t\t\t\tinstanceClient,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tinstancesRestarted += 1;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tif (i + 1 !== instanceClients.length) {\n\t\t\t\t\t\t\t// If it fails to restart, or wasn't available, warn for a bit then move on.\n\t\t\t\t\t\t\ttoast.loading(`Failed Restarting Instance ${i + 1} of ${instanceClients.length}`, {\n\t\t\t\t\t\t\t\t...toastConfig,\n\t\t\t\t\t\t\t\tid: toastId,\n\t\t\t\t\t\t\t\tdescription: 'We will carry on momentarily.',\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tawait sleep(3000);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsetIsRestartPending(false);\n\t\tvoid queryClient.invalidateQueries({ queryKey: [clusterId] });\n\n\t\tif (canceled) {\n\t\t\ttoast.error('Cancelled', {\n\t\t\t\tid: toastId,\n\t\t\t\tdescription: `The restart was partially cancelled.`,\n\t\t\t\tduration: 10_000,\n\t\t\t\taction: {\n\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t},\n\t\t\t});\n\t\t} else if (allInstances.length === instancesRestarted) {\n\t\t\tonRestartedSuccessfully?.();\n\t\t\ttoast.success('Success', {\n\t\t\t\tid: toastId,\n\t\t\t\tdescription: `Cluster fully restarted!`,\n\t\t\t\tduration: 10_000,\n\t\t\t\taction: {\n\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t},\n\t\t\t});\n\t\t} else {\n\t\t\tconst allTheInstances = pluralize(allInstances.length, 'instance', 'instances');\n\t\t\tconst someRunningInstancesWere = pluralize(\n\t\t\t\tinstancesRestarted,\n\t\t\t\t'\"RUNNING\" instance was',\n\t\t\t\t'\"RUNNING\" instances were',\n\t\t\t);\n\t\t\ttoast.error('Error', {\n\t\t\t\tid: toastId,\n\t\t\t\tdescription: `Failed to fully restart cluster.\\n`\n\t\t\t\t\t+ ([\n\t\t\t\t\t\tallInstances.length === 0 && 'No instances were found within the cluster to restart.',\n\t\t\t\t\t\tinstancesRestarted === 0 && `No instances were in a \"RUNNING\" state of ${allTheInstances}.`,\n\t\t\t\t\t\tallInstances.length !== instancesRestarted\n\t\t\t\t\t\t&& `Only ${someRunningInstancesWere} restarted of ${allTheInstances}.`,\n\t\t\t\t\t].filter(excludeFalsy).shift() || ''),\n\t\t\t\tduration: 10_000,\n\t\t\t\taction: {\n\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}, [clusterId, onRestartedSuccessfully, queryClient]);\n\n\treturn {\n\t\tonRestartClick,\n\t\tisRestartPending,\n\t};\n}\n","import { isLocalStudio } from '@/config/constants';\nimport { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { useRestartInstance } from '@/integrations/api/instance/status/restartInstance';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useParams } from '@tanstack/react-router';\nimport { useCallback } from 'react';\nimport { toast } from 'sonner';\n\ninterface RestartInstanceClickParams extends InstanceClientConfig {\n\toperation: 'restart_service' | 'restart';\n\tonRestartedSuccessfully?: () => void;\n}\n\ninterface RestartInstanceClickResponse {\n\tonRestartClick: () => void;\n\tisRestartPending: boolean;\n}\n\nexport function useRestartInstanceClick({\n\toperation,\n\tinstanceClient,\n\tonRestartedSuccessfully,\n}: RestartInstanceClickParams): RestartInstanceClickResponse {\n\tconst { clusterId, instanceId }: { clusterId?: string; instanceId?: string } = useParams({ strict: false });\n\tconst targetNoun = (instanceId || isLocalStudio) ? 'Instance' : 'Cluster';\n\tconst { mutate: restartInstance, isPending: isRestartPending } = useRestartInstance();\n\tconst queryClient = useQueryClient();\n\tconst onRestartClick = useCallback(() => {\n\t\tconst toastId = toast.loading('Restarting', {\n\t\t\tdescription: `Restarting ${targetNoun.toLowerCase()}. This may take up to 60 seconds.`,\n\t\t\tduration: 180_000,\n\t\t\taction: {\n\t\t\t\tlabel: 'Dismiss',\n\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t},\n\t\t});\n\t\trestartInstance({\n\t\t\toperation,\n\t\t\treplicated: operation === 'restart_service' && targetNoun === 'Cluster',\n\t\t\tinstanceClient,\n\t\t}, {\n\t\t\tonSuccess: () => {\n\t\t\t\tvoid queryClient.invalidateQueries({ queryKey: [clusterId] });\n\t\t\t\tvoid queryClient.invalidateQueries({ queryKey: [instanceId] });\n\t\t\t\ttoast.dismiss(toastId);\n\t\t\t\ttoast.success('Success', {\n\t\t\t\t\tdescription: `${targetNoun} restarted!`,\n\t\t\t\t\taction: {\n\t\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tonRestartedSuccessfully?.();\n\t\t\t},\n\t\t\tonError: () => {\n\t\t\t\ttoast.dismiss(toastId);\n\t\t\t\ttoast.error('Error', {\n\t\t\t\t\tdescription: `Failed to restart ${targetNoun.toLowerCase()}.`,\n\t\t\t\t\taction: {\n\t\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t},\n\t\t});\n\t}, [\n\t\tclusterId,\n\t\tinstanceClient,\n\t\tinstanceId,\n\t\tonRestartedSuccessfully,\n\t\toperation,\n\t\tqueryClient,\n\t\trestartInstance,\n\t\ttargetNoun,\n\t]);\n\n\treturn {\n\t\tonRestartClick,\n\t\tisRestartPending,\n\t};\n}\n","import { Button } from '@/components/ui/button';\nimport { buttonVariants } from '@/components/ui/buttonVariants';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';\nimport { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { useRestartClusterClick } from '@/hooks/useRestartClusterClick';\nimport { useRestartInstanceClick } from '@/hooks/useRestartInstanceClick';\nimport { cx, VariantProps } from 'class-variance-authority';\nimport { RotateCcwIcon } from 'lucide-react';\n\ninterface RestartButtonParams extends InstanceClientConfig, VariantProps<typeof buttonVariants> {\n\tclassName?: string;\n\tdisabled?: boolean;\n\thideText?: boolean;\n\toperation: 'restart_service' | 'restart';\n\ttargetNoun: 'Instance' | 'Cluster';\n\ttooltip?: string;\n}\n\nexport function RestartButton({\n\tclassName,\n\tdisabled,\n\thideText,\n\tinstanceClient,\n\toperation,\n\ttargetNoun,\n\ttooltip,\n\tvariant,\n}: RestartButtonParams) {\n\tconst { onRestartClick: onRestartClusterClick, isRestartPending: isRestartClusterPending } = useRestartClusterClick();\n\tconst { onRestartClick, isRestartPending } = useRestartInstanceClick({ operation, instanceClient });\n\treturn (\n\t\t<Tooltip>\n\t\t\t<TooltipTrigger asChild>\n\t\t\t\t<Button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tvariant={variant || 'positiveOutline'}\n\t\t\t\t\tclassName={cx('mx-0 md:mx-4 rounded-full', className)}\n\t\t\t\t\tonClick={targetNoun === 'Cluster' && operation === 'restart' ? onRestartClusterClick : onRestartClick}\n\t\t\t\t\tdisabled={disabled || isRestartPending || isRestartClusterPending}\n\t\t\t\t\ttitle={`Restart ${targetNoun}`}\n\t\t\t\t>\n\t\t\t\t\t<RotateCcwIcon className=\"pointer-events-none\" />\n\t\t\t\t\t{hideText !== true && (\n\t\t\t\t\t\t<span className=\"hidden md:inline-block pointer-events-none\">\n\t\t\t\t\t\t\tRestart <span className=\"hidden 2xl:inline-block\">{targetNoun}</span>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t</Button>\n\t\t\t</TooltipTrigger>\n\t\t\t<TooltipContent side=\"bottom\">\n\t\t\t\t{tooltip\n\t\t\t\t\t? tooltip\n\t\t\t\t\t: operation === 'restart_service'\n\t\t\t\t\t? 'Restarts all service threads to apply changes. No downtime expected. Performance may be briefly slower during restart.'\n\t\t\t\t\t: 'This fully restarts the Harper service and causes downtime.'}\n\t\t\t</TooltipContent>\n\t\t</Tooltip>\n\t);\n}\n","import { RestartButton } from '@/components/RestartButton';\nimport { Button } from '@/components/ui/button';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { useEditorFileContent } from '@/features/instance/applications/context/editorFileContent';\nimport { isDirectory } from '@/features/instance/applications/context/isDirectory';\nimport { useEditorView } from '@/features/instance/applications/hooks/useEditorView';\nimport { useInstanceBrowseManagePermission } from '@/hooks/usePermissions';\nimport { useEmitToListeners } from '@/lib/events/listener';\nimport { useSetWatchedValue } from '@/lib/events/watcher';\nimport {\n\tDownloadIcon,\n\tFileIcon,\n\tFolderIcon,\n\tLockIcon,\n\tPackageIcon,\n\tPanelRightCloseIcon,\n\tPanelRightOpenIcon,\n\tPencilIcon,\n\tPlusIcon,\n\tSaveIcon,\n\tTrashIcon,\n\tUndo2Icon,\n} from 'lucide-react';\nimport { newApplication } from './ApplicationsSidebar/specialItems';\n\nimport './ContentActions.css';\n\nexport function ContentActions({\n\ttoggledSidebar,\n\ttoggleSidebar,\n}: {\n\ttoggledSidebar: boolean;\n\ttoggleSidebar: () => void;\n}) {\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst { openedEntryContents, openedEntry, isSavingFile, restrictPackageModification } = useEditorView();\n\tconst { content: updatedFileContent } = useEditorFileContent(openedEntry?.path);\n\tconst canManageBrowseInstance = useInstanceBrowseManagePermission();\n\tconst targetNoun = instanceParams.entityType === 'instance' ? 'Instance' : 'Cluster';\n\n\tconst onAddFileClick = useSetWatchedValue('ShowAddDirectoryOrFileModalType', 'file');\n\tconst onAddDirectoryClick = useSetWatchedValue('ShowAddDirectoryOrFileModalType', 'directory');\n\tconst onDownloadApplicationClick = useSetWatchedValue('ShowDownloadApplicationModal', true);\n\tconst onRenameClick = useSetWatchedValue('ShowRenameFileModal', true);\n\tconst onDeleteClick = useSetWatchedValue('ShowDeleteDirectoryOrFileModal', true);\n\tconst onRedeployClick = useSetWatchedValue('ShowRedeployApplicationModal', true);\n\tconst onSaveClick = useEmitToListeners('SaveFile', true);\n\tconst onRevertChangesClicked = useEmitToListeners('RevertChanges', true);\n\tconst onNewTableClick = useEmitToListeners('ShowNewTableModal', true);\n\n\tconst fileIsClean = updatedFileContent === undefined || updatedFileContent === openedEntryContents;\n\n\treturn (\n\t\t<div className=\"absolute top-0 right-0 left-0 backdrop-blur-sm bg-black-10 shadow-xl flex pr-4 md:pr-12\">\n\t\t\t<Button\n\t\t\t\ttype=\"button\"\n\t\t\t\tvariant=\"ghost\"\n\t\t\t\tclassName={(toggledSidebar ? 'toggled-sidebar-toggler' : 'hidden-sidebar-toggler')\n\t\t\t\t\t+ ' inline-flex'\n\t\t\t\t\t+ ' text-sm md:hidden'\n\t\t\t\t\t+ ' focus:outline-none'\n\t\t\t\t\t+ ' focus:ring-2'\n\t\t\t\t\t+ ' text-white'\n\t\t\t\t\t+ ' hover:text-grey focus:ring-gray-600 rounded-none'}\n\t\t\t\tonClick={toggleSidebar}\n\t\t\t>\n\t\t\t\t<span className=\"sr-only\">{toggledSidebar ? 'Close' : 'Open'} sidebar</span>\n\t\t\t\t{toggledSidebar ? <PanelRightOpenIcon /> : <PanelRightCloseIcon />}\n\t\t\t</Button>\n\n\t\t\t{openedEntry && openedEntry?.path !== newApplication && (\n\t\t\t\t<>\n\t\t\t\t\t{openedEntry.package && (\n\t\t\t\t\t\t<Tooltip>\n\t\t\t\t\t\t\t<TooltipTrigger asChild>\n\t\t\t\t\t\t\t\t<Button variant=\"ghost\" type=\"button\" className=\"cursor-help\">\n\t\t\t\t\t\t\t\t\t<LockIcon width={16} height={16} />\n\t\t\t\t\t\t\t\t\t<span className=\"hidden md:inline-block\">Imported applications are read-only</span>\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</TooltipTrigger>\n\t\t\t\t\t\t\t<TooltipContent>\n\t\t\t\t\t\t\t\t{restrictPackageModification\n\t\t\t\t\t\t\t\t\t? (\n\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\tThis application is read-only, and cannot be modified.\n\t\t\t\t\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\t\t\t\t\tIt helps govern clustering amongst your instances.\n\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t: (\n\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\tThis application is read-only, and cannot be directly modified. But you can re-deploy or remove\n\t\t\t\t\t\t\t\t\t\t\tit.\n\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</TooltipContent>\n\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{!isDirectory(openedEntry) && !openedEntry.package && canManageBrowseInstance && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"default\"\n\t\t\t\t\t\t\tclassName=\"rounded-none\"\n\t\t\t\t\t\t\tonClick={onSaveClick}\n\t\t\t\t\t\t\tdisabled={fileIsClean || isSavingFile}\n\t\t\t\t\t\t\ttitle=\"Save\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<SaveIcon className=\"pointer-events-none\" />\n\t\t\t\t\t\t\t<span className=\"hidden lg:inline-block pointer-events-none\">\n\t\t\t\t\t\t\t\t<u>S</u>ave\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{!isDirectory(openedEntry) && !openedEntry.package && canManageBrowseInstance && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\tclassName=\"rounded-none\"\n\t\t\t\t\t\t\tonClick={onRenameClick}\n\t\t\t\t\t\t\tdisabled={!fileIsClean || isSavingFile}\n\t\t\t\t\t\t\ttitle=\"Rename\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<PencilIcon className=\"pointer-events-none\" />\n\t\t\t\t\t\t\t<span className=\"hidden lg:inline-block pointer-events-none\">\n\t\t\t\t\t\t\t\t<u>R</u>ename\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{!openedEntry.package && canManageBrowseInstance && (\n\t\t\t\t\t\t<Button variant=\"ghost\" className=\"rounded-none\" onClick={onAddFileClick} title=\"New File\">\n\t\t\t\t\t\t\t<FileIcon className=\"pointer-events-none\" />\n\t\t\t\t\t\t\t<span className=\"pointer-events-none hidden lg:inline-block\">\n\t\t\t\t\t\t\t\t<u>N</u>ew\n\t\t\t\t\t\t\t\t<span className=\"hidden lg:inline-block\"> File</span>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{!openedEntry.package && canManageBrowseInstance && (\n\t\t\t\t\t\t<Button variant=\"ghost\" className=\"rounded-none\" onClick={onAddDirectoryClick} title=\"Add Directory\">\n\t\t\t\t\t\t\t<FolderIcon className=\"pointer-events-none\" />\n\t\t\t\t\t\t\t<span className=\"pointer-events-none hidden lg:inline-block\">\n\t\t\t\t\t\t\t\t<u>A</u>dd\n\t\t\t\t\t\t\t\t<span className=\"hidden xl:inline-block\"> Directory</span>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{openedEntry.path.endsWith('.graphql') && canManageBrowseInstance && (\n\t\t\t\t\t\t<Button variant=\"ghost\" className=\"rounded-none\" onClick={onNewTableClick} title=\"New Table\">\n\t\t\t\t\t\t\t<PlusIcon className=\"pointer-events-none\" />\n\t\t\t\t\t\t\t<span className=\"hidden lg:inline-block pointer-events-none\">\n\t\t\t\t\t\t\t\t<span className=\"hidden xl:inline-block\">New</span> Table\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{openedEntry.project && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\tclassName=\"rounded-none\"\n\t\t\t\t\t\t\tonClick={onDownloadApplicationClick}\n\t\t\t\t\t\t\ttitle=\"Download Application\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<DownloadIcon className=\"pointer-events-none\" />\n\t\t\t\t\t\t\t<span className=\"hidden lg:inline-block pointer-events-none\">\n\t\t\t\t\t\t\t\tDownload\n\t\t\t\t\t\t\t\t<span className=\"hidden 2xl:inline-block\"> Application</span>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{!!openedEntry.package && canManageBrowseInstance && !restrictPackageModification && (\n\t\t\t\t\t\t<Button variant=\"ghost\" className=\"rounded-none\" onClick={onRedeployClick} title=\"Redeploy Package\">\n\t\t\t\t\t\t\t<PackageIcon className=\"pointer-events-none\" />\n\t\t\t\t\t\t\t<span className=\"pointer-events-none\">\n\t\t\t\t\t\t\t\tRedeploy <u>P</u>ackage\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\n\t\t\t\t\t<div className=\"grow\"></div>\n\n\t\t\t\t\t{canManageBrowseInstance && (\n\t\t\t\t\t\t<RestartButton\n\t\t\t\t\t\t\ttargetNoun={targetNoun}\n\t\t\t\t\t\t\tinstanceClient={instanceParams.instanceClient}\n\t\t\t\t\t\t\toperation=\"restart_service\"\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\tclassName=\"rounded-none mx-0 md:mx-0\"\n\t\t\t\t\t\t\tdisabled={!fileIsClean || isSavingFile}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{!isDirectory(openedEntry) && !openedEntry.package && canManageBrowseInstance && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\tclassName=\"rounded-none\"\n\t\t\t\t\t\t\tonClick={onRevertChangesClicked}\n\t\t\t\t\t\t\tdisabled={fileIsClean || isSavingFile}\n\t\t\t\t\t\t\ttitle=\"Revert Changes\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Undo2Icon className=\"pointer-events-none\" />\n\t\t\t\t\t\t\t<span className=\"hidden xl:inline-block pointer-events-none\">\n\t\t\t\t\t\t\t\tRevert <span className=\"hidden 2xl:inline-block\">Changes</span>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{!restrictPackageModification && canManageBrowseInstance && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tvariant=\"destructiveGhost\"\n\t\t\t\t\t\t\tclassName=\"rounded-none\"\n\t\t\t\t\t\t\tonClick={onDeleteClick}\n\t\t\t\t\t\t\ttitle=\"Delete\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<TrashIcon className=\"pointer-events-none\" />\n\t\t\t\t\t\t\t<span className=\"hidden xl:inline-block pointer-events-none\">\n\t\t\t\t\t\t\t\t<u>D</u>elete\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import { currentUrlIncludingHash } from '@/lib/urls/currentUrlIncludingHash';\nimport { useCallback } from 'react';\nimport { UrlTransform } from 'react-markdown';\n\nexport function useReadMeUrlTransformer(project?: string) {\n\treturn useCallback((url: string, key: string, node: Parameters<UrlTransform>['2']): string | null | undefined => {\n\t\tif (key !== 'href') {\n\t\t\treturn url;\n\t\t}\n\t\tif (url.startsWith('http')) {\n\t\t\tnode.properties['target'] = '_blank';\n\t\t\treturn url;\n\t\t} else {\n\t\t\tconst urlSansSearch = currentUrlIncludingHash().split('?')[0];\n\t\t\tswitch (url) {\n\t\t\t\tcase './apis':\n\t\t\t\tcase './config':\n\t\t\t\tcase './config/roles':\n\t\t\t\tcase './config/users':\n\t\t\t\tcase './databases':\n\t\t\t\tcase './logs':\n\t\t\t\tcase './status':\n\t\t\t\t\treturn `${urlSansSearch}/${url.slice(2)}`;\n\t\t\t}\n\t\t\treturn `${urlSansSearch}?open=${project}/${url.slice(url.startsWith('../') ? 3 : 2)}`;\n\t\t}\n\t}, [project]);\n}\n","'use client';\n\nimport * as SeparatorPrimitive from '@radix-ui/react-separator';\nimport * as React from 'react';\n\nimport { cn } from '@/lib/cn';\n\nfunction Separator({\n\tclassName,\n\torientation = 'horizontal',\n\tdecorative = true,\n\t...props\n}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {\n\treturn (\n\t\t<SeparatorPrimitive.Root\n\t\t\tdata-slot=\"separator-root\"\n\t\t\tdecorative={decorative}\n\t\t\torientation={orientation}\n\t\t\tclassName={cn(\n\t\t\t\t'bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport { Separator };\n","import { cn } from '@/lib/cn';\nimport * as TabsPrimitive from '@radix-ui/react-tabs';\nimport * as React from 'react';\n\nfunction Tabs({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Root>) {\n\treturn <TabsPrimitive.Root data-slot=\"tabs\" className={cn('flex flex-col gap-2', className)} {...props} />;\n}\n\nfunction TabsList({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.List>) {\n\treturn (\n\t\t<TabsPrimitive.List\n\t\t\tdata-slot=\"tabs-list\"\n\t\t\tclassName={cn(\n\t\t\t\t'text-muted-foreground inline-flex w-fit items-center justify-center rounded-full bg-gray-950 p-1',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Trigger>) {\n\treturn (\n\t\t<TabsPrimitive.Trigger\n\t\t\tdata-slot=\"tabs-trigger\"\n\t\t\tclassName={cn(\n\t\t\t\t// 'data-[state=inactive]:border-b-4 data-[state=inactive]:border-b-grey-700 ' +\n\t\t\t\t'data-[state=active]:text-white data-[state=active]:bg-gray-600 '\n\t\t\t\t\t+ 'dark:data-[state=active]:text-foreground '\n\t\t\t\t\t+ 'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring '\n\t\t\t\t\t+ 'focus-visible:ring-[3px] focus-visible:outline-1 '\n\t\t\t\t\t+ 'text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 '\n\t\t\t\t\t+ 'border rounded-full border-transparent '\n\t\t\t\t\t+ 'px-2 py-1 '\n\t\t\t\t\t+ 'font-medium whitespace-nowrap '\n\t\t\t\t\t+ 'transition-[color,box-shadow] '\n\t\t\t\t\t+ 'disabled:pointer-events-none disabled:opacity-50 '\n\t\t\t\t\t+ \"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Content>) {\n\treturn <TabsPrimitive.Content data-slot=\"tabs-content\" className={cn('flex-1 outline-none', className)} {...props} />;\n}\n\nexport { Tabs, TabsContent, TabsList, TabsTrigger };\n","export function findBy<T, F extends keyof T>(array: T[], fieldName: F, value: T[F]): T | undefined {\n\tfor (const element of array) {\n\t\tif (element[fieldName] === value) {\n\t\t\treturn element;\n\t\t}\n\t}\n\treturn undefined;\n}\n","import { isLocalStudio } from '@/config/constants';\nimport { useInstanceClientParams } from '@/config/useInstanceClient';\nimport { useInstanceAuth } from '@/hooks/useAuth';\nimport { Cluster, Instance } from '@/integrations/api/api.patch';\nimport { excludeFalsy } from '@/lib/arrays/excludeFalsy';\nimport { toKebabCase } from '@/lib/string/to-kebab-case';\nimport { getOperationsUrlForCluster } from '@/lib/urls/getOperationsUrlForCluster';\nimport { getOperationsUrlForInstance } from '@/lib/urls/getOperationsUrlForInstance';\nimport { useRouteContext } from '@tanstack/react-router';\nimport { useMemo } from 'react';\n\nexport function useCLISteps(appName: string) {\n\tconst { user } = useInstanceAuth();\n\tconst instanceParams = useInstanceClientParams();\n\tconst { instance, cluster }: { instance?: Instance; cluster?: Cluster } = useRouteContext({ strict: false });\n\tconst target = isLocalStudio\n\t\t? instanceParams.instanceClient.defaults.baseURL\n\t\t: instance\n\t\t? getOperationsUrlForInstance(instance)\n\t\t: getOperationsUrlForCluster(cluster);\n\n\treturn useMemo(() => {\n\t\tconst directoryName = toKebabCase(appName);\n\t\tconst createArgs = [\n\t\t\tuser?.username && ` --deploymentUsername=\"${user?.username}\"`,\n\t\t\ttarget && ` --deploymentURL=\"${target}\"`,\n\t\t].filter(excludeFalsy).join('');\n\t\treturn [\n\t\t\t{\n\t\t\t\ttitle: 'Install or update the Harper CLI',\n\t\t\t\tcode: 'npm install -g harper',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttitle: 'Create your awesome app',\n\t\t\t\tcode: `npm create harper ${directoryName}${createArgs.length ? ' --' : ''}${createArgs}`,\n\t\t\t\tnote: 'You will be asked some easy questions to get you started. To make deployments easy, enter your'\n\t\t\t\t\t+ ' password for this cluster. It will get saved into your local .env file.',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttitle: 'Start local Harper instance',\n\t\t\t\tcode: 'npm run dev',\n\t\t\t\tnote: 'You will be prompted to configure Harper.',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttitle: 'Learn, make changes, grow!',\n\t\t\t\tcode: `cat AGENTS.md`,\n\t\t\t},\n\t\t\t{\n\t\t\t\ttitle: 'Deploy!',\n\t\t\t\tcode: `npm run deploy`,\n\t\t\t\tnote: 'Remember that .env file? It makes this deployment easy!',\n\t\t\t},\n\t\t];\n\t}, [appName, target, user?.username]);\n}\n","import { Button } from '@/components/ui/button';\nimport { CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';\nimport { Separator } from '@/components/ui/separator';\nimport { useCopyToClipboard } from '@/hooks/useCopyToClipboard';\nimport { CheckIcon, CopyIcon } from 'lucide-react';\nimport { FormState, UseFormWatch } from 'react-hook-form';\nimport { z } from 'zod';\nimport { NewApplicationSchema } from './schema';\nimport { useCLISteps } from './useCLISteps';\n\nexport function CLIInstructions({\n\tdefaultApplicationName,\n\tformState,\n\twatch,\n}: {\n\tdefaultApplicationName: string;\n\tformState: FormState<z.infer<typeof NewApplicationSchema>>;\n\twatch: UseFormWatch<z.infer<typeof NewApplicationSchema>>;\n}) {\n\tconst applicationName = watch('applicationName') || defaultApplicationName;\n\tconst cliSteps = useCLISteps(applicationName);\n\tconst cliCopyClicks = useCopyToClipboard(\n\t\t...cliSteps.map(step => step.code),\n\t);\n\n\treturn (\n\t\t<>\n\t\t\t<CardHeader>\n\t\t\t\t<CardTitle>Deploy with Harper CLI</CardTitle>\n\t\t\t\t<CardDescription>\n\t\t\t\t\tFollow these steps to deploy your application using the Harper CLI\n\t\t\t\t</CardDescription>\n\t\t\t</CardHeader>\n\t\t\t<CardContent className=\"space-y-6\">\n\t\t\t\t{cliSteps.map((cliStep, index) => (\n\t\t\t\t\t<div key={cliStep.title} className=\"space-y-3\">\n\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t<div className=\"w-6 h-6 rounded-full bg-primary text-primary-foreground flex items-center justify-center shrink-0\">\n\t\t\t\t\t\t\t\t{index + 1}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<h3>{cliStep.title}</h3>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div className=\"ml-8\">\n\t\t\t\t\t\t\t<div className=\"bg-black rounded-lg p-4 flex items-center justify-between group\">\n\t\t\t\t\t\t\t\t<code className=\"text-sm overflow-auto pl-8 -indent-8 wrap-anywhere\">{cliStep.code}</code>\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tvariant=\"default\"\n\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\tonClick={cliCopyClicks[index]}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<CopyIcon className=\"w-4 h-4\" />\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{cliStep.note && <p className=\"text-muted-foreground text-sm mt-2\">{cliStep.note}</p>}\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<Separator className=\"bg-black\" />\n\t\t\t\t\t</div>\n\t\t\t\t))}\n\n\t\t\t\t{applicationName && (\n\t\t\t\t\t<div className=\"bg-accent rounded-lg p-4\">\n\t\t\t\t\t\t<p className=\"text-sm\">\n\t\t\t\t\t\t\t<strong>Application Name:</strong> {applicationName}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p className=\"text-muted-foreground text-sm mt-2\">\n\t\t\t\t\t\t\tYour application will be deployed with this name\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t<Button\n\t\t\t\t\tclassName=\"w-full\"\n\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\tdisabled={!formState.isValid}\n\t\t\t\t>\n\t\t\t\t\t<CheckIcon className=\"w-4 h-4 mr-2\" />\n\t\t\t\t\tI Have Completed These Steps\n\t\t\t\t</Button>\n\t\t\t</CardContent>\n\t\t</>\n\t);\n}\n","import { CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { Control } from 'react-hook-form';\nimport { z } from 'zod';\nimport { NewApplicationSchema } from './schema';\n\nexport function CommonInstructions({\n\tcontrol,\n\tdefaultApplicationName,\n}: {\n\tcontrol: Control<z.infer<typeof NewApplicationSchema>>;\n\tdefaultApplicationName: string;\n}) {\n\treturn (\n\t\t<>\n\t\t\t<CardHeader>\n\t\t\t\t<CardTitle>Application Name</CardTitle>\n\t\t\t\t<CardDescription>\n\t\t\t\t\tChoose a name for your new API application\n\t\t\t\t</CardDescription>\n\t\t\t</CardHeader>\n\t\t\t<CardContent>\n\t\t\t\t<div className=\"space-y-2\">\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\tname=\"applicationName\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Name</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"words\"\n\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\tautoFocus={true}\n\t\t\t\t\t\t\t\t\t\tplaceholder={defaultApplicationName}\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<p className=\"text-muted-foreground text-sm\">\n\t\t\t\t\t\tUse lowercase letters, numbers, underscores, and hyphens\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t</CardContent>\n\t\t</>\n\t);\n}\n","import { cva } from 'class-variance-authority';\n\nexport const alertVariants = cva(\n\t'relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current',\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: 'bg-card text-card-foreground',\n\t\t\t\tdestructive:\n\t\t\t\t\t'text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90',\n\t\t\t\twarning:\n\t\t\t\t\t'border-amber-500/50 text-amber-600 dark:text-amber-400 bg-amber-50/50 dark:bg-amber-950/20 [&>svg]:text-amber-600 dark:[&>svg]:text-amber-400',\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tvariant: 'default',\n\t\t},\n\t},\n);\n","import { alertVariants } from '@/components/ui/alertVariants';\nimport { cn } from '@/lib/cn';\nimport { VariantProps } from 'class-variance-authority';\nimport * as React from 'react';\n\nexport function Alert({\n\tclassName,\n\tvariant,\n\t...props\n}: React.ComponentProps<'div'> & VariantProps<typeof alertVariants>) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"alert\"\n\t\t\trole=\"alert\"\n\t\t\tclassName={cn(alertVariants({ variant }), className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport function AlertTitle({ className, ...props }: React.ComponentProps<'div'>) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"alert-title\"\n\t\t\tclassName={cn(\n\t\t\t\t'col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport function AlertDescription({\n\tclassName,\n\t...props\n}: React.ComponentProps<'div'>) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"alert-description\"\n\t\t\tclassName={cn(\n\t\t\t\t'text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n","import { Alert, AlertDescription } from '@/components/ui/alert';\nimport { Button } from '@/components/ui/button';\nimport { CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { Separator } from '@/components/ui/separator';\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';\nimport { Link } from '@tanstack/react-router';\nimport { GitMergeIcon, LinkIcon, PackageIcon, RocketIcon } from 'lucide-react';\nimport { useCallback } from 'react';\nimport { Control, FormState, UseFormSetValue, UseFormWatch } from 'react-hook-form';\nimport { z } from 'zod';\nimport { NewApplicationSchema } from './schema';\n\nexport function ImportInstructions({\n\tcontrol,\n\tformState,\n\tisImportingApplication,\n\tsetValue,\n\twatch,\n}: {\n\tcontrol: Control<z.infer<typeof NewApplicationSchema>>;\n\tformState: FormState<z.infer<typeof NewApplicationSchema>>;\n\tisImportingApplication: boolean;\n\tsetValue: UseFormSetValue<z.infer<typeof NewApplicationSchema>>;\n\twatch: UseFormWatch<z.infer<typeof NewApplicationSchema>>;\n}) {\n\tconst importSource = watch('contents.source');\n\tconst setImportSource = useCallback((source: string) => {\n\t\tsetValue('contents.source', source as 'git' | 'npm' | 'tarball');\n\t}, [setValue]);\n\n\treturn (\n\t\t<>\n\t\t\t<CardHeader>\n\t\t\t\t<CardTitle>Import Existing Application</CardTitle>\n\t\t\t\t<CardDescription>\n\t\t\t\t\tImport from Git, NPM, or a tarball URL\n\t\t\t\t</CardDescription>\n\t\t\t</CardHeader>\n\t\t\t<CardContent className=\"space-y-6\">\n\t\t\t\t<Tabs value={importSource} onValueChange={setImportSource}>\n\t\t\t\t\t<TabsList className=\"grid w-full grid-cols-3\">\n\t\t\t\t\t\t<TabsTrigger value=\"git\">\n\t\t\t\t\t\t\t<GitMergeIcon className=\"w-4 h-4 mr-2\" />\n\t\t\t\t\t\t\tGit\n\t\t\t\t\t\t</TabsTrigger>\n\t\t\t\t\t\t<TabsTrigger value=\"npm\">\n\t\t\t\t\t\t\t<PackageIcon className=\"w-4 h-4 mr-2\" />\n\t\t\t\t\t\t\tNPM\n\t\t\t\t\t\t</TabsTrigger>\n\t\t\t\t\t\t<TabsTrigger value=\"tarball\">\n\t\t\t\t\t\t\t<LinkIcon className=\"w-4 h-4 mr-2\" />\n\t\t\t\t\t\t\tTarball\n\t\t\t\t\t\t</TabsTrigger>\n\t\t\t\t\t</TabsList>\n\n\t\t\t\t\t<TabsContent value=\"git\" className=\"space-y-4 mt-4\">\n\t\t\t\t\t\t<div className=\"space-y-2\">\n\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\t\t\tname=\"contents.ref\"\n\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Git Repository URL</FormLabel>\n\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\t\tautoFocus={true}\n\t\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</TabsContent>\n\n\t\t\t\t\t<TabsContent value=\"npm\" className=\"space-y-4 mt-4\">\n\t\t\t\t\t\t<div className=\"space-y-2\">\n\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\t\t\tname=\"contents.ref\"\n\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">NPM Package Reference</FormLabel>\n\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\t\tautoFocus={true}\n\t\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t{/*placeholder=\"@org/package-name or package-name@version\"*/}\n\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</TabsContent>\n\n\t\t\t\t\t<TabsContent value=\"tarball\" className=\"space-y-4 mt-4\">\n\t\t\t\t\t\t<div className=\"space-y-2\">\n\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\t\t\tname=\"contents.ref\"\n\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Tarball URL</FormLabel>\n\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"url\"\n\t\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\t\tautoFocus={true}\n\t\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</TabsContent>\n\t\t\t\t</Tabs>\n\n\t\t\t\t<FormField\n\t\t\t\t\tcontrol={control}\n\t\t\t\t\tname=\"contents.installCommand\"\n\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Install Command</FormLabel>\n\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\tplaceholder=\"npm install\"\n\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t)}\n\t\t\t\t/>\n\n\t\t\t\t<FormLabel>Authorization</FormLabel>\n\t\t\t\t<FormField\n\t\t\t\t\tcontrol={control}\n\t\t\t\t\tname=\"contents.requiresAuth\"\n\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t<Tabs\n\t\t\t\t\t\t\tclassName=\"w-full pt-2 pb-0 mb-0\"\n\t\t\t\t\t\t\tvalue={String(field.value)}\n\t\t\t\t\t\t\tonValueChange={value => field.onChange(value === 'true')}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<TabsList className=\"grid w-full grid-cols-2\">\n\t\t\t\t\t\t\t\t<TabsTrigger value=\"false\">\n\t\t\t\t\t\t\t\t\tPublic Access\n\t\t\t\t\t\t\t\t</TabsTrigger>\n\t\t\t\t\t\t\t\t<TabsTrigger value=\"true\">\n\t\t\t\t\t\t\t\t\tRequires Auth\n\t\t\t\t\t\t\t\t</TabsTrigger>\n\t\t\t\t\t\t\t</TabsList>\n\n\t\t\t\t\t\t\t<TabsContent value=\"false\" className=\"space-y-4 mt-4\">\n\t\t\t\t\t\t\t</TabsContent>\n\n\t\t\t\t\t\t\t<TabsContent value=\"true\" className=\"space-y-4 mt-4\">\n\t\t\t\t\t\t\t\t<Alert>\n\t\t\t\t\t\t\t\t\t<AlertDescription>\n\t\t\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t\t\tYou can manage your certificates over in{' '}\n\t\t\t\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\t\t\t\tto=\"config\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"underline\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\tConfig\n\t\t\t\t\t\t\t\t\t\t\t</Link>{' '}\n\t\t\t\t\t\t\t\t\t\t\t>{' '}\n\t\t\t\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\t\t\t\tto=\"config/ssh-keys\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"underline\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\tSSH Keys\n\t\t\t\t\t\t\t\t\t\t\t</Link>. This enables SSH based auth for private repos, i.e. following the pattern of{' '}\n\t\t\t\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\t\t\t\thref=\"https://github.com/HarperFast/Studio\"\n\t\t\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"underline\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\tgit@github.com:HarperFast/studio.git\n\t\t\t\t\t\t\t\t\t\t\t</a>. If you have more than one key, make sure to utilize unique hostnames!\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</AlertDescription>\n\t\t\t\t\t\t\t\t</Alert>\n\t\t\t\t\t\t\t</TabsContent>\n\t\t\t\t\t\t</Tabs>\n\t\t\t\t\t)}\n\t\t\t\t/>\n\n\t\t\t\t<Separator className=\"bg-black\" />\n\n\t\t\t\t<Button\n\t\t\t\t\tclassName=\"w-full\"\n\t\t\t\t\tdisabled={!formState.isValid || isImportingApplication}\n\t\t\t\t>\n\t\t\t\t\t<RocketIcon className=\"w-4 h-4 mr-2\" />\n\t\t\t\t\tImport Application\n\t\t\t\t</Button>\n\t\t\t</CardContent>\n\t\t</>\n\t);\n}\n","export const templates = [\n\t{\n\t\tid: 'vanilla-js',\n\t\tname: 'Web + REST ORM',\n\t\tdescription: \"Define your entities in schema.graphql, add your HTML/CSS/JS in web, and you're cooking!\",\n\t\ttags: ['Harper', 'ORM', 'REST', 'GraphQL'],\n\t\tnpm: '@harperfast/template-vanilla-studio',\n\t\tgithubUrl: 'https://github.com/HarperFast/create-harper/tree/main/template-vanilla',\n\t},\n\t{\n\t\tid: 'vanilla-ts',\n\t\tname: 'TypeScript',\n\t\tdescription: 'The same Web + REST ORM from the first template, but with TypeScript sprinkled in.',\n\t\ttags: ['Harper', 'TypeScript', 'GraphQL'],\n\t\tnpm: '@harperfast/template-vanilla-ts-studio',\n\t\tgithubUrl: 'https://github.com/HarperFast/create-harper/tree/main/template-vanilla-ts',\n\t},\n\t// {\n\t// \tid: 'nextjs',\n\t// \tname: 'Next.js',\n\t// \tdescription: 'Full-stack React framework with API routes',\n\t// \ttags: ['React', 'SSR', 'API Routes'],\n\t// \tgithubUrl: 'https://github.com/vercel/next.js',\n\t// },\n\t// {\n\t// \tid: 'angular',\n\t// \tname: 'Angular',\n\t// \tdescription: 'Enterprise-ready framework with TypeScript',\n\t// \ttags: ['TypeScript', 'SPA', 'Enterprise'],\n\t// \tgithubUrl: 'https://github.com/angular/angular',\n\t// },\n\t// {\n\t// \tid: 'fastify',\n\t// \tname: 'Fastify',\n\t// \tdescription: 'Fast and low overhead web framework',\n\t// \ttags: ['Node.js', 'REST', 'Performance'],\n\t// \tgithubUrl: 'https://github.com/fastify/fastify',\n\t// },\n\t// {\n\t// \tid: 'vector-search',\n\t// \tname: 'Vector Search',\n\t// \tdescription: 'AI-powered semantic search application',\n\t// \ttags: ['AI', 'Embeddings', 'Search'],\n\t// \tgithubUrl: 'https://github.com/HarperDB/vector-search-template',\n\t// },\n\t// {\n\t// \tid: 'express',\n\t// \tname: 'Express',\n\t// \tdescription: 'Minimal and flexible Node.js framework',\n\t// \ttags: ['Node.js', 'REST', 'Minimal'],\n\t// \tgithubUrl: 'https://github.com/expressjs/express',\n\t// },\n\t// {\n\t// \tid: 'graphql',\n\t// \tname: 'GraphQL API',\n\t// \tdescription: 'API with GraphQL query language',\n\t// \ttags: ['GraphQL', 'Apollo', 'API'],\n\t// \tgithubUrl: 'https://github.com/graphql/graphql-js',\n\t// },\n];\n","import { z } from 'zod';\nimport { templates } from './templates';\n\nexport const TemplateSchema = z.object({\n\ttype: z.literal('template'),\n\tid: z.string('Please select a template.'),\n});\n\nexport const defaultTemplateOptions: z.infer<typeof TemplateSchema> = {\n\ttype: 'template',\n\tid: templates[0].id,\n};\n\nexport const ImportSchema = z.object({\n\ttype: z.literal('import'),\n\tsource: z.enum(['git', 'npm', 'tarball']),\n\tref: z.string().nonempty('Please enter a URL or package reference.'),\n\tinstallCommand: z.string(),\n\trequiresAuth: z.boolean(),\n});\n\nexport const defaultImportOptions: z.infer<typeof ImportSchema> = {\n\ttype: 'import',\n\tsource: 'git',\n\tref: '',\n\trequiresAuth: false,\n\tinstallCommand: '',\n};\n\nexport const CLISchema = z.object({\n\ttype: z.literal('cli'),\n});\n\nexport const defaultCLIOptions: z.infer<typeof CLISchema> = {\n\ttype: 'cli',\n};\n\nexport const NewApplicationSchema = z.object({\n\tapplicationName: z\n\t\t.string()\n\t\t.trim()\n\t\t.max(75, { error: 'Application name cannot be longer than 75 characters.' })\n\t\t.regex(/^[a-zA-Z0-9-_]*$/, { error: 'Can only contain letters, numbers, dashes and underscores.' }),\n\tcontents: z.discriminatedUnion('type', [\n\t\tTemplateSchema,\n\t\tImportSchema,\n\t\tCLISchema,\n\t]),\n});\n","import { cn } from '@/lib/cn';\nimport * as RadioGroupPrimitive from '@radix-ui/react-radio-group';\nimport { CircleIcon } from 'lucide-react';\nimport * as React from 'react';\n\nfunction RadioGroup({\n\tclassName,\n\t...props\n}: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {\n\treturn (\n\t\t<RadioGroupPrimitive.Root\n\t\t\tdata-slot=\"radio-group\"\n\t\t\tclassName={cn('grid gap-3', className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction RadioGroupItem({\n\tclassName,\n\t...props\n}: React.ComponentProps<typeof RadioGroupPrimitive.Item>) {\n\treturn (\n\t\t<RadioGroupPrimitive.Item\n\t\t\tdata-slot=\"radio-group-item\"\n\t\t\tclassName={cn(\n\t\t\t\t'border-input text-primary '\n\t\t\t\t\t+ 'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] '\n\t\t\t\t\t+ 'aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive '\n\t\t\t\t\t+ 'dark:bg-input/30 '\n\t\t\t\t\t+ 'aspect-square size-4 shrink-0 rounded-full border shadow-xs transition-[color,box-shadow] outline-none '\n\t\t\t\t\t+ 'disabled:cursor-not-allowed disabled:opacity-50',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<RadioGroupPrimitive.Indicator\n\t\t\t\tdata-slot=\"radio-group-indicator\"\n\t\t\t\tclassName=\"relative flex items-center justify-center\"\n\t\t\t>\n\t\t\t\t<CircleIcon className=\"fill-primary absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2\" />\n\t\t\t</RadioGroupPrimitive.Indicator>\n\t\t</RadioGroupPrimitive.Item>\n\t);\n}\n\nexport { RadioGroup, RadioGroupItem };\n","import { BaseSyntheticEvent } from 'react';\n\nexport function onClickStopPropagation(e: BaseSyntheticEvent) {\n\te.stopPropagation();\n}\n","import { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport { CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { Label } from '@/components/ui/label';\nimport { RadioGroup, RadioGroupItem } from '@/components/ui/radioGroup';\nimport { Separator } from '@/components/ui/separator';\nimport { onClickStopPropagation } from '@/lib/onClickStopPropagation';\nimport { RocketIcon } from 'lucide-react';\nimport { Control, FormState } from 'react-hook-form';\nimport { z } from 'zod';\nimport { NewApplicationSchema } from './schema';\nimport { templates } from './templates';\n\nexport function TemplateInstructions({\n\tcontrol,\n\tformState,\n\tisCreatingFromTemplate,\n}: {\n\tcontrol: Control<z.infer<typeof NewApplicationSchema>>;\n\tformState: FormState<z.infer<typeof NewApplicationSchema>>;\n\tisCreatingFromTemplate: boolean;\n}) {\n\treturn (\n\t\t<>\n\t\t\t<CardHeader>\n\t\t\t\t<CardTitle>Choose a Template</CardTitle>\n\t\t\t\t<CardDescription>\n\t\t\t\t\tStart with a pre-configured template for common use cases\n\t\t\t\t</CardDescription>\n\t\t\t</CardHeader>\n\t\t\t<CardContent>\n\t\t\t\t<FormField\n\t\t\t\t\tcontrol={control}\n\t\t\t\t\tname=\"contents.id\"\n\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t<RadioGroup value={field.value} onValueChange={field.onChange}>\n\t\t\t\t\t\t\t<div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n\t\t\t\t\t\t\t\t{templates.map((template) => (\n\t\t\t\t\t\t\t\t\t<div key={template.id} className=\"relative\">\n\t\t\t\t\t\t\t\t\t\t<RadioGroupItem\n\t\t\t\t\t\t\t\t\t\t\tvalue={template.id}\n\t\t\t\t\t\t\t\t\t\t\tid={template.id}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"peer sr-only\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t<Label\n\t\t\t\t\t\t\t\t\t\t\thtmlFor={template.id}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"flex flex-col gap-3 p-4 border-2 rounded-lg cursor-pointer hover:bg-accent peer-data-[state=checked]:border-green peer-data-[state=checked]:bg-primary/5\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"mb-1 flex items-center gap-2 justify-between\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div>{template.name}</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\t\t\t\t\t\thref={template.githubUrl}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={onClickStopPropagation}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"opacity-70 hover:opacity-100 transition-colors -m-4 p-4\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsrc=\"/github/GitHub_Lockup_White.svg\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\talt=\"GitHub\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"h-4\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t<p className=\"text-muted-foreground text-sm\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t{template.description}\n\t\t\t\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t<div className=\"flex flex-wrap gap-2\">\n\t\t\t\t\t\t\t\t\t\t\t\t{template.tags.map((tag) => (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Badge key={tag} variant=\"outline\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{tag}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</Label>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</RadioGroup>\n\t\t\t\t\t)}\n\t\t\t\t/>\n\n\t\t\t\t<Separator className=\"my-6 bg-black\" />\n\t\t\t\t<Button\n\t\t\t\t\tclassName=\"w-full\"\n\t\t\t\t\tdisabled={!formState.isValid || isCreatingFromTemplate}\n\t\t\t\t>\n\t\t\t\t\t<RocketIcon className=\"w-4 h-4 mr-2\" />\n\t\t\t\t\tCreate from Template\n\t\t\t\t</Button>\n\t\t\t</CardContent>\n\t\t</>\n\t);\n}\n","import { useInstanceClientParams } from '@/config/useInstanceClient';\nimport { useEditorView } from '@/features/instance/applications/hooks/useEditorView';\nimport { APIDirectoryEntry } from '@/integrations/api/instance/applications/getComponents';\nimport { useCallback, useMemo } from 'react';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { CLISchema } from './schema';\n\nexport function useCheckCLI(\n\tsetIsReloading: (isReloading: boolean) => void,\n) {\n\tconst instanceParams = useInstanceClientParams();\n\tconst { reloadRootEntries, setFocusedItem, setExpandedItems, setSelectedItems } = useEditorView();\n\tconst callback = useCallback(({\n\t\t// contents,\n\t\tproject,\n\t}: {\n\t\tcontents: z.infer<typeof CLISchema>;\n\t\tproject: string;\n\t}) => {\n\t\tconst toastId = toast.loading(`Looking for application...`, {\n\t\t\tdescription: 'This may take a bit.',\n\t\t\tduration: 300_000,\n\t\t});\n\n\t\tsetIsReloading(true);\n\t\treloadRootEntries().then((apiComponents: APIDirectoryEntry) => {\n\t\t\tconst entries = apiComponents?.entries || [];\n\t\t\tfor (const entry of entries) {\n\t\t\t\tif (entry.name.toLowerCase() === project.toLowerCase()) {\n\t\t\t\t\tsetFocusedItem(entry.name);\n\t\t\t\t\tsetSelectedItems([entry.name]);\n\t\t\t\t\tsetExpandedItems([entry.name]);\n\t\t\t\t\tsetIsReloading(false);\n\t\t\t\t\ttoast.success(`Imported successfully`, {\n\t\t\t\t\t\tdescription: `${project} is now available in your ${instanceParams.entityType}!`,\n\t\t\t\t\t\tid: toastId,\n\t\t\t\t\t\tduration: 5_000,\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttoast.warning(`Deployment Not Detected`, {\n\t\t\t\tdescription:\n\t\t\t\t\t`I searched for ${project} but did not find it in the ${instanceParams.entityType} yet. Do you see it on the left? Did you use a different name, perhaps?`,\n\t\t\t\tid: toastId,\n\t\t\t\tduration: 10_000,\n\t\t\t});\n\t\t\tsetIsReloading(false);\n\t\t});\n\t}, [instanceParams, setIsReloading, reloadRootEntries, setFocusedItem, setExpandedItems, setSelectedItems]);\n\n\treturn useMemo(() => ({\n\t\tcheckCLI: callback,\n\t}), [callback]);\n}\n","import { InstanceClientConfig, InstanceTypeConfig } from '@/config/instanceClientConfig';\nimport { ReplicatedResponse } from '@/integrations/api/replication';\nimport { useMutation } from '@tanstack/react-query';\n\nexport interface CreateComponentFormData {\n\tproject: string;\n\ttemplate: string;\n}\n\nexport async function addComponent({\n\tinstanceClient,\n\tproject,\n\ttemplate,\n\tentityType,\n}: CreateComponentFormData & InstanceClientConfig & InstanceTypeConfig): Promise<ReplicatedResponse> {\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation: 'add_component',\n\t\tproject,\n\t\ttemplate,\n\t\treplicated: entityType === 'cluster',\n\t}, { timeout: 300_000 });\n\treturn data;\n}\n\nexport function useAddComponentMutation() {\n\treturn useMutation({\n\t\tmutationFn: addComponent,\n\t});\n}\n","import { useInstanceClientParams } from '@/config/useInstanceClient';\nimport { useEditorView } from '@/features/instance/applications/hooks/useEditorView';\nimport { useAddComponentMutation } from '@/integrations/api/instance/applications/addComponent';\nimport { findBy } from '@/lib/arrays/findBy';\nimport { useCallback, useMemo } from 'react';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { TemplateSchema } from './schema';\nimport { templates } from './templates';\n\nexport function useCreateFromTemplate(\n\tsetIsReloading: (isReloading: boolean) => void,\n) {\n\tconst { mutate, isPending: isCreatingFromTemplate } = useAddComponentMutation();\n\tconst instanceParams = useInstanceClientParams();\n\tconst { reloadRootEntries, setFocusedItem, setExpandedItems, setSelectedItems } = useEditorView();\n\tconst callback = useCallback(({\n\t\tcontents,\n\t\tproject,\n\t}: {\n\t\tcontents: z.infer<typeof TemplateSchema>;\n\t\tproject: string;\n\t}) => {\n\t\tconst toastId = toast.loading(`Creating from template...`, {\n\t\t\tdescription: 'This may take a bit.',\n\t\t\tduration: 300_000,\n\t\t});\n\t\tconst template = findBy(templates, 'id', contents.id);\n\t\tif (!template) {\n\t\t\treturn toast.error('Template Not Found', {\n\t\t\t\tdescription: 'Please select a template',\n\t\t\t\tduration: 10_000,\n\t\t\t\tid: toastId,\n\t\t\t});\n\t\t}\n\t\tmutate({\n\t\t\tproject,\n\t\t\ttemplate: template.npm || template.githubUrl,\n\t\t\t...instanceParams,\n\t\t}, {\n\t\t\tonSuccess: () => {\n\t\t\t\ttoast.success(`Created successfully!`, {\n\t\t\t\t\tdescription: `${project} will be available once you restart your ${instanceParams.entityType}!`,\n\t\t\t\t\tid: toastId,\n\t\t\t\t\tduration: 5_000,\n\t\t\t\t});\n\t\t\t\tsetIsReloading(true);\n\t\t\t\tvoid reloadRootEntries();\n\t\t\t\tsetFocusedItem(project);\n\t\t\t\tsetSelectedItems([project]);\n\t\t\t\tsetExpandedItems([project]);\n\t\t\t},\n\t\t});\n\t}, [mutate, instanceParams, setIsReloading, reloadRootEntries, setFocusedItem, setExpandedItems, setSelectedItems]);\n\n\treturn useMemo(() => ({\n\t\tisCreatingFromTemplate,\n\t\tcreateFromTemplate: callback,\n\t}), [isCreatingFromTemplate, callback]);\n}\n","import { InstanceClientConfig, InstanceTypeConfig } from '@/config/instanceClientConfig';\nimport { ReplicatedResponse } from '@/integrations/api/replication';\nimport { useMutation } from '@tanstack/react-query';\n\nexport interface DeployComponentFormData {\n\tapplicationName: string;\n\tapplicationUrl: string;\n\tinstallCommand?: string;\n}\n\nasync function onDeployComponentSubmit({\n\tapplicationName,\n\tapplicationUrl,\n\tinstallCommand,\n\tentityType,\n\tinstanceClient,\n}: DeployComponentFormData & InstanceClientConfig & InstanceTypeConfig): Promise<ReplicatedResponse> {\n\tconst { data } = await instanceClient.post(\n\t\t'/',\n\t\t{\n\t\t\toperation: 'deploy_component',\n\t\t\tpackage: applicationUrl,\n\t\t\tproject: applicationName,\n\t\t\treplicated: entityType === 'cluster',\n\t\t\tinstall_command: installCommand || undefined,\n\t\t\trestart: 'rolling',\n\t\t},\n\t\t{ timeout: 300_000 },\n\t);\n\treturn data;\n}\n\nexport function useDeployComponentMutation() {\n\treturn useMutation({\n\t\tmutationFn: onDeployComponentSubmit,\n\t});\n}\n","import { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { useEditorView } from '@/features/instance/applications/hooks/useEditorView';\nimport { useDeployComponentMutation } from '@/integrations/api/instance/applications/deployComponent';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useCallback, useMemo } from 'react';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { ImportSchema } from './schema';\n\nexport function useImportApplication(\n\tsetIsReloading: (isReloading: boolean) => void,\n) {\n\tconst { mutate, isPending: isImportingApplication } = useDeployComponentMutation();\n\n\tconst queryClient = useQueryClient();\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst { reloadRootEntries, setFocusedItem, setExpandedItems, setSelectedItems } = useEditorView();\n\tconst callback = useCallback(({\n\t\tcontents,\n\t\tproject,\n\t}: {\n\t\tcontents: z.infer<typeof ImportSchema>;\n\t\tproject: string;\n\t}) => {\n\t\tconst toastId = toast.loading(`Importing application...`, {\n\t\t\tdescription: 'This may take a bit.',\n\t\t\tduration: 300_000,\n\t\t});\n\t\tmutate({\n\t\t\tapplicationName: project,\n\t\t\tapplicationUrl: contents.ref,\n\t\t\tinstallCommand: contents.installCommand,\n\t\t\t...instanceParams,\n\t\t}, {\n\t\t\tonSuccess: () => {\n\t\t\t\ttoast.success(`Imported successfully`, {\n\t\t\t\t\tdescription: `${project} will be available once you restart your ${instanceParams.entityType}!`,\n\t\t\t\t\tid: toastId,\n\t\t\t\t\tduration: 5_000,\n\t\t\t\t});\n\t\t\t\tsetIsReloading(true);\n\t\t\t\tvoid queryClient.invalidateQueries({ queryKey: [instanceParams.entityId] });\n\t\t\t\tvoid reloadRootEntries();\n\t\t\t\tsetFocusedItem(project);\n\t\t\t\tsetSelectedItems([project]);\n\t\t\t\tsetExpandedItems([project]);\n\t\t\t},\n\t\t\tonError: () => {\n\t\t\t\ttoast.dismiss(toastId);\n\t\t\t},\n\t\t});\n\t}, [\n\t\tmutate,\n\t\tqueryClient,\n\t\tinstanceParams,\n\t\tsetIsReloading,\n\t\treloadRootEntries,\n\t\tsetFocusedItem,\n\t\tsetExpandedItems,\n\t\tsetSelectedItems,\n\t]);\n\n\treturn useMemo(() => ({\n\t\tisImportingApplication,\n\t\timportApplication: callback,\n\t}), [isImportingApplication, callback]);\n}\n","import { Card } from '@/components/ui/card';\nimport { Form } from '@/components/ui/form/Form';\nimport { Separator } from '@/components/ui/separator';\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';\nimport { useEditorView } from '@/features/instance/applications/hooks/useEditorView';\nimport { Cluster, Instance, Organization } from '@/integrations/api/api.patch';\nimport { findBy } from '@/lib/arrays/findBy';\nimport { toKebabCase } from '@/lib/string/to-kebab-case';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useRouteContext } from '@tanstack/react-router';\nimport { BoxesIcon, GitBranchIcon, TerminalIcon } from 'lucide-react';\nimport { useCallback, useMemo, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { z } from 'zod';\nimport { CLIInstructions } from './CLIInstructions';\nimport { CommonInstructions } from './CommonInstructions';\nimport { ImportInstructions } from './ImportInstructions';\nimport { defaultCLIOptions, defaultImportOptions, defaultTemplateOptions, NewApplicationSchema } from './schema';\nimport { TemplateInstructions } from './TemplateInstructions';\nimport { useCheckCLI } from './useCheckCLI';\nimport { useCreateFromTemplate } from './useCreateFromTemplate';\nimport { useImportApplication } from './useImportApplication';\n\nexport function NewApplication() {\n\tconst { rootEntries } = useEditorView();\n\tconst { organization, instance, cluster }: {\n\t\torganization?: Organization;\n\t\tinstance?: Instance;\n\t\tcluster?: Cluster;\n\t} = useRouteContext({ strict: false });\n\n\tconst defaultApplicationName = useMemo(() => {\n\t\tconst defaultName = toKebabCase(cluster?.name || instance?.name || organization?.name || '');\n\t\tif (defaultName === '') {\n\t\t\treturn defaultName;\n\t\t}\n\t\tlet uniqueName = defaultName;\n\t\tlet number = 1;\n\t\twhile (findBy(rootEntries, 'name', uniqueName)) {\n\t\t\tnumber += 1;\n\t\t\tuniqueName = `${defaultName}-${number}`;\n\t\t}\n\t\treturn uniqueName;\n\t}, [rootEntries, cluster, instance, organization]);\n\n\tconst refineZod = useCallback((data: z.infer<typeof NewApplicationSchema>, ctx: z.RefinementCtx) => {\n\t\tif (!data.applicationName && !defaultApplicationName) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: 'custom',\n\t\t\t\tpath: [`applicationName`],\n\t\t\t\tmessage: 'Please name your application!',\n\t\t\t});\n\t\t} else if (rootEntries.find(rootEntry => rootEntry.name === data.applicationName)) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: 'custom',\n\t\t\t\tpath: [`applicationName`],\n\t\t\t\tmessage: 'That application name is already in use!',\n\t\t\t});\n\t\t}\n\t}, [defaultApplicationName, rootEntries]);\n\n\tconst methods = useForm({\n\t\tresolver: zodResolver(NewApplicationSchema.superRefine(refineZod)),\n\t\tdefaultValues: {\n\t\t\tapplicationName: '',\n\t\t\tcontents: {\n\t\t\t\t...defaultImportOptions,\n\t\t\t\t...defaultCLIOptions,\n\t\t\t\t// The last option will be the default selection.\n\t\t\t\t...defaultTemplateOptions,\n\t\t\t},\n\t\t},\n\t});\n\tconst { watch, handleSubmit, control, setValue, formState, trigger } = methods;\n\n\tconst [isReloading, setIsReloading] = useState(false);\n\n\tconst { isCreatingFromTemplate, createFromTemplate } = useCreateFromTemplate(setIsReloading);\n\tconst { isImportingApplication, importApplication } = useImportApplication(setIsReloading);\n\tconst { checkCLI } = useCheckCLI(setIsReloading);\n\n\tconst submitForm = useCallback((formData: z.infer<typeof NewApplicationSchema>) => {\n\t\tconst project = formData.applicationName || defaultApplicationName;\n\t\tswitch (formData.contents.type) {\n\t\t\tcase 'template': {\n\t\t\t\tcreateFromTemplate({ contents: formData.contents, project });\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'import': {\n\t\t\t\timportApplication({ contents: formData.contents, project });\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'cli': {\n\t\t\t\tcheckCLI({ contents: formData.contents, project });\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}, [checkCLI, createFromTemplate, defaultApplicationName, importApplication]);\n\n\tconst contentsType = watch('contents.type');\n\tconst setContentsType = useCallback((type: string) => {\n\t\tconst wasValid = formState.isValid;\n\t\tsetValue('contents.type', type as 'template' | 'import' | 'cli');\n\t\tif (!wasValid) {\n\t\t\tvoid trigger();\n\t\t}\n\t}, [setValue, formState, trigger]);\n\n\treturn (\n\t\t<div className=\"mx-auto max-w-4xl mt-6\">\n\t\t\t<div className=\"text-center\">\n\t\t\t\t<h1 className=\"text-4xl pt-4 pb-2\">Bootstrap New API Application</h1>\n\t\t\t\t<p className=\"text-muted-foreground\">\n\t\t\t\t\tCreate a new application from templates, import existing code, or deploy with Harper CLI\n\t\t\t\t</p>\n\t\t\t</div>\n\n\t\t\t<Form {...methods}>\n\t\t\t\t<form\n\t\t\t\t\tid=\"instance-add-application-form\"\n\t\t\t\t\tname=\"instance-add-application-form\"\n\t\t\t\t\tonSubmit={handleSubmit(submitForm)}\n\t\t\t\t\tclassName=\"flex flex-col gap-4 p-4\"\n\t\t\t\t>\n\t\t\t\t\t<fieldset disabled={isImportingApplication || isCreatingFromTemplate || isReloading}>\n\t\t\t\t\t\t<Card className=\"bg-black-dark\">\n\t\t\t\t\t\t\t<CommonInstructions\n\t\t\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\t\t\tdefaultApplicationName={defaultApplicationName}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</Card>\n\n\t\t\t\t\t\t<Card className=\"bg-black-dark mt-4 pt-0\">\n\t\t\t\t\t\t\t<Tabs defaultValue={contentsType} onValueChange={setContentsType}>\n\t\t\t\t\t\t\t\t<TabsList className=\"w-full grid grid-cols-3 mt-0\">\n\t\t\t\t\t\t\t\t\t<TabsTrigger value=\"template\">\n\t\t\t\t\t\t\t\t\t\t<BoxesIcon />\n\t\t\t\t\t\t\t\t\t\t<span className=\"hidden sm:inline-block\">Templates</span>\n\t\t\t\t\t\t\t\t\t</TabsTrigger>\n\t\t\t\t\t\t\t\t\t<TabsTrigger value=\"import\">\n\t\t\t\t\t\t\t\t\t\t<GitBranchIcon />\n\t\t\t\t\t\t\t\t\t\tImport\n\t\t\t\t\t\t\t\t\t</TabsTrigger>\n\t\t\t\t\t\t\t\t\t<TabsTrigger value=\"cli\">\n\t\t\t\t\t\t\t\t\t\t<TerminalIcon />\n\t\t\t\t\t\t\t\t\t\t<span className=\"hidden md:inline-block\">Harper</span> CLI\n\t\t\t\t\t\t\t\t\t</TabsTrigger>\n\t\t\t\t\t\t\t\t</TabsList>\n\n\t\t\t\t\t\t\t\t<div className=\"mx-6 mt-1\">\n\t\t\t\t\t\t\t\t\t<Separator className=\"bg-black\" />\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<TabsContent value=\"template\" className=\"space-y-4\">\n\t\t\t\t\t\t\t\t\t<TemplateInstructions\n\t\t\t\t\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\t\t\t\t\tformState={formState}\n\t\t\t\t\t\t\t\t\t\tisCreatingFromTemplate={isCreatingFromTemplate}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</TabsContent>\n\n\t\t\t\t\t\t\t\t<TabsContent value=\"import\" className=\"space-y-4\">\n\t\t\t\t\t\t\t\t\t<ImportInstructions\n\t\t\t\t\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\t\t\t\t\tformState={formState}\n\t\t\t\t\t\t\t\t\t\tisImportingApplication={isImportingApplication}\n\t\t\t\t\t\t\t\t\t\tsetValue={setValue}\n\t\t\t\t\t\t\t\t\t\twatch={watch}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</TabsContent>\n\n\t\t\t\t\t\t\t\t<TabsContent value=\"cli\" className=\"space-y-4\">\n\t\t\t\t\t\t\t\t\t<CLIInstructions\n\t\t\t\t\t\t\t\t\t\tdefaultApplicationName={defaultApplicationName}\n\t\t\t\t\t\t\t\t\t\tformState={formState}\n\t\t\t\t\t\t\t\t\t\twatch={watch}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</TabsContent>\n\t\t\t\t\t\t\t</Tabs>\n\t\t\t\t\t\t</Card>\n\t\t\t\t\t</fieldset>\n\t\t\t\t</form>\n\t\t\t</Form>\n\t\t</div>\n\t);\n}\n","import { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { useEditorFileContent } from '@/features/instance/applications/context/editorFileContent';\nimport { useEditorView } from '@/features/instance/applications/hooks/useEditorView';\nimport { registerWithEditor } from '@/features/instance/applications/shortcuts';\nimport { useInstanceBrowseManagePermission } from '@/hooks/usePermissions';\nimport { useListener } from '@/lib/events/listener';\nimport { parseFileExtension } from '@/lib/string/parseFileExtension';\nimport { Editor, EditorProps, OnMount } from '@monaco-editor/react';\nimport { useCallback, useEffect, useState } from 'react';\nimport './monaco-customizations.css';\n\nconst extensionToLanguageMap: Record<string, string> = {\n\tjs: 'javascript',\n\tcjs: 'javascript',\n\tjsx: 'javascript',\n\tyaml: 'yaml',\n\tts: 'typescript',\n\ttsx: 'typescript',\n\tjson: 'json',\n\tmd: 'markdown',\n\thtml: 'html',\n\tcss: 'css',\n\tgraphql: 'graphql',\n\tmjs: 'javascript',\n};\n\nexport function TextEditorView() {\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst { openedEntryContents, openedEntry, restrictPackageModification, isSavingFile, saveFile } = useEditorView();\n\tconst {\n\t\tcontent: updatedFileContent,\n\t\tsetContent,\n\t} = useEditorFileContent(!!openedEntry && !openedEntry.package && openedEntry.path);\n\n\tconst setUpdatedFileContent = useCallback((newValue: string | undefined) => {\n\t\tsetContent(newValue !== openedEntryContents ? newValue : undefined);\n\t}, [openedEntryContents, setContent]);\n\n\tconst canManageBrowseInstance = useInstanceBrowseManagePermission();\n\tconst [mounted, setMounted] = useState<Parameters<OnMount> | null>(null);\n\n\tconst extension = parseFileExtension(openedEntry?.path);\n\tconst language = extensionToLanguageMap[extension] || 'plaintext';\n\n\tconst handleEditorDidMount: EditorProps['onMount'] = useCallback<OnMount>((editor, monaco) => {\n\t\tsetMounted([editor, monaco]);\n\t}, []);\n\n\tuseEffect(() => {\n\t\tif (mounted && canManageBrowseInstance && !openedEntry?.package && !restrictPackageModification) {\n\t\t\treturn registerWithEditor(mounted);\n\t\t}\n\t}, [mounted, canManageBrowseInstance, openedEntry, restrictPackageModification]);\n\n\tuseListener(\n\t\t'SaveFile',\n\t\t() => {\n\t\t\tif (openedEntry && !isSavingFile && updatedFileContent !== undefined) {\n\t\t\t\tsaveFile(\n\t\t\t\t\t{\n\t\t\t\t\t\t...instanceParams,\n\t\t\t\t\t\tfile: openedEntry.path.split('/').slice(1).join('/'),\n\t\t\t\t\t\tpayload: updatedFileContent,\n\t\t\t\t\t\tproject: openedEntry.project,\n\t\t\t\t\t},\n\t\t\t\t\topenedEntry.path,\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t\t[openedEntry, instanceParams, updatedFileContent],\n\t);\n\n\tuseListener(\n\t\t'RevertChanges',\n\t\t() => {\n\t\t\tif (openedEntryContents !== undefined && mounted) {\n\t\t\t\tconst [editor] = mounted;\n\t\t\t\tsetUpdatedFileContent(undefined);\n\t\t\t\teditor.setValue(openedEntryContents);\n\t\t\t}\n\t\t},\n\t\t[openedEntryContents, mounted],\n\t);\n\n\tif (!openedEntry) {\n\t\treturn null;\n\t}\n\n\tconst readOnly = isSavingFile || !!openedEntry.package || !canManageBrowseInstance;\n\n\treturn (\n\t\t<Editor\n\t\t\tclassName=\"w-full min-h-full h-80\"\n\t\t\tlanguage={language}\n\t\t\ttheme=\"vs-dark\"\n\t\t\tvalue={updatedFileContent ?? openedEntryContents}\n\t\t\tonMount={handleEditorDidMount}\n\t\t\tonChange={readOnly ? undefined : setUpdatedFileContent}\n\t\t\toptions={{\n\t\t\t\tautomaticLayout: true,\n\t\t\t\tminimap: { enabled: false },\n\t\t\t\treadOnly,\n\t\t\t\tpadding: { top: 48 },\n\t\t\t}}\n\t\t/>\n\t);\n}\n","import { Button } from '@/components/ui/button';\nimport { isDirectory } from '@/features/instance/applications/context/isDirectory';\nimport { useEditorView } from '@/features/instance/applications/hooks/useEditorView';\nimport { useReadMeUrlTransformer } from '@/features/instance/applications/lib/readMeUrlTransform';\nimport { useCopyToClipboard } from '@/hooks/useCopyToClipboard';\nimport { hasImageFileExtension } from '@/lib/string/hasImageFileExtension';\nimport { parseFileExtension } from '@/lib/string/parseFileExtension';\nimport { CopyIcon } from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\nimport Markdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport { newApplication } from './ApplicationsSidebar/specialItems';\nimport { NewApplication } from './NewApplication';\nimport { TextEditorView } from './TextEditorView';\nimport './directoryReadMe.css';\n\nexport function ContentViewer() {\n\tconst { openedEntry, openedEntryContents } = useEditorView();\n\tconst urlTransform = useReadMeUrlTransformer(openedEntry?.project);\n\n\tif (openedEntry?.path === newApplication) {\n\t\treturn <NewApplication />;\n\t}\n\n\tif (isDirectory(openedEntry)) {\n\t\treturn (\n\t\t\t<div className=\"directoryReadMe max-w-3xl\">\n\t\t\t\t<Markdown\n\t\t\t\t\turlTransform={urlTransform}\n\t\t\t\t\tremarkPlugins={[remarkGfm]}\n\t\t\t\t\tcomponents={{ code: MarkdownCode }}\n\t\t\t\t>\n\t\t\t\t\t{openedEntryContents}\n\t\t\t\t</Markdown>\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (hasImageFileExtension(openedEntry?.name)) {\n\t\treturn (\n\t\t\t<div className=\"mt-9 absolute top-0 right-0 bottom-0 left-0\">\n\t\t\t\t<img\n\t\t\t\t\tclassName=\"w-full h-full object-contain p-20\"\n\t\t\t\t\talt={openedEntry?.name}\n\t\t\t\t\tsrc={`data:image/${parseFileExtension(openedEntry?.name)};base64,${openedEntryContents}`}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t);\n\t} else {\n\t\treturn <TextEditorView />;\n\t}\n}\n\nfunction MermaidDiagram({ chart }: { chart: string }) {\n\tconst containerRef = useRef<HTMLDivElement>(null);\n\tconst [svg, setSvg] = useState('');\n\tconst [error, setError] = useState<string | null>(null);\n\n\tuseEffect(() => {\n\t\tconst id = `mermaid-${Math.random().toString(36).slice(2, 9)}`;\n\t\tlet cancelled = false;\n\n\t\timport('mermaid').then(({ default: mermaid }) => {\n\t\t\tif (cancelled) { return; }\n\t\t\tmermaid.initialize({ startOnLoad: false, theme: 'default' });\n\t\t\tmermaid\n\t\t\t\t.render(id, chart)\n\t\t\t\t.then(({ svg }) => {\n\t\t\t\t\tif (!cancelled) {\n\t\t\t\t\t\tsetSvg(svg);\n\t\t\t\t\t\tsetError(null);\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.catch((err) => {\n\t\t\t\t\tif (!cancelled) {\n\t\t\t\t\t\tconsole.error('Mermaid render error:', err);\n\t\t\t\t\t\tsetError(String(err));\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t});\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [chart]);\n\n\tif (error) {\n\t\treturn (\n\t\t\t<pre className=\"text-red-500 bg-red-50 p-3 rounded text-sm overflow-auto\">\n\t\t\t\t<code>{chart}</code>\n\t\t\t</pre>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tref={containerRef}\n\t\t\tclassName=\"my-4 flex justify-center overflow-auto\"\n\t\t\tdangerouslySetInnerHTML={{ __html: svg }}\n\t\t/>\n\t);\n}\n\nfunction MarkdownCode({\n\tinline,\n\tclassName,\n\tchildren,\n}: {\n\tinline?: boolean;\n\tclassName?: string;\n\tchildren?: unknown;\n}) {\n\tconst code = String(children ?? '').replace(/\\n$/, '');\n\tconst [copy] = useCopyToClipboard(code);\n\tconst language = className?.replace('language-', '');\n\n\tif (inline || !code.includes('\\n')) {\n\t\treturn <code className={className}>{children as any}</code>;\n\t}\n\n\tif (language === 'mermaid') {\n\t\treturn <MermaidDiagram chart={code} />;\n\t}\n\n\treturn (\n\t\t<code className=\"relative\">\n\t\t\t<Button\n\t\t\t\tclassName=\"absolute top-2 right-2\"\n\t\t\t\ttype=\"button\"\n\t\t\t\tvariant=\"default\"\n\t\t\t\tsize=\"sm\"\n\t\t\t\tonClick={copy}\n\t\t\t>\n\t\t\t\t<CopyIcon className=\"w-4 h-4\" />\n\t\t\t</Button>\n\t\t\t{code}\n\t\t</code>\n\t);\n}\n","export function linkify(fqdn: string): string {\n\treturn new URL(\n\t\t!fqdn.match(/^https?:\\/\\//i)\n\t\t\t? `https://${fqdn}`\n\t\t\t: fqdn,\n\t).toString();\n}\n","import { Cluster } from '@/integrations/api/api.patch';\nimport { linkify } from '@/lib/urls/linkify';\n\nexport function getRestUrlForCluster(cluster: undefined | Pick<Cluster, 'fqdn' | 'domains'>): string | null {\n\tif (cluster?.domains) {\n\t\tfor (const domain of cluster.domains) {\n\t\t\tif (domain.domain) {\n\t\t\t\treturn linkify(domain.domain);\n\t\t\t}\n\t\t}\n\t}\n\tif (!cluster?.fqdn) {\n\t\treturn null;\n\t}\n\treturn linkify(cluster.fqdn);\n}\n","import { useInstanceClient } from '@/config/useInstanceClient';\nimport { authStore } from '@/features/auth/store/authStore';\nimport { getClusterInfoQueryOptions } from '@/features/cluster/queries/getClusterInfoQuery';\nimport { getRestUrlForCluster } from '@/lib/urls/getRestUrlForCluster';\nimport { useQuery } from '@tanstack/react-query';\nimport { useParams } from '@tanstack/react-router';\n\nexport function useEntityRestURL(): string | null {\n\tconst { clusterId, instanceId }: { clusterId?: string; instanceId?: string } = useParams({ strict: false });\n\tconst instanceClient = useInstanceClient();\n\tconst { data: cluster } = useQuery(\n\t\tgetClusterInfoQueryOptions(clusterId),\n\t);\n\n\tconst isFabricConnect = (!!clusterId && authStore.checkForFabricConnect(clusterId))\n\t\t|| !!instanceId && authStore.checkForFabricConnect(instanceId);\n\tif (isFabricConnect || (cluster && !instanceId)) {\n\t\treturn getRestUrlForCluster(cluster);\n\t} else if (instanceClient.defaults.baseURL) {\n\t\treturn instanceClient.defaults.baseURL.replace(/:9925\\/?/, '');\n\t}\n\treturn null;\n}\n","export function transformNodes<Transformed, Branch, Leaf>(\n\tnodes: Array<Branch | Leaf>,\n\tnestedPropertyName: keyof Branch,\n\ttransformer: (node: Branch | Leaf, parents: Branch[]) => Transformed,\n\tparents: Branch[] = [],\n): Transformed[] {\n\tconst results: Transformed[] = [];\n\n\tfor (const node of nodes) {\n\t\tconst transformed = transformer(node, parents);\n\t\tresults.push(transformed);\n\t\tconst potentialBranch = node as Branch;\n\t\tconst nestedNodes = potentialBranch[nestedPropertyName] as Array<Branch | Leaf>;\n\t\tif (nestedNodes) {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t(transformed as any)[nestedPropertyName] = transformNodes(nestedNodes, nestedPropertyName, transformer, [\n\t\t\t\t...parents,\n\t\t\t\tpotentialBranch,\n\t\t\t]);\n\t\t}\n\t}\n\n\treturn results;\n}\n","import { DirectoryEntry } from '@/features/instance/applications/context/directoryEntry';\nimport { FileEntry } from '@/features/instance/applications/context/fileEntry';\nimport { isDirectory } from '@/features/instance/applications/context/isDirectory';\nimport { APIDirectoryEntry, APIFileEntry } from '@/integrations/api/instance/applications/getComponents';\nimport { transformNodes } from '@/lib/arrays/transformNodes';\n\nexport function calculateRootEntries(entries: Array<APIDirectoryEntry | APIFileEntry>): {\n\trootEntries: Array<DirectoryEntry | FileEntry>;\n\tpathsRegistry: Set<string>;\n} {\n\tconst pathsRegistry = new Set<string>();\n\tconst rootEntries = transformNodes(\n\t\tentries || [],\n\t\t'entries',\n\t\t(node: APIFileEntry | APIDirectoryEntry, parents: APIDirectoryEntry[]) => {\n\t\t\tconst readMeAPIFile = isDirectory(node) && node.entries.find(e => e.name.toLowerCase() === 'readme.md');\n\t\t\tconst path = [...parents.map(p => p.name), node.name].join('/');\n\t\t\tpathsRegistry.add(path);\n\t\t\treturn {\n\t\t\t\tname: node.name,\n\t\t\t\tpath,\n\t\t\t\tproject: (parents[0] || node)?.name,\n\t\t\t\tpackage: (parents[0] || node)?.package,\n\t\t\t\toverviewEntry: readMeAPIFile && !isDirectory(readMeAPIFile) && {\n\t\t\t\t\t\t\tname: readMeAPIFile.name,\n\t\t\t\t\t\t\tpath: [...parents.map(p => p.name), node.name, readMeAPIFile.name].join('/'),\n\t\t\t\t\t\t\tproject: (parents[0] || node)?.name,\n\t\t\t\t\t\t\tpackage: (parents[0] || node)?.package,\n\t\t\t\t\t\t} || undefined,\n\t\t\t} satisfies DirectoryEntry | FileEntry;\n\t\t},\n\t);\n\treturn {\n\t\trootEntries,\n\t\tpathsRegistry,\n\t};\n}\n","import { GetComponentFileResponse } from '@/integrations/api/instance/applications/getComponentFile';\n\nexport function parseReadMe(\n\tcontents: string,\n\tbaseURL: string,\n\tresponse: Pick<GetComponentFileResponse, 'project'>,\n): string {\n\tconst operations9925URL = baseURL;\n\tconst rest9926URL = baseURL\n\t\t.replace(/:9925/, '')\n\t\t.replace(/\\/?$/, '');\n\tif (operations9925URL) {\n\t\tcontents = contents.replaceAll(/https?:\\/\\/localhost:9926/g, rest9926URL);\n\t}\n\tif (response.project) {\n\t\tcontents = contents\n\t\t\t.replaceAll('Your New Harper Fabric App', response.project)\n\t\t\t.replaceAll('your-project-name-here', response.project);\n\t}\n\treturn contents;\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport interface APIDirectoryEntry extends APIFileEntry {\n\tentries: Array<APIDirectoryEntry | APIFileEntry>;\n\tpackage?: string;\n}\n\nexport interface APIFileEntry {\n\tname: string;\n}\n\nexport async function getComponents({ instanceClient }: InstanceClientIdConfig) {\n\tconst { data }: { data: APIDirectoryEntry } = await instanceClient.post('/', {\n\t\toperation: 'get_components',\n\t});\n\treturn data;\n}\n\nexport function getComponentsQueryOptions(params: InstanceClientIdConfig) {\n\treturn queryOptions({\n\t\tqueryKey: [params.entityId, 'get_components'] as const,\n\t\tqueryFn: () => getComponents(params),\n\t\tretry: false,\n\t});\n}\n","import { useEntityRestURL } from '@/config/useEntityRestURL';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport {\n\tcalculateRootEntries,\n} from '@/features/instance/applications/components/ApplicationsSidebar/calculateRootEntries';\nimport {\n\timportedApplications,\n\tnewApplication,\n} from '@/features/instance/applications/components/ApplicationsSidebar/specialItems';\nimport { useEditorFileContent } from '@/features/instance/applications/context/editorFileContent';\nimport { parseReadMe } from '@/features/instance/applications/lib/parseReadMe';\nimport { useSessionStorage } from '@/hooks/useSessionStorage';\nimport {\n\tgetComponentFileQueryKey,\n\tgetComponentFileQueryOptions,\n} from '@/integrations/api/instance/applications/getComponentFile';\nimport { APIDirectoryEntry, getComponentsQueryOptions } from '@/integrations/api/instance/applications/getComponents';\nimport {\n\tSetComponentFileRequest,\n\tuseSetComponentFile,\n} from '@/integrations/api/instance/applications/setComponentFile';\nimport { useListener } from '@/lib/events/listener';\nimport { setWatchedValue } from '@/lib/events/watcher';\nimport { useQuery, useQueryClient, useSuspenseQuery } from '@tanstack/react-query';\nimport { useNavigate, useSearch } from '@tanstack/react-router';\nimport { PropsWithChildren, useCallback, useEffect, useMemo, useState } from 'react';\nimport { TreeItemIndex } from 'react-complex-tree/src/types';\nimport { DirectoryEntry } from './directoryEntry';\nimport { EditorViewContext, EditorViewContextValue } from './EditorViewContext';\nimport { FileEntry } from './fileEntry';\nimport { isDirectory } from './isDirectory';\n\nexport function EditorViewProvider({ children }: PropsWithChildren) {\n\tconst navigate = useNavigate();\n\tconst [openedEntry, setOpenedEntry] = useState<DirectoryEntry | FileEntry | undefined>(undefined);\n\tconst [openedEntryContents, setOpenedEntryContents] = useState<string | undefined>(undefined);\n\tconst { setContent: setUpdatedEntryContents } = useEditorFileContent(openedEntry?.path);\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst baseURL = useEntityRestURL();\n\tconst queryClient = useQueryClient();\n\tconst { open }: { open?: string } = useSearch({ strict: false });\n\n\t/*\n\t Create our structured view from the relational API data.\n\t */\n\tconst { data: apiComponents } = useSuspenseQuery(getComponentsQueryOptions(instanceParams));\n\tconst mappedData = useMemo(() => calculateRootEntries(apiComponents.entries), [apiComponents]);\n\n\tconst reloadRootEntries = useCallback(async () =>\n\t\tqueryClient.fetchQuery<APIDirectoryEntry>({\n\t\t\tqueryKey: [instanceParams.entityId, 'get_components'],\n\t\t\tnetworkMode: 'online',\n\t\t}), [queryClient, instanceParams]);\n\n\tuseListener('ReloadApplicationRootEntries', reloadRootEntries, [reloadRootEntries]);\n\n\tconst entryExists = useCallback((path: string) => {\n\t\treturn mappedData.pathsRegistry.has(path);\n\t}, [mappedData.pathsRegistry]);\n\n\tconst defaultFolderExpansions = mappedData.rootEntries.filter(rootEntry =>\n\t\t!rootEntry.package && rootEntry.path !== newApplication\n\t).map<TreeItemIndex>(rootEntry => rootEntry.name);\n\tlet defaultFocusedItem = defaultFolderExpansions[0];\n\tlet defaultSelectedItem = defaultFolderExpansions.slice(0, 1);\n\tif (!defaultFocusedItem) {\n\t\tdefaultFocusedItem = newApplication;\n\t\tdefaultSelectedItem = [newApplication];\n\t}\n\tconst [focusedItem, setFocusedItem] = useSessionStorage(\n\t\t`FileFocused/${instanceParams.entityId}` as 'FileFocused/{entityId}',\n\t\tdefaultFocusedItem as TreeItemIndex | undefined,\n\t);\n\tconst [expandedItems, setExpandedItems] = useSessionStorage(\n\t\t`FolderOpened/${instanceParams.entityId}` as 'FolderOpened/{entityId}',\n\t\tdefaultFolderExpansions,\n\t);\n\tconst [selectedItems, setSelectedItems] = useSessionStorage(\n\t\t`FileSelected/${instanceParams.entityId}` as 'FileSelected/{entityId}',\n\t\tdefaultSelectedItem,\n\t);\n\n\t/*\n\t Support URL links to files.\n\t */\n\tuseEffect(() => {\n\t\tif (open?.length) {\n\t\t\t// ./schema.graphql?ShowNewTableModal=true\n\t\t\tconst openParts = open.split('?');\n\t\t\tconst ref = openParts[0];\n\t\t\tconst action = openParts[1];\n\t\t\tconst refParts = ref.split('/');\n\n\t\t\tif (action) {\n\t\t\t\tconst actionParts = action.split('=');\n\t\t\t\tsetWatchedValue(\n\t\t\t\t\tactionParts[0] as any,\n\t\t\t\t\tactionParts[1] === 'true' ? true : actionParts[1] === 'false' ? false : actionParts[1],\n\t\t\t\t);\n\t\t\t}\n\t\t\tsetExpandedItems(expandedItems => {\n\t\t\t\tconst expansion = new Set(expandedItems);\n\t\t\t\tfor (let i = 1; i < refParts.length; i++) {\n\t\t\t\t\texpansion.add(refParts.slice(0, i).join('/'));\n\t\t\t\t}\n\t\t\t\treturn [...expansion];\n\t\t\t});\n\n\t\t\tsetSelectedItems([ref]);\n\t\t\tsetFocusedItem(ref);\n\n\t\t\tvoid navigate({ search: undefined });\n\t\t}\n\t}, [navigate, open, setExpandedItems, setFocusedItem, setSelectedItems]);\n\n\t/*\n\t Load the selected file contents.\n\t */\n\tconst pathToLoad = openedEntry && (isDirectory(openedEntry) ? openedEntry.overviewEntry?.path : openedEntry.path)\n\t\t|| '';\n\tconst projectToLoad =\n\t\topenedEntry && (isDirectory(openedEntry) ? openedEntry.overviewEntry?.project : openedEntry.project) || '';\n\tconst loadedOverviewEntry = openedEntry && (isDirectory(openedEntry) ? !!openedEntry.overviewEntry?.path : false)\n\t\t|| false;\n\tconst fileQueryKey = getComponentFileQueryKey({\n\t\tfile: pathToLoad?.split('/').slice(1).join('/'),\n\t\tproject: projectToLoad,\n\t\t...instanceParams,\n\t});\n\tconst { data: getComponentFileQueryData } = useQuery(\n\t\tgetComponentFileQueryOptions(\n\t\t\t{\n\t\t\t\tfile: pathToLoad?.split('/').slice(1).join('/'),\n\t\t\t\tproject: projectToLoad,\n\t\t\t\t...instanceParams,\n\t\t\t},\n\t\t),\n\t);\n\tuseEffect(function setOpenedEntryContentsFromAPIResponse() {\n\t\tconst loadedPath = getComponentFileQueryData?.project + '/' + getComponentFileQueryData?.file;\n\t\tlet contents = getComponentFileQueryData?.message;\n\t\tif (\n\t\t\tloadedPath === pathToLoad && contents !== undefined\n\t\t) {\n\t\t\tif (loadedOverviewEntry && baseURL && getComponentFileQueryData) {\n\t\t\t\tcontents = parseReadMe(contents, baseURL, getComponentFileQueryData);\n\t\t\t}\n\t\t\t// eslint-disable-next-line react-hooks/set-state-in-effect\n\t\t\tsetOpenedEntryContents(contents);\n\t\t} else {\n\t\t\tsetOpenedEntryContents(undefined);\n\t\t}\n\t}, [getComponentFileQueryData, pathToLoad, loadedOverviewEntry, instanceParams]);\n\n\t/*\n\t Save changes.\n\t */\n\tconst { mutate: saveComponentFile, isPending: isSavingFile } = useSetComponentFile();\n\tconst saveFile = useCallback(\n\t\t(data: SetComponentFileRequest, filePath: string) => {\n\t\t\tsaveComponentFile(data, {\n\t\t\t\tonSuccess: () => {\n\t\t\t\t\tif (openedEntry?.path === filePath && data.payload !== undefined) {\n\t\t\t\t\t\tsetUpdatedEntryContents(undefined);\n\t\t\t\t\t\tsetOpenedEntryContents(data.payload || undefined);\n\t\t\t\t\t\tqueryClient.setQueryData(fileQueryKey, { ...getComponentFileQueryData, message: data.payload });\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tonError: (error) => {\n\t\t\t\t\tconsole.error('Error saving file:', error);\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t\t[\n\t\t\tfileQueryKey,\n\t\t\tgetComponentFileQueryData,\n\t\t\topenedEntry?.path,\n\t\t\tqueryClient,\n\t\t\tsaveComponentFile,\n\t\t\tsetUpdatedEntryContents,\n\t\t],\n\t);\n\n\tconst restrictPackageModification = useMemo(() => {\n\t\tif (!openedEntry) {\n\t\t\treturn false;\n\t\t}\n\t\treturn openedEntry.package?.includes('github.com/HarperDB/status-check-fabric')\n\t\t\t|| openedEntry.package?.includes('github.com/HarperFast/status-check-fabric')\n\t\t\t|| openedEntry.path === importedApplications\n\t\t\t|| openedEntry.path === newApplication;\n\t}, [openedEntry]);\n\n\t/*\n\t Memoize the tracked state.\n\t */\n\tconst value = useMemo<EditorViewContextValue>(() => {\n\t\treturn {\n\t\t\trootEntries: mappedData.rootEntries,\n\t\t\treloadRootEntries,\n\t\t\tentryExists,\n\n\t\t\tfocusedItem,\n\t\t\tsetFocusedItem,\n\t\t\texpandedItems,\n\t\t\tsetExpandedItems,\n\t\t\tselectedItems,\n\t\t\tsetSelectedItems,\n\n\t\t\trestrictPackageModification,\n\t\t\topenedEntry,\n\t\t\tsetOpenedEntry,\n\n\t\t\topenedEntryContents,\n\t\t\tsetOpenedEntryContents,\n\n\t\t\tsaveFile,\n\t\t\tisSavingFile,\n\t\t};\n\t}, [\n\t\tmappedData.rootEntries,\n\t\treloadRootEntries,\n\t\tentryExists,\n\n\t\tfocusedItem,\n\t\tsetFocusedItem,\n\t\texpandedItems,\n\t\tsetExpandedItems,\n\t\tselectedItems,\n\t\tsetSelectedItems,\n\n\t\trestrictPackageModification,\n\t\topenedEntry,\n\t\tsetOpenedEntry,\n\n\t\topenedEntryContents,\n\t\tsetOpenedEntryContents,\n\n\t\tsaveFile,\n\t\tisSavingFile,\n\t]);\n\treturn <EditorViewContext.Provider value={value}>{children}</EditorViewContext.Provider>;\n}\n","import { sleep } from '@/lib/sleep';\n\ninterface IFocusable {\n\tfocus?: () => void;\n}\n\ninterface ITargetFocusable {\n\ttarget?: IFocusable;\n}\n\nexport function attemptToRestoreFocus(trigger?: unknown) {\n\tconst focusableTrigger = trigger as IFocusable;\n\tif (focusableTrigger?.focus) {\n\t\tfocusElement(focusableTrigger);\n\t} else {\n\t\tconst triggerTargetFocusable = trigger as ITargetFocusable;\n\t\tif (triggerTargetFocusable?.target?.focus) {\n\t\t\tfocusElement(triggerTargetFocusable.target);\n\t\t}\n\t}\n}\n\nfunction focusElement(element: IFocusable) {\n\tsleep(1).then(() => {\n\t\telement.focus?.();\n\t});\n}\n","import { Button } from '@/components/ui/button';\nimport {\n\tDialog,\n\tDialogContent,\n\tDialogDescription,\n\tDialogFooter,\n\tDialogHeader,\n\tDialogTitle,\n} from '@/components/ui/dialog';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { isDirectory } from '@/features/instance/applications/context/isDirectory';\nimport { useEditorView } from '@/features/instance/applications/hooks/useEditorView';\nimport { useSetComponentFile } from '@/integrations/api/instance/applications/setComponentFile';\nimport { excludeFalsy } from '@/lib/arrays/excludeFalsy';\nimport { attemptToRestoreFocus } from '@/lib/attemptToRestoreFocus';\nimport { setWatchedValue, useWatchedValue } from '@/lib/events/watcher';\nimport { capitalizeWords } from '@/lib/string/capitalizeWords';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { Plus } from 'lucide-react';\nimport { useCallback } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport z from 'zod';\n\nexport function AddDirectoryOrFileModal() {\n\tconst { value: type, trigger } = useWatchedValue('ShowAddDirectoryOrFileModalType', false);\n\n\tconst closeModal = useCallback(() => {\n\t\tsetWatchedValue('ShowAddDirectoryOrFileModalType', false);\n\t\tattemptToRestoreFocus(trigger);\n\t}, [trigger]);\n\n\tconst {\n\t\topenedEntry,\n\t\tentryExists,\n\t\treloadRootEntries,\n\t\tsetFocusedItem,\n\t\tsetSelectedItems,\n\t\tsetExpandedItems,\n\t} = useEditorView();\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst { mutate: addFolderFile, isPending } = useSetComponentFile();\n\tconst NewFileFolderSchema = z.object({\n\t\tname: z\n\t\t\t.string()\n\t\t\t.nonempty({ error: 'Please enter a valid name.' })\n\t\t\t.regex(/^[a-zA-Z0-9_\\- .]*$/, {\n\t\t\t\terror: 'Names can only contain letters, numbers, underscores, hyphens, periods, and spaces.',\n\t\t\t})\n\t\t\t.max(50, { error: 'Names cannot be longer than 50 characters.' })\n\t\t\t.trim(),\n\t});\n\n\tconst form = useForm({\n\t\tresolver: zodResolver(NewFileFolderSchema),\n\t\tdefaultValues: {\n\t\t\tname: '',\n\t\t},\n\t});\n\n\tconst submitForm = useCallback((data: z.infer<typeof NewFileFolderSchema>) => {\n\t\tif (!openedEntry || !type) {\n\t\t\treturn;\n\t\t}\n\t\tconst splitPath = openedEntry.path.split('/');\n\t\tconst filePath = (\n\t\t\tisDirectory(openedEntry)\n\t\t\t\t? splitPath.slice(1)\n\t\t\t\t: splitPath.slice(1, -1)\n\t\t).join('/');\n\t\tconst file = filePath ? `${filePath}/${data.name}` : data.name;\n\t\tif (entryExists(openedEntry.project + '/' + file)) {\n\t\t\ttoast.error(`${capitalizeWords(type)} already exists!`, {\n\t\t\t\tdescription: file,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\taddFolderFile(\n\t\t\t{\n\t\t\t\tfile,\n\t\t\t\tproject: openedEntry.project,\n\t\t\t\tpayload: type === 'directory' ? undefined : '',\n\t\t\t\t...instanceParams,\n\t\t\t},\n\t\t\t{\n\t\t\t\tonSuccess: () => {\n\t\t\t\t\tvoid reloadRootEntries();\n\t\t\t\t\tcloseModal();\n\t\t\t\t\tform.reset();\n\t\t\t\t\tconst treeId = [openedEntry.project, filePath, data.name].filter(excludeFalsy).join('/');\n\t\t\t\t\tsetFocusedItem(treeId);\n\t\t\t\t\tsetSelectedItems([treeId]);\n\t\t\t\t\tif (type === 'directory') {\n\t\t\t\t\t\tsetExpandedItems(expandedItems => [...expandedItems, treeId]);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}, [\n\t\taddFolderFile,\n\t\tform,\n\t\tcloseModal,\n\t\tinstanceParams,\n\t\topenedEntry,\n\t\tentryExists,\n\t\treloadRootEntries,\n\t\tsetExpandedItems,\n\t\tsetFocusedItem,\n\t\tsetSelectedItems,\n\t\ttype,\n\t]);\n\n\tconst onCancelClick = useCallback(() => {\n\t\tcloseModal();\n\t\tform.reset();\n\t}, [closeModal, form]);\n\n\treturn (\n\t\t<Dialog onOpenChange={closeModal} open={!!type}>\n\t\t\t<DialogContent aria-describedby={undefined} className=\"text-white\">\n\t\t\t\t<Form {...form}>\n\t\t\t\t\t<form\n\t\t\t\t\t\tid={`instance-add-app-${type}-form`}\n\t\t\t\t\t\tname={`instance-add-app-${type}-form`}\n\t\t\t\t\t\tonSubmit={form.handleSubmit(submitForm)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<DialogHeader>\n\t\t\t\t\t\t\t<DialogTitle>Add {type}</DialogTitle>\n\t\t\t\t\t\t\t<DialogDescription>\n\t\t\t\t\t\t\t\tEnter the name of the {type} you want to add{type === 'file' ? \", don't forget the extension\" : ''}!\n\t\t\t\t\t\t\t</DialogDescription>\n\t\t\t\t\t\t</DialogHeader>\n\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"name\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem className=\"my-2\">\n\t\t\t\t\t\t\t\t\t<FormLabel>Name</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\tdisabled={isPending}\n\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<DialogFooter>\n\t\t\t\t\t\t\t<div className=\"flex justify-between w-full\">\n\t\t\t\t\t\t\t\t<Button type=\"button\" variant=\"ghostOutline\" className=\"rounded-full\" onClick={onCancelClick}>\n\t\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tvariant=\"positiveOutline\"\n\t\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\t\tdisabled={isPending}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Plus /> Add {type}\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</DialogFooter>\n\t\t\t\t\t</form>\n\t\t\t\t</Form>\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { Button } from '@/components/ui/button';\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { isDirectory } from '@/features/instance/applications/context/isDirectory';\nimport { useEditorView } from '@/features/instance/applications/hooks/useEditorView';\nimport { dropComponent } from '@/integrations/api/instance/applications/dropComponent';\nimport { attemptToRestoreFocus } from '@/lib/attemptToRestoreFocus';\nimport { setWatchedValue, useWatchedValue } from '@/lib/events/watcher';\nimport { pluralize } from '@/lib/pluralize';\nimport { Trash } from 'lucide-react';\nimport { MouseEvent, useCallback } from 'react';\nimport { toast } from 'sonner';\n\nexport function DeleteDirectoryOrFileModal() {\n\tconst { value: isModalOpen, trigger } = useWatchedValue('ShowDeleteDirectoryOrFileModal', false);\n\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst { openedEntry, reloadRootEntries, setFocusedItem, setSelectedItems, selectedItems } = useEditorView();\n\n\tconst multipleSelected = selectedItems.length > 1;\n\tconst isDirectorySelected = isDirectory(openedEntry);\n\tconst isApplicationSelected = isDirectorySelected && openedEntry.path === openedEntry.project;\n\tconst isPackageSelected = !!openedEntry?.package;\n\tconst action = isPackageSelected ? 'Remove' : 'Delete';\n\tconst thing = isPackageSelected\n\t\t? 'Imported Application'\n\t\t: isApplicationSelected\n\t\t? 'Application'\n\t\t: isDirectorySelected\n\t\t? 'Directory'\n\t\t: 'File';\n\n\tconst closeModal = useCallback(() => {\n\t\tsetWatchedValue('ShowDeleteDirectoryOrFileModal', false);\n\t\tattemptToRestoreFocus(trigger);\n\t}, [trigger]);\n\n\tconst handleDeleteFolderOrFile = useCallback(async () => {\n\t\tcloseModal();\n\n\t\tlet split: string[] = [];\n\t\tlet count = 0;\n\t\tlet canceled = false;\n\n\t\tconst toastCancelAction = {\n\t\t\tlabel: 'Cancel',\n\t\t\tonClick: () => {\n\t\t\t\tcanceled = true;\n\t\t\t},\n\t\t};\n\t\tconst toastOKAction = {\n\t\t\tlabel: 'OK',\n\t\t\tonClick: () => undefined,\n\t\t};\n\n\t\tconst id = 'deleting-files';\n\n\t\tfor (const selectedItem of selectedItems.reverse()) {\n\t\t\tsplit = (selectedItem as string).split('/');\n\t\t\tconst project = split[0];\n\t\t\tconst file = split.length > 1 ? split.slice(1).join('/') : undefined;\n\n\t\t\ttoast.loading(`${action} in progress...`, {\n\t\t\t\tid,\n\t\t\t\tdescription: `${count} of ${pluralize(selectedItems.length, 'item', 'items')}`,\n\t\t\t\taction: toastCancelAction,\n\t\t\t});\n\t\t\tawait dropComponent({\n\t\t\t\tfile,\n\t\t\t\tproject,\n\t\t\t\t...instanceParams,\n\t\t\t});\n\t\t\tif (canceled) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcount += 1;\n\t\t}\n\n\t\tif (canceled) {\n\t\t\ttoast.warning(`${action} canceled!`, { id, description: '', action: toastOKAction });\n\t\t} else {\n\t\t\ttoast.success(`${action} completed!`, { id, description: '', action: toastOKAction });\n\t\t}\n\n\t\tif (split.length) {\n\t\t\tconst itemToFocus = split.slice(0, -1).join('/');\n\t\t\tsetFocusedItem(itemToFocus || undefined);\n\t\t\tsetSelectedItems(itemToFocus ? [itemToFocus] : []);\n\t\t\tvoid reloadRootEntries();\n\t\t}\n\t}, [action, closeModal, instanceParams, reloadRootEntries, selectedItems, setFocusedItem, setSelectedItems]);\n\n\tconst onClickYes = useCallback((e: MouseEvent) => {\n\t\te.preventDefault();\n\t\tvoid handleDeleteFolderOrFile();\n\t}, [handleDeleteFolderOrFile]);\n\n\treturn (\n\t\t<Dialog onOpenChange={closeModal} open={isModalOpen}>\n\t\t\t<DialogContent aria-describedby={undefined} className=\"text-white\">\n\t\t\t\t<DialogHeader>\n\t\t\t\t\t<DialogTitle>{action} {thing}</DialogTitle>\n\t\t\t\t\t<DialogDescription>\n\t\t\t\t\t\tAre you sure you want to {action.toLowerCase()}{' '}\n\t\t\t\t\t\t{multipleSelected ? `these ${selectedItems.length} items` : `this ${thing.toLowerCase()}`}?\n\t\t\t\t\t</DialogDescription>\n\t\t\t\t\t{!isPackageSelected\n\t\t\t\t\t\t&& (\n\t\t\t\t\t\t\t<DialogDescription className=\"whitespace-pre\">\n\t\t\t\t\t\t\t\t{multipleSelected ? selectedItems.join('\\n') : openedEntry?.path}\n\t\t\t\t\t\t\t</DialogDescription>\n\t\t\t\t\t\t)}\n\t\t\t\t</DialogHeader>\n\n\t\t\t\t<div className=\"flex w-full gap-4\">\n\t\t\t\t\t<Button type=\"button\" variant=\"ghostOutline\" className=\"w-full rounded-full\" onClick={closeModal}>\n\t\t\t\t\t\tCancel\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"destructiveOutline\"\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"w-full rounded-full\"\n\t\t\t\t\t\tautoFocus={true}\n\t\t\t\t\t\tonClick={onClickYes}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Trash /> {action} {multipleSelected ? 'items' : thing}\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { useMutation } from '@tanstack/react-query';\n\ninterface PackageComponentParams {\n\tpackageName?: string;\n\tproject: string;\n\tskipNodeModules?: boolean;\n\tskipSymlinks?: boolean;\n}\n\ninterface PackageResponse {\n\tpayload: string;\n}\n\nasync function packageComponent({\n\tpackageName,\n\tproject,\n\tskipNodeModules,\n\tskipSymlinks,\n\tinstanceClient,\n}: PackageComponentParams & InstanceClientConfig): Promise<PackageResponse> {\n\tconst { data } = await instanceClient.post(\n\t\t'/',\n\t\t{\n\t\t\toperation: 'package_component',\n\t\t\tpackage: packageName,\n\t\t\tproject,\n\t\t\tskip_node_modules: skipNodeModules,\n\t\t\tskip_symlinks: skipSymlinks,\n\t\t},\n\t\t{ timeout: 300_000 },\n\t);\n\treturn data;\n}\n\nexport function usePackageComponentMutation() {\n\treturn useMutation({\n\t\tmutationFn: packageComponent,\n\t});\n}\n","import { Button } from '@/components/ui/button';\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { useEditorView } from '@/features/instance/applications/hooks/useEditorView';\nimport { usePackageComponentMutation } from '@/integrations/api/instance/applications/packageComponent';\nimport { attemptToRestoreFocus } from '@/lib/attemptToRestoreFocus';\nimport { setWatchedValue, useWatchedValue } from '@/lib/events/watcher';\nimport { DownloadIcon } from 'lucide-react';\nimport { ChangeEvent, MouseEvent, useCallback, useState } from 'react';\nimport { toast } from 'sonner';\n\nexport function DownloadApplicationModal() {\n\tconst { value: isModalOpen, trigger } = useWatchedValue('ShowDownloadApplicationModal', false);\n\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst { openedEntry } = useEditorView();\n\tconst { mutate: packageComponent, isPending, isSuccess } = usePackageComponentMutation();\n\tconst actionStatus = isSuccess ? `Downloaded` : isPending ? `Downloading` : 'Download';\n\n\tconst [includeNodeModules, setIncludeNodeModules] = useState(false);\n\n\tconst includeNodeModulesChanged = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n\t\tsetIncludeNodeModules(e.target.checked);\n\t}, []);\n\n\tconst closeModal = useCallback(() => {\n\t\tsetWatchedValue('ShowDownloadApplicationModal', false);\n\t\tattemptToRestoreFocus(trigger);\n\t}, [trigger]);\n\tconst onClickYes = useCallback((e: MouseEvent) => {\n\t\te.preventDefault();\n\t\tif (!openedEntry) {\n\t\t\treturn;\n\t\t}\n\t\tcloseModal();\n\t\tconst toastId = toast.loading('Packaging...');\n\t\tpackageComponent(\n\t\t\t{\n\t\t\t\tpackageName: openedEntry.package,\n\t\t\t\tproject: openedEntry.project,\n\t\t\t\tskipNodeModules: !includeNodeModules,\n\t\t\t\t...instanceParams,\n\t\t\t},\n\t\t\t{\n\t\t\t\tonSuccess: (response) => {\n\t\t\t\t\ttoast.success('Download ready!', { id: toastId });\n\n\t\t\t\t\tconst element = document.createElement('a');\n\t\t\t\t\telement.setAttribute('class', 'invisible absolute top-0');\n\t\t\t\t\tconst bytes = Uint8Array.from(atob(response.payload), c => c.charCodeAt(0));\n\t\t\t\t\tconst file = new Blob([bytes], { type: 'application/gzip' });\n\t\t\t\t\telement.href = URL.createObjectURL(file);\n\t\t\t\t\telement.download = `${openedEntry.project}.gz`;\n\t\t\t\t\tdocument.body.appendChild(element);\n\t\t\t\t\telement.click();\n\t\t\t\t\tdocument.body.removeChild(element);\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}, [openedEntry, packageComponent, includeNodeModules, instanceParams, closeModal]);\n\n\treturn (\n\t\t<Dialog onOpenChange={closeModal} open={isModalOpen}>\n\t\t\t<DialogContent aria-describedby={undefined} className=\"text-white\">\n\t\t\t\t<DialogHeader>\n\t\t\t\t\t<DialogTitle>Download Application</DialogTitle>\n\t\t\t\t\t<DialogDescription>\n\t\t\t\t\t\tThis will package up the contents of <strong>{openedEntry?.project}</strong> into a gzipped file.\n\t\t\t\t\t</DialogDescription>\n\t\t\t\t</DialogHeader>\n\n\t\t\t\t<Label className=\"flex\">\n\t\t\t\t\t<Input\n\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\tclassName=\"w-6\"\n\t\t\t\t\t\tdisabled={isPending}\n\t\t\t\t\t\tchecked={includeNodeModules}\n\t\t\t\t\t\tonChange={includeNodeModulesChanged}\n\t\t\t\t\t/>\n\t\t\t\t\t<span className=\"pl-4 pr-8 flex-1 py-2.5\">Include Node Modules</span>\n\t\t\t\t</Label>\n\n\t\t\t\t<div className=\"flex w-full gap-4\">\n\t\t\t\t\t<Button type=\"button\" variant=\"ghostOutline\" className=\"w-full rounded-full\" onClick={closeModal}>\n\t\t\t\t\t\tCancel\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"positive\"\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"w-full rounded-full\"\n\t\t\t\t\t\tdisabled={isPending}\n\t\t\t\t\t\tautoFocus={true}\n\t\t\t\t\t\tonClick={onClickYes}\n\t\t\t\t\t>\n\t\t\t\t\t\t<DownloadIcon /> {actionStatus}\n\t\t\t\t\t\t{isPending ? '...' : ''}\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { MouseEvent, useCallback, useMemo, useState } from 'react';\n\nexport function useToggler(defaultValue: boolean = false) {\n\tconst [toggled, setToggled] = useState<boolean>(defaultValue);\n\n\tconst toggle = useCallback((e?: MouseEvent | unknown) => {\n\t\t(e as MouseEvent)?.preventDefault?.();\n\t\tsetToggled((checked: boolean) => {\n\t\t\treturn !checked;\n\t\t});\n\t}, []);\n\tconst toggleOn = useCallback((e?: MouseEvent | unknown) => {\n\t\t(e as MouseEvent)?.preventDefault?.();\n\t\tsetToggled(true);\n\t}, []);\n\tconst toggleOff = useCallback((e?: MouseEvent | unknown) => {\n\t\t(e as MouseEvent)?.preventDefault?.();\n\t\tsetToggled(false);\n\t}, []);\n\n\treturn useMemo(() => {\n\t\treturn {\n\t\t\ttoggled,\n\t\t\tsetToggled,\n\t\t\ttoggle,\n\t\t\ttoggleOn,\n\t\t\ttoggleOff,\n\t\t};\n\t}, [toggle, setToggled, toggleOff, toggleOn, toggled]);\n}\n","import { FormControl } from '@/components/ui/form/FormControl';\nimport { FormDescription } from '@/components/ui/form/FormDescription';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { useToggler } from '@/hooks/useToggler';\nimport { cx } from 'class-variance-authority';\nimport { ArrowDownIcon, ArrowRightIcon } from 'lucide-react';\nimport { ControllerRenderProps } from 'react-hook-form';\nimport { z } from 'zod';\nimport { newTableSchema } from './newTableSchema';\n\nexport function DatabaseName(\n\t{ field }: { field: ControllerRenderProps<z.infer<typeof newTableSchema>, 'databaseName'> },\n) {\n\tconst { toggled, toggle } = useToggler(false);\n\treturn (\n\t\t<FormItem className=\"my-4\">\n\t\t\t<FormLabel\n\t\t\t\tonClick={toggle}\n\t\t\t\tclassName={cx(\n\t\t\t\t\t'flex items-center gap-2',\n\t\t\t\t\ttoggled ? '' : 'text-muted-foreground italic',\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{toggled ? <ArrowDownIcon /> : <ArrowRightIcon />} Optional Database Name\n\t\t\t</FormLabel>\n\t\t\t<FormDescription className={toggled ? '' : 'hidden'}>\"data\" is the default recommended name</FormDescription>\n\t\t\t<FormControl className={toggled ? '' : 'hidden'}>\n\t\t\t\t<Input type=\"text\" className=\"my-1\" {...field} />\n\t\t\t</FormControl>\n\t\t\t<FormMessage />\n\t\t</FormItem>\n\t);\n}\n","export enum FieldType {\n\tAny = 'Any',\n\tBigInt = 'BigInt',\n\tBlob = 'Blob',\n\tBoolean = 'Boolean',\n\tBytes = 'Bytes',\n\tDate = 'Date',\n\tFloat = 'Float',\n\tID = 'ID',\n\tInt = 'Int',\n\tLong = 'Long',\n\tString = 'String',\n}\n","export const schemaRegex = /^[\\x20-\\x2E|\\x30-\\x5F|\\x61-\\x7E]*$/;\n","import { z } from 'zod';\nimport { schemaRegex } from './schemaRegex';\n\nexport const databaseNameSchema = z\n\t.string()\n\t.regex(schemaRegex, {\n\t\terror: 'Database name cannot include backticks or forward slashes.',\n\t})\n\t.max(75, { error: 'Database name cannot be longer than 75 characters.' });\n","import { z } from 'zod';\nimport { schemaRegex } from './schemaRegex';\n\nexport const fieldNameSchema = z\n\t.string()\n\t.nonempty({\n\t\terror: 'Field name is required.',\n\t})\n\t.regex(schemaRegex, {\n\t\terror: 'Field name cannot include backticks or forward slashes.',\n\t})\n\t.max(250, {\n\t\terror: 'Field name cannot be longer than 250 characters.',\n\t});\n","import { z } from 'zod';\nimport { schemaRegex } from './schemaRegex';\n\nexport const tableNameSchema = z\n\t.string()\n\t.nonempty({\n\t\terror: 'Table name is required.',\n\t})\n\t.regex(schemaRegex, {\n\t\terror: 'Table name cannot include backticks or forward slashes.',\n\t})\n\t.max(250, {\n\t\terror: 'Table name cannot be longer than 250 characters.',\n\t});\n","import { databaseNameSchema } from '@/integrations/api/instance/database/databaseNameSchema';\nimport { fieldNameSchema } from '@/integrations/api/instance/database/fieldNameSchema';\nimport { FieldType } from '@/integrations/api/instance/database/fieldType';\nimport { tableNameSchema } from '@/integrations/api/instance/database/tableNameSchema';\nimport { z } from 'zod';\n\nexport const newTableSchema = z.object({\n\ttableName: tableNameSchema,\n\tdatabaseName: databaseNameSchema,\n\texpiration: z.int32().or(z.literal('')),\n\tenableRest: z.boolean(),\n\tsealed: z.boolean(),\n\ttableFields: z.array(\n\t\tz.object({\n\t\t\tfieldName: fieldNameSchema,\n\t\t\tfieldType: z.enum(FieldType),\n\t\t\tprimaryKey: z.boolean(),\n\t\t\tnullable: z.boolean(),\n\t\t\tindexed: z.boolean(),\n\t\t\tarray: z.boolean(),\n\t\t}),\n\t).min(1, { error: 'Please add at least one field.' }),\n});\n","import { FormControl } from '@/components/ui/form/FormControl';\nimport { FormDescription } from '@/components/ui/form/FormDescription';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { useToggler } from '@/hooks/useToggler';\nimport { cx } from 'class-variance-authority';\nimport { ArrowDownIcon, ArrowRightIcon } from 'lucide-react';\nimport { ChangeEvent, useCallback } from 'react';\nimport { ControllerRenderProps } from 'react-hook-form';\nimport { z } from 'zod';\nimport { newTableSchema } from './newTableSchema';\n\nexport function OptionalExpiration(\n\t{ field }: { field: ControllerRenderProps<z.infer<typeof newTableSchema>, 'expiration'> },\n) {\n\tconst { toggled, toggle } = useToggler(false);\n\tconst onChange = useCallback(\n\t\t(e: ChangeEvent<HTMLInputElement>) =>\n\t\t\tfield.onChange(e.target.value ? parseInt(e.target.value, 10) : e.target.value),\n\t\t[],\n\t);\n\treturn (\n\t\t<FormItem className=\"my-4\">\n\t\t\t<FormLabel\n\t\t\t\tonClick={toggle}\n\t\t\t\tclassName={cx(\n\t\t\t\t\t'flex items-center gap-2',\n\t\t\t\t\ttoggled ? '' : 'text-muted-foreground italic',\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{toggled ? <ArrowDownIcon /> : <ArrowRightIcon />} Optional Expiration\n\t\t\t</FormLabel>\n\t\t\t<FormDescription className={toggled ? '' : 'hidden'}>\n\t\t\t\tAfter how many seconds should records be automatically evicted? Leave blank or set to 0 to skip this feature.\n\t\t\t\t(It can be useful for cache records.)\n\t\t\t</FormDescription>\n\t\t\t<FormControl className={toggled ? '' : 'hidden'}>\n\t\t\t\t<Input {...field} type=\"number\" min={0} step={1} className=\"my-1\" onChange={onChange} />\n\t\t\t</FormControl>\n\t\t\t<FormMessage />\n\t\t</FormItem>\n\t);\n}\n","import { Button } from '@/components/ui/button';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';\nimport { DatabaseName } from '@/features/instance/applications/components/NewTableForm/DatabaseName';\nimport { useEditorFileContent } from '@/features/instance/applications/context/editorFileContent';\nimport { useEditorView } from '@/features/instance/applications/hooks/useEditorView';\nimport { FieldType } from '@/integrations/api/instance/database/fieldType';\nimport { excludeFalsy } from '@/lib/arrays/excludeFalsy';\nimport { useSetWatchedValue } from '@/lib/events/watcher';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { Ban, Plus, PlusIcon, TrashIcon } from 'lucide-react';\nimport { useCallback } from 'react';\nimport { useFieldArray, useForm } from 'react-hook-form';\nimport { z } from 'zod';\nimport { newTableSchema } from './newTableSchema';\nimport { OptionalExpiration } from './OptionalExpiration';\n\nexport function NewTableForm() {\n\tconst closeModal = useSetWatchedValue('ShowNewTableModal', false);\n\tconst { openedEntry, openedEntryContents } = useEditorView();\n\tconst { setContent } = useEditorFileContent(!!openedEntry && !openedEntry.package && openedEntry.path);\n\n\tconst methods = useForm({\n\t\tresolver: zodResolver(newTableSchema),\n\t\tdefaultValues: {\n\t\t\ttableName: '',\n\t\t\tdatabaseName: 'data',\n\t\t\texpiration: '',\n\t\t\tenableRest: true,\n\t\t\tsealed: true,\n\t\t\ttableFields: [\n\t\t\t\t{\n\t\t\t\t\tfieldName: 'id',\n\t\t\t\t\tfieldType: FieldType.ID,\n\t\t\t\t\tprimaryKey: true,\n\t\t\t\t\tnullable: true,\n\t\t\t\t\tindexed: false,\n\t\t\t\t\tarray: false,\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t});\n\tconst { control, handleSubmit, formState } = methods;\n\n\tconst { fields, append, remove } = useFieldArray({\n\t\tname: 'tableFields',\n\t\tcontrol,\n\t});\n\n\tconst addFieldClicked = useCallback(() => {\n\t\tappend({\n\t\t\tfieldName: '',\n\t\t\tfieldType: FieldType.String,\n\t\t\tprimaryKey: false,\n\t\t\tnullable: false,\n\t\t\tindexed: false,\n\t\t\tarray: false,\n\t\t});\n\t}, [append]);\n\n\tconst submitForm = useCallback(async (formData: z.infer<typeof newTableSchema>) => {\n\t\tsetContent(existingContent => {\n\t\t\tconst prefix = existingContent || openedEntryContents || '';\n\n\t\t\tconst tableParams = [\n\t\t\t\t!!formData.databaseName && formData.databaseName !== 'data' && `database: \"${formData.databaseName}\"`,\n\t\t\t\t!!formData.expiration && formData.expiration > 0 && `expiration: ${formData.expiration}`,\n\t\t\t].filter(excludeFalsy);\n\t\t\tconst joinedTableParams = tableParams.length ? `(${tableParams.join(', ')})` : '';\n\t\t\tconst maybeExport = formData.enableRest ? ' @export' : '';\n\t\t\tconst maybeSealed = formData.sealed ? ' @sealed' : '';\n\t\t\tconst fieldDefinitions = formData.tableFields.map(tableField => {\n\t\t\t\tconst fieldType = tableField.array ? `[${tableField.fieldType}]` : tableField.fieldType;\n\t\t\t\tconst maybeNullable = tableField.nullable ? '' : '!';\n\t\t\t\tconst maybePK = tableField.primaryKey ? ' @primaryKey' : '';\n\t\t\t\tconst maybeIndexed = tableField.indexed ? ' @indexed' : '';\n\t\t\t\treturn `\\n\\t${tableField.fieldName}: ${fieldType}${maybeNullable}${maybePK}${maybeIndexed}`;\n\t\t\t}).join('');\n\n\t\t\treturn `${prefix}\\ntype ${formData.tableName} @table${joinedTableParams}${maybeExport}${maybeSealed} {${fieldDefinitions}\\n}\\n`;\n\t\t});\n\t\tcloseModal();\n\t}, [setContent, closeModal, openedEntryContents]);\n\n\treturn (\n\t\t<Form {...methods}>\n\t\t\t<form\n\t\t\t\tid=\"instance-new-app-table-form\"\n\t\t\t\tname=\"instance-new-app-table-form\"\n\t\t\t\tonSubmit={handleSubmit(submitForm)}\n\t\t\t>\n\t\t\t\t<FormField\n\t\t\t\t\tcontrol={control}\n\t\t\t\t\tname=\"tableName\"\n\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t<FormItem className=\"my-4\">\n\t\t\t\t\t\t\t<FormLabel>Table Name</FormLabel>\n\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t<Input type=\"text\" className=\"my-1\" {...field} />\n\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t)}\n\t\t\t\t/>\n\n\t\t\t\t<h3 className=\"text-lg\">Table Fields</h3>\n\n\t\t\t\t{fields.map((field, index) => (\n\t\t\t\t\t<div key={field.id} className=\"p-4 my-2 border rounded-lg\">\n\t\t\t\t\t\t<div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\t\t\tname={`tableFields.${index}.fieldName`}\n\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t\t<FormLabel>Field Name</FormLabel>\n\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t<Input type=\"text\" {...field} />\n\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\t\t\tname={`tableFields.${index}.fieldType`}\n\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t\t<FormLabel>Type</FormLabel>\n\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t<Select {...field} onValueChange={field.onChange} defaultValue={field.value}>\n\t\t\t\t\t\t\t\t\t\t\t\t<SelectTrigger className=\"w-full\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectValue />\n\t\t\t\t\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"Any\">Any</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"BigInt\">BigInt</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"Blob\">Blob</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"Boolean\">Boolean</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"Bytes\">Bytes</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"Date\">Date</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"Float\">Float</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"ID\">ID</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"Int\">Int</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"Long\">Long</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"String\">String</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div className=\"flex flex-wrap items-center mt-2 gap-x-2 md:gap-x-4\">\n\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\t\t\tname={`tableFields.${index}.indexed`}\n\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t<FormItem className=\"inline-flex\">\n\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"w-5\"\n\t\t\t\t\t\t\t\t\t\t\t\tchecked={field.value}\n\t\t\t\t\t\t\t\t\t\t\t\tonChange={(e) => field.onChange(e.target.checked)}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t<FormLabel className=\"flex-1 py-2.5\">Indexed</FormLabel>\n\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\t\t\tname={`tableFields.${index}.primaryKey`}\n\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t<FormItem className=\"inline-flex\">\n\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"w-5\"\n\t\t\t\t\t\t\t\t\t\t\t\tchecked={field.value}\n\t\t\t\t\t\t\t\t\t\t\t\tonChange={(e) => field.onChange(e.target.checked)}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t<FormLabel className=\"flex-1 py-2.5\">Primary Key</FormLabel>\n\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\t\t\tname={`tableFields.${index}.nullable`}\n\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t<FormItem className=\"inline-flex\">\n\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"w-5\"\n\t\t\t\t\t\t\t\t\t\t\t\tchecked={field.value}\n\t\t\t\t\t\t\t\t\t\t\t\tonChange={(e) => field.onChange(e.target.checked)}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t<FormLabel className=\"flex-1 py-2.5\">Nullable</FormLabel>\n\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\t\t\tname={`tableFields.${index}.array`}\n\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t<FormItem className=\"inline-flex\">\n\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"w-5\"\n\t\t\t\t\t\t\t\t\t\t\t\tchecked={field.value}\n\t\t\t\t\t\t\t\t\t\t\t\tonChange={(e) => field.onChange(e.target.checked)}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t<FormLabel className=\"flex-1 py-2.5\">Array</FormLabel>\n\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t\t<div className=\"grow\"></div>\n\t\t\t\t\t\t\t<Button type=\"button\" variant=\"destructiveGhost\" className=\"rounded-full\" onClick={() => remove(index)}>\n\t\t\t\t\t\t\t\t<TrashIcon /> Remove Field\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t))}\n\n\t\t\t\t<Button\n\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"w-full\"\n\t\t\t\t\tonClick={addFieldClicked}\n\t\t\t\t>\n\t\t\t\t\t<Plus /> Add Another Field\n\t\t\t\t</Button>\n\n\t\t\t\t<hr className=\"my-6 border-gray-600\" />\n\n\t\t\t\t<FormField\n\t\t\t\t\tcontrol={control}\n\t\t\t\t\tname=\"databaseName\"\n\t\t\t\t\trender={({ field }) => <DatabaseName field={field} />}\n\t\t\t\t/>\n\t\t\t\t<FormField\n\t\t\t\t\tcontrol={control}\n\t\t\t\t\tname=\"expiration\"\n\t\t\t\t\trender={({ field }) => <OptionalExpiration field={field} />}\n\t\t\t\t/>\n\t\t\t\t<FormField\n\t\t\t\t\tcontrol={control}\n\t\t\t\t\tname=\"enableRest\"\n\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t<FormItem className=\"flex\">\n\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\tclassName=\"w-5\"\n\t\t\t\t\t\t\t\t\tchecked={field.value}\n\t\t\t\t\t\t\t\t\tonChange={(e) => field.onChange(e.target.checked)}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t<FormLabel className=\"flex-1 py-2.5\">\n\t\t\t\t\t\t\t\tMake available as a REST endpoint (add{' '}\n\t\t\t\t\t\t\t\t<code className=\"text-muted-foreground italic ml-1\">@export</code>)\n\t\t\t\t\t\t\t</FormLabel>\n\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t)}\n\t\t\t\t/>\n\t\t\t\t<FormField\n\t\t\t\t\tcontrol={control}\n\t\t\t\t\tname=\"sealed\"\n\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t<FormItem className=\"flex\">\n\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\tclassName=\"w-5\"\n\t\t\t\t\t\t\t\t\tchecked={field.value}\n\t\t\t\t\t\t\t\t\tonChange={(e) => field.onChange(e.target.checked)}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t<FormLabel className=\"flex-1 py-2.5\">\n\t\t\t\t\t\t\t\tSealed (add\n\t\t\t\t\t\t\t\t<code className=\"text-muted-foreground italic ml-1\">@sealed</code> to ignore unspecified properties)\n\t\t\t\t\t\t\t</FormLabel>\n\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t)}\n\t\t\t\t/>\n\n\t\t\t\t<div className=\"text-muted-foreground italic text-sm pb-2\">\n\t\t\t\t\tThere are even more directives available to you when editing your schema.graphql by hand! You can read more\n\t\t\t\t\tabout them{' '}\n\t\t\t\t\t<a\n\t\t\t\t\t\tclassName=\"underline\"\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\thref=\"https://docs.harperdb.io/docs/developers/applications/defining-schemas\"\n\t\t\t\t\t>\n\t\t\t\t\t\tin our documentation\n\t\t\t\t\t</a>.\n\t\t\t\t</div>\n\n\t\t\t\t<div className=\"flex w-full gap-4 sticky -bottom-6 pb-6 pt-4 bg-black\">\n\t\t\t\t\t<Button type=\"button\" variant=\"ghost\" className=\"w-full rounded-full\" onClick={closeModal}>\n\t\t\t\t\t\t<Ban /> Cancel\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"positive\"\n\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\tclassName=\"w-full rounded-full\"\n\t\t\t\t\t\tdisabled={!formState.isValid}\n\t\t\t\t\t>\n\t\t\t\t\t\t<PlusIcon /> New Table\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</form>\n\t\t</Form>\n\t);\n}\n","import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog';\nimport { NewTableForm } from '@/features/instance/applications/components/NewTableForm';\nimport { attemptToRestoreFocus } from '@/lib/attemptToRestoreFocus';\nimport { setWatchedValue, useWatchedValue } from '@/lib/events/watcher';\nimport { useCallback } from 'react';\n\nexport function NewTableModal() {\n\tconst { value: isModalOpen, trigger } = useWatchedValue('ShowNewTableModal', false);\n\n\tconst closeModal = useCallback(() => {\n\t\tsetWatchedValue('ShowNewTableModal', false);\n\t\tattemptToRestoreFocus(trigger);\n\t}, [trigger]);\n\n\treturn (\n\t\t<Dialog onOpenChange={closeModal} open={isModalOpen}>\n\t\t\t<DialogContent aria-describedby={undefined} className=\"text-white\">\n\t\t\t\t<DialogHeader>\n\t\t\t\t\t<DialogTitle>New Table</DialogTitle>\n\t\t\t\t\t<DialogDescription>\n\t\t\t\t\t\tCreating a table is the basis of a data-driven application and can immediately be used as RESTful endpoints.\n\t\t\t\t\t\tThis can also be configured as a caching table and extended and customized for specific endpoint behavior.\n\t\t\t\t\t</DialogDescription>\n\t\t\t\t</DialogHeader>\n\n\t\t\t\t<NewTableForm />\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { Button } from '@/components/ui/button';\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { useEditorView } from '@/features/instance/applications/hooks/useEditorView';\nimport { useDeployComponentMutation } from '@/integrations/api/instance/applications/deployComponent';\nimport { attemptToRestoreFocus } from '@/lib/attemptToRestoreFocus';\nimport { setWatchedValue, useWatchedValue } from '@/lib/events/watcher';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { RefreshCwIcon } from 'lucide-react';\nimport { useCallback, useEffect } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\n\nexport function RedeployApplicationModal() {\n\tconst { value: isModalOpen, trigger } = useWatchedValue('ShowRedeployApplicationModal', false);\n\n\tconst queryClient = useQueryClient();\n\tconst instanceParams = useInstanceClientIdParams();\n\n\tconst { openedEntry } = useEditorView();\n\tconst packageUrl = openedEntry?.package;\n\n\tconst { mutate: reDeployApplication, isPending } = useDeployComponentMutation();\n\n\tconst methods = useForm({\n\t\tdefaultValues: {\n\t\t\tapplicationUrl: packageUrl,\n\t\t\tinstallCommand: '',\n\t\t},\n\t});\n\n\tconst { control, handleSubmit, reset } = methods;\n\n\tuseEffect(() => {\n\t\treset({ applicationUrl: packageUrl });\n\t}, [reset, packageUrl]);\n\n\tconst closeModal = useCallback(() => {\n\t\tsetWatchedValue('ShowRedeployApplicationModal', false);\n\t\tattemptToRestoreFocus(trigger);\n\t\treset({ applicationUrl: packageUrl });\n\t}, [reset, packageUrl, trigger]);\n\n\tconst redeployPackage = useCallback((applicationUrl: string, installCommand: string | undefined) => {\n\t\tif (!openedEntry) {\n\t\t\treturn;\n\t\t}\n\t\tcloseModal();\n\n\t\tconst toastId = toast.loading('Redeploying...');\n\t\treDeployApplication({\n\t\t\tapplicationName: openedEntry.project,\n\t\t\tapplicationUrl,\n\t\t\tinstallCommand,\n\t\t\t...instanceParams,\n\t\t}, {\n\t\t\tonSuccess: () => {\n\t\t\t\ttoast.success(\n\t\t\t\t\t`Application ${openedEntry.project} redeployed successfully`,\n\t\t\t\t\t{\n\t\t\t\t\t\tid: toastId,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tvoid queryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: [instanceParams.entityId, 'get_components'],\n\t\t\t\t\trefetchType: 'active',\n\t\t\t\t});\n\t\t\t},\n\t\t\tonError: () => {\n\t\t\t\ttoast.dismiss(toastId);\n\t\t\t},\n\t\t});\n\t}, [reDeployApplication, openedEntry, instanceParams, queryClient, closeModal]);\n\n\tconst submitForm = ({ applicationUrl, installCommand }: {\n\t\tapplicationUrl: string | undefined;\n\t\tinstallCommand: string | undefined;\n\t}) => {\n\t\tif (applicationUrl) {\n\t\t\tredeployPackage(applicationUrl, installCommand);\n\t\t}\n\t};\n\n\treturn (\n\t\t<Dialog\n\t\t\tonOpenChange={closeModal}\n\t\t\topen={isModalOpen}\n\t\t>\n\t\t\t<DialogContent aria-describedby={undefined} className=\"text-white\">\n\t\t\t\t<DialogHeader>\n\t\t\t\t\t<DialogTitle>Redeploy Package</DialogTitle>\n\t\t\t\t\t<DialogDescription>Redeploy this package?</DialogDescription>\n\t\t\t\t</DialogHeader>\n\n\t\t\t\t<div>\n\t\t\t\t\t<Form {...methods}>\n\t\t\t\t\t\t<form\n\t\t\t\t\t\t\tid=\"instance-redeploy-app-form\"\n\t\t\t\t\t\t\tname=\"instance-redeploy-app-form\"\n\t\t\t\t\t\t\tclassName=\"flex flex-col w-full gap-4\"\n\t\t\t\t\t\t\tonSubmit={handleSubmit(submitForm)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\t\t\tname=\"applicationUrl\"\n\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Package Reference</FormLabel>\n\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\t\tautoFocus={true}\n\t\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\tcontrol={control}\n\t\t\t\t\t\t\t\tname=\"installCommand\"\n\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Install Command</FormLabel>\n\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\t\tplaceholder=\"npm install\"\n\t\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tvariant=\"positiveOutline\"\n\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\tclassName=\"w-full rounded-full\"\n\t\t\t\t\t\t\t\tdisabled={isPending}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<RefreshCwIcon /> Redeploy Application\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tvariant=\"ghostOutline\"\n\t\t\t\t\t\t\t\tclassName=\"w-full rounded-full\"\n\t\t\t\t\t\t\t\tonClick={closeModal}\n\t\t\t\t\t\t\t\tdisabled={isPending}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</form>\n\t\t\t\t\t</Form>\n\t\t\t\t</div>\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { joinPath } from '@/lib/string/paths/joinPath';\n\nexport function removeFileNameFromPath(path: string): string {\n\treturn joinPath(path.split('/').slice(0, -1));\n}\n","import { joinPath } from '@/lib/string/paths/joinPath';\nimport { removeFileNameFromPath } from '@/lib/string/paths/removeFileNameFromPath';\n\nexport function renameFileInPath(path: string, newFileName: string): string {\n\treturn joinPath(removeFileNameFromPath(path), newFileName);\n}\n","import { Button } from '@/components/ui/button';\nimport {\n\tDialog,\n\tDialogContent,\n\tDialogDescription,\n\tDialogFooter,\n\tDialogHeader,\n\tDialogTitle,\n} from '@/components/ui/dialog';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { isDirectory } from '@/features/instance/applications/context/isDirectory';\nimport { useEditorView } from '@/features/instance/applications/hooks/useEditorView';\nimport { useRenameFiles } from '@/features/instance/applications/hooks/useRenameFiles';\nimport { attemptToRestoreFocus } from '@/lib/attemptToRestoreFocus';\nimport { setWatchedValue, useWatchedValue } from '@/lib/events/watcher';\nimport { renameFileInPath } from '@/lib/string/paths/renameFileInPath';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { PencilIcon } from 'lucide-react';\nimport { useCallback, useEffect, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport z from 'zod';\n\nexport function RenameFileModal() {\n\tconst { value: isModalOpen, trigger } = useWatchedValue('ShowRenameFileModal', false);\n\n\tconst closeModal = useCallback(() => {\n\t\tsetWatchedValue('ShowRenameFileModal', false);\n\t\tattemptToRestoreFocus(trigger);\n\t}, [trigger]);\n\n\tconst { openedEntry, entryExists } = useEditorView();\n\tconst RenameFileSchema = z.object({\n\t\tname: z\n\t\t\t.string()\n\t\t\t.nonempty({ error: 'Please enter a valid name.' })\n\t\t\t.regex(/^[a-zA-Z0-9_\\- .]*$/, {\n\t\t\t\terror: 'Names can only contain letters, numbers, underscores, hyphens, periods, and spaces.',\n\t\t\t})\n\t\t\t.max(50, { error: 'Names cannot be longer than 50 characters.' })\n\t\t\t.trim()\n\t\t\t.refine((name) => name !== openedEntry?.name, {\n\t\t\t\terror: 'Please enter a new name.',\n\t\t\t}),\n\t});\n\tconst [isPending, setIsPending] = useState(false);\n\tconst renameFiles = useRenameFiles();\n\n\tconst form = useForm({\n\t\tresolver: zodResolver(RenameFileSchema),\n\t});\n\n\tuseEffect(() => {\n\t\tif (openedEntry?.name) {\n\t\t\tform.reset({ name: openedEntry?.name });\n\t\t}\n\t}, [form, openedEntry?.name]);\n\n\tconst submitForm = useCallback(async (data: z.infer<typeof RenameFileSchema>) => {\n\t\tif (!openedEntry) {\n\t\t\treturn;\n\t\t}\n\t\tconst to = renameFileInPath(openedEntry.path, data.name);\n\t\tif (entryExists(to)) {\n\t\t\ttoast.error(`${isDirectory(openedEntry) ? 'Directory' : 'File'} already exists!`, {\n\t\t\t\tdescription: to,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tsetIsPending(true);\n\t\tawait renameFiles([{ from: openedEntry.path, to }]);\n\t\tcloseModal();\n\t\tform.reset();\n\t\tsetIsPending(false);\n\t}, [closeModal, entryExists, form, openedEntry, renameFiles, setIsPending]);\n\n\tconst onCancelClick = useCallback(() => {\n\t\tcloseModal();\n\t\tform.reset();\n\t}, [closeModal, form]);\n\n\treturn (\n\t\t<Dialog onOpenChange={closeModal} open={isModalOpen}>\n\t\t\t<DialogContent aria-describedby={undefined} className=\"text-white\">\n\t\t\t\t<Form {...form}>\n\t\t\t\t\t<form\n\t\t\t\t\t\tid=\"instance-rename-app-file-form\"\n\t\t\t\t\t\tname=\"instance-rename-app-file-form\"\n\t\t\t\t\t\tonSubmit={form.handleSubmit(submitForm)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<DialogHeader>\n\t\t\t\t\t\t\t<DialogTitle>Rename File</DialogTitle>\n\t\t\t\t\t\t\t<DialogDescription>\n\t\t\t\t\t\t\t\t{openedEntry?.path}\n\t\t\t\t\t\t\t</DialogDescription>\n\t\t\t\t\t\t</DialogHeader>\n\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"name\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem className=\"my-2\">\n\t\t\t\t\t\t\t\t\t<FormLabel>Name</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\tdisabled={isPending}\n\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<DialogFooter>\n\t\t\t\t\t\t\t<div className=\"flex justify-between w-full\">\n\t\t\t\t\t\t\t\t<Button type=\"button\" variant=\"ghostOutline\" className=\"rounded-full\" onClick={onCancelClick}>\n\t\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tvariant=\"positiveOutline\"\n\t\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\t\tdisabled={isPending || !form.formState.isDirty || !form.formState.isValid}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<PencilIcon /> Rename\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</DialogFooter>\n\t\t\t\t\t</form>\n\t\t\t\t</Form>\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { useSessionToggler } from '@/hooks/useSessionToggler';\nimport { cx } from 'class-variance-authority';\nimport { ApplicationsSidebar } from './components/ApplicationsSidebar';\nimport { ContentActions } from './components/ContentActions';\nimport { ContentViewer } from './components/ContentViewer';\nimport { EditorViewProvider } from './context/EditorViewProvider';\nimport { AddDirectoryOrFileModal } from './modals/AddDirectoryOrFileModal';\nimport { DeleteDirectoryOrFileModal } from './modals/DeleteDirectoryOrFileModal';\nimport { DownloadApplicationModal } from './modals/DownloadApplicationModal';\nimport { NewTableModal } from './modals/NewTableModal';\nimport { RedeployApplicationModal } from './modals/RedeployApplicationModal';\nimport { RenameFileModal } from './modals/RenameFileModal';\n\nexport function ApplicationsEditor() {\n\tconst { toggle, toggled } = useSessionToggler('ApplicationsSidebarOpened', true);\n\n\treturn (\n\t\t<EditorViewProvider>\n\t\t\t<aside\n\t\t\t\tid=\"file-explorer-sidebar\"\n\t\t\t\tclassName={cx(\n\t\t\t\t\t'pt-[calc(--spacing(32))] w-56 fixed top-0 left-0 bottom-0 z-30',\n\t\t\t\t\t'bg-black-dark shadow shadow-black',\n\t\t\t\t\t'transition-transform -translate-x-full',\n\t\t\t\t\ttoggled ? 'translate-x-0' : 'md:translate-x-0',\n\t\t\t\t)}\n\t\t\t\taria-label=\"Sidebar\"\n\t\t\t>\n\t\t\t\t<ApplicationsSidebar />\n\t\t\t</aside>\n\n\t\t\t<div\n\t\t\t\tclassName={cx(\n\t\t\t\t\t'applications-content',\n\t\t\t\t\t'overflow-y-auto overflow-x-hidden',\n\t\t\t\t\t'fixed top-32 right-0 bottom-0 left-0',\n\t\t\t\t\t'transition-[left]',\n\t\t\t\t\t'md:left-56',\n\t\t\t\t\ttoggled && 'sm:left-56',\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<ContentViewer />\n\t\t\t\t<ContentActions toggledSidebar={toggled} toggleSidebar={toggle} />\n\t\t\t</div>\n\n\t\t\t<AddDirectoryOrFileModal />\n\t\t\t<NewTableModal />\n\t\t\t<DeleteDirectoryOrFileModal />\n\t\t\t<DownloadApplicationModal />\n\t\t\t<RedeployApplicationModal />\n\t\t\t<RenameFileModal />\n\t\t</EditorViewProvider>\n\t);\n}\n","import { ApplicationsEditor } from '@/features/instance/applications';\nimport { createInstanceLayoutRoute } from '@/features/instance/instanceLayoutRoute';\nimport { createRoute } from '@tanstack/react-router';\n\nexport function createApplicationsRoutes(instanceLayoutRoute: ReturnType<typeof createInstanceLayoutRoute>) {\n\tconst instanceApplicationsIndexRoute = createRoute({\n\t\tgetParentRoute: () => instanceLayoutRoute,\n\t\tpath: '/',\n\t\tcomponent: ApplicationsEditor,\n\t});\n\n\treturn [\n\t\tinstanceApplicationsIndexRoute,\n\t];\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport interface CertificateDetails {\n\tissuer: string;\n\tsubject: string;\n\tserial_number: string;\n\tvalid_from: string;\n\tvalid_to: string;\n\tsubject_alt_name?: string;\n}\n\nexport interface Certificate {\n\tname: string;\n\tcertificate: string;\n\tprivate_key_name?: string;\n\tis_authority: boolean;\n\tis_self_signed: boolean;\n\tuses: string[];\n\tdetails: CertificateDetails;\n\thosts?: string[];\n}\n\nasync function listCertificates({ instanceClient }: InstanceClientIdConfig) {\n\tconst { data } = await instanceClient.post<Certificate[]>('/', {\n\t\toperation: 'list_certificates',\n\t});\n\treturn data;\n}\n\nexport function listCertificatesQueryOptions(params: InstanceClientIdConfig) {\n\treturn queryOptions({\n\t\tqueryKey: [params.entityId, 'list_certificates'] as const,\n\t\tqueryFn: () => listCertificates(params),\n\t});\n}\n","import { Certificate } from '@/integrations/api/instance/certificates/listCertificates';\nimport { ColumnDef, createColumnHelper } from '@tanstack/react-table';\n\nconst columnHelper = createColumnHelper<Certificate>();\n\nexport const dataTableColumns: Array<ColumnDef<Certificate>> = [\n\t{\n\t\theader: 'Certificate Name',\n\t\taccessorKey: 'name',\n\t\tenableSorting: true,\n\t},\n\t{\n\t\theader: 'Issuer',\n\t\taccessorKey: 'details.issuer',\n\t\tenableSorting: true,\n\t},\n\tcolumnHelper.display({\n\t\theader: 'Expires At',\n\t\tenableSorting: false,\n\t\tid: 'details.valid_to',\n\t\tcell: (props) =>\n\t\t\tprops.row.original.details.valid_to ? new Date(props.row.original.details.valid_to).toLocaleString() : 'N/A',\n\t}),\n];\n","import { cn } from '@/lib/cn';\nimport * as SwitchPrimitive from '@radix-ui/react-switch';\nimport * as React from 'react';\n\nfunction Switch({\n\tclassName,\n\t...props\n}: React.ComponentProps<typeof SwitchPrimitive.Root>) {\n\treturn (\n\t\t<SwitchPrimitive.Root\n\t\t\tdata-slot=\"switch\"\n\t\t\tclassName={cn(\n\t\t\t\t'peer '\n\t\t\t\t\t+ 'data-[state=checked]:bg-green '\n\t\t\t\t\t+ 'data-[state=unchecked]:bg-input '\n\t\t\t\t\t+ 'focus-visible:border-ring '\n\t\t\t\t\t+ 'focus-visible:ring-ring/50 '\n\t\t\t\t\t+ 'dark:data-[state=unchecked]:bg-input/80 inline-flex '\n\t\t\t\t\t+ 'h-[1.15rem] w-8 shrink-0 '\n\t\t\t\t\t+ 'items-center rounded-full '\n\t\t\t\t\t+ 'border border-transparent '\n\t\t\t\t\t+ 'shadow-xs '\n\t\t\t\t\t+ 'transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<SwitchPrimitive.Thumb\n\t\t\t\tdata-slot=\"switch-thumb\"\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'bg-white dark:data-[state=unchecked]:bg-white dark:data-[state=checked]:bg-white '\n\t\t\t\t\t\t+ 'pointer-events-none '\n\t\t\t\t\t\t+ 'block size-4 rounded-full ring-0 '\n\t\t\t\t\t\t+ 'transition-transform '\n\t\t\t\t\t\t+ 'data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0',\n\t\t\t\t)}\n\t\t\t/>\n\t\t</SwitchPrimitive.Root>\n\t);\n}\n\nexport { Switch };\n","import { cn } from '@/lib/cn';\nimport * as React from 'react';\n\nexport function Textarea({ className, ...props }: React.ComponentProps<'textarea'>) {\n\treturn (\n\t\t<textarea\n\t\t\tdata-slot=\"input\"\n\t\t\tclassName={cn(\n\t\t\t\t`border-input file:text-foreground placeholder:text-muted-foreground selection:bg-purple\n selection:text-primary-foreground\n dark:aria-invalid:outline-destructive dark:aria-invalid:ring-destructive/50 ring-ring/10\n dark:ring-ring/20 dark:outline-ring/40 outline-ring/50 aria-invalid:outline-destructive/60\n aria-invalid:ring-destructive/20 aria-invalid:border-destructive/60 dark:aria-invalid:border-destructive\n flex w-full min-w-0 rounded-md border bg-grey-700 px-3 py-1 text-base text-white\n file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium\n focus-visible:ring-1 focus-visible:outline-none focus-visible:ring-purple disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50\n aria-invalid:focus-visible:ring-[1px] aria-invalid:focus-visible:outline-none md:text-sm dark:aria-invalid:focus-visible:ring-1`,\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\n\nexport interface AddCertificateParams {\n\tname: string;\n\tcertificate: string;\n\tprivate_key?: string;\n\tis_authority: boolean;\n\thosts?: string[];\n\tuses?: string[];\n}\n\nexport async function addCertificate({ instanceClient }: InstanceClientIdConfig, params: AddCertificateParams) {\n\tconst { data } = await instanceClient.post<{ message: string }>('/', {\n\t\toperation: 'add_certificate',\n\t\t...params,\n\t});\n\treturn data;\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { useMutation } from '@tanstack/react-query';\nimport { z } from 'zod';\nimport { addCertificate, AddCertificateParams } from './addCertificate';\n\nexport const CertificateSchema = z.object({\n\tname: z.string().min(1, 'Name is required'),\n\tcertificate: z.string().min(1, 'Certificate is required'),\n\tprivate_key: z.string().optional(),\n\tis_authority: z.boolean().default(false),\n\thosts: z.string().optional(),\n\tuses: z.string().optional(),\n});\n\nexport function useAddCertificate() {\n\treturn useMutation({\n\t\tmutationFn: ({\n\t\t\tinstanceParams,\n\t\t\tcertificateParams,\n\t\t}: {\n\t\t\tinstanceParams: InstanceClientIdConfig;\n\t\t\tcertificateParams: AddCertificateParams;\n\t\t}) => addCertificate(instanceParams, certificateParams),\n\t});\n}\n","import { Button } from '@/components/ui/button';\nimport {\n\tDialog,\n\tDialogContent,\n\tDialogDescription,\n\tDialogFooter,\n\tDialogHeader,\n\tDialogTitle,\n} from '@/components/ui/dialog';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormDescription } from '@/components/ui/form/FormDescription';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { Switch } from '@/components/ui/switch';\nimport { Textarea } from '@/components/ui/textarea';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { CertificateSchema, useAddCertificate } from '@/integrations/api/instance/certificates/useAddCertificate';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { Save } from 'lucide-react';\nimport { useCallback } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\n\nexport function AddCertificateModal({\n\tisModalOpen,\n\tonChangesSaved,\n\tsetIsModalOpen,\n}: {\n\tisModalOpen: boolean;\n\tonChangesSaved: () => void;\n\tsetIsModalOpen: (open: boolean) => void;\n}) {\n\tconst form = useForm({\n\t\tresolver: zodResolver(CertificateSchema),\n\t\tdefaultValues: {\n\t\t\tname: '',\n\t\t\tcertificate: '',\n\t\t\tprivate_key: '',\n\t\t\tis_authority: false,\n\t\t\thosts: '',\n\t\t\tuses: '',\n\t\t},\n\t});\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst { mutate: addCertificate, isPending } = useAddCertificate();\n\n\tconst onSubmitClick = useCallback(\n\t\tasync (formData: z.infer<typeof CertificateSchema>) => {\n\t\t\tconst { hosts, uses, private_key, ...rest } = formData;\n\t\t\tconst hostsArray = hosts\n\t\t\t\t? hosts\n\t\t\t\t\t.split(',')\n\t\t\t\t\t.map((h) => h.trim())\n\t\t\t\t\t.filter(Boolean)\n\t\t\t\t: undefined;\n\n\t\t\tconst usesArray = uses\n\t\t\t\t? uses\n\t\t\t\t\t.split(',')\n\t\t\t\t\t.map((u) => u.trim())\n\t\t\t\t\t.filter(Boolean)\n\t\t\t\t: undefined;\n\n\t\t\taddCertificate(\n\t\t\t\t{\n\t\t\t\t\tinstanceParams,\n\t\t\t\t\tcertificateParams: {\n\t\t\t\t\t\t...rest,\n\t\t\t\t\t\tprivate_key: private_key || undefined,\n\t\t\t\t\t\thosts: hostsArray && hostsArray.length > 0 ? hostsArray : undefined,\n\t\t\t\t\t\tuses: usesArray && usesArray.length > 0 ? usesArray : undefined,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tonSuccess: () => {\n\t\t\t\t\t\tform.reset();\n\t\t\t\t\t\tonChangesSaved();\n\t\t\t\t\t\ttoast.success('Certificate added successfully!');\n\t\t\t\t\t\tsetIsModalOpen(false);\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t\t[addCertificate, form, instanceParams, onChangesSaved, setIsModalOpen],\n\t);\n\n\tconst onClickCancel = useCallback(() => {\n\t\tform.reset();\n\t\tsetIsModalOpen(false);\n\t}, [form, setIsModalOpen]);\n\n\treturn (\n\t\t<Dialog onOpenChange={setIsModalOpen} open={isModalOpen}>\n\t\t\t<DialogContent aria-describedby={undefined}>\n\t\t\t\t<Form {...form}>\n\t\t\t\t\t<form\n\t\t\t\t\t\tid=\"instance-add-certificate-form\"\n\t\t\t\t\t\tname=\"instance-add-certificate-form\"\n\t\t\t\t\t\tonSubmit={form.handleSubmit(onSubmitClick)}\n\t\t\t\t\t\tclassName=\"grid gap-4 my-4\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<DialogHeader>\n\t\t\t\t\t\t\t<DialogTitle>Add New Certificate</DialogTitle>\n\t\t\t\t\t\t\t<DialogDescription>\n\t\t\t\t\t\t\t\tEnter the details of your Certificate below.\n\t\t\t\t\t\t\t</DialogDescription>\n\t\t\t\t\t\t</DialogHeader>\n\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"name\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Name</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoFocus={true}\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"is_authority\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem className=\"flex flex-row items-center justify-between rounded-lg border border-gray-800 p-3 shadow-sm\">\n\t\t\t\t\t\t\t\t\t<div className=\"space-y-0.5\">\n\t\t\t\t\t\t\t\t\t\t<FormLabel>Is Authority</FormLabel>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Switch\n\t\t\t\t\t\t\t\t\t\t\tchecked={field.value}\n\t\t\t\t\t\t\t\t\t\t\tonCheckedChange={field.onChange}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"certificate\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Certificate</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Textarea\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\t\t\trows={5}\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"hosts\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Hosts (optional)</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormDescription>\n\t\t\t\t\t\t\t\t\t\tComma-separated list of hostnames this certificate is valid for.\n\t\t\t\t\t\t\t\t\t</FormDescription>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tplaceholder=\"e.g. example.com, *.example.com\"\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"uses\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Uses (optional)</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormDescription>\n\t\t\t\t\t\t\t\t\t\tComma-separated list of intended uses, e.g. \"https, operations, wss\".\n\t\t\t\t\t\t\t\t\t</FormDescription>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tplaceholder=\"e.g. https, operations, wss\"\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"private_key\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Private Key (optional)</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormDescription>\n\t\t\t\t\t\t\t\t\t\tPEM formatted private key string.\n\t\t\t\t\t\t\t\t\t</FormDescription>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Textarea\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\t\t\trows={5}\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<DialogFooter>\n\t\t\t\t\t\t\t<div className=\"flex justify-between w-full\">\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tvariant=\"destructiveOutline\"\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\t\tonClick={onClickCancel}\n\t\t\t\t\t\t\t\t\tdisabled={isPending}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\t\tvariant=\"submit\"\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\t\tdisabled={isPending || !form.formState.isDirty || !form.formState.isValid}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Save /> Add Certificate\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</DialogFooter>\n\t\t\t\t\t</form>\n\t\t\t\t</Form>\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\n\nexport async function removeCertificate({ instanceClient }: InstanceClientIdConfig, name: string) {\n\tconst { data } = await instanceClient.post<{ message: string }>('/', {\n\t\toperation: 'remove_certificate',\n\t\tname,\n\t});\n\treturn data;\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { useMutation } from '@tanstack/react-query';\nimport { removeCertificate } from './removeCertificate';\n\nexport function useRemoveCertificate() {\n\treturn useMutation({\n\t\tmutationFn: ({ instanceParams, name }: { instanceParams: InstanceClientIdConfig; name: string }) =>\n\t\t\tremoveCertificate(instanceParams, name),\n\t});\n}\n","import { ConfirmDeletionModal } from '@/components/ConfirmDeletionModal';\nimport { Button } from '@/components/ui/button';\nimport {\n\tDialog,\n\tDialogContent,\n\tDialogDescription,\n\tDialogFooter,\n\tDialogHeader,\n\tDialogTitle,\n} from '@/components/ui/dialog';\nimport { Label } from '@/components/ui/label';\nimport { Textarea } from '@/components/ui/textarea';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { Certificate } from '@/integrations/api/instance/certificates/listCertificates';\nimport { useRemoveCertificate } from '@/integrations/api/instance/certificates/useRemoveCertificate';\nimport { Row } from '@tanstack/react-table';\nimport { useCallback, useState } from 'react';\nimport { toast } from 'sonner';\n\nexport function ViewCertificateModal({\n\tdata,\n\tisModalOpen,\n\tcloseModal,\n\tonSelectCertificate,\n\tonChangesSaved,\n}: {\n\tdata: Certificate;\n\tisModalOpen: boolean;\n\tcloseModal: () => void;\n\tonSelectCertificate: (row?: Row<Certificate>) => void;\n\tonChangesSaved: () => void;\n}) {\n\tconst { name } = data;\n\tconst instanceParams = useInstanceClientIdParams();\n\n\tconst { mutate: removeCertificate, isPending: isRemovePending } = useRemoveCertificate();\n\n\tconst [isConfirmRemoveModalOpen, setIsConfirmRemoveModalOpen] = useState(false);\n\n\tconst onCertificateRemoveClicked = useCallback(() => {\n\t\tsetIsConfirmRemoveModalOpen(true);\n\t}, []);\n\n\tconst onDeletionConfirmed = useCallback(() => {\n\t\tremoveCertificate(\n\t\t\t{\n\t\t\t\tinstanceParams,\n\t\t\t\tname,\n\t\t\t},\n\t\t\t{\n\t\t\t\tonSuccess: () => {\n\t\t\t\t\ttoast.success('Certificate removed successfully!');\n\t\t\t\t\tonSelectCertificate(undefined);\n\t\t\t\t\tonChangesSaved();\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}, [name, removeCertificate, instanceParams, onChangesSaved, onSelectCertificate]);\n\n\treturn (\n\t\t<>\n\t\t\t<Dialog onOpenChange={closeModal} open={isModalOpen}>\n\t\t\t\t<DialogContent className=\"sm:max-w-[800px] max-h-[90vh] overflow-y-auto\" aria-describedby={undefined}>\n\t\t\t\t\t<div className=\"grid gap-4 my-4\">\n\t\t\t\t\t\t<DialogHeader>\n\t\t\t\t\t\t\t<DialogTitle>View Certificate: {name}</DialogTitle>\n\t\t\t\t\t\t\t<DialogDescription>\n\t\t\t\t\t\t\t\tDetails of the selected certificate.\n\t\t\t\t\t\t\t</DialogDescription>\n\t\t\t\t\t\t</DialogHeader>\n\n\t\t\t\t\t\t<div className=\"space-y-4\">\n\t\t\t\t\t\t\t<div className=\"grid grid-cols-2 gap-4 text-sm bg-gray-900/50 p-4 rounded-lg border border-gray-800\">\n\t\t\t\t\t\t\t\t<div className=\"col-span-2\">\n\t\t\t\t\t\t\t\t\t<p className=\"font-semibold\">Issuer</p>\n\t\t\t\t\t\t\t\t\t<p className=\"text-gray-400 break-all\">{data.details.issuer || 'N/A'}</p>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"col-span-2\">\n\t\t\t\t\t\t\t\t\t<p className=\"font-semibold\">Subject</p>\n\t\t\t\t\t\t\t\t\t<p className=\"text-gray-400 break-all\">{data.details.subject || 'N/A'}</p>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t{data.details.subject_alt_name && (\n\t\t\t\t\t\t\t\t\t<div className=\"col-span-2\">\n\t\t\t\t\t\t\t\t\t\t<p className=\"font-semibold\">Subject Alternative Name</p>\n\t\t\t\t\t\t\t\t\t\t<p className=\"text-gray-400 break-all\">{data.details.subject_alt_name}</p>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t<p className=\"font-semibold\">Valid From</p>\n\t\t\t\t\t\t\t\t\t<p className=\"text-gray-400\">\n\t\t\t\t\t\t\t\t\t\t{data.details.valid_from ? new Date(data.details.valid_from).toLocaleString() : 'N/A'}\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t<p className=\"font-semibold\">Valid To (Expires At)</p>\n\t\t\t\t\t\t\t\t\t<p className=\"text-gray-400\">\n\t\t\t\t\t\t\t\t\t\t{data.details.valid_to ? new Date(data.details.valid_to).toLocaleString() : 'N/A'}\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t<p className=\"font-semibold\">Serial Number</p>\n\t\t\t\t\t\t\t\t\t<p className=\"text-gray-400 font-mono text-xs break-all\">{data.details.serial_number || 'N/A'}</p>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t<p className=\"font-semibold\">Private Key Name</p>\n\t\t\t\t\t\t\t\t\t<p className=\"text-gray-400\">{data.private_key_name || 'N/A'}</p>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t<p className=\"font-semibold\">Is Authority</p>\n\t\t\t\t\t\t\t\t\t<p className=\"text-gray-400\">{data.is_authority ? 'Yes' : 'No'}</p>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t<p className=\"font-semibold\">Is Self-Signed</p>\n\t\t\t\t\t\t\t\t\t<p className=\"text-gray-400\">{data.is_self_signed ? 'Yes' : 'No'}</p>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t{data.hosts && data.hosts.length > 0 && (\n\t\t\t\t\t\t\t\t\t<div className=\"col-span-2\">\n\t\t\t\t\t\t\t\t\t\t<p className=\"font-semibold\">Hosts</p>\n\t\t\t\t\t\t\t\t\t\t<p className=\"text-gray-400\">{data.hosts.join(', ')}</p>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t<div className=\"col-span-2\">\n\t\t\t\t\t\t\t\t\t<p className=\"font-semibold\">Uses</p>\n\t\t\t\t\t\t\t\t\t<p className=\"text-gray-400\">{data.uses?.join(', ') || 'N/A'}</p>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<div className=\"space-y-2\">\n\t\t\t\t\t\t\t\t<Label>Certificate Content</Label>\n\t\t\t\t\t\t\t\t<Textarea\n\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\trows={8}\n\t\t\t\t\t\t\t\t\treadOnly={true}\n\t\t\t\t\t\t\t\t\tclassName=\"font-mono text-xs\"\n\t\t\t\t\t\t\t\t\tvalue={data.certificate}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<DialogFooter>\n\t\t\t\t\t\t\t<div className=\"flex justify-between w-full\">\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tvariant=\"destructiveOutline\"\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\t\tonClick={onCertificateRemoveClicked}\n\t\t\t\t\t\t\t\t\tdisabled={isRemovePending}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tRemove Certificate\n\t\t\t\t\t\t\t\t</Button>\n\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tvariant=\"defaultOutline\"\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\t\tonClick={() => closeModal()}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tClose\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</DialogFooter>\n\t\t\t\t\t</div>\n\t\t\t\t</DialogContent>\n\t\t\t</Dialog>\n\t\t\t<ConfirmDeletionModal\n\t\t\t\tisModalOpen={isConfirmRemoveModalOpen}\n\t\t\t\tsetIsModalOpen={setIsConfirmRemoveModalOpen}\n\t\t\t\tdeletionConfirmed={onDeletionConfirmed}\n\t\t\t\tdeletionPending={isRemovePending}\n\t\t\t\ttypeOfThingBeingDeleted=\"certificate\"\n\t\t\t\tpresentParticiple=\"Removing\"\n\t\t\t\ttransitiveVerb=\"Remove\"\n\t\t\t\tnameOfThingBeingDeleted={name}\n\t\t\t\thideDataLossWarning={true}\n\t\t\t/>\n\t\t</>\n\t);\n}\n","import { SimpleBrowseDataTable } from '@/components/SimpleBrowseDataTable';\nimport { Button } from '@/components/ui/button';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { useRefreshClick } from '@/hooks/useRefreshClick';\nimport { Certificate, listCertificatesQueryOptions } from '@/integrations/api/instance/certificates/listCertificates';\nimport { useQuery } from '@tanstack/react-query';\nimport { Link, useNavigate, useParams } from '@tanstack/react-router';\nimport { Row } from '@tanstack/react-table';\nimport { PlusIcon, RefreshCwIcon } from 'lucide-react';\nimport { useCallback, useMemo, useState } from 'react';\nimport { dataTableColumns } from './constants/tableDefinition';\nimport { AddCertificateModal } from './modals/AddCertificateModal';\nimport { ViewCertificateModal } from './modals/ViewCertificateModal';\n\nexport function ConfigCertificatesIndex() {\n\tconst navigate = useNavigate();\n\tconst { certName }: { certName?: string } = useParams({ strict: false });\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst {\n\t\tdata: certificates,\n\t\trefetch,\n\t\tisFetching,\n\t\tisRefetching,\n\t} = useQuery(listCertificatesQueryOptions(instanceParams));\n\n\tconst selectedCertificate = useMemo(\n\t\t() => certificates?.find((cert) => cert.name === certName),\n\t\t[certificates, certName],\n\t);\n\n\tconst onSelectCertificate = useCallback(\n\t\t(row?: Row<Certificate>) => {\n\t\t\tconst newCertName = row?.original?.name;\n\t\t\tconst parts = [certName ? '..' : '', newCertName].filter(Boolean);\n\t\t\tvoid navigate({ to: parts.join('/') });\n\t\t},\n\t\t[certName, navigate],\n\t);\n\n\tconst isViewModalOpen = !!certName && !!selectedCertificate;\n\n\tconst [isAddModalOpen, setIsAddModalOpen] = useState(false);\n\n\tconst onAddClicked = useCallback(() => {\n\t\tsetIsAddModalOpen(true);\n\t}, [setIsAddModalOpen]);\n\n\tconst onRefreshClick = useRefreshClick(refetch);\n\n\treturn (\n\t\t<>\n\t\t\t<SimpleBrowseDataTable\n\t\t\t\tcolumns={dataTableColumns}\n\t\t\t\tdata={certificates || []}\n\t\t\t\tisFetching={isFetching}\n\t\t\t\tonRowClick={onSelectCertificate}\n\t\t\t>\n\t\t\t\t<Link\n\t\t\t\t\tclassName=\"inline-block underline text-sm text-gray-400 hover:text-white\"\n\t\t\t\t\tto=\"https://docs.harperdb.io/docs/developers/operations-api/certificate-management\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t>\n\t\t\t\t\tCertificate Management Docs\n\t\t\t\t</Link>\n\t\t\t\t<Button variant=\"defaultOutline\" onClick={onRefreshClick} accessKey=\"r\" disabled={isFetching || isRefetching}>\n\t\t\t\t\t<RefreshCwIcon />\n\t\t\t\t\t<span className=\"hidden lg:inline-block\">\n\t\t\t\t\t\t<u>R</u>efresh\n\t\t\t\t\t</span>\n\t\t\t\t</Button>\n\t\t\t\t<Button variant=\"positiveOutline\" onClick={onAddClicked} accessKey=\"a\" disabled={isAddModalOpen}>\n\t\t\t\t\t<PlusIcon />\n\t\t\t\t\t<span>\n\t\t\t\t\t\t<u>A</u>dd\n\t\t\t\t\t</span>\n\t\t\t\t</Button>\n\t\t\t</SimpleBrowseDataTable>\n\t\t\t{isAddModalOpen && (\n\t\t\t\t<AddCertificateModal\n\t\t\t\t\tisModalOpen={isAddModalOpen}\n\t\t\t\t\tonChangesSaved={refetch}\n\t\t\t\t\tsetIsModalOpen={setIsAddModalOpen}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t{isViewModalOpen && (\n\t\t\t\t<ViewCertificateModal\n\t\t\t\t\tisModalOpen={isViewModalOpen}\n\t\t\t\t\tcloseModal={onSelectCertificate}\n\t\t\t\t\tdata={selectedCertificate}\n\t\t\t\t\tonSelectCertificate={onSelectCertificate}\n\t\t\t\t\tonChangesSaved={refetch}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t);\n}\n","import { DomainsManagement } from '@/features/cluster/domains/Management';\n\nexport function ConfigDomainsIndex() {\n\treturn <DomainsManagement />;\n}\n","import { Loading } from '@/components/Loading';\nimport { isLocalStudio } from '@/config/constants';\nimport { getClusterInfoQueryOptions } from '@/features/cluster/queries/getClusterInfoQuery';\nimport { useInstanceManagePermission } from '@/hooks/usePermissions';\nimport { clusterIsSelfManaged } from '@/integrations/api/clusterIsSelfManaged';\nimport { RegistrationInfoResponse } from '@/integrations/api/instance/status/getRegistrationInfo';\nimport { wasAReleasedBeforeB } from '@/lib/string/wasAReleasedBeforeB';\nimport { buildAbsoluteLinkToPage } from '@/lib/urls/buildAbsoluteLinkToPage';\nimport { useQuery } from '@tanstack/react-query';\nimport { Link, Outlet, useLoaderData, useParams } from '@tanstack/react-router';\nimport { GlobeIcon, HandshakeIcon, KeyIcon, PieChartIcon, ShieldCheckIcon, UsersIcon } from 'lucide-react';\nimport { ReactNode, Suspense } from 'react';\n\nconst sharedClasses = 'flex items-center p-2 rounded-lg group';\nconst inactiveProps = { className: 'text-white hover:bg-gray-700' };\nconst activeProps = { className: 'text-black bg-white pointer-events-none cursor-default' };\n\nexport function ConfigIndex() {\n\tconst params: {\n\t\tclusterId?: string;\n\t\tinstanceId?: string;\n\t\torganizationId?: string;\n\t} = useParams({ strict: false });\n\tconst { version }: RegistrationInfoResponse = useLoaderData({ strict: false });\n\tconst certsAvailable = wasAReleasedBeforeB('4.6.0', version);\n\n\tconst { clusterId } = params;\n\tconst canManage = useInstanceManagePermission();\n\tconst { data: cluster } = useQuery(\n\t\tgetClusterInfoQueryOptions(clusterId, false),\n\t);\n\tconst isSelfManaged = cluster === undefined || clusterIsSelfManaged(cluster);\n\n\tconst children = canManage && (\n\t\t<>\n\t\t\t<li>\n\t\t\t\t<Link\n\t\t\t\t\tto={buildAbsoluteLinkToPage(params, 'config/users')}\n\t\t\t\t\tclassName={sharedClasses}\n\t\t\t\t\tinactiveProps={inactiveProps}\n\t\t\t\t\tactiveProps={activeProps}\n\t\t\t\t>\n\t\t\t\t\t<UsersIcon className=\"hidden md:inline-block\" /> <span className=\"ms-3\">Users</span>\n\t\t\t\t</Link>\n\t\t\t</li>\n\t\t\t<li>\n\t\t\t\t<Link\n\t\t\t\t\tto={buildAbsoluteLinkToPage(params, 'config/roles')}\n\t\t\t\t\tclassName={sharedClasses}\n\t\t\t\t\tinactiveProps={inactiveProps}\n\t\t\t\t\tactiveProps={activeProps}\n\t\t\t\t>\n\t\t\t\t\t<HandshakeIcon className=\"hidden md:inline-block\" /> <span className=\"ms-3\">Roles</span>\n\t\t\t\t</Link>\n\t\t\t</li>\n\t\t\t{certsAvailable && (\n\t\t\t\t<li>\n\t\t\t\t\t<Link\n\t\t\t\t\t\tto={buildAbsoluteLinkToPage(params, 'config/certificates')}\n\t\t\t\t\t\tclassName={sharedClasses}\n\t\t\t\t\t\tinactiveProps={inactiveProps}\n\t\t\t\t\t\tactiveProps={activeProps}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ShieldCheckIcon className=\"hidden md:inline-block\" /> <span className=\"ms-3\">Certificates</span>\n\t\t\t\t\t</Link>\n\t\t\t\t</li>\n\t\t\t)}\n\t\t\t{!isLocalStudio && !isSelfManaged && (\n\t\t\t\t<li>\n\t\t\t\t\t<Link\n\t\t\t\t\t\tto={buildAbsoluteLinkToPage(params, 'config/domains')}\n\t\t\t\t\t\tclassName={sharedClasses}\n\t\t\t\t\t\tinactiveProps={inactiveProps}\n\t\t\t\t\t\tactiveProps={activeProps}\n\t\t\t\t\t>\n\t\t\t\t\t\t<GlobeIcon className=\"hidden md:inline-block\" /> <span className=\"ms-3\">Domains</span>\n\t\t\t\t\t</Link>\n\t\t\t\t</li>\n\t\t\t)}\n\t\t\t{certsAvailable && (\n\t\t\t\t<li>\n\t\t\t\t\t<Link\n\t\t\t\t\t\tto={buildAbsoluteLinkToPage(params, 'config/ssh-keys')}\n\t\t\t\t\t\tclassName={sharedClasses}\n\t\t\t\t\t\tinactiveProps={inactiveProps}\n\t\t\t\t\t\tactiveProps={activeProps}\n\t\t\t\t\t>\n\t\t\t\t\t\t<KeyIcon className=\"hidden md:inline-block\" /> <span className=\"ms-3\">SSH Keys</span>\n\t\t\t\t\t</Link>\n\t\t\t\t</li>\n\t\t\t)}\n\t\t</>\n\t);\n\n\treturn (\n\t\t<div className=\"md:grid gap-4 md:grid-cols-12 min-h-[calc(100vh-(--spacing(36)))]\">\n\t\t\t<section className=\"col-span-1 text-white md:col-span-4 lg:col-span-3 md:border-r border-b md:border-b-0 md:pr-4 border-gray-700\">\n\t\t\t\t<DesktopConfigNavBar params={params}>{children}</DesktopConfigNavBar>\n\t\t\t\t<MobileConfigNavBar params={params}>{children}</MobileConfigNavBar>\n\t\t\t</section>\n\t\t\t<section className=\"col-span-1 text-white md:col-span-8 lg:col-span-9 md:pt-4\">\n\t\t\t\t<Suspense fallback={<Loading className=\"flex flex-col items-center justify-center h-full\" text=\"Loading...\" />}>\n\t\t\t\t\t<Outlet />\n\t\t\t\t</Suspense>\n\t\t\t</section>\n\t\t</div>\n\t);\n}\n\nfunction DesktopConfigNavBar({ params, children }: {\n\tparams: {\n\t\tclusterId?: string;\n\t\tinstanceId?: string;\n\t\torganizationId?: string;\n\t};\n\tchildren: ReactNode;\n}) {\n\treturn (\n\t\t<div className=\"hidden md:block pl-4 pt-4\">\n\t\t\t<Link\n\t\t\t\tto={buildAbsoluteLinkToPage(params, 'config')}\n\t\t\t\tclassName={sharedClasses}\n\t\t\t\tactiveOptions={{ exact: true }}\n\t\t\t\tinactiveProps={inactiveProps}\n\t\t\t\tactiveProps={activeProps}\n\t\t\t>\n\t\t\t\t<PieChartIcon className=\"hidden md:inline-block\" /> <span className=\"ms-3\">Overview</span>\n\t\t\t</Link>\n\n\t\t\t{children && (\n\t\t\t\t<ul className=\"border-t border-gray-700 pt-4 mt-4 space-y-2\">\n\t\t\t\t\t{children}\n\t\t\t\t</ul>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nfunction MobileConfigNavBar({ params, children }: {\n\tparams: {\n\t\tclusterId?: string;\n\t\tinstanceId?: string;\n\t\torganizationId?: string;\n\t};\n\tchildren: ReactNode;\n}) {\n\treturn (\n\t\t<ul className=\"flex space-x-2 md:hidden py-2 px-4\">\n\t\t\t<li>\n\t\t\t\t<Link\n\t\t\t\t\tto={buildAbsoluteLinkToPage(params, 'config')}\n\t\t\t\t\tclassName={sharedClasses}\n\t\t\t\t\tactiveOptions={{ exact: true }}\n\t\t\t\t\tinactiveProps={inactiveProps}\n\t\t\t\t\tactiveProps={activeProps}\n\t\t\t\t>\n\t\t\t\t\t<PieChartIcon className=\"hidden md:inline-block\" /> <span className=\"ms-3\">Overview</span>\n\t\t\t\t</Link>\n\t\t\t</li>\n\t\t\t{children}\n\t\t</ul>\n\t);\n}\n","import { isLocalStudio } from '@/config/constants';\nimport { queryOptions } from '@tanstack/react-query';\nimport { getClusterInfo } from './getClusterInfoQuery';\n\ninterface GetInstanceInfoParams {\n\tclusterId?: string;\n\tinstanceId?: string;\n}\n\nasync function getInstanceInfo({ clusterId, instanceId }: GetInstanceInfoParams) {\n\tif (isLocalStudio) {\n\t\treturn null;\n\t}\n\tif (!clusterId) {\n\t\tthrow new Error('clusterId is required when outside of local mode and calling getInstanceInfo');\n\t}\n\tconst cluster = await getClusterInfo(clusterId);\n\tif (!cluster) {\n\t\treturn null;\n\t}\n\tconst instance = cluster.instances?.find(instance => instanceId === undefined || instance.id === instanceId);\n\tif (!instance) {\n\t\treturn null;\n\t}\n\treturn { cluster, instance };\n}\n\nexport function getInstanceInfoQueryOptions(params: GetInstanceInfoParams) {\n\treturn queryOptions({\n\t\tqueryKey: [params.clusterId, params.instanceId] as const,\n\t\tqueryFn: () => getInstanceInfo(params),\n\t\tretry: false,\n\t});\n}\n","import { TextLoadingSkeleton } from '@/components/TextLoadingSkeleton';\nimport { RegistrationInfoResponse } from '@/integrations/api/instance/status/getRegistrationInfo';\n\nexport const HarperVersion = ({\n\tloadingRegistration,\n\tregistrationInfo,\n}: {\n\tloadingRegistration?: boolean;\n\tregistrationInfo?: RegistrationInfoResponse;\n}) => {\n\tconst link = !!registrationInfo?.version\n\t\t&& parseInt(registrationInfo.version[0], 10) >= 5\n\t\t&& `https://github.com/HarperFast/harper/releases/tag/v${registrationInfo.version}`;\n\treturn (\n\t\t<>\n\t\t\t<dt className=\"font-bold text-sm/6\">Harper Version</dt>\n\t\t\t<dd className=\"text-sm/6 sm:mt-2\">\n\t\t\t\t{loadingRegistration\n\t\t\t\t\t? <TextLoadingSkeleton className=\"w-10\" />\n\t\t\t\t\t: link\n\t\t\t\t\t? (\n\t\t\t\t\t\t<a href={link} target=\"_blank\" className=\"underline hover:text-blue-300\" rel=\"noopener noreferrer\">\n\t\t\t\t\t\t\t{registrationInfo.version}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t)\n\t\t\t\t\t: registrationInfo?.version || 'Unknown'}\n\t\t\t</dd>\n\t\t</>\n\t);\n};\n","import { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { ReplicatedResponse } from '@/integrations/api/replication';\n\ninterface SetConfigurationParams extends InstanceClientConfig {\n\t[key: string]: unknown;\n}\n\nexport async function setConfiguration({\n\tinstanceClient,\n\t...changes\n}: SetConfigurationParams): Promise<ReplicatedResponse> {\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation: 'set_configuration',\n\t\t...changes,\n\t});\n\treturn data;\n}\n","import { ProgressBar } from '@/components/ProgressBar';\nimport { getInstanceClient } from '@/config/getInstanceClient';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { authStore } from '@/features/auth/store/authStore';\nimport { getClusterInfo } from '@/features/cluster/queries/getClusterInfoQuery';\nimport { Instance } from '@/integrations/api/api.patch';\nimport { getInstanceUserInfo } from '@/integrations/api/instance/status/getInstanceUserInfo';\nimport { restartInstance } from '@/integrations/api/instance/status/restartInstance';\nimport { setConfiguration } from '@/integrations/api/instance/status/setConfiguration';\nimport { excludeFalsy } from '@/lib/arrays/excludeFalsy';\nimport { pluralize } from '@/lib/pluralize';\nimport { sleep } from '@/lib/sleep';\nimport { getOperationsUrlForInstance } from '@/lib/urls/getOperationsUrlForInstance';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useCallback, useState } from 'react';\nimport { toast } from 'sonner';\n\ninterface RollingConfigUpdateParams {\n\tonRestartedSuccessfully?: () => void;\n}\n\ninterface RollingConfigUpdateResponse {\n\tonConfigUpdate: (params: Record<string, unknown>) => void;\n\tisPending: boolean;\n}\n\nexport function useRollingConfigUpdate(\n\t{ onRestartedSuccessfully }: RollingConfigUpdateParams = {},\n): RollingConfigUpdateResponse {\n\tconst operationsParams = useInstanceClientIdParams();\n\tconst queryClient = useQueryClient();\n\tconst [isPending, setIsPending] = useState(false);\n\tconst onConfigUpdate = useCallback(async (params: Record<string, unknown>) => {\n\t\tsetIsPending(true);\n\n\t\tlet canceled = false;\n\t\tconst toastConfig = {\n\t\t\tduration: 60_000,\n\t\t\taction: {\n\t\t\t\tlabel: 'Cancel',\n\t\t\t\tonClick: () => {\n\t\t\t\t\tcanceled = true;\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\n\t\tconst toastId = toast.loading('Restarting', {\n\t\t\t...toastConfig,\n\t\t\tdescription: (\n\t\t\t\t<ProgressBar\n\t\t\t\t\tanimated={true}\n\t\t\t\t\twidth=\"0%\"\n\t\t\t\t/>\n\t\t\t),\n\t\t});\n\n\t\tconst cluster = operationsParams.entityType === 'cluster'\n\t\t\t? await getClusterInfo(operationsParams.entityId)\n\t\t\t: null;\n\t\tconst allInstances = operationsParams.entityType === 'cluster'\n\t\t\t? cluster?.instances || []\n\t\t\t: [{ id: operationsParams.entityId, status: 'RUNNING' } as Instance];\n\t\tconst clusterUsesFabricConnect = !!cluster && authStore.checkForFabricConnect(cluster.id);\n\t\tconst instanceClients = operationsParams.entityType === 'cluster'\n\t\t\t? allInstances\n\t\t\t\t.filter(instance => instance.status === 'RUNNING')\n\t\t\t\t.map(instance =>\n\t\t\t\t\tgetInstanceClient({\n\t\t\t\t\t\tid: instance.id,\n\t\t\t\t\t\tforceFabricConnect: clusterUsesFabricConnect,\n\t\t\t\t\t\toperationsUrl: getOperationsUrlForInstance(instance),\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t\t\t.reverse()\n\t\t\t: [operationsParams.instanceClient];\n\t\tlet instancesRestarted = 0;\n\n\t\tif (instanceClients.length) {\n\t\t\tfor (let i = 0; i < instanceClients.length; i++) {\n\t\t\t\tconst instanceClient = instanceClients[i];\n\t\t\t\tif (!canceled) {\n\t\t\t\t\ttoast.loading(`Updating Instance ${i + 1} of ${instanceClients.length}`, {\n\t\t\t\t\t\t...toastConfig,\n\t\t\t\t\t\tid: toastId,\n\t\t\t\t\t\tdescription: (\n\t\t\t\t\t\t\t<ProgressBar\n\t\t\t\t\t\t\t\tanimated={true}\n\t\t\t\t\t\t\t\twidth={(i === 0 ? 0 : (i / instanceClients.length * 100)) + '%'}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t});\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Make sure the instance is responding.\n\t\t\t\t\t\tawait getInstanceUserInfo({\n\t\t\t\t\t\t\tinstanceClient,\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tawait setConfiguration({\n\t\t\t\t\t\t\t...params,\n\t\t\t\t\t\t\tinstanceClient,\n\t\t\t\t\t\t});\n\t\t\t\t\t\t// Then restart it.\n\t\t\t\t\t\tawait restartInstance({\n\t\t\t\t\t\t\toperation: 'restart_service',\n\t\t\t\t\t\t\treplicated: false,\n\t\t\t\t\t\t\tinstanceClient,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tinstancesRestarted += 1;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tif (i + 1 !== instanceClients.length) {\n\t\t\t\t\t\t\t// If it fails to restart, or wasn't available, warn for a bit then move on.\n\t\t\t\t\t\t\ttoast.loading(`Failed Restarting Instance ${i + 1} of ${instanceClients.length}`, {\n\t\t\t\t\t\t\t\t...toastConfig,\n\t\t\t\t\t\t\t\tid: toastId,\n\t\t\t\t\t\t\t\tdescription: 'We will carry on momentarily.',\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tawait sleep(3000);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsetIsPending(false);\n\t\tvoid queryClient.invalidateQueries({ queryKey: [operationsParams.entityId, 'get_configuration'] });\n\n\t\tif (canceled) {\n\t\t\ttoast.error('Cancelled', {\n\t\t\t\tid: toastId,\n\t\t\t\tdescription: `The config update was partially cancelled.`,\n\t\t\t\tduration: 10_000,\n\t\t\t\taction: {\n\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t},\n\t\t\t});\n\t\t} else if (allInstances.length === instancesRestarted) {\n\t\t\tonRestartedSuccessfully?.();\n\t\t\ttoast.success('Success', {\n\t\t\t\tid: toastId,\n\t\t\t\tdescription: `Your configuration has been updated successfully!`,\n\t\t\t\tduration: 10_000,\n\t\t\t\taction: {\n\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t},\n\t\t\t});\n\t\t} else {\n\t\t\tconst allTheInstances = pluralize(allInstances.length, 'instance', 'instances');\n\t\t\tconst someRunningInstancesWere = pluralize(\n\t\t\t\tinstancesRestarted,\n\t\t\t\t'\"RUNNING\" instance was',\n\t\t\t\t'\"RUNNING\" instances were',\n\t\t\t);\n\t\t\ttoast.error('Error', {\n\t\t\t\tid: toastId,\n\t\t\t\tdescription: `Failed to fully update cluster.\\n`\n\t\t\t\t\t+ ([\n\t\t\t\t\t\tallInstances.length === 0 && 'No instances were found within the cluster to restart.',\n\t\t\t\t\t\tinstancesRestarted === 0 && `No instances were in a \"RUNNING\" state of ${allTheInstances}.`,\n\t\t\t\t\t\tallInstances.length !== instancesRestarted\n\t\t\t\t\t\t&& `Only ${someRunningInstancesWere} restarted of ${allTheInstances}.`,\n\t\t\t\t\t].filter(excludeFalsy).shift() || ''),\n\t\t\t\tduration: 10_000,\n\t\t\t\taction: {\n\t\t\t\t\tlabel: 'Dismiss',\n\t\t\t\t\tonClick: () => toast.dismiss(),\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}, [operationsParams, onRestartedSuccessfully, queryClient]);\n\n\treturn {\n\t\tonConfigUpdate,\n\t\tisPending,\n\t};\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { queryOptions } from '@tanstack/react-query';\n\ninterface ConfigurationInfoResponse {\n\tlicense_expiration_date: string;\n\tram_allocation: number;\n\tregistered: boolean;\n\tversion: string;\n\thttp: {\n\t\tport: number | null;\n\t\tsecurePort: number | null;\n\t\tcors: boolean;\n\t\tcorsAccessList: string[];\n\t};\n}\n\nexport function getConfigurationQueryOptions({ entityId, instanceClient }: InstanceClientIdConfig) {\n\treturn queryOptions({\n\t\tqueryKey: [entityId, 'get_configuration'] as const,\n\t\tqueryFn: async () => {\n\t\t\tconst { data } = await instanceClient.post('/', {\n\t\t\t\toperation: 'get_configuration',\n\t\t\t});\n\t\t\treturn data as ConfigurationInfoResponse;\n\t\t},\n\t});\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport interface RegistrationInfoResponse {\n\tversion: string;\n}\n\nexport function getRegistrationInfoQueryOptions({ entityId, instanceClient }: InstanceClientIdConfig) {\n\treturn queryOptions({\n\t\tqueryKey: [entityId, 'registration_info'] as const,\n\t\tstaleTime: 60_000,\n\t\tgcTime: 5_000,\n\t\tqueryFn: async () => {\n\t\t\tconst { data } = await instanceClient.post('/', {\n\t\t\t\toperation: 'registration_info',\n\t\t\t});\n\t\t\treturn data as RegistrationInfoResponse;\n\t\t},\n\t});\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { queryOptions } from '@tanstack/react-query';\n\ninterface UsageLicense {\n\tid: string;\n\tlevel: string;\n\tregion: string;\n\treads: string;\n\twrites: string;\n\treadBytes: string;\n\twriteBytes: string;\n\trealTimeMessages: string;\n\trealTimeBytes: string;\n\tcpuTime: string;\n\tstorage: string;\n\tusedReads: string;\n\tusedWrites: string;\n\tusedReadBytes: string;\n\tusedWriteBytes: string;\n\tusedRealTimeMessages: string;\n\tusedRealTimeBytes: string;\n\tusedCpuTime: string;\n\tusedStorage: string;\n\texpiration: string;\n\tautoRenew: string;\n\t__createdtime__: string;\n\t__updatedtime__: string;\n}\n\nexport function getUsageLicensesQueryOptions({ entityId, instanceClient }: InstanceClientIdConfig, enabled: boolean) {\n\treturn queryOptions({\n\t\tqueryKey: [entityId, 'get_usage_licenses'] as const,\n\t\tenabled,\n\t\tqueryFn: async () => {\n\t\t\ttry {\n\t\t\t\tconst { data } = await instanceClient.post<UsageLicense[]>('/', {\n\t\t\t\t\toperation: 'get_usage_licenses',\n\t\t\t\t});\n\t\t\t\treturn data;\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(err);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\t});\n}\n","export const RESTRICTED_CONFIG: Record<string, any> = {\n\thttp: {\n\t\tport: 'blocked',\n\t\tsecurePort: 'blocked',\n\t},\n\tthreads: 'blocked',\n\tauthentication: {\n\t\tenableSessions: 'blocked',\n\t},\n\tlogging: {\n\t\tauditLog: 'blocked',\n\t\troot: 'blocked',\n\t\trotation: {\n\t\t\tpath: 'blocked',\n\t\t},\n\t},\n\tmqtt: {\n\t\tnetwork: {\n\t\t\tport: 'blocked',\n\t\t\tsecurePort: 'blocked',\n\t\t},\n\t},\n\toperationsApi: {\n\t\tnetwork: {\n\t\t\tdomainSocket: 'blocked',\n\t\t\tport: 'blocked',\n\t\t\tsecurePort: 'blocked',\n\t\t},\n\t},\n\trootPath: 'blocked',\n\treplication: 'blocked_except_databases',\n\tstorage: 'blocked',\n\ttls: 'blocked',\n\tnode: 'blocked',\n\tlicense: 'blocked',\n\tcomponentsRoot: 'blocked',\n\tanalytics: 'allowed',\n\tapplications: 'allowed',\n\tlocalStudio: 'allowed',\n};\n\nexport function isRestrictedConfigPath(path: string, value: any, originalValue: any): boolean {\n\t// If value hasn't changed, it's not \"blocked\" from staying the same\n\tif (JSON.stringify(value) === JSON.stringify(originalValue)) {\n\t\treturn false;\n\t}\n\n\tconst parts = path.split('.');\n\tlet current: any = RESTRICTED_CONFIG;\n\n\tfor (let i = 0; i < parts.length; i++) {\n\t\tconst part = parts[i];\n\t\tif (current === 'blocked') { return true; }\n\t\tif (current === 'blocked_except_databases') {\n\t\t\treturn part !== 'databases';\n\t\t}\n\t\tif (typeof current === 'object' && current !== null && part in current) {\n\t\t\tcurrent = current[part];\n\t\t} else {\n\t\t\t// Not in RESTRICTED_CONFIG, so it's allowed\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn current === 'blocked';\n}\n\nexport function omitRestrictedFields(obj: any, schema: any = RESTRICTED_CONFIG): any {\n\tif (typeof obj !== 'object' || obj === null) { return obj; }\n\n\tconst result = Array.isArray(obj) ? [] : {};\n\n\tfor (const key in obj) {\n\t\tconst value = obj[key];\n\t\tconst restriction = schema?.[key];\n\n\t\tif (restriction === 'blocked') {\n\t\t\tcontinue;\n\t\t} else if (restriction === 'blocked_except_databases') {\n\t\t\tif (value && typeof value === 'object' && 'databases' in value) {\n\t\t\t\t(result as any).replication = { databases: value.databases };\n\t\t\t}\n\t\t\tcontinue;\n\t\t} else if (typeof restriction === 'object' && restriction !== null) {\n\t\t\tconst sanitized = omitRestrictedFields(value, restriction);\n\t\t\tif (sanitized !== undefined && (typeof sanitized !== 'object' || Object.keys(sanitized).length > 0)) {\n\t\t\t\t(result as any)[key] = sanitized;\n\t\t\t}\n\t\t} else {\n\t\t\t(result as any)[key] = value;\n\t\t}\n\t}\n\n\treturn result;\n}\n\nexport function getChangedFields(original: any, edited: any): any {\n\tif (typeof original !== 'object' || original === null || typeof edited !== 'object' || edited === null) {\n\t\treturn JSON.stringify(original) !== JSON.stringify(edited) ? edited : undefined;\n\t}\n\n\tconst changes: any = {};\n\tconst allKeys = new Set([...Object.keys(original), ...Object.keys(edited)]);\n\n\tfor (const key of allKeys) {\n\t\tconst val1 = original[key];\n\t\tconst val2 = edited[key];\n\n\t\tif (\n\t\t\tval1 !== null && typeof val1 === 'object' && val2 !== null && typeof val2 === 'object' && !Array.isArray(val1)\n\t\t\t&& !Array.isArray(val2)\n\t\t) {\n\t\t\tconst nestedChanges = getChangedFields(val1, val2);\n\t\t\tif (Object.keys(nestedChanges).length > 0) {\n\t\t\t\tchanges[key] = nestedChanges;\n\t\t\t}\n\t\t} else if (JSON.stringify(val1) !== JSON.stringify(val2)) {\n\t\t\tchanges[key] = val2;\n\t\t}\n\t}\n\n\treturn changes;\n}\n\nexport function flattenConfig(obj: any, prefix = ''): Record<string, any> {\n\tconst result: Record<string, any> = {};\n\n\tfor (const key in obj) {\n\t\tconst value = obj[key];\n\t\tconst newKey = prefix ? `${prefix}_${key}` : key;\n\n\t\tif (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n\t\t\tObject.assign(result, flattenConfig(value, newKey));\n\t\t} else {\n\t\t\tresult[newKey] = value;\n\t\t}\n\t}\n\n\treturn result;\n}\n","import { ApplyLicensesButton } from '@/components/ApplyLicensesButton';\nimport { RestartButton } from '@/components/RestartButton';\nimport { TextLoadingSkeleton } from '@/components/TextLoadingSkeleton';\nimport { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';\nimport { Button } from '@/components/ui/button';\nimport { isLocalStudio } from '@/config/constants';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { getInstanceInfoQueryOptions } from '@/features/cluster/queries/getInstanceInfoQuery';\nimport { ApplicationURL } from '@/features/instance/config/overview/components/ApplicationURL';\nimport { ClusterDomainsList } from '@/features/instance/config/overview/components/ClusterDomainsList';\nimport { HarperVersion } from '@/features/instance/config/overview/components/HarperVersion';\nimport { InstanceNodeName } from '@/features/instance/config/overview/components/InstanceNodeName';\nimport { InstanceURL } from '@/features/instance/config/overview/components/InstanceURL';\nimport { useRollingConfigUpdate } from '@/hooks/useRollingConfigUpdate';\nimport { getConfigurationQueryOptions } from '@/integrations/api/instance/status/getConfiguration';\nimport {\n\tgetRegistrationInfoQueryOptions,\n\tRegistrationInfoResponse,\n} from '@/integrations/api/instance/status/getRegistrationInfo';\nimport { getUsageLicensesQueryOptions } from '@/integrations/api/instance/status/getUsageLicenses';\nimport { keyBy } from '@/lib/keyBy';\nimport { wasAReleasedBeforeB } from '@/lib/string/wasAReleasedBeforeB';\nimport Editor from '@monaco-editor/react';\nimport { useQuery } from '@tanstack/react-query';\nimport { useLoaderData, useParams } from '@tanstack/react-router';\nimport { AlertCircleIcon, EditIcon, SaveIcon, XIcon } from 'lucide-react';\nimport { ReactNode, useCallback, useEffect, useMemo, useState } from 'react';\nimport { flattenConfig, getChangedFields, isRestrictedConfigPath, omitRestrictedFields } from './configRestrictions';\n\nconst LocalStudioOverview = ({ children }: { children: ReactNode }) => {\n\treturn <>{children}</>;\n};\n\nconst CloudStudioOverview = ({ children }: { children: ReactNode }) => {\n\treturn <>{children}</>;\n};\n\nexport function ConfigOverviewIndex() {\n\tconst { clusterId, instanceId }: { instanceId?: string; clusterId?: string } = useParams({ strict: false });\n\tconst { data: info, isLoading: loadingInstanceInfo } = useQuery(\n\t\tgetInstanceInfoQueryOptions({ clusterId, instanceId }),\n\t);\n\tconst targetNoun = (instanceId || isLocalStudio) ? 'Instance' : 'Cluster';\n\tconst instanceParams = useInstanceClientIdParams();\n\n\tconst { version }: RegistrationInfoResponse = useLoaderData({ strict: false });\n\tconst checkUsageLicenses = !isLocalStudio && wasAReleasedBeforeB('4.7.0-alpha.1', version);\n\n\tconst { data: appliedLicenses } = useQuery(\n\t\tgetUsageLicensesQueryOptions(instanceParams, checkUsageLicenses),\n\t);\n\tconst clusterInfo = info?.cluster;\n\tconst instanceInfo = info?.instance;\n\tconst { data: registrationInfo, isLoading: loadingRegistration } = useQuery(\n\t\tgetRegistrationInfoQueryOptions(instanceParams),\n\t);\n\tconst { data: configurationInfo, isLoading: loadingConfig } = useQuery(\n\t\tgetConfigurationQueryOptions(instanceParams),\n\t);\n\n\tconst sanitizedConfigInfo = useMemo(() => {\n\t\tif (!configurationInfo) { return null; }\n\t\treturn omitRestrictedFields(configurationInfo);\n\t}, [configurationInfo]);\n\n\tconst [isEditing, setIsEditing] = useState(false);\n\tconst [editedConfig, setEditedConfig] = useState<string>('');\n\tconst [jsonError, setJsonError] = useState<string | null>(null);\n\tconst [restrictedError, setRestrictedError] = useState<string[]>([]);\n\n\tconst { onConfigUpdate, isPending: isSaving } = useRollingConfigUpdate();\n\n\tuseEffect(() => {\n\t\tif (sanitizedConfigInfo && !isEditing) {\n\t\t\tsetEditedConfig(JSON.stringify(sanitizedConfigInfo, null, 4));\n\t\t\tsetJsonError(null);\n\t\t\tsetRestrictedError([]);\n\t\t}\n\t}, [sanitizedConfigInfo, isEditing]);\n\n\tconst handleEditorChange = useCallback((value: string | undefined) => {\n\t\tsetEditedConfig(value || '');\n\t\tif (value) {\n\t\t\ttry {\n\t\t\t\tconst parsed = JSON.parse(value);\n\t\t\t\tsetJsonError(null);\n\n\t\t\t\tconst blockedFields: string[] = [];\n\t\t\t\tconst checkBlocked = (obj: any, orig: any, path = '') => {\n\t\t\t\t\tfor (const key in obj) {\n\t\t\t\t\t\tconst currentPath = path ? `${path}.${key}` : key;\n\t\t\t\t\t\tconst val = obj[key];\n\t\t\t\t\t\tconst origVal = orig?.[key];\n\n\t\t\t\t\t\tif (isRestrictedConfigPath(currentPath, val, origVal)) {\n\t\t\t\t\t\t\tblockedFields.push(currentPath);\n\t\t\t\t\t\t} else if (typeof val === 'object' && val !== null && !Array.isArray(val)) {\n\t\t\t\t\t\t\tcheckBlocked(val, origVal, currentPath);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// Also check for deleted keys if they were blocked\n\t\t\t\t\tfor (const key in orig) {\n\t\t\t\t\t\tconst currentPath = path ? `${path}.${key}` : key;\n\t\t\t\t\t\tif (!(key in obj)) {\n\t\t\t\t\t\t\tif (isRestrictedConfigPath(currentPath, undefined, orig[key])) {\n\t\t\t\t\t\t\t\tblockedFields.push(currentPath);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tif (sanitizedConfigInfo) {\n\t\t\t\t\tcheckBlocked(parsed, sanitizedConfigInfo);\n\t\t\t\t}\n\t\t\t\tsetRestrictedError(blockedFields);\n\t\t\t} catch (e: any) {\n\t\t\t\tsetJsonError(e.message);\n\t\t\t\tsetRestrictedError([]);\n\t\t\t}\n\t\t}\n\t}, [configurationInfo]);\n\n\tconst handleSave = useCallback(() => {\n\t\tif (jsonError || restrictedError.length > 0) { return; }\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(editedConfig);\n\t\t\tconst changedFields = getChangedFields(sanitizedConfigInfo, parsed);\n\t\t\tconst flattened = flattenConfig(changedFields);\n\n\t\t\tonConfigUpdate(flattened);\n\t\t\tsetIsEditing(false);\n\t\t} catch (e: any) {\n\t\t\tsetJsonError(e.message);\n\t\t}\n\t}, [editedConfig, jsonError, onConfigUpdate, sanitizedConfigInfo, restrictedError.length]);\n\n\tconst newLicenses = useMemo(() => {\n\t\tif (isLocalStudio) {\n\t\t\treturn [];\n\t\t}\n\t\tconst cloudLicenses = instanceInfo?.licenses;\n\t\tif (appliedLicenses && cloudLicenses) {\n\t\t\tconst appliedLicensesById = keyBy(appliedLicenses, 'id');\n\t\t\treturn cloudLicenses.filter(cloudLicense => !appliedLicensesById[cloudLicense.id]);\n\t\t}\n\t\treturn [];\n\t}, [appliedLicenses, instanceInfo]);\n\n\treturn (\n\t\t<div className=\"h-full flex flex-col\">\n\t\t\t{isLocalStudio\n\t\t\t\t? (\n\t\t\t\t\t<LocalStudioOverview>\n\t\t\t\t\t\t<dl className=\"grid grid-cols-1 sm:grid-cols-3\">\n\t\t\t\t\t\t\t<div className=\"px-4 pb-4 sm:col-span-2 sm:px-0\">\n\t\t\t\t\t\t\t\t<HarperVersion loadingRegistration={loadingRegistration} registrationInfo={registrationInfo} />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div className=\"px-4 pb-4 text-right sm:col-span-1 sm:px-0\">\n\t\t\t\t\t\t\t\t<RestartButton\n\t\t\t\t\t\t\t\t\ttargetNoun={targetNoun}\n\t\t\t\t\t\t\t\t\tinstanceClient={instanceParams.instanceClient}\n\t\t\t\t\t\t\t\t\toperation=\"restart\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</dl>\n\t\t\t\t\t</LocalStudioOverview>\n\t\t\t\t)\n\t\t\t\t: (\n\t\t\t\t\t<CloudStudioOverview>\n\t\t\t\t\t\t<dl className=\"flex-none grid grid-cols-1 sm:grid-cols-4\">\n\t\t\t\t\t\t\t<div className=\"px-4 pb-4 sm:col-span-1 sm:px-0\">\n\t\t\t\t\t\t\t\t<HarperVersion loadingRegistration={loadingRegistration} registrationInfo={registrationInfo} />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div className=\"px-4 pb-4 sm:col-span-2 sm:px-0\">\n\t\t\t\t\t\t\t\t<InstanceURL loadingInstanceInfo={loadingInstanceInfo} instanceInfo={instanceInfo} />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div className=\"px-4 pb-4 text-right sm:col-span-1 sm:px-0 grid gap-1\">\n\t\t\t\t\t\t\t\t{newLicenses?.length > 0 && <ApplyLicensesButton newLicenses={newLicenses} />}\n\t\t\t\t\t\t\t\t<RestartButton\n\t\t\t\t\t\t\t\t\ttargetNoun={targetNoun}\n\t\t\t\t\t\t\t\t\tinstanceClient={instanceParams.instanceClient}\n\t\t\t\t\t\t\t\t\toperation=\"restart\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div className=\"px-4 pb-4 sm:col-span-1 sm:px-0\">\n\t\t\t\t\t\t\t\t<InstanceNodeName loadingInstanceInfo={loadingInstanceInfo} instanceInfo={instanceInfo} />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div className=\"px-4 pb-4 sm:col-span-2 sm:px-0\">\n\t\t\t\t\t\t\t\t<ApplicationURL loadingInstanceInfo={loadingInstanceInfo} clusterInfo={clusterInfo} />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{clusterInfo?.domains?.length && (\n\t\t\t\t\t\t\t\t<div className=\"px-4 pb-4 sm:col-span-3 sm:px-0\">\n\t\t\t\t\t\t\t\t\t<ClusterDomainsList loadingInstanceInfo={loadingInstanceInfo} clusterInfo={clusterInfo} />\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</dl>\n\t\t\t\t\t</CloudStudioOverview>\n\t\t\t\t)}\n\n\t\t\t<div className=\"flex-none flex items-center justify-between mb-2\">\n\t\t\t\t<div>\n\t\t\t\t\t<h3 className=\"font-bold text-sm/6\">Instance Config {isEditing ? '(editing)' : '(read only)'}</h3>\n\t\t\t\t\t{!instanceId && !isLocalStudio && (\n\t\t\t\t\t\t<p className=\"text-muted-foreground italic text-sm\">\n\t\t\t\t\t\t\tYou are viewing the config for one instance in your cluster, based on what the load balancer selected for\n\t\t\t\t\t\t\tyou.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<div className=\"flex items-center gap-2 pr-4\">\n\t\t\t\t\t{!isEditing\n\t\t\t\t\t\t? (\n\t\t\t\t\t\t\t<Button size=\"sm\" onClick={() => setIsEditing(true)}>\n\t\t\t\t\t\t\t\t<EditIcon className=\"w-4 h-4 mr-1\" /> Edit\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)\n\t\t\t\t\t\t: (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={() => setIsEditing(false)}>\n\t\t\t\t\t\t\t\t\t<XIcon className=\"w-4 h-4 mr-1\" /> Cancel\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\tdisabled={!!jsonError || restrictedError.length > 0 || isSaving}\n\t\t\t\t\t\t\t\t\tonClick={handleSave}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<SaveIcon className=\"w-4 h-4 mr-1\" /> {isSaving ? 'Saving...' : 'Save & Restart'}\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{jsonError && (\n\t\t\t\t<Alert variant=\"destructive\" className=\"mb-4\">\n\t\t\t\t\t<AlertCircleIcon className=\"h-4 w-4\" />\n\t\t\t\t\t<AlertTitle>Invalid JSON</AlertTitle>\n\t\t\t\t\t<AlertDescription>{jsonError}</AlertDescription>\n\t\t\t\t</Alert>\n\t\t\t)}\n\n\t\t\t{restrictedError.length > 0 && (\n\t\t\t\t<Alert variant=\"destructive\" className=\"mb-4\">\n\t\t\t\t\t<AlertCircleIcon className=\"h-4 w-4\" />\n\t\t\t\t\t<AlertTitle>Restricted Configuration</AlertTitle>\n\t\t\t\t\t<AlertDescription>\n\t\t\t\t\t\tThe following fields cannot be modified via Studio:\n\t\t\t\t\t\t<ul className=\"list-disc ml-4 mt-2\">\n\t\t\t\t\t\t\t{restrictedError.map(field => (\n\t\t\t\t\t\t\t\t<li key={field}>\n\t\t\t\t\t\t\t\t\t<code>{field}</code>\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t</AlertDescription>\n\t\t\t\t</Alert>\n\t\t\t)}\n\n\t\t\t<div className=\"grow\">\n\t\t\t\t{!loadingConfig\n\t\t\t\t\t? (\n\t\t\t\t\t\t<Editor\n\t\t\t\t\t\t\tclassName=\"w-full min-h-full h-96\"\n\t\t\t\t\t\t\tlanguage=\"json\"\n\t\t\t\t\t\t\ttheme=\"vs-dark\"\n\t\t\t\t\t\t\toptions={{ readOnly: !isEditing, scrollBeyondLastLine: false }}\n\t\t\t\t\t\t\tvalue={isEditing ? editedConfig : JSON.stringify(sanitizedConfigInfo, null, 4)}\n\t\t\t\t\t\t\tonChange={handleEditorChange}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)\n\t\t\t\t\t: (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<TextLoadingSkeleton className=\"w-full\" />\n\t\t\t\t\t\t\t<TextLoadingSkeleton className=\"w-full\" />\n\t\t\t\t\t\t\t<TextLoadingSkeleton className=\"w-1/2\" />\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","import { LocalRole } from '@/integrations/api/api.patch';\nimport { translateSecondsToAgo } from '@/lib/translateSecondsToAgo';\nimport { ColumnDef, createColumnHelper } from '@tanstack/react-table';\n\nconst columnHelper = createColumnHelper<LocalRole>();\n\nexport const dataTableColumns: Array<ColumnDef<LocalRole>> = [\n\t{\n\t\theader: 'Role',\n\t\taccessorKey: 'role',\n\t\tenableSorting: false,\n\t},\n\tcolumnHelper.display({\n\t\theader: 'Created',\n\t\tenableSorting: false,\n\t\tid: '__createdtime__',\n\t\tcell: (props) =>\n\t\t\ttranslateSecondsToAgo(\n\t\t\t\t(Date.now() - props.row.original.__createdtime__) / 1000,\n\t\t\t\tprops.row.original.__createdtime__,\n\t\t\t),\n\t}),\n\tcolumnHelper.display({\n\t\theader: 'Updated',\n\t\tid: '__updatedtime__',\n\t\tenableSorting: false,\n\t\tcell: (props) =>\n\t\t\ttranslateSecondsToAgo(\n\t\t\t\t(Date.now() - props.row.original.__updatedtime__) / 1000,\n\t\t\t\tprops.row.original.__updatedtime__,\n\t\t\t),\n\t}),\n\tcolumnHelper.display({\n\t\theader: 'Super User',\n\t\tid: 'super_user',\n\t\tenableSorting: false,\n\t\tcell: (props) => (props.row.original.permission.super_user ? 'Yes' : 'No'),\n\t}),\n\tcolumnHelper.display({\n\t\theader: 'Structure User',\n\t\tid: 'structure_user',\n\t\tenableSorting: false,\n\t\tcell: (props) => (props.row.original.permission.structure_user ? 'Yes' : 'No'),\n\t}),\n];\n","import { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { useMutation } from '@tanstack/react-query';\n\nexport interface AddRoleFormData {\n\trole: string;\n\tsuper_user?: boolean;\n\tstructure_user?: boolean;\n}\n\nexport async function onAddRoleSubmit(formData: AddRoleFormData & InstanceClientConfig) {\n\tconst { role, super_user, structure_user, instanceClient } = formData;\n\tconst { data } = await instanceClient.post(\n\t\t'/',\n\t\t{\n\t\t\toperation: 'add_role',\n\t\t\trole,\n\t\t\tpermission: {\n\t\t\t\tsuper_user,\n\t\t\t\tstructure_user,\n\t\t\t},\n\t\t},\n\t);\n\treturn data;\n}\n\nexport function useAddRoleMutation() {\n\treturn useMutation({\n\t\tmutationFn: onAddRoleSubmit,\n\t});\n}\n","import { z } from 'zod';\n\nexport const AddRoleFormSchema = z.object({\n\trole: z\n\t\t.string()\n\t\t.nonempty({ error: 'Please enter a role.' })\n\t\t.regex(/^[a-zA-Z_]*$/, {\n\t\t\terror: 'Role must contain only letters and underscores.',\n\t\t})\n\t\t.max(30, {\n\t\t\terror: 'Role cannot be longer than 30 characters.',\n\t\t}),\n\tsuper_user: z.boolean(),\n\tstructure_user: z.boolean(),\n});\n","import { Button } from '@/components/ui/button';\nimport {\n\tDialog,\n\tDialogContent,\n\tDialogDescription,\n\tDialogFooter,\n\tDialogHeader,\n\tDialogTitle,\n} from '@/components/ui/dialog';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { AddRoleFormData, useAddRoleMutation } from '@/integrations/api/instance/auth/addRole';\nimport { AddRoleFormSchema } from '@/integrations/api/instance/auth/addRoleFormSchema';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { Save } from 'lucide-react';\nimport { useCallback } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\n\nexport function AddRoleModal({\n\tisModalOpen,\n\tonChangesSaved,\n\tsetIsModalOpen,\n}: {\n\tisModalOpen: boolean;\n\tonChangesSaved: (roleName: string) => void;\n\tsetIsModalOpen: (open: boolean) => void;\n}) {\n\tconst form = useForm({\n\t\tresolver: zodResolver(AddRoleFormSchema),\n\t\tdefaultValues: {\n\t\t\trole: '',\n\t\t\tsuper_user: false,\n\t\t\tstructure_user: false,\n\t\t},\n\t});\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst { mutate: addRole, isPending: isAddPending } = useAddRoleMutation();\n\n\tconst onSubmitClick = useCallback(\n\t\tasync (formData: AddRoleFormData) => {\n\t\t\tif (formData) {\n\t\t\t\taddRole(\n\t\t\t\t\t{\n\t\t\t\t\t\trole: formData.role,\n\t\t\t\t\t\tsuper_user: formData.super_user,\n\t\t\t\t\t\tstructure_user: formData.structure_user,\n\t\t\t\t\t\t...instanceParams,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tonSuccess: () => {\n\t\t\t\t\t\t\tform.reset();\n\t\t\t\t\t\t\tonChangesSaved(formData.role);\n\t\t\t\t\t\t\ttoast.success('Role added successfully!');\n\t\t\t\t\t\t\tsetIsModalOpen(false);\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t\t[addRole, form, instanceParams, onChangesSaved, setIsModalOpen],\n\t);\n\n\tconst onClickCancel = useCallback(() => {\n\t\tform.reset();\n\t\tsetIsModalOpen(false);\n\t}, [form, setIsModalOpen]);\n\n\treturn (\n\t\t<Dialog onOpenChange={setIsModalOpen} open={isModalOpen}>\n\t\t\t{/* NOTE - Is this okay to do for the aria describedby? */}\n\t\t\t<DialogContent aria-describedby={undefined}>\n\t\t\t\t<Form {...form}>\n\t\t\t\t\t<form\n\t\t\t\t\t\tid=\"instance-add-role-form\"\n\t\t\t\t\t\tname=\"instance-add-role-form\"\n\t\t\t\t\t\tonSubmit={form.handleSubmit(onSubmitClick)}\n\t\t\t\t\t\tclassName=\"grid gap-4 my-4 md:grid-cols-2\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<DialogHeader className=\"md:col-span-2\">\n\t\t\t\t\t\t\t<DialogTitle>Add New Role</DialogTitle>\n\t\t\t\t\t\t\t<DialogDescription>\n\t\t\t\t\t\t\t\tAfter adding the role, you will be able to edit the per-table permissions.\n\t\t\t\t\t\t\t</DialogDescription>\n\t\t\t\t\t\t</DialogHeader>\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"role\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem className=\"md:col-span-2\">\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Name</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input type=\"text\" {...field} />\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"super_user\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem className=\"flex\">\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"w-6\"\n\t\t\t\t\t\t\t\t\t\t\tchecked={field.value}\n\t\t\t\t\t\t\t\t\t\t\tonChange={(e) => field.onChange(e.target.checked)}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pl-4 pr-8 flex-1 py-2.5\">Super User</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"structure_user\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem className=\"flex\">\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"w-6\"\n\t\t\t\t\t\t\t\t\t\t\tchecked={field.value}\n\t\t\t\t\t\t\t\t\t\t\tonChange={(e) => field.onChange(e.target.checked)}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pl-4 pr-8 flex-1 py-2.5\">Structure User</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<DialogFooter className=\"md:col-span-2\">\n\t\t\t\t\t\t\t<div className=\"flex justify-between w-full\">\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tvariant=\"destructiveOutline\"\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\t\tonClick={onClickCancel}\n\t\t\t\t\t\t\t\t\tdisabled={isAddPending}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t<Button type=\"submit\" variant=\"submit\" className=\"rounded-full\" disabled={isAddPending}>\n\t\t\t\t\t\t\t\t\t<Save /> Add Role\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</DialogFooter>\n\t\t\t\t\t</form>\n\t\t\t\t</Form>\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { InstanceClientConfig, InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { LocalRole } from '@/integrations/api/api.patch';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport function getListRolesQueryOptions({ entityId, instanceClient }: InstanceClientIdConfig) {\n\treturn queryOptions({\n\t\tqueryKey: [entityId, 'list_roles'] as const,\n\t\tqueryFn: () => getListRoles({ instanceClient }),\n\t\trefetchInterval: 10_000,\n\t});\n}\n\nasync function getListRoles({ instanceClient }: InstanceClientConfig) {\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation: 'list_roles',\n\t});\n\treturn data as LocalRole[];\n}\n","import {\n\tInstanceDatabaseMap,\n\tLocalLegacyRolePermissionTable,\n\tLocalRolePermission,\n\tLocalRolePermissionTable,\n} from '@/integrations/api/api.patch';\nimport { keyBy } from '@/lib/keyBy';\n\nexport function calculateDefaultPermissions({\n\tinstanceDatabaseMap,\n\tcurrentRolePermissions,\n\tversion,\n\tshowAttributes,\n}: {\n\tinstanceDatabaseMap: InstanceDatabaseMap;\n\tcurrentRolePermissions: LocalRolePermission;\n\tversion: string;\n\tshowAttributes: boolean;\n}): LocalRolePermission {\n\tconst permissionStructure: LocalRolePermission = {\n\t\t...currentRolePermissions,\n\t};\n\tif (\n\t\tcurrentRolePermissions.super_user || currentRolePermissions.structure_user || currentRolePermissions.cluster_user\n\t) {\n\t\treturn currentRolePermissions;\n\t}\n\tconst [major, minor, patch] = version.split('.').map(number => parseInt(number, 10));\n\tconst legacy = version !== '2.0.000' && major <= 2 && minor <= 1 && patch <= 2;\n\n\tfor (const databaseName in instanceDatabaseMap) {\n\t\tpermissionStructure[databaseName] = {\n\t\t\ttables: {},\n\t\t};\n\t\tfor (const tableName in instanceDatabaseMap[databaseName]) {\n\t\t\tconst thisTable = instanceDatabaseMap[databaseName][tableName];\n\t\t\tconst attributes = thisTable.attributes.map((a) => a.attribute).sort();\n\t\t\tif (legacy) {\n\t\t\t\tconst extantTablePermissions = currentRolePermissions && currentRolePermissions[databaseName]\n\t\t\t\t\t&& currentRolePermissions[databaseName].tables[tableName];\n\t\t\t\tpermissionStructure[databaseName].tables[tableName] = buildLegacy(\n\t\t\t\t\textantTablePermissions as LocalLegacyRolePermissionTable,\n\t\t\t\t\tattributes,\n\t\t\t\t\tshowAttributes,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconst extantTablePermissions = currentRolePermissions && currentRolePermissions[databaseName]\n\t\t\t\t\t&& currentRolePermissions[databaseName].tables[tableName];\n\t\t\t\tpermissionStructure[databaseName].tables[tableName] = buildCurrent(\n\t\t\t\t\textantTablePermissions as LocalRolePermissionTable,\n\t\t\t\t\tattributes,\n\t\t\t\t\tshowAttributes,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn permissionStructure;\n}\n\nfunction buildLegacy(\n\textantTablePermissions: LocalLegacyRolePermissionTable | undefined,\n\tattributes: string[],\n\tshowAttributes: boolean,\n): LocalLegacyRolePermissionTable {\n\tconst attributeRestrictionsMap = extantTablePermissions\n\t\t&& keyBy(extantTablePermissions.attribute_restrictions, 'attribute_name');\n\treturn {\n\t\tread: extantTablePermissions ? extantTablePermissions.read : true,\n\t\tinsert: extantTablePermissions ? extantTablePermissions.insert : true,\n\t\tupdate: extantTablePermissions ? extantTablePermissions.update : true,\n\t\tdelete: extantTablePermissions ? extantTablePermissions.delete : true,\n\t\tattribute_restrictions: attributes\n\t\t\t.filter(() => showAttributes)\n\t\t\t.map((a) => {\n\t\t\t\tconst extantAttributePermissions = attributeRestrictionsMap?.[a];\n\n\t\t\t\treturn {\n\t\t\t\t\tattribute_name: a,\n\t\t\t\t\tread: extantAttributePermissions\n\t\t\t\t\t\t? extantAttributePermissions.read\n\t\t\t\t\t\t: extantTablePermissions\n\t\t\t\t\t\t? extantTablePermissions.read\n\t\t\t\t\t\t: true,\n\t\t\t\t\tinsert: extantAttributePermissions\n\t\t\t\t\t\t? extantAttributePermissions.insert\n\t\t\t\t\t\t: extantTablePermissions\n\t\t\t\t\t\t? extantTablePermissions.insert\n\t\t\t\t\t\t: true,\n\t\t\t\t\tupdate: extantAttributePermissions\n\t\t\t\t\t\t? extantAttributePermissions.update\n\t\t\t\t\t\t: extantTablePermissions\n\t\t\t\t\t\t? extantTablePermissions.update\n\t\t\t\t\t\t: true,\n\t\t\t\t\tdelete: extantAttributePermissions\n\t\t\t\t\t\t? extantAttributePermissions.delete\n\t\t\t\t\t\t: extantTablePermissions\n\t\t\t\t\t\t? extantTablePermissions.delete\n\t\t\t\t\t\t: true,\n\t\t\t\t};\n\t\t\t}),\n\t};\n}\n\nfunction buildCurrent(\n\textantTablePermissions: LocalRolePermissionTable | undefined,\n\tattributes: string[],\n\tshowAttributes: boolean,\n): LocalRolePermissionTable {\n\tconst attributePermissionsMap = extantTablePermissions\n\t\t&& keyBy(extantTablePermissions.attribute_permissions || [], 'attribute_name');\n\treturn {\n\t\tread: extantTablePermissions ? extantTablePermissions.read : false,\n\t\tinsert: extantTablePermissions ? extantTablePermissions.insert : false,\n\t\tupdate: extantTablePermissions ? extantTablePermissions.update : false,\n\t\tdelete: extantTablePermissions ? extantTablePermissions.delete : false,\n\t\tattribute_permissions: showAttributes\n\t\t\t? attributes\n\t\t\t\t.map((a: string) => {\n\t\t\t\t\tconst extantAttributePermissions = attributePermissionsMap?.[a];\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\tattribute_name: a,\n\t\t\t\t\t\tread: extantAttributePermissions\n\t\t\t\t\t\t\t? extantAttributePermissions.read\n\t\t\t\t\t\t\t: extantTablePermissions?.attribute_permissions?.length\n\t\t\t\t\t\t\t? false\n\t\t\t\t\t\t\t: extantTablePermissions?.read || false,\n\t\t\t\t\t\tinsert: extantAttributePermissions\n\t\t\t\t\t\t\t? extantAttributePermissions.insert\n\t\t\t\t\t\t\t: extantTablePermissions?.attribute_permissions?.length\n\t\t\t\t\t\t\t? false\n\t\t\t\t\t\t\t: extantTablePermissions?.insert || false,\n\t\t\t\t\t\tupdate: extantAttributePermissions\n\t\t\t\t\t\t\t? extantAttributePermissions.update\n\t\t\t\t\t\t\t: extantTablePermissions?.attribute_permissions?.length\n\t\t\t\t\t\t\t? false\n\t\t\t\t\t\t\t: extantTablePermissions?.update || false,\n\t\t\t\t\t};\n\t\t\t\t})\n\t\t\t: null,\n\t};\n}\n","import { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { LocalRolePermission } from '@/integrations/api/api.patch';\nimport { useMutation } from '@tanstack/react-query';\n\ninterface AlterRoleRequestBody extends InstanceClientConfig {\n\tid: string;\n\tpermission: LocalRolePermission;\n}\n\ninterface AlterRoleResponse {\n\tid: string;\n\tpermission: object;\n\trole: string;\n\t__createdtime__: number;\n\t__updatedtime__: number;\n}\n\nasync function onAlterRole({\n\tid,\n\tpermission,\n\tinstanceClient,\n}: AlterRoleRequestBody): Promise<AlterRoleResponse> {\n\tconst { data } = await instanceClient.post(\n\t\t'/',\n\t\t{\n\t\t\toperation: 'alter_role',\n\t\t\tid,\n\t\t\tpermission,\n\t\t},\n\t);\n\treturn data as AlterRoleResponse;\n}\n\nexport function useAlterRole() {\n\treturn useMutation({\n\t\tmutationFn: onAlterRole,\n\t});\n}\n","import { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { useMutation } from '@tanstack/react-query';\n\ninterface DeleteRoleData extends InstanceClientConfig {\n\tid: string;\n}\n\ninterface DeleteRoleResponse {\n\tmessage: string;\n}\n\nasync function onDeleteRole({ id, instanceClient }: DeleteRoleData) {\n\tconst { data } = await instanceClient.post<DeleteRoleResponse>('/', {\n\t\toperation: 'drop_role',\n\t\tid,\n\t});\n\treturn data;\n}\n\nexport function useDeleteRoleMutation() {\n\treturn useMutation({\n\t\tmutationFn: onDeleteRole,\n\t});\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { InstanceDatabaseMap } from '@/integrations/api/api.patch';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport async function getDescribeAll({ instanceClient }: InstanceClientIdConfig) {\n\tconst { data } = await instanceClient.post<InstanceDatabaseMap>('/', {\n\t\toperation: 'describe_all',\n\t});\n\treturn data;\n}\n\nexport function getDescribeAllQueryOptions(params: InstanceClientIdConfig) {\n\treturn queryOptions({\n\t\tqueryKey: [params.entityId, 'describe_all'] as const,\n\t\tqueryFn: () => getDescribeAll(params),\n\t\tstaleTime: 60_000,\n\t\tgcTime: 5_000,\n\t\tretry: false,\n\t});\n}\n","import { TextLoadingSkeleton } from '@/components/TextLoadingSkeleton';\nimport { Button } from '@/components/ui/button';\nimport { Dialog, DialogContent, DialogDescription, DialogFooter, DialogTitle } from '@/components/ui/dialog';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { calculateDefaultPermissions } from '@/features/instance/config/roles/defaultCalculator';\nimport { useInstanceAuth } from '@/hooks/useAuth';\nimport { useCheckboxCallback } from '@/hooks/useCheckboxCallback';\nimport { LocalRole, LocalRolePermission } from '@/integrations/api/api.patch';\nimport { useAlterRole } from '@/integrations/api/instance/auth/alterRole';\nimport { useDeleteRoleMutation } from '@/integrations/api/instance/auth/deleteRole';\nimport { getDescribeAllQueryOptions } from '@/integrations/api/instance/database/getDescribeAll';\nimport { getRegistrationInfoQueryOptions } from '@/integrations/api/instance/status/getRegistrationInfo';\nimport { safeParse } from '@/lib/string/safeParse';\nimport { Editor } from '@monaco-editor/react';\nimport { useQuery } from '@tanstack/react-query';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { toast } from 'sonner';\n\nexport function EditRoleModal({\n\tdata,\n\tinstanceId,\n\tclusterId,\n\tisModalOpen,\n\tcloseModal,\n\tonSelectRole,\n\tonChangesSaved,\n}: {\n\tdata: LocalRole;\n\tinstanceId?: string;\n\tclusterId?: string;\n\tisModalOpen: boolean;\n\tcloseModal: () => void;\n\tonSelectRole: (role?: string) => void;\n\tonChangesSaved: () => void;\n}) {\n\tconst { role, permission: initialPermissions } = data;\n\tconst [updatedPermissions, setUpdatedPermissions] = useState<string | undefined>(\n\t\tJSON.stringify(initialPermissions, null, 2),\n\t);\n\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst [isValidJSON, setIsValidJSON] = useState(true);\n\tconst { data: instanceDatabaseMap } = useQuery(getDescribeAllQueryOptions(instanceParams));\n\tconst { data: registrationInfo } = useQuery(\n\t\tgetRegistrationInfoQueryOptions(instanceParams),\n\t);\n\tconst auth = useInstanceAuth(instanceId ?? clusterId);\n\tconst isSelf = auth.user?.role?.role === data.role;\n\n\tconst [showAttributes, onShowAttributesChanged] = useCheckboxCallback(updatedPermissions?.includes('attribute_name'));\n\n\tconst { mutate: alterRole, isPending } = useAlterRole();\n\tconst { mutate: dropRole } = useDeleteRoleMutation();\n\n\tconst onValidate = useCallback(\n\t\t(markers: unknown[]) => {\n\t\t\tsetIsValidJSON(markers.length === 0);\n\t\t},\n\t\t[setIsValidJSON],\n\t);\n\n\tconst defaultValue = useMemo(() => {\n\t\treturn JSON.stringify(\n\t\t\tinstanceDatabaseMap && registrationInfo && calculateDefaultPermissions({\n\t\t\t\tinstanceDatabaseMap,\n\t\t\t\tcurrentRolePermissions: updatedPermissions && safeParse(updatedPermissions) || initialPermissions,\n\t\t\t\tversion: registrationInfo.version,\n\t\t\t\tshowAttributes: showAttributes,\n\t\t\t}),\n\t\t\tnull,\n\t\t\t2,\n\t\t);\n\t\t// We exclude updatedPermissions on purpose from the deps.\n\t}, [initialPermissions, instanceDatabaseMap, registrationInfo, showAttributes, updatedPermissions]);\n\n\tuseEffect(() => {\n\t\tsetUpdatedPermissions(defaultValue);\n\t}, [defaultValue]);\n\n\tconst onRoleUpdated = useCallback(\n\t\t(updatedPermissions: string) => {\n\t\t\tif (updatedPermissions) {\n\t\t\t\tconst parsedPermissions = JSON.parse(updatedPermissions) as LocalRolePermission;\n\t\t\t\tif (parsedPermissions.super_user || parsedPermissions.structure_user || parsedPermissions.cluster_user) {\n\t\t\t\t\tfor (const parsedPermissionsKey in parsedPermissions) {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tparsedPermissionsKey !== 'super_user' && parsedPermissionsKey !== 'structure_user'\n\t\t\t\t\t\t\t&& parsedPermissionsKey !== 'cluster_user'\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t// If you're a super, structure or cluster user, you don't need more specific permissions.\n\t\t\t\t\t\t\tdelete parsedPermissions[parsedPermissionsKey];\n\t\t\t\t\t\t} else if (parsedPermissions[parsedPermissionsKey] === false) {\n\t\t\t\t\t\t\t// If you've set one of the top-level properties, clear out any others set to false.\n\t\t\t\t\t\t\tdelete parsedPermissions[parsedPermissionsKey];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\talterRole(\n\t\t\t\t\t{\n\t\t\t\t\t\tid: data.id,\n\t\t\t\t\t\tpermission: parsedPermissions,\n\t\t\t\t\t\t...instanceParams,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tonSuccess: () => {\n\t\t\t\t\t\t\ttoast.success('Role updated successfully!');\n\t\t\t\t\t\t\tonSelectRole(undefined);\n\t\t\t\t\t\t\tonChangesSaved();\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t\t[alterRole, data.id, instanceParams, onChangesSaved, onSelectRole],\n\t);\n\n\tconst onRoleDeleted = useCallback(() => {\n\t\tdropRole(\n\t\t\t{\n\t\t\t\tid: data.id,\n\t\t\t\t...instanceParams,\n\t\t\t},\n\t\t\t{\n\t\t\t\tonSuccess: () => {\n\t\t\t\t\ttoast.success('Role deleted successfully!');\n\t\t\t\t\tonSelectRole(undefined);\n\t\t\t\t\tonChangesSaved();\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}, [data.id, dropRole, instanceParams, onChangesSaved, onSelectRole]);\n\n\tconst onSubmitClick = useCallback(() => {\n\t\tif (updatedPermissions && isValidJSON) {\n\t\t\tonRoleUpdated(updatedPermissions);\n\t\t}\n\t}, [updatedPermissions, onRoleUpdated, isValidJSON]);\n\n\tconst onRoleDeleteClick = useCallback(() => {\n\t\tonRoleDeleted();\n\t}, [onRoleDeleted]);\n\n\treturn (\n\t\t<Dialog onOpenChange={closeModal} open={isModalOpen}>\n\t\t\t<DialogContent className=\"sm:max-w-[750px]\">\n\t\t\t\t<DialogTitle>{isSelf ? 'View' : 'Edit'} Role \"{role}\"</DialogTitle>\n\t\t\t\t<DialogDescription>\n\t\t\t\t\t{isSelf\n\t\t\t\t\t\t? 'You can view your own role, but you cannot edit it. Please assign yourself a different'\n\t\t\t\t\t\t\t+ ' role to edit this role.'\n\t\t\t\t\t\t: \"Edit the role's permissions in JSON format or remove the role entirely.\"}\n\t\t\t\t</DialogDescription>\n\t\t\t\t{defaultValue\n\t\t\t\t\t? (\n\t\t\t\t\t\t<Editor\n\t\t\t\t\t\t\ttheme=\"vs-dark\"\n\t\t\t\t\t\t\theight=\"400px\"\n\t\t\t\t\t\t\tdefaultLanguage=\"json\"\n\t\t\t\t\t\t\tvalue={updatedPermissions}\n\t\t\t\t\t\t\toptions={isSelf ? { readOnly: true } : undefined}\n\t\t\t\t\t\t\tonValidate={onValidate}\n\t\t\t\t\t\t\tonChange={setUpdatedPermissions}\n\t\t\t\t\t\t\tdefaultValue={defaultValue}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)\n\t\t\t\t\t: <TextLoadingSkeleton />}\n\t\t\t\t<DialogFooter>\n\t\t\t\t\t{!isSelf && (\n\t\t\t\t\t\t<div className=\"flex justify-between w-full\">\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tvariant=\"destructiveOutline\"\n\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\tonClick={onRoleDeleteClick}\n\t\t\t\t\t\t\t\tdisabled={isPending}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tDelete Role\n\t\t\t\t\t\t\t</Button>\n\n\t\t\t\t\t\t\t<div className=\"grow\" />\n\n\t\t\t\t\t\t\t<Label className=\"flex\">\n\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\tclassName=\"w-6\"\n\t\t\t\t\t\t\t\t\tchecked={showAttributes}\n\t\t\t\t\t\t\t\t\tonChange={onShowAttributesChanged}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<span className=\"pl-4 pr-8 flex-1 py-2.5\">Pick Attributes</span>\n\t\t\t\t\t\t\t</Label>\n\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tvariant=\"submit\"\n\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\tonClick={onSubmitClick}\n\t\t\t\t\t\t\t\tdisabled={isPending || !isValidJSON}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tSave Changes\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</DialogFooter>\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { Loading } from '@/components/Loading';\nimport { SimpleBrowseDataTable } from '@/components/SimpleBrowseDataTable';\nimport { Button } from '@/components/ui/button';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { dataTableColumns } from '@/features/instance/config/roles/constants/tableDefinition';\nimport { AddRoleModal } from '@/features/instance/config/roles/modals/AddRoleModal';\nimport { useRefreshClick } from '@/hooks/useRefreshClick';\nimport { LocalRole } from '@/integrations/api/api.patch';\nimport { getListRolesQueryOptions } from '@/integrations/api/instance/auth/getListRoles';\nimport { useSuspenseQuery } from '@tanstack/react-query';\nimport { useNavigate, useParams } from '@tanstack/react-router';\nimport { Row } from '@tanstack/react-table';\nimport { PlusIcon, RefreshCwIcon } from 'lucide-react';\nimport { Suspense, useCallback, useMemo, useState } from 'react';\nimport { EditRoleModal } from './modals/EditRoleModal';\n\nexport function ConfigRolesIndex() {\n\tconst navigate = useNavigate();\n\tconst { clusterId, instanceId, roleId }: {\n\t\tinstanceId?: string;\n\t\tclusterId?: string;\n\t\troleId?: string;\n\t} = useParams({ strict: false });\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst {\n\t\tdata: localRoles,\n\t\trefetch,\n\t\tisFetching,\n\t\tisRefetching,\n\t} = useSuspenseQuery(getListRolesQueryOptions(instanceParams));\n\n\tconst selectedRole = useMemo(() => localRoles?.find((role) => role.id === roleId), [localRoles, roleId]);\n\n\tconst onSelectRole = useCallback(\n\t\t(newRole: string | undefined) => {\n\t\t\tconst parts = [roleId ? '..' : '', newRole].filter(Boolean);\n\t\t\tvoid navigate({ to: parts.join('/') });\n\t\t},\n\t\t[roleId, navigate],\n\t);\n\n\tconst isEditModalOpen = !!roleId && !!selectedRole;\n\n\tconst [isAddModalOpen, setIsAddModalOpen] = useState(false);\n\n\tconst onAddClicked = useCallback(() => {\n\t\tsetIsAddModalOpen(true);\n\t}, [setIsAddModalOpen]);\n\tconst onRoleAdded = useCallback((roleName: string) => {\n\t\tvoid refetch();\n\t\tsetIsAddModalOpen(false);\n\t\tonSelectRole(roleName);\n\t}, [onSelectRole, refetch]);\n\n\tconst onRowClick = useCallback(\n\t\t(rowData: Row<LocalRole>) => {\n\t\t\tonSelectRole(rowData.original.role);\n\t\t},\n\t\t[onSelectRole],\n\t);\n\tconst closeEditModal = useCallback(() => {\n\t\tonSelectRole(undefined);\n\t}, [onSelectRole]);\n\n\tconst onRefreshClick = useRefreshClick(refetch);\n\n\treturn (\n\t\t<Suspense fallback={<Loading className=\"flex flex-col items-center justify-center h-full\" text=\"Loading...\" />}>\n\t\t\t<SimpleBrowseDataTable\n\t\t\t\tcolumns={dataTableColumns}\n\t\t\t\tdata={localRoles}\n\t\t\t\tisFetching={isFetching}\n\t\t\t\tonRowClick={onRowClick}\n\t\t\t>\n\t\t\t\t<Button variant=\"defaultOutline\" onClick={onRefreshClick} accessKey=\"r\" disabled={isFetching || isRefetching}>\n\t\t\t\t\t<RefreshCwIcon />\n\t\t\t\t\t<span className=\"hidden lg:inline-block\">\n\t\t\t\t\t\t<u>R</u>efresh\n\t\t\t\t\t</span>\n\t\t\t\t</Button>\n\t\t\t\t<Button variant=\"positiveOutline\" onClick={onAddClicked} accessKey=\"a\" disabled={isAddModalOpen}>\n\t\t\t\t\t<PlusIcon />\n\t\t\t\t\t<span>\n\t\t\t\t\t\t<u>A</u>dd\n\t\t\t\t\t</span>\n\t\t\t\t</Button>\n\t\t\t</SimpleBrowseDataTable>\n\t\t\t<AddRoleModal isModalOpen={isAddModalOpen} onChangesSaved={onRoleAdded} setIsModalOpen={setIsAddModalOpen} />\n\t\t\t{isEditModalOpen && (\n\t\t\t\t<EditRoleModal\n\t\t\t\t\tinstanceId={instanceId}\n\t\t\t\t\tclusterId={clusterId}\n\t\t\t\t\tisModalOpen={isEditModalOpen}\n\t\t\t\t\tcloseModal={closeEditModal}\n\t\t\t\t\tdata={selectedRole}\n\t\t\t\t\tonSelectRole={onSelectRole}\n\t\t\t\t\tonChangesSaved={() => refetch()}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</Suspense>\n\t);\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport interface SSHKeyName {\n\tname: string;\n}\n\nasync function listSSHKeys({ instanceClient }: InstanceClientIdConfig) {\n\tconst { data } = await instanceClient.post<SSHKeyName[]>('/', {\n\t\toperation: 'list_ssh_keys',\n\t});\n\treturn data;\n}\n\nexport function listSSHKeysQueryOptions(params: InstanceClientIdConfig) {\n\treturn queryOptions({\n\t\tqueryKey: [params.entityId, 'list_ssh_keys'] as const,\n\t\tqueryFn: () => listSSHKeys(params),\n\t});\n}\n","import { SSHKeyName } from '@/integrations/api/instance/ssh/listSSHKeys';\nimport { ColumnDef } from '@tanstack/react-table';\n\nexport const dataTableColumns: Array<ColumnDef<SSHKeyName>> = [\n\t{\n\t\theader: 'SSH Key Name',\n\t\taccessorKey: 'name',\n\t\tenableSorting: false,\n\t},\n];\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { queryOptions } from '@tanstack/react-query';\n\ninterface SSHKeyKnownHosts {\n\tknown_hosts: string | null;\n}\n\nasync function getSSHKnownHosts({ instanceClient }: InstanceClientIdConfig) {\n\tconst { data } = await instanceClient.post<SSHKeyKnownHosts>('/', {\n\t\toperation: 'get_ssh_known_hosts',\n\t});\n\treturn data;\n}\n\nexport function getSSHKnownHostsQueryOptions(params: InstanceClientIdConfig) {\n\treturn queryOptions({\n\t\tqueryKey: [params.entityId, 'get_ssh_known_hosts'] as const,\n\t\tqueryFn: () => getSSHKnownHosts(params),\n\t});\n}\n","import { InstanceClientConfig, InstanceTypeConfig } from '@/config/instanceClientConfig';\nimport { ReplicatedResponse } from '@/integrations/api/replication';\nimport { useMutation } from '@tanstack/react-query';\nimport { z } from 'zod';\n\nexport const SSHKnownHostsSchema = z.object({\n\tknown_hosts: z.string().trim(),\n});\n\ntype SetSSHKnownHostsFormData = z.infer<typeof SSHKnownHostsSchema> & InstanceClientConfig & InstanceTypeConfig;\n\nasync function setSSHKnownHosts(formData: SetSSHKnownHostsFormData) {\n\tconst { instanceClient, entityType, ...sshKey } = formData;\n\tconst { data } = await instanceClient.post<ReplicatedResponse>('/', {\n\t\toperation: 'set_ssh_known_hosts',\n\t\treplicated: entityType === 'cluster',\n\t\t...sshKey,\n\t});\n\treturn data;\n}\n\nexport function useSetSSHKnownHosts() {\n\treturn useMutation({\n\t\tmutationFn: setSSHKnownHosts,\n\t});\n}\n","import { Button } from '@/components/ui/button';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormDescription } from '@/components/ui/form/FormDescription';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Textarea } from '@/components/ui/textarea';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { getSSHKnownHostsQueryOptions } from '@/integrations/api/instance/ssh/getSSHKnownHosts';\nimport { SSHKnownHostsSchema, useSetSSHKnownHosts } from '@/integrations/api/instance/ssh/setSSHKnownHosts';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useSuspenseQuery } from '@tanstack/react-query';\nimport { Save } from 'lucide-react';\nimport { useCallback } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\n\nexport function KnownHosts() {\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst { data } = useSuspenseQuery(getSSHKnownHostsQueryOptions(instanceParams));\n\tconst form = useForm({\n\t\tresolver: zodResolver(SSHKnownHostsSchema),\n\t\tdefaultValues: {\n\t\t\tknown_hosts: data?.known_hosts || '',\n\t\t},\n\t});\n\tconst { mutate: setSSHKnownHosts, isPending } = useSetSSHKnownHosts();\n\n\tconst onSubmitClick = useCallback(\n\t\tasync (formData: z.infer<typeof SSHKnownHostsSchema>) => {\n\t\t\tconst { known_hosts } = formData;\n\t\t\tif (known_hosts) {\n\t\t\t\tsetSSHKnownHosts(\n\t\t\t\t\t{\n\t\t\t\t\t\tknown_hosts: known_hosts.trim() + '\\n',\n\t\t\t\t\t\t...instanceParams,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tonSuccess: () => {\n\t\t\t\t\t\t\tform.reset(formData);\n\t\t\t\t\t\t\ttoast.success('Known hosts saved!');\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t\t[setSSHKnownHosts, form, instanceParams],\n\t);\n\n\treturn (\n\t\t<Form {...form}>\n\t\t\t<form\n\t\t\t\tid=\"instance-edit-known-hosts-form\"\n\t\t\t\tname=\"instance-edit-known-hosts-form\"\n\t\t\t\tonSubmit={form.handleSubmit(onSubmitClick)}\n\t\t\t\tclassName=\"grid my-4 md:grid-cols-2 overflow-x-auto rounded-md\"\n\t\t\t>\n\t\t\t\t<FormField\n\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\tname=\"known_hosts\"\n\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t<FormItem className=\"md:col-span-2 gap-0\">\n\t\t\t\t\t\t\t<FormLabel className=\"bg-black-dark py-3 px-2 m-0 text-left font-medium whitespace-nowrap\">\n\t\t\t\t\t\t\t\tKnown Hosts\n\t\t\t\t\t\t\t</FormLabel>\n\t\t\t\t\t\t\t<div className=\"border border-grey-700 p-2 pb-3\">\n\t\t\t\t\t\t\t\t<FormDescription className=\"pb-2\">\n\t\t\t\t\t\t\t\t\tManage your known hosts here. When you add a SSH Key with a hostname of \"github.com\", we'll\n\t\t\t\t\t\t\t\t\tautomatically attempt to resolve GitHub's known hosts for you.\n\t\t\t\t\t\t\t\t</FormDescription>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Textarea\n\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"whitespace-nowrap\"\n\t\t\t\t\t\t\t\t\t\trows={10}\n\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\t\tvariant=\"submit\"\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-full mt-2\"\n\t\t\t\t\t\t\t\t\tdisabled={isPending || !form.formState.isDirty || !form.formState.isValid}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Save /> {isPending ? 'Saving' : 'Save'} Known Hosts{isPending ? '...' : ''}\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t)}\n\t\t\t\t/>\n\t\t\t</form>\n\t\t</Form>\n\t);\n}\n","import { InstanceClientIdConfig, InstanceTypeConfig } from '@/config/instanceClientConfig';\nimport { ReplicatedResponse } from '@/integrations/api/replication';\nimport { useMutation } from '@tanstack/react-query';\nimport { z } from 'zod';\n\nexport const SSHKeySchema = z.object({\n\tname: z\n\t\t.string()\n\t\t.trim()\n\t\t.min(1)\n\t\t.regex(/^[a-zA-Z0-9-_]*$/, { error: 'Can only contain letters, numbers, dashes and underscores.' }),\n\tkey: z.string().min(1).trim(),\n\thost: z.string().min(1).trim(),\n\thostname: z.string().min(1).trim(),\n\tknown_hosts: z.string().trim().optional(),\n});\n\ntype AddSSHKeyFormData = z.infer<typeof SSHKeySchema> & InstanceClientIdConfig & InstanceTypeConfig;\n\nasync function addSSHKey(formData: AddSSHKeyFormData) {\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\tconst { instanceClient, entityType, entityId, ...sshKey } = formData;\n\tconst { data } = await instanceClient.post<ReplicatedResponse>('/', {\n\t\toperation: 'add_ssh_key',\n\t\treplicated: entityType === 'cluster',\n\t\t...sshKey,\n\t});\n\treturn data;\n}\n\nexport function useAddSSHKey() {\n\treturn useMutation({\n\t\tmutationFn: addSSHKey,\n\t});\n}\n","import { Button } from '@/components/ui/button';\nimport {\n\tDialog,\n\tDialogContent,\n\tDialogDescription,\n\tDialogFooter,\n\tDialogHeader,\n\tDialogTitle,\n} from '@/components/ui/dialog';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormDescription } from '@/components/ui/form/FormDescription';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { Textarea } from '@/components/ui/textarea';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { SSHKeySchema, useAddSSHKey } from '@/integrations/api/instance/ssh/addSSHKey';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { Save } from 'lucide-react';\nimport { useCallback } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\n\nexport function AddSSHKeyModal({\n\tisModalOpen,\n\tonChangesSaved,\n\tsetIsModalOpen,\n}: {\n\tisModalOpen: boolean;\n\tonChangesSaved: () => void;\n\tsetIsModalOpen: (open: boolean) => void;\n}) {\n\tconst form = useForm({\n\t\tresolver: zodResolver(SSHKeySchema),\n\t\tdefaultValues: {\n\t\t\tname: '',\n\t\t\tkey: '',\n\t\t\thost: '',\n\t\t\thostname: '',\n\t\t\tknown_hosts: '',\n\t\t},\n\t});\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst { mutate: addSSHKey, isPending } = useAddSSHKey();\n\n\tconst onSubmitClick = useCallback(\n\t\tasync (formData: z.infer<typeof SSHKeySchema>) => {\n\t\t\tif (formData) {\n\t\t\t\tconst { name, key, host, hostname, known_hosts } = formData;\n\t\t\t\taddSSHKey(\n\t\t\t\t\t{\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tkey: key.trim() + '\\n',\n\t\t\t\t\t\thost,\n\t\t\t\t\t\thostname,\n\t\t\t\t\t\tknown_hosts: known_hosts || undefined,\n\t\t\t\t\t\t...instanceParams,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tonSuccess: () => {\n\t\t\t\t\t\t\tform.reset();\n\t\t\t\t\t\t\tonChangesSaved();\n\t\t\t\t\t\t\ttoast.success('SSH Key added successfully!');\n\t\t\t\t\t\t\tsetIsModalOpen(false);\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t\t[addSSHKey, form, instanceParams, onChangesSaved, setIsModalOpen],\n\t);\n\n\tconst onClickCancel = useCallback(() => {\n\t\tform.reset();\n\t\tsetIsModalOpen(false);\n\t}, [form, setIsModalOpen]);\n\n\treturn (\n\t\t<Dialog onOpenChange={setIsModalOpen} open={isModalOpen}>\n\t\t\t<DialogContent aria-describedby={undefined}>\n\t\t\t\t<Form {...form}>\n\t\t\t\t\t<form\n\t\t\t\t\t\tid=\"instance-add-ssh-key-form\"\n\t\t\t\t\t\tname=\"instance-add-ssh-key-form\"\n\t\t\t\t\t\tonSubmit={form.handleSubmit(onSubmitClick)}\n\t\t\t\t\t\tclassName=\"grid gap-4 my-4 md:grid-cols-2\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<DialogHeader className=\"md:col-span-2\">\n\t\t\t\t\t\t\t<DialogTitle>Add New SSH Key</DialogTitle>\n\t\t\t\t\t\t\t<DialogDescription>\n\t\t\t\t\t\t\t\tEnter the details of your SSH Key below.\n\t\t\t\t\t\t\t</DialogDescription>\n\t\t\t\t\t\t</DialogHeader>\n\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"name\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem className=\"md:col-span-2\">\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Name</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoFocus={true}\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"key\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem className=\"md:col-span-2\">\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Key</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormDescription>\n\t\t\t\t\t\t\t\t\t\tYour private key. Don't have one? Try out \"ssh-keygen\"! You'll want to add your public key to your\n\t\t\t\t\t\t\t\t\t\tregistry, i.e. GitHub.\n\t\t\t\t\t\t\t\t\t</FormDescription>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Textarea\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\t\t\trows={3}\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"host\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem className=\"md:col-span-2\">\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Host</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormDescription>\n\t\t\t\t\t\t\t\t\t\tA unique identifying name for the combination of this key and your hostname, i.e.\n\t\t\t\t\t\t\t\t\t\t\"your-repo.github.com\". You will use this instead of the direct hostname to pick your key when\n\t\t\t\t\t\t\t\t\t\timporting applications.\n\t\t\t\t\t\t\t\t\t</FormDescription>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"hostname\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem className=\"md:col-span-2\">\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Hostname</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormDescription>\n\t\t\t\t\t\t\t\t\t\tWhen making the request, the actual hostname to use, i.e. \"github.com\".\n\t\t\t\t\t\t\t\t\t</FormDescription>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"known_hosts\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem className=\"md:col-span-2\">\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Known Hosts</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormDescription>\n\t\t\t\t\t\t\t\t\t\tOptionally, append known hosts, one per line. GitHub known hosts should resolve automatically.\n\t\t\t\t\t\t\t\t\t</FormDescription>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Textarea\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"whitespace-nowrap\"\n\t\t\t\t\t\t\t\t\t\t\trows={3}\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<DialogFooter className=\"md:col-span-2\">\n\t\t\t\t\t\t\t<div className=\"flex justify-between w-full\">\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tvariant=\"destructiveOutline\"\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\t\tonClick={onClickCancel}\n\t\t\t\t\t\t\t\t\tdisabled={isPending}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\t\tvariant=\"submit\"\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\t\tdisabled={isPending || !form.formState.isDirty || !form.formState.isValid}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Save /> Add SSH Key\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</DialogFooter>\n\t\t\t\t\t</form>\n\t\t\t\t</Form>\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { InstanceClientConfig, InstanceTypeConfig } from '@/config/instanceClientConfig';\nimport { ReplicatedResponse } from '@/integrations/api/replication';\nimport { useMutation } from '@tanstack/react-query';\n\ninterface DeleteSSHKeyFormData extends InstanceClientConfig, InstanceTypeConfig {\n\tname: string;\n}\n\nasync function deleteSSHKey(formData: DeleteSSHKeyFormData) {\n\tconst { instanceClient, entityType, name } = formData;\n\tconst { data } = await instanceClient.post<ReplicatedResponse>('/', {\n\t\toperation: 'delete_ssh_key',\n\t\treplicated: entityType === 'cluster',\n\t\tname,\n\t});\n\treturn data;\n}\n\nexport function useDeleteSSHKey() {\n\treturn useMutation({\n\t\tmutationFn: deleteSSHKey,\n\t});\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { queryOptions } from '@tanstack/react-query';\n\ninterface GetSSHKeyFormData extends InstanceClientIdConfig {\n\tname: string;\n}\n\ninterface SSHKey {\n\tname: string;\n\tkey: unknown;\n\thost?: string;\n\thostname?: string;\n}\n\nasync function getSSHKey({ name, instanceClient }: GetSSHKeyFormData) {\n\tconst { data } = await instanceClient.post<SSHKey>('/', {\n\t\toperation: 'get_ssh_key',\n\t\tname,\n\t});\n\treturn data;\n}\n\nexport function getSSHKeyQueryOptions(params: GetSSHKeyFormData) {\n\treturn queryOptions({\n\t\tqueryKey: [params.entityId, 'get_ssh_key'] as const,\n\t\tqueryFn: () => getSSHKey(params),\n\t\trefetchInterval: 10_000,\n\t});\n}\n","import { InstanceClientConfig, InstanceTypeConfig } from '@/config/instanceClientConfig';\nimport { ReplicatedResponse } from '@/integrations/api/replication';\nimport { useMutation } from '@tanstack/react-query';\nimport { z } from 'zod';\n\nexport const UpdateSSHKeySchema = z.object({\n\tname: z.string().trim(),\n\tkey: z.string().min(1).trim(),\n});\n\ntype UpdateSSHKeyFormData = z.infer<typeof UpdateSSHKeySchema> & InstanceClientConfig & InstanceTypeConfig;\n\nasync function updateSSHKey(formData: UpdateSSHKeyFormData) {\n\tconst { instanceClient, entityType, name, key } = formData;\n\tconst { data } = await instanceClient.post<ReplicatedResponse>('/', {\n\t\toperation: 'update_ssh_key',\n\t\treplicated: entityType === 'cluster',\n\t\tname,\n\t\tkey,\n\t});\n\treturn data;\n}\n\nexport function useUpdateSSHKey() {\n\treturn useMutation({\n\t\tmutationFn: updateSSHKey,\n\t});\n}\n","import { Button } from '@/components/ui/button';\nimport { Dialog, DialogContent, DialogFooter, DialogTitle } from '@/components/ui/dialog';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormDescription } from '@/components/ui/form/FormDescription';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { Textarea } from '@/components/ui/textarea';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { useDeleteSSHKey } from '@/integrations/api/instance/ssh/deleteSSHKey';\nimport { getSSHKeyQueryOptions } from '@/integrations/api/instance/ssh/getSSHKey';\nimport { SSHKeyName } from '@/integrations/api/instance/ssh/listSSHKeys';\nimport { UpdateSSHKeySchema, useUpdateSSHKey } from '@/integrations/api/instance/ssh/updateSSHKey';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useQuery } from '@tanstack/react-query';\nimport { Row } from '@tanstack/react-table';\nimport { useCallback } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\n\nexport function EditSSHKeyModal({\n\tdata,\n\tisModalOpen,\n\tcloseModal,\n\tonSelectSSHKey,\n\tonChangesSaved,\n}: {\n\tdata: SSHKeyName;\n\tisModalOpen: boolean;\n\tcloseModal: () => void;\n\tonSelectSSHKey: (row?: Row<SSHKeyName>) => void;\n\tonChangesSaved: () => void;\n}) {\n\tconst { name } = data;\n\n\tconst form = useForm({\n\t\tresolver: zodResolver(UpdateSSHKeySchema),\n\t\tdefaultValues: {\n\t\t\tname,\n\t\t\tkey: '',\n\t\t},\n\t});\n\n\tconst instanceParams = useInstanceClientIdParams();\n\n\tconst { data: fullData } = useQuery(getSSHKeyQueryOptions({\n\t\t...instanceParams,\n\t\tname,\n\t}));\n\n\tconst { mutate: updateSSHKey, isPending } = useUpdateSSHKey();\n\tconst { mutate: deleteSSHKey } = useDeleteSSHKey();\n\n\tconst onSubmitClick = useCallback(\n\t\tasync ({ key }: z.infer<typeof UpdateSSHKeySchema>) => {\n\t\t\tif (key) {\n\t\t\t\tupdateSSHKey(\n\t\t\t\t\t{\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tkey: key.trim() + '\\n',\n\t\t\t\t\t\t...instanceParams,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tonSuccess: () => {\n\t\t\t\t\t\t\ttoast.success('SSH Key updated successfully!');\n\t\t\t\t\t\t\tonSelectSSHKey(undefined);\n\t\t\t\t\t\t\tonChangesSaved();\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t\t[updateSSHKey, name, instanceParams, onSelectSSHKey, onChangesSaved],\n\t);\n\n\tconst onSSHKeyDeleteClicked = useCallback(() => {\n\t\tdeleteSSHKey(\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\t...instanceParams,\n\t\t\t},\n\t\t\t{\n\t\t\t\tonSuccess: () => {\n\t\t\t\t\ttoast.success('SSH Key deleted successfully!');\n\t\t\t\t\tonSelectSSHKey(undefined);\n\t\t\t\t\tonChangesSaved();\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}, [name, deleteSSHKey, instanceParams, onChangesSaved, onSelectSSHKey]);\n\n\treturn (\n\t\t<Dialog onOpenChange={closeModal} open={isModalOpen}>\n\t\t\t<DialogContent className=\"sm:max-w-[750px]\" aria-describedby={undefined}>\n\t\t\t\t<Form {...form}>\n\t\t\t\t\t<form\n\t\t\t\t\t\tid=\"instance-edit-ssh-key-form\"\n\t\t\t\t\t\tname=\"instance-edit-ssh-key-form\"\n\t\t\t\t\t\tonSubmit={form.handleSubmit(onSubmitClick)}\n\t\t\t\t\t\tclassName=\"grid gap-4 my-4 md:grid-cols-2\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<DialogTitle>Edit SSH Key</DialogTitle>\n\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"name\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem className=\"md:col-span-2\">\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Name</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\t\t\treadOnly={true}\n\t\t\t\t\t\t\t\t\t\t\tdisabled={true}\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"key\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem className=\"md:col-span-2\">\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Key</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormDescription>\n\t\t\t\t\t\t\t\t\t\tReplace your existing private key. Lost it? Try out \"ssh-keygen\"! You'll want to add your public key\n\t\t\t\t\t\t\t\t\t\tto your registry, i.e. GitHub.\n\t\t\t\t\t\t\t\t\t</FormDescription>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Textarea\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoFocus={true}\n\t\t\t\t\t\t\t\t\t\t\trows={3}\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<FormItem className=\"md:col-span-2\">\n\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Host</FormLabel>\n\t\t\t\t\t\t\t<FormDescription>\n\t\t\t\t\t\t\t\tA unique identifying name for the combination of this key and your hostname, i.e.\n\t\t\t\t\t\t\t\t\"your-repo.github.com\". You will use this instead of the direct hostname to pick your key when importing\n\t\t\t\t\t\t\t\tapplications.\n\t\t\t\t\t\t\t</FormDescription>\n\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\tvalue={fullData?.host || ''}\n\t\t\t\t\t\t\t\t\tdisabled={true}\n\t\t\t\t\t\t\t\t\treadOnly={true}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t</FormItem>\n\n\t\t\t\t\t\t<FormItem className=\"md:col-span-2\">\n\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Hostname</FormLabel>\n\t\t\t\t\t\t\t<FormDescription>\n\t\t\t\t\t\t\t\tWhen making the request, the actual hostname to use, i.e. \"github.com\".\n\t\t\t\t\t\t\t</FormDescription>\n\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\tvalue={fullData?.hostname || ''}\n\t\t\t\t\t\t\t\t\tdisabled={true}\n\t\t\t\t\t\t\t\t\treadOnly={true}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t</FormItem>\n\n\t\t\t\t\t\t<DialogFooter>\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tvariant=\"destructiveOutline\"\n\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\tonClick={onSSHKeyDeleteClicked}\n\t\t\t\t\t\t\t\tdisabled={isPending}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tDelete SSH Key\n\t\t\t\t\t\t\t</Button>\n\n\t\t\t\t\t\t\t<div className=\"grow\" />\n\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\tvariant=\"submit\"\n\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\tdisabled={isPending || !form.formState.isValid}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tUpdate SSH Key\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</DialogFooter>\n\t\t\t\t\t</form>\n\t\t\t\t</Form>\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { Loading } from '@/components/Loading';\nimport { SimpleBrowseDataTable } from '@/components/SimpleBrowseDataTable';\nimport { Button } from '@/components/ui/button';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { useRefreshClick } from '@/hooks/useRefreshClick';\nimport { listSSHKeysQueryOptions, SSHKeyName } from '@/integrations/api/instance/ssh/listSSHKeys';\nimport { useQuery } from '@tanstack/react-query';\nimport { Link, useNavigate, useParams } from '@tanstack/react-router';\nimport { Row } from '@tanstack/react-table';\nimport { PlusIcon, RefreshCwIcon } from 'lucide-react';\nimport { Suspense, useCallback, useMemo, useState } from 'react';\nimport { dataTableColumns } from './constants/tableDefinition';\nimport { KnownHosts } from './KnownHosts';\nimport { AddSSHKeyModal } from './modals/AddSSHKeyModal';\nimport { EditSSHKeyModal } from './modals/EditSSHKeyModal';\n\nexport function ConfigSSHKeysIndex() {\n\tconst navigate = useNavigate();\n\tconst { keyName }: { keyName?: string } = useParams({ strict: false });\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst {\n\t\tdata: localSSHKeys,\n\t\trefetch,\n\t\tisFetching,\n\t\tisRefetching,\n\t} = useQuery(listSSHKeysQueryOptions(instanceParams));\n\n\tconst selectedSSHKey = useMemo(() => localSSHKeys?.find((role) => role.name === keyName), [localSSHKeys, keyName]);\n\n\tconst onSelectSSHKey = useCallback(\n\t\t(row?: Row<SSHKeyName>) => {\n\t\t\tconst newKeyName = row?.original?.name;\n\t\t\tconst parts = [keyName ? '..' : '', newKeyName].filter(Boolean);\n\t\t\tvoid navigate({ to: parts.join('/') });\n\t\t},\n\t\t[keyName, navigate],\n\t);\n\n\tconst isEditModalOpen = !!keyName && !!selectedSSHKey;\n\n\tconst [isAddModalOpen, setIsAddModalOpen] = useState(false);\n\n\tconst onAddClicked = useCallback(() => {\n\t\tsetIsAddModalOpen(true);\n\t}, [setIsAddModalOpen]);\n\n\tconst onRefreshClick = useRefreshClick(refetch);\n\n\treturn (\n\t\t<>\n\t\t\t<SimpleBrowseDataTable\n\t\t\t\tcolumns={dataTableColumns}\n\t\t\t\tdata={localSSHKeys || []}\n\t\t\t\tisFetching={isFetching}\n\t\t\t\tonRowClick={onSelectSSHKey}\n\t\t\t>\n\t\t\t\t<Link\n\t\t\t\t\tclassName=\"inline-block underline text-sm text-gray-400 hover:text-white\"\n\t\t\t\t\tto=\"https://docs.harperdb.io/docs/developers/security/certificate-management\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t>\n\t\t\t\t\tCertificate Management Docs\n\t\t\t\t</Link>\n\t\t\t\t<Button variant=\"defaultOutline\" onClick={onRefreshClick} accessKey=\"r\" disabled={isFetching || isRefetching}>\n\t\t\t\t\t<RefreshCwIcon />\n\t\t\t\t\t<span className=\"hidden lg:inline-block\">\n\t\t\t\t\t\t<u>R</u>efresh\n\t\t\t\t\t</span>\n\t\t\t\t</Button>\n\t\t\t\t<Button variant=\"positiveOutline\" onClick={onAddClicked} accessKey=\"a\" disabled={isAddModalOpen}>\n\t\t\t\t\t<PlusIcon />\n\t\t\t\t\t<span>\n\t\t\t\t\t\t<u>A</u>dd\n\t\t\t\t\t</span>\n\t\t\t\t</Button>\n\t\t\t</SimpleBrowseDataTable>\n\t\t\t{isAddModalOpen && (\n\t\t\t\t<AddSSHKeyModal isModalOpen={isAddModalOpen} onChangesSaved={refetch} setIsModalOpen={setIsAddModalOpen} />\n\t\t\t)}\n\t\t\t{isEditModalOpen && (\n\t\t\t\t<EditSSHKeyModal\n\t\t\t\t\tisModalOpen={isEditModalOpen}\n\t\t\t\t\tcloseModal={onSelectSSHKey}\n\t\t\t\t\tdata={selectedSSHKey}\n\t\t\t\t\tonSelectSSHKey={onSelectSSHKey}\n\t\t\t\t\tonChangesSaved={refetch}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t<Suspense fallback={<Loading text=\"Loading...\" />}>\n\t\t\t\t<KnownHosts />\n\t\t\t</Suspense>\n\t\t</>\n\t);\n}\n","import { LocalUser } from '@/integrations/api/api.patch';\nimport { translateSecondsToAgo } from '@/lib/translateSecondsToAgo';\nimport { ColumnDef, createColumnHelper } from '@tanstack/react-table';\n\nconst columnHelper = createColumnHelper<LocalUser>();\n\nexport const dataTableColumns: Array<ColumnDef<LocalUser>> = [\n\t{\n\t\theader: 'Username',\n\t\taccessorKey: 'username',\n\t\tenableSorting: false,\n\t},\n\tcolumnHelper.display({\n\t\theader: 'Role',\n\t\tenableSorting: false,\n\t\tid: 'role',\n\t\tcell: (props) => props.row.original.role.role,\n\t}),\n\t{\n\t\theader: 'Active',\n\t\taccessorKey: 'active',\n\t\tenableSorting: false,\n\t},\n\tcolumnHelper.display({\n\t\theader: 'Created',\n\t\tenableSorting: false,\n\t\tid: '__createdtime__',\n\t\tcell: (props) =>\n\t\t\ttranslateSecondsToAgo(\n\t\t\t\t(Date.now() - props.row.original.__createdtime__) / 1000,\n\t\t\t\tprops.row.original.__createdtime__,\n\t\t\t),\n\t}),\n\t{\n\t\theader: 'Updated',\n\t\taccessorKey: '__updatedtime__',\n\t\tenableSorting: false,\n\t\tcell: (props) =>\n\t\t\ttranslateSecondsToAgo(\n\t\t\t\t(Date.now() - props.row.original.__updatedtime__) / 1000,\n\t\t\t\tprops.row.original.__updatedtime__,\n\t\t\t),\n\t},\n];\n","import { TextLoadingSkeleton } from '@/components/TextLoadingSkeleton';\nimport { Button } from '@/components/ui/button';\nimport { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport {\n\tSelect,\n\tSelectContent,\n\tSelectGroup,\n\tSelectItem,\n\tSelectLabel,\n\tSelectTrigger,\n\tSelectValue,\n} from '@/components/ui/select';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { useAddUserMutation } from '@/integrations/api/instance/auth/addUser';\nimport { AddUserFormSchema } from '@/integrations/api/instance/auth/addUserFormSchema';\nimport { getListRolesQueryOptions } from '@/integrations/api/instance/auth/getListRoles';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useSuspenseQuery } from '@tanstack/react-query';\nimport { Save } from 'lucide-react';\nimport { Suspense, useCallback } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\n\nexport function AddUserModal({\n\tisModalOpen,\n\tonChangesSaved,\n\tsetIsModalOpen,\n}: {\n\tisModalOpen: boolean;\n\tonChangesSaved: () => void;\n\tsetIsModalOpen: (open: boolean) => void;\n}) {\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst { data: roles } = useSuspenseQuery(getListRolesQueryOptions(instanceParams));\n\tconst form = useForm({\n\t\tresolver: zodResolver(AddUserFormSchema),\n\t\tdefaultValues: {\n\t\t\tusername: '',\n\t\t\trole: '',\n\t\t\tpassword: '',\n\t\t\tconfirmPassword: '',\n\t\t},\n\t});\n\tconst { mutate: addUser, isPending: isAddPending } = useAddUserMutation();\n\n\tconst onSubmitClick = useCallback(async (formData: z.infer<typeof AddUserFormSchema>) => {\n\t\tif (formData) {\n\t\t\taddUser(\n\t\t\t\t{\n\t\t\t\t\tactive: true,\n\t\t\t\t\tpassword: formData.password,\n\t\t\t\t\trole: formData.role,\n\t\t\t\t\tusername: formData.username,\n\t\t\t\t\t...instanceParams,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tonSuccess: () => {\n\t\t\t\t\t\tconst lastRole = formData.role;\n\t\t\t\t\t\tform.reset();\n\t\t\t\t\t\t// Persist the selected role if they open the form again.\n\t\t\t\t\t\tform.setValue('role', lastRole);\n\t\t\t\t\t\tonChangesSaved();\n\t\t\t\t\t\ttoast.success('User added successfully!');\n\t\t\t\t\t\tsetIsModalOpen(false);\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}, [addUser, form, instanceParams, onChangesSaved, setIsModalOpen]);\n\n\treturn (\n\t\t<Dialog onOpenChange={setIsModalOpen} open={isModalOpen}>\n\t\t\t{/* NOTE - Is this okay to do for the aria describedby? */}\n\t\t\t<DialogContent aria-describedby={undefined}>\n\t\t\t\t<Form {...form}>\n\t\t\t\t\t<form\n\t\t\t\t\t\tid=\"instance-add-user-form\"\n\t\t\t\t\t\tname=\"instance-add-user-form\"\n\t\t\t\t\t\tonSubmit={form.handleSubmit(onSubmitClick)}\n\t\t\t\t\t\tclassName=\"grid gap-4 my-4\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<DialogHeader>\n\t\t\t\t\t\t\t<DialogTitle>Add New User</DialogTitle>\n\t\t\t\t\t\t</DialogHeader>\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"username\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Username</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\tenterKeyHint=\"next\"\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"username\"\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"password\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Password</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\t\t\tenterKeyHint=\"next\"\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"new-password\"\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"confirmPassword\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Confirm Password</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\t\t\tenterKeyHint=\"next\"\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"new-password\"\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"role\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Role</FormLabel>\n\n\t\t\t\t\t\t\t\t\t<Suspense fallback={<TextLoadingSkeleton />}>\n\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t<Select {...field} onValueChange={(role) => field.onChange(role)}>\n\t\t\t\t\t\t\t\t\t\t\t\t<SelectTrigger className=\"w-full\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectValue placeholder=\"Choose Role\" />\n\t\t\t\t\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectGroup>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectLabel>Role</SelectLabel>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{roles?.map((role) => (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey={role.id}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue={role.id}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{role.role}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</SelectGroup>\n\t\t\t\t\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t</Suspense>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<DialogFooter>\n\t\t\t\t\t\t\t<div className=\"flex justify-between w-full\">\n\t\t\t\t\t\t\t\t<Button type=\"submit\" variant=\"submit\" className=\"rounded-full\" disabled={isAddPending}>\n\t\t\t\t\t\t\t\t\t<Save /> Add User\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</DialogFooter>\n\t\t\t\t\t</form>\n\t\t\t\t</Form>\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { AddUserFormSchema } from '@/integrations/api/instance/auth/addUserFormSchema';\nimport { z } from 'zod';\n\nexport const AlterUserFormSchema = z.object({\n\tusername: AddUserFormSchema.shape.username,\n\trole: AddUserFormSchema.shape.role,\n\tnewPassword: AddUserFormSchema.shape.password.or(z.literal('')).optional(),\n\tconfirmPassword: AddUserFormSchema.shape.confirmPassword,\n})\n\t.refine((data) => !data.newPassword || data.newPassword.length >= 8, {\n\t\terror: 'Password must be at least 8 characters long.',\n\t\tpath: ['password'],\n\t})\n\t.refine((data) => !data.newPassword || data.newPassword === data.confirmPassword, {\n\t\terror: 'Passwords do not match.',\n\t\tpath: ['confirmPassword'],\n\t});\n","import { TextLoadingSkeleton } from '@/components/TextLoadingSkeleton';\nimport { Button } from '@/components/ui/button';\nimport { DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport {\n\tSelect,\n\tSelectContent,\n\tSelectGroup,\n\tSelectItem,\n\tSelectLabel,\n\tSelectTrigger,\n\tSelectValue,\n} from '@/components/ui/select';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { LocalUser } from '@/integrations/api/api.patch';\nimport { AlterUserRequestBody, useAlterUser } from '@/integrations/api/instance/auth/alterUser';\nimport { AlterUserFormSchema } from '@/integrations/api/instance/auth/alterUserFormSchema';\nimport { getListRolesQueryOptions } from '@/integrations/api/instance/auth/getListRoles';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useSuspenseQuery } from '@tanstack/react-query';\nimport { Save } from 'lucide-react';\nimport { Suspense, useCallback } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\n\nexport function AlterUserForm({\n\tdata,\n\tonUserUpdated,\n}: {\n\tdata: LocalUser;\n\tonUserUpdated: () => void;\n}) {\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst { data: roles } = useSuspenseQuery(getListRolesQueryOptions(instanceParams));\n\tconst { mutate: alterUser, isPending: isUpdateUserPending } = useAlterUser();\n\tconst alterForm = useForm({\n\t\tresolver: zodResolver(AlterUserFormSchema),\n\t\tdefaultValues: {\n\t\t\tusername: data.username,\n\t\t\trole: data.role.role,\n\t\t\tnewPassword: '',\n\t\t\tconfirmPassword: '',\n\t\t},\n\t});\n\n\tconst onSubmitClick = useCallback((formData: z.infer<typeof AlterUserFormSchema>) => {\n\t\tconst alterBody: AlterUserRequestBody = {\n\t\t\tusername: data.username,\n\t\t\trole: formData.role,\n\t\t\t...instanceParams,\n\t\t};\n\t\tif (formData.newPassword) {\n\t\t\talterBody.password = formData.newPassword;\n\t\t}\n\t\talterUser(\n\t\t\talterBody,\n\t\t\t{\n\t\t\t\tonSuccess: () => {\n\t\t\t\t\talterForm.reset();\n\t\t\t\t\ttoast.success('User edited successfully!');\n\t\t\t\t\tonUserUpdated();\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}, [alterForm, alterUser, data.username, instanceParams, onUserUpdated]);\n\n\treturn (\n\t\t<Form {...alterForm}>\n\t\t\t<form\n\t\t\t\tid=\"instance-edit-user-form\"\n\t\t\t\tname=\"instance-edit-user-form\"\n\t\t\t\tonSubmit={alterForm.handleSubmit(onSubmitClick)}\n\t\t\t\tclassName=\"grid gap-4 my-4\"\n\t\t\t>\n\t\t\t\t<DialogHeader>\n\t\t\t\t\t<DialogTitle>Edit User</DialogTitle>\n\t\t\t\t</DialogHeader>\n\n\t\t\t\t<FormField\n\t\t\t\t\tcontrol={alterForm.control}\n\t\t\t\t\tname=\"username\"\n\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Username</FormLabel>\n\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\tenterKeyHint=\"next\"\n\t\t\t\t\t\t\t\t\tautoComplete=\"username\"\n\t\t\t\t\t\t\t\t\tdisabled={true}\n\t\t\t\t\t\t\t\t\treadOnly={true}\n\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t)}\n\t\t\t\t/>\n\n\t\t\t\t<FormField\n\t\t\t\t\tcontrol={alterForm.control}\n\t\t\t\t\tname=\"newPassword\"\n\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Change Password</FormLabel>\n\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\tenterKeyHint=\"next\"\n\t\t\t\t\t\t\t\t\tautoComplete=\"new-password\"\n\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t)}\n\t\t\t\t/>\n\t\t\t\t<FormField\n\t\t\t\t\tcontrol={alterForm.control}\n\t\t\t\t\tname=\"confirmPassword\"\n\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Confirm Password</FormLabel>\n\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\tenterKeyHint=\"next\"\n\t\t\t\t\t\t\t\t\tautoComplete=\"new-password\"\n\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t)}\n\t\t\t\t/>\n\n\t\t\t\t<FormField\n\t\t\t\t\tcontrol={alterForm.control}\n\t\t\t\t\tname=\"role\"\n\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Role</FormLabel>\n\n\t\t\t\t\t\t\t<Suspense fallback={<TextLoadingSkeleton />}>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Select {...field} onValueChange={(role) => field.onChange(role)}>\n\t\t\t\t\t\t\t\t\t\t<SelectTrigger className=\"w-full\">\n\t\t\t\t\t\t\t\t\t\t\t<SelectValue placeholder=\"Choose Role\" />\n\t\t\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t\t\t\t<SelectGroup>\n\t\t\t\t\t\t\t\t\t\t\t\t<SelectLabel>Role</SelectLabel>\n\t\t\t\t\t\t\t\t\t\t\t\t{roles?.map((role) => (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey={role.id}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue={role.id}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{role.role}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t\t\t</SelectGroup>\n\t\t\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t</Suspense>\n\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t)}\n\t\t\t\t/>\n\n\t\t\t\t<DialogFooter>\n\t\t\t\t\t<div className=\"flex justify-between w-full\">\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"submit\"\n\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\tdisabled={isUpdateUserPending}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Save /> Save Changes\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t</DialogFooter>\n\t\t\t</form>\n\t\t</Form>\n\t);\n}\n","import { zodRequireUsername } from '@/lib/zod/username';\nimport { z } from 'zod';\n\nexport const DeleteUserFormSchema = z.object({\n\tusername: zodRequireUsername,\n\tconfirmUsernameForDeletion: z\n\t\t.string()\n\t\t.nonempty({\n\t\t\terror: 'Please type the username again to confirm deletion.',\n\t\t})\n\t\t.toLowerCase(),\n})\n\t.refine((data) => data.username === data.confirmUsernameForDeletion, {\n\t\terror: 'Username does not match.',\n\t\tpath: ['confirmUsernameForDeletion'], // This specifies where the error message should be attached\n\t});\n","import { Button } from '@/components/ui/button';\nimport { DialogFooter } from '@/components/ui/dialog';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { useInstanceClientParams } from '@/config/useInstanceClient';\nimport { LocalUser } from '@/integrations/api/api.patch';\nimport { useDeleteUserMutation } from '@/integrations/api/instance/auth/deleteUser';\nimport { DeleteUserFormSchema } from '@/integrations/api/instance/auth/deleteUserFormSchema';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { Trash } from 'lucide-react';\nimport { useCallback } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\n\nexport function DeleteUserForm({\n\tdata,\n\tonUserDeleted,\n}: {\n\tdata: LocalUser;\n\tonUserDeleted: () => void;\n}) {\n\tconst { mutate: deleteUser, isPending: isDeleteUserPending } = useDeleteUserMutation();\n\tconst deleteForm = useForm({\n\t\tresolver: zodResolver(DeleteUserFormSchema),\n\t\tdefaultValues: {\n\t\t\tusername: data.username,\n\t\t\tconfirmUsernameForDeletion: '',\n\t\t},\n\t});\n\n\tconst instanceParams = useInstanceClientParams();\n\tconst onDeleteClicked = useCallback(() => {\n\t\tdeleteUser(\n\t\t\t{\n\t\t\t\tusername: data.username,\n\t\t\t\t...instanceParams,\n\t\t\t},\n\t\t\t{\n\t\t\t\tonSuccess: () => {\n\t\t\t\t\tdeleteForm.reset();\n\t\t\t\t\ttoast.success('User deleted successfully!');\n\t\t\t\t\tonUserDeleted();\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}, [data.username, deleteForm, deleteUser, instanceParams, onUserDeleted]);\n\n\treturn (\n\t\t<Form {...deleteForm}>\n\t\t\t<form\n\t\t\t\tid=\"instance-delete-user-form\"\n\t\t\t\tname=\"instance-delete-user-form\"\n\t\t\t\tonSubmit={deleteForm.handleSubmit(onDeleteClicked)}\n\t\t\t\tclassName=\"grid gap-4 my-4\"\n\t\t\t>\n\t\t\t\t<FormField\n\t\t\t\t\tcontrol={deleteForm.control}\n\t\t\t\t\tname=\"confirmUsernameForDeletion\"\n\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Confirm Username</FormLabel>\n\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\tenterKeyHint=\"next\"\n\t\t\t\t\t\t\t\t\tautoComplete=\"username\"\n\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t)}\n\t\t\t\t/>\n\n\t\t\t\t<DialogFooter>\n\t\t\t\t\t<div className=\"flex justify-between w-full\">\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"destructive\"\n\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\tdisabled={isDeleteUserPending || !deleteForm.formState.isValid}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Trash /> Delete User\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t</DialogFooter>\n\t\t\t</form>\n\t\t</Form>\n\t);\n}\n","import { Dialog, DialogContent } from '@/components/ui/dialog';\nimport { AlterUserForm } from '@/features/instance/config/users/components/AlterUserForm';\nimport { DeleteUserForm } from '@/features/instance/config/users/components/DeleteUserForm';\nimport { useInstanceAuth } from '@/hooks/useAuth';\nimport { LocalUser } from '@/integrations/api/api.patch';\n\nexport function EditUserModal({\n\tcloseModal,\n\tclusterId,\n\tinstanceId,\n\tdata,\n\tisModalOpen,\n\tonUserDeleted,\n\tonUserUpdated,\n}: {\n\tclusterId?: string;\n\tinstanceId?: string;\n\tisModalOpen: boolean;\n\tcloseModal: () => void;\n\tdata: LocalUser;\n\tonUserDeleted: () => void;\n\tonUserUpdated: () => void;\n}) {\n\tconst auth = useInstanceAuth(instanceId ?? clusterId);\n\tconst isSelf = auth.user?.username === data.username;\n\tconst canDelete = !isSelf;\n\n\treturn (\n\t\t<Dialog onOpenChange={closeModal} open={isModalOpen}>\n\t\t\t<DialogContent className=\"sm:max-w-[750px]\">\n\t\t\t\t<AlterUserForm data={data} onUserUpdated={onUserUpdated} />\n\t\t\t\t{canDelete && <DeleteUserForm data={data} onUserDeleted={onUserDeleted} />}\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { InstanceClientConfig, InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { LocalUser } from '@/integrations/api/api.patch';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport function getListUsersQueryOptions({ entityId, instanceClient }: InstanceClientIdConfig) {\n\treturn queryOptions({\n\t\tqueryKey: [entityId, 'list_users'] as const,\n\t\tqueryFn: () => getListUsers({ instanceClient }),\n\t\trefetchInterval: 10_000,\n\t});\n}\n\nasync function getListUsers({ instanceClient }: InstanceClientConfig) {\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation: 'list_users',\n\t});\n\treturn data as LocalUser[];\n}\n","import { Loading } from '@/components/Loading';\nimport { SimpleBrowseDataTable } from '@/components/SimpleBrowseDataTable';\nimport { Button } from '@/components/ui/button';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { dataTableColumns } from '@/features/instance/config/users/constants/tableDefinition';\nimport { AddUserModal } from '@/features/instance/config/users/modals/AddUserModal';\nimport { EditUserModal } from '@/features/instance/config/users/modals/EditUserModal';\nimport { useRefreshClick } from '@/hooks/useRefreshClick';\nimport { LocalUser } from '@/integrations/api/api.patch';\nimport { getListUsersQueryOptions } from '@/integrations/api/instance/auth/getListUsers';\nimport { useSuspenseQuery } from '@tanstack/react-query';\nimport { useNavigate, useParams } from '@tanstack/react-router';\nimport { Row } from '@tanstack/react-table';\nimport { PlusIcon, RefreshCwIcon } from 'lucide-react';\nimport { Suspense, useCallback, useMemo, useState } from 'react';\n\nexport function ConfigUsersIndex() {\n\tconst navigate = useNavigate();\n\tconst { instanceId, clusterId, username }: {\n\t\tinstanceId?: string;\n\t\tclusterId?: string;\n\t\tusername?: string;\n\t} = useParams({ strict: false });\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst {\n\t\tdata: localUsers,\n\t\trefetch,\n\t\tisFetching,\n\t\tisRefetching,\n\t} = useSuspenseQuery(getListUsersQueryOptions(instanceParams));\n\tconst selectedUser = useMemo(\n\t\t() => localUsers?.find(user => user.username === username),\n\t\t[localUsers, username],\n\t);\n\n\tconst onSelectUser = useCallback((newUsername: string | undefined) => {\n\t\tconst parts = [username ? '..' : '', newUsername].filter(Boolean);\n\t\tvoid navigate({ to: parts.join('/') });\n\t}, [username, navigate]);\n\n\tconst isEditModalOpen = !!username && !!selectedUser;\n\n\tconst [isAddModalOpen, setIsAddModalOpen] = useState(false);\n\tconst [sortTableDataParams] = useState({\n\t\tattribute: 'username',\n\t\tdescending: false,\n\t});\n\tconst sortingState = useMemo(() => [{\n\t\tdesc: sortTableDataParams.descending,\n\t\tid: sortTableDataParams.attribute,\n\t}], [sortTableDataParams]);\n\n\tconst onAddClicked = useCallback(() => {\n\t\tsetIsAddModalOpen(true);\n\t}, [setIsAddModalOpen]);\n\tconst onUsedAdded = useCallback(() => {\n\t\tvoid refetch();\n\t\tsetIsAddModalOpen(false);\n\t}, [refetch, setIsAddModalOpen]);\n\n\tconst onRowClick = useCallback((rowData: Row<LocalUser>) => {\n\t\tonSelectUser(rowData.original.username);\n\t}, [onSelectUser]);\n\tconst closeEditModal = useCallback(() => {\n\t\tonSelectUser(undefined);\n\t}, [onSelectUser]);\n\n\tconst onUserUpdated = useCallback(() => {\n\t\tvoid refetch();\n\t\tonSelectUser(undefined);\n\t}, [onSelectUser, refetch]);\n\tconst onUserDeleted = useCallback(() => {\n\t\tvoid refetch();\n\t\tonSelectUser(undefined);\n\t}, [onSelectUser, refetch]);\n\n\tconst onRefreshClick = useRefreshClick(refetch);\n\n\treturn (\n\t\t<Suspense\n\t\t\tfallback={<Loading className=\"flex flex-col items-center justify-center h-full\" text=\"Loading...\" />}\n\t\t>\n\t\t\t<SimpleBrowseDataTable<LocalUser, unknown>\n\t\t\t\tdata={localUsers}\n\t\t\t\tisFetching={isFetching || isRefetching}\n\t\t\t\tcolumns={dataTableColumns}\n\t\t\t\tonRowClick={onRowClick}\n\t\t\t\tsortingState={sortingState}\n\t\t\t>\n\t\t\t\t{/*<UploadCSVModal />*/}\n\t\t\t\t{/*disabled={tableDataFetching}*/}\n\t\t\t\t<Button variant=\"defaultOutline\" onClick={onRefreshClick} accessKey=\"r\" disabled={isFetching || isRefetching}>\n\t\t\t\t\t<RefreshCwIcon />{' '}\n\t\t\t\t\t<span className=\"hidden lg:inline-block\">\n\t\t\t\t\t\t<u>R</u>efresh\n\t\t\t\t\t</span>\n\t\t\t\t</Button>\n\t\t\t\t{/*<Button variant=\"defaultOutline\" onClick={notYetImplemented}><SearchIcon /> <span*/}\n\t\t\t\t{/*\tclassName=\"hidden lg:inline-block\">Search</span></Button>*/}\n\t\t\t\t<Button variant=\"positiveOutline\" onClick={onAddClicked} accessKey=\"a\" disabled={isAddModalOpen}>\n\t\t\t\t\t<PlusIcon />{' '}\n\t\t\t\t\t<span>\n\t\t\t\t\t\t<u>A</u>dd\n\t\t\t\t\t</span>\n\t\t\t\t</Button>\n\t\t\t</SimpleBrowseDataTable>\n\t\t\t<AddUserModal\n\t\t\t\tisModalOpen={isAddModalOpen}\n\t\t\t\tonChangesSaved={onUsedAdded}\n\t\t\t\tsetIsModalOpen={setIsAddModalOpen}\n\t\t\t/>\n\t\t\t{isEditModalOpen && (\n\t\t\t\t<EditUserModal\n\t\t\t\t\tinstanceId={instanceId}\n\t\t\t\t\tclusterId={clusterId}\n\t\t\t\t\tcloseModal={closeEditModal}\n\t\t\t\t\tdata={selectedUser}\n\t\t\t\t\tisModalOpen={isEditModalOpen}\n\t\t\t\t\tonUserDeleted={onUserDeleted}\n\t\t\t\t\tonUserUpdated={onUserUpdated}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</Suspense>\n\t);\n}\n","import { getInstanceClientIdFromParams } from '@/config/useInstanceClient';\nimport { getRegistrationInfoQueryOptions } from '@/integrations/api/instance/status/getRegistrationInfo';\nimport { QueryClient } from '@tanstack/react-query';\n\nexport function registrationInfoLoader({\n\tcontext,\n\tparams,\n}: {\n\tcontext: { queryClient: QueryClient };\n\tparams: { organizationId?: string; clusterId?: string; instanceId?: string };\n}) {\n\tconst operationsParams = getInstanceClientIdFromParams(params);\n\treturn context.queryClient.ensureQueryData(getRegistrationInfoQueryOptions(operationsParams));\n}\n","import { ConfigCertificatesIndex } from '@/features/instance/config/certificates';\nimport { ConfigDomainsIndex } from '@/features/instance/config/domains';\nimport { ConfigIndex } from '@/features/instance/config/index';\nimport { ConfigOverviewIndex } from '@/features/instance/config/overview';\nimport { ConfigRolesIndex } from '@/features/instance/config/roles';\nimport { ConfigSSHKeysIndex } from '@/features/instance/config/sshKeys';\nimport { ConfigUsersIndex } from '@/features/instance/config/users';\nimport { createInstanceLayoutRoute } from '@/features/instance/instanceLayoutRoute';\nimport { registrationInfoLoader } from '@/features/instance/registrationInfoLoader';\nimport { createRoute } from '@tanstack/react-router';\n\nexport function createConfigRouteTree(instanceLayoutRoute: ReturnType<typeof createInstanceLayoutRoute>) {\n\tconst instanceConfigRoute = createRoute({\n\t\tgetParentRoute: () => instanceLayoutRoute,\n\t\tpath: 'config',\n\t\tcomponent: ConfigIndex,\n\t\tloader: registrationInfoLoader,\n\t});\n\tconst instanceOverviewRoute = createRoute({\n\t\tgetParentRoute: () => instanceConfigRoute,\n\t\tpath: '/',\n\t\tcomponent: ConfigOverviewIndex,\n\t\tloader: registrationInfoLoader,\n\t});\n\n\tconst instanceConfigRolesRoute = createRoute({\n\t\tgetParentRoute: () => instanceConfigRoute,\n\t\tpath: 'roles',\n\t\tcomponent: ConfigRolesIndex,\n\t});\n\tconst instanceConfigRoleRoute = createRoute({\n\t\tgetParentRoute: () => instanceConfigRoute,\n\t\tpath: 'roles/$roleId',\n\t\tcomponent: ConfigRolesIndex,\n\t});\n\n\tconst instanceConfigUsersRoute = createRoute({\n\t\tgetParentRoute: () => instanceConfigRoute,\n\t\tpath: 'users',\n\t\tcomponent: ConfigUsersIndex,\n\t});\n\tconst instanceConfigUserRoute = createRoute({\n\t\tgetParentRoute: () => instanceConfigRoute,\n\t\tpath: 'users/$username',\n\t\tcomponent: ConfigUsersIndex,\n\t});\n\n\tconst instanceConfigDomainsRoute = createRoute({\n\t\tgetParentRoute: () => instanceConfigRoute,\n\t\tpath: 'domains',\n\t\tcomponent: ConfigDomainsIndex,\n\t});\n\n\tconst instanceConfigSSHKeysRoute = createRoute({\n\t\tgetParentRoute: () => instanceConfigRoute,\n\t\tpath: 'ssh-keys',\n\t\tcomponent: ConfigSSHKeysIndex,\n\t});\n\tconst instanceConfigSSHKeyRoute = createRoute({\n\t\tgetParentRoute: () => instanceConfigRoute,\n\t\tpath: 'ssh-keys/$keyName',\n\t\tcomponent: ConfigSSHKeysIndex,\n\t});\n\n\tconst instanceConfigCertificatesRoute = createRoute({\n\t\tgetParentRoute: () => instanceConfigRoute,\n\t\tpath: 'certificates',\n\t\tcomponent: ConfigCertificatesIndex,\n\t});\n\tconst instanceConfigCertificateRoute = createRoute({\n\t\tgetParentRoute: () => instanceConfigRoute,\n\t\tpath: 'certificates/$certName',\n\t\tcomponent: ConfigCertificatesIndex,\n\t});\n\n\treturn instanceConfigRoute.addChildren([\n\t\tinstanceOverviewRoute,\n\n\t\tinstanceConfigRolesRoute,\n\t\tinstanceConfigRoleRoute,\n\n\t\tinstanceConfigUsersRoute,\n\t\tinstanceConfigUserRoute,\n\n\t\tinstanceConfigDomainsRoute,\n\n\t\tinstanceConfigSSHKeysRoute,\n\t\tinstanceConfigSSHKeyRoute,\n\n\t\tinstanceConfigCertificatesRoute,\n\t\tinstanceConfigCertificateRoute,\n\t]);\n}\n","import { excludeFalsy } from '@/lib/arrays/excludeFalsy';\nimport { buildAbsoluteLinkToPage } from '@/lib/urls/buildAbsoluteLinkToPage';\n\nexport function buildAbsoluteLinkToDatabasePage({\n\tclusterId,\n\tdatabaseName,\n\tinstanceId,\n\torganizationId,\n\ttableName,\n}: {\n\tclusterId?: string;\n\tdatabaseName?: string;\n\tinstanceId?: string;\n\torganizationId?: string;\n\ttableName?: string;\n}): string {\n\tconst databases = [`databases`, databaseName, tableName].filter(excludeFalsy).join('/');\n\treturn buildAbsoluteLinkToPage({\n\t\torganizationId,\n\t\tinstanceId,\n\t\tclusterId,\n\t}, databases);\n}\n","import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';\nimport * as React from 'react';\n\nimport { cn } from '@/lib/cn';\n\nfunction ScrollArea({\n\tclassName,\n\tchildren,\n\t...props\n}: React.ComponentProps<typeof ScrollAreaPrimitive.Root>) {\n\treturn (\n\t\t<ScrollAreaPrimitive.Root\n\t\t\tdata-slot=\"scroll-area\"\n\t\t\tclassName={cn('relative', className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<ScrollAreaPrimitive.Viewport\n\t\t\t\tdata-slot=\"scroll-area-viewport\"\n\t\t\t\tclassName=\"focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1\"\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</ScrollAreaPrimitive.Viewport>\n\t\t\t<ScrollBar />\n\t\t\t<ScrollAreaPrimitive.Corner />\n\t\t</ScrollAreaPrimitive.Root>\n\t);\n}\n\nfunction ScrollBar({\n\tclassName,\n\torientation = 'vertical',\n\t...props\n}: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) {\n\treturn (\n\t\t<ScrollAreaPrimitive.ScrollAreaScrollbar\n\t\t\tdata-slot=\"scroll-area-scrollbar\"\n\t\t\torientation={orientation}\n\t\t\tclassName={cn(\n\t\t\t\t'flex touch-none p-px transition-colors select-none',\n\t\t\t\torientation === 'vertical'\n\t\t\t\t\t&& 'h-full w-2.5 border-l border-l-transparent',\n\t\t\t\torientation === 'horizontal'\n\t\t\t\t\t&& 'h-2.5 flex-col border-t border-t-transparent',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<ScrollAreaPrimitive.ScrollAreaThumb\n\t\t\t\tdata-slot=\"scroll-area-thumb\"\n\t\t\t\tclassName=\"bg-border relative flex-1 rounded-full\"\n\t\t\t/>\n\t\t</ScrollAreaPrimitive.ScrollAreaScrollbar>\n\t);\n}\n\nexport { ScrollArea, ScrollBar };\n","import { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { ReplicatedResponse } from '@/integrations/api/replication';\nimport { useMutation } from '@tanstack/react-query';\n\ninterface CreateTableFormData extends InstanceClientConfig {\n\tdatabaseName: string;\n\ttableName: string;\n\tprimaryKey: string;\n\treplicated: boolean;\n}\n\nasync function onCreateTableSubmit({\n\tdatabaseName,\n\ttableName,\n\tprimaryKey,\n\treplicated,\n\tinstanceClient,\n}: CreateTableFormData): Promise<ReplicatedResponse> {\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation: 'create_table',\n\t\tdatabase: databaseName,\n\t\ttable: tableName,\n\t\tprimary_key: primaryKey,\n\t\treplicated,\n\t});\n\treturn data;\n}\n\nexport function useCreateTableMutation() {\n\treturn useMutation({\n\t\tmutationFn: onCreateTableSubmit,\n\t});\n}\n","import { Button } from '@/components/ui/button';\nimport {\n\tDialog,\n\tDialogContent,\n\tDialogDescription,\n\tDialogFooter,\n\tDialogHeader,\n\tDialogTitle,\n\tDialogTrigger,\n} from '@/components/ui/dialog';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { useCreateTableMutation } from '@/integrations/api/instance/database/createTable';\nimport { databaseNameSchema } from '@/integrations/api/instance/database/databaseNameSchema';\nimport { schemaRegex } from '@/integrations/api/instance/database/schemaRegex';\nimport { tableNameSchema } from '@/integrations/api/instance/database/tableNameSchema';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useRouter } from '@tanstack/react-router';\nimport { Plus, Table } from 'lucide-react';\nimport { useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\n\nconst CreateTableSchema = z.object({\n\tdatabaseName: databaseNameSchema,\n\ttableName: tableNameSchema,\n\tprimaryKey: z\n\t\t.string()\n\t\t.regex(schemaRegex, {\n\t\t\terror: 'Primary key cannot include backticks or forward slashes.',\n\t\t})\n\t\t.max(250, {\n\t\t\terror: 'Primary key cannot be longer than 250 characters.',\n\t\t}),\n});\n\nexport function CreateNewTableModal({ databaseName, onSelectTable }: {\n\treadonly databaseName: string | undefined;\n\treadonly onSelectTable: (databaseName: string | undefined, tableName: string | undefined) => void;\n}) {\n\tconst queryClient = useQueryClient();\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst router = useRouter();\n\tconst [isModalOpen, setIsModalOpen] = useState(false);\n\tconst form = useForm({\n\t\tresolver: zodResolver(CreateTableSchema),\n\t\tdefaultValues: {\n\t\t\tdatabaseName: databaseName || '',\n\t\t\ttableName: '',\n\t\t\tprimaryKey: '',\n\t\t},\n\t});\n\n\tconst { mutate: submitNewTableData } = useCreateTableMutation();\n\n\tconst submitForm = async (formData: z.infer<typeof CreateTableSchema>) => {\n\t\tconst databaseName = formData.databaseName || 'data';\n\t\tconst tableName = formData.tableName;\n\t\tsubmitNewTableData({\n\t\t\tdatabaseName,\n\t\t\ttableName,\n\t\t\tprimaryKey: formData.primaryKey || 'id',\n\t\t\t...instanceParams,\n\t\t\treplicated: instanceParams.entityType === 'cluster',\n\t\t}, {\n\t\t\tonSuccess: async () => {\n\t\t\t\tawait queryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: [instanceParams.entityId, 'describe_all'],\n\t\t\t\t\trefetchType: 'all',\n\t\t\t\t});\n\t\t\t\ttoast.success(`Table ${tableName} created successfully`);\n\t\t\t\tsetIsModalOpen(false);\n\t\t\t\tform.reset();\n\t\t\t\tonSelectTable(databaseName, tableName);\n\t\t\t\tawait router.invalidate();\n\t\t\t},\n\t\t});\n\t};\n\n\treturn (\n\t\t<Dialog open={isModalOpen} onOpenChange={setIsModalOpen}>\n\t\t\t<DialogTrigger asChild>\n\t\t\t\t<div className=\"sticky bottom-0 py-4 bg-black/70 backdrop-blur-xs\">\n\t\t\t\t\t<Button variant=\"positiveOutline\" className=\"w-full rounded-full\" size=\"lg\" accessKey=\"t\">\n\t\t\t\t\t\t<Plus />\n\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\tCreate a <u>T</u>able\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</DialogTrigger>\n\t\t\t<DialogContent className=\"sm:max-w-[425px]\">\n\t\t\t\t<DialogHeader>\n\t\t\t\t\t<DialogTitle>Create a New Table</DialogTitle>\n\t\t\t\t\t<DialogDescription>\n\t\t\t\t\t\tWhat would you like to create?\n\t\t\t\t\t</DialogDescription>\n\t\t\t\t</DialogHeader>\n\t\t\t\t<Form {...form}>\n\t\t\t\t\t<form\n\t\t\t\t\t\tid=\"instance-new-table-form\"\n\t\t\t\t\t\tname=\"instance-new-table-form\"\n\t\t\t\t\t\tonSubmit={form.handleSubmit(submitForm)}\n\t\t\t\t\t\tclassName=\"grid gap-6 text-white\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"tableName\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem className=\"\">\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Table Name</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\tmaxLength={CreateTableSchema.shape.tableName.maxLength!}\n\t\t\t\t\t\t\t\t\t\t\tautoFocus={true}\n\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoCorrect=\"off\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"primaryKey\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem className=\"\">\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Primary Key</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t\tplaceholder=\"id\"\n\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\tmaxLength={CreateTableSchema.shape.primaryKey.maxLength!}\n\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoCorrect=\"off\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\tname=\"databaseName\"\n\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t<FormItem className=\"\">\n\t\t\t\t\t\t\t\t\t<FormLabel className=\"pb-1\">Database Name</FormLabel>\n\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\tplaceholder=\"data\"\n\t\t\t\t\t\t\t\t\t\t\tmaxLength={CreateTableSchema.shape.databaseName.maxLength!}\n\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\tautoCorrect=\"off\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<DialogFooter>\n\t\t\t\t\t\t\t<Button type=\"submit\" variant=\"submit\" className=\"rounded-full\">\n\t\t\t\t\t\t\t\t<Table />\n\t\t\t\t\t\t\t\tCreate New Table\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</DialogFooter>\n\t\t\t\t\t</form>\n\t\t\t\t</Form>\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { TextLoadingSkeleton } from '@/components/TextLoadingSkeleton';\nimport { Button } from '@/components/ui/button';\nimport { ScrollArea } from '@/components/ui/scrollArea';\nimport { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';\nimport { CreateNewTableModal } from '@/features/instance/databases/modals/CreateNewTableModal';\nimport { useInstanceBrowseManagePermission } from '@/hooks/usePermissions';\nimport { InstanceDatabaseMap } from '@/integrations/api/api.patch';\nimport { buildAbsoluteLinkToDatabasePage } from '@/lib/urls/buildAbsoluteLinkToDatabasePage';\nimport { useNavigate, useParams, useRouter } from '@tanstack/react-router';\nimport { ArrowRight } from 'lucide-react';\nimport { useCallback, useMemo } from 'react';\n\nexport function DatabasesSidebar({ instanceDatabaseMap }: { instanceDatabaseMap?: InstanceDatabaseMap }) {\n\tconst router = useRouter();\n\n\tconst loading = !instanceDatabaseMap;\n\n\tconst params: { databaseName?: string; tableName?: string } = useParams({ strict: false });\n\tconst navigate = useNavigate();\n\tconst canManageBrowseInstance = useInstanceBrowseManagePermission();\n\n\tconst { databaseNames, tableNames } = useMemo(() => {\n\t\tconst databaseNames = Object.keys(instanceDatabaseMap || {}).sort();\n\t\tconst tableNames = params.databaseName ? Object.keys(instanceDatabaseMap?.[params.databaseName] || []).sort() : [];\n\t\treturn {\n\t\t\tdatabaseNames,\n\t\t\ttableNames,\n\t\t};\n\t}, [instanceDatabaseMap, params.databaseName]);\n\n\tconst onSelectDatabase = useCallback((newDatabaseName: string | undefined) => {\n\t\tconst tableNames = newDatabaseName ? Object.keys(instanceDatabaseMap?.[newDatabaseName] || []).sort() : [];\n\t\tif (!params.databaseName) {\n\t\t\tvoid router.invalidate();\n\t\t} else {\n\t\t\tvoid navigate({\n\t\t\t\tto: buildAbsoluteLinkToDatabasePage({\n\t\t\t\t\t...params,\n\t\t\t\t\tdatabaseName: newDatabaseName,\n\t\t\t\t\ttableName: tableNames[0],\n\t\t\t\t}),\n\t\t\t});\n\t\t}\n\t}, [instanceDatabaseMap, params, router, navigate]);\n\n\tconst onSelectTable = useCallback((newDatabaseName: string | undefined, newTableName: string | undefined) => {\n\t\tvoid navigate({\n\t\t\tto: buildAbsoluteLinkToDatabasePage({\n\t\t\t\t...params,\n\t\t\t\tdatabaseName: newDatabaseName,\n\t\t\t\ttableName: newTableName,\n\t\t\t}),\n\t\t});\n\t}, [navigate, params]);\n\n\treturn (\n\t\t<div className=\"pl-3\">\n\t\t\t<h1 className=\"pt-3 pb-3 text-3xl\">Databases</h1>\n\t\t\t{loading\n\t\t\t\t? <TextLoadingSkeleton className=\"w-full h-9 m-0 rounded-md bg-gray-700\" />\n\t\t\t\t: (\n\t\t\t\t\t<div className=\"flex space-x-2\">\n\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\tname=\"databaseSelect\"\n\t\t\t\t\t\t\tvalue={params.databaseName || ''}\n\t\t\t\t\t\t\tdisabled={databaseNames.length === 0}\n\t\t\t\t\t\t\tonValueChange={onSelectDatabase}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<SelectTrigger className=\"w-full\">\n\t\t\t\t\t\t\t\t<SelectValue placeholder=\"Select a Database\" />\n\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t<SelectGroup>\n\t\t\t\t\t\t\t\t\t{databaseNames.map((databaseName) => (\n\t\t\t\t\t\t\t\t\t\t<SelectItem key={databaseName} value={databaseName}>\n\t\t\t\t\t\t\t\t\t\t\t{databaseName}\n\t\t\t\t\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</SelectGroup>\n\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t</Select>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t{loading\n\t\t\t\t? <TextLoadingSkeleton className=\"w-full min-h-80 rounded-md bg-gray-700 mb-0\" />\n\t\t\t\t: (\n\t\t\t\t\t<ScrollArea className=\"border rounded-md min-h-80 border-grey-700 mt-4\">\n\t\t\t\t\t\t{tableNames.length === 0 && params.databaseName?.length\n\t\t\t\t\t\t\t? (\n\t\t\t\t\t\t\t\t<div className=\"w-full h-full text-center\">\n\t\t\t\t\t\t\t\t\t<p className=\"py-6\">No tables found in this database.</p>\n\t\t\t\t\t\t\t\t\t{canManageBrowseInstance && (\n\t\t\t\t\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t\t\t\t\tTap \"Create a Table\" below!\n\t\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t: tableNames.length === 0 && !params.databaseName?.length\n\t\t\t\t\t\t\t? (\n\t\t\t\t\t\t\t\t// If no database is selected, show a message\n\t\t\t\t\t\t\t\t<p className=\"pt-2 text-sm text-center\">\n\t\t\t\t\t\t\t\t\tPlease {databaseNames.length === 0 ? 'create' : 'select'} a table.\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t: (\n\t\t\t\t\t\t\t\t''\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t<ul>\n\t\t\t\t\t\t\t{tableNames.map((tableName) => (\n\t\t\t\t\t\t\t\t<li key={tableName} className=\"flex items-center p-2 border-b hover:bg-grey-700/80 border-grey-700\">\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\t\t\tonSelectTable(params.databaseName, tableName)}\n\t\t\t\t\t\t\t\t\t\tsize=\"lg\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"items-center justify-between w-full bg-transparent border-none shadow-none hover:bg-transparent\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{tableName}\n\t\t\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t\t\t{params.tableName === tableName && <ArrowRight />}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t</ScrollArea>\n\t\t\t\t)}\n\t\t\t{canManageBrowseInstance && (\n\t\t\t\t<CreateNewTableModal\n\t\t\t\t\tdatabaseName={params.databaseName}\n\t\t\t\t\tonSelectTable={onSelectTable}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import { InstanceAttribute, InstanceTable } from '@/integrations/api/api.patch';\nimport { ColumnDef } from '@tanstack/react-table';\n\nexport function formatBrowseDataTableHeader(instanceTable?: InstanceTable): {\n\tdataTableColumns: Array<ColumnDef<Record<string, unknown>>>;\n\tprimaryKey: string;\n} {\n\tif (!instanceTable) {\n\t\treturn {\n\t\t\tdataTableColumns: [],\n\t\t\tprimaryKey: '',\n\t\t};\n\t}\n\tconst primaryKey = instanceTable.primary_key ?? instanceTable.hash_attribute ?? '';\n\tconst { attributes } = instanceTable;\n\tconst primaryKeyColumns: ColumnDef<Record<string, unknown>>[] = [];\n\tconst sortableColumns: ColumnDef<Record<string, unknown>>[] = [];\n\tconst normalColumns: ColumnDef<Record<string, unknown>>[] = [];\n\tconst timeColumns: ColumnDef<Record<string, unknown>>[] = [];\n\tfor (let i = attributes.length - 1; i >= 0; i--) {\n\t\tconst { attribute, type, is_primary_key, indexed } = attributes[i];\n\n\t\tconst dataTableColumn: ColumnDef<Record<string, unknown>> = {\n\t\t\theader: attribute,\n\t\t\taccessorKey: attribute,\n\t\t\tenableSorting: Boolean(is_primary_key || indexed),\n\t\t\tenableColumnFilter: Boolean(is_primary_key || indexed),\n\t\t\t// enableResizing: true,\n\t\t\tsize: sizeByAttributeType(type),\n\t\t};\n\t\tif (is_primary_key) {\n\t\t\tprimaryKeyColumns.push(dataTableColumn);\n\t\t} else if (attribute === '__createdtime__' || attribute === '__updatedtime__') {\n\t\t\ttimeColumns.push(dataTableColumn);\n\t\t} else if (dataTableColumn.enableSorting) {\n\t\t\tsortableColumns.push(dataTableColumn);\n\t\t} else {\n\t\t\tnormalColumns.push(dataTableColumn);\n\t\t}\n\t}\n\treturn {\n\t\tdataTableColumns: [...primaryKeyColumns, ...sortableColumns, ...normalColumns, ...timeColumns],\n\t\tprimaryKey,\n\t};\n}\n\nfunction sizeByAttributeType(type: InstanceAttribute['type']) {\n\tswitch (type) {\n\t\tcase 'Id':\n\t\tcase 'ID':\n\t\t\treturn 1;\n\t\tcase 'Boolean':\n\t\t\treturn 1;\n\t\tcase 'Int':\n\t\tcase 'Long':\n\t\tcase 'Float':\n\t\tcase 'BigInt':\n\t\t\treturn 1;\n\t\tcase 'Date':\n\t\tcase 'String':\n\t\tdefault:\n\t\t\treturn Math.round(window.innerWidth * 0.1);\n\t}\n}\n","import { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { useMutation } from '@tanstack/react-query';\n\ninterface InsertTableRecordsData extends InstanceClientConfig {\n\tdatabaseName: string;\n\ttableName: string;\n\trecords: object[];\n}\n\nexport interface InsertTableRecordsResponse {\n\tmessage: string;\n\tinserted_hashes: string[];\n\tskipped_hashes: string[];\n}\n\nexport async function insertTableRecords({ databaseName, tableName, records, instanceClient }: InsertTableRecordsData) {\n\tconst { data } = await instanceClient.post<InsertTableRecordsResponse>('/', {\n\t\toperation: 'insert',\n\t\tdatabase: databaseName,\n\t\ttable: tableName,\n\t\trecords: records,\n\t});\n\treturn data;\n}\n\nexport function useInsertTableRecords() {\n\treturn useMutation({\n\t\tmutationFn: insertTableRecords,\n\t});\n}\n","import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';\nimport { Button } from '@/components/ui/button';\nimport { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { InstanceAttribute, InstanceTable } from '@/integrations/api/api.patch';\nimport { useInsertTableRecords } from '@/integrations/api/instance/database/insertTableRecords';\nimport { pluralize } from '@/lib/pluralize';\nimport Editor, { EditorProps, OnMount } from '@monaco-editor/react';\nimport { Save, TerminalIcon } from 'lucide-react';\nimport { useCallback, useMemo, useState } from 'react';\nimport { toast } from 'sonner';\n\nexport function AddTableRowModal({\n\tisModalOpen,\n\tinstanceTable,\n\tsetIsModalOpen,\n\trefreshTable,\n}: {\n\tinstanceTable: InstanceTable;\n\tisModalOpen: boolean;\n\tsetIsModalOpen: (open: boolean) => void;\n\trefreshTable: () => void;\n}) {\n\tconst { mutate: addTableRecords, isPending: isAddTableRecordsPending } = useInsertTableRecords();\n\tconst instanceParams = useInstanceClientIdParams();\n\n\tconst [isValidJSON, setIsValidJSON] = useState(true);\n\tconst [addTableRecordData, setAddTableRecordData] = useState<string>();\n\tconst [madeChanges, setMadeChanges] = useState(false);\n\tconst [skippedHashes, setSkippedHashes] = useState<string[]>([]);\n\n\tconst sampleJSON = useMemo(() => {\n\t\tconst sample: Record<string, unknown> = {};\n\t\tfor (const attribute of instanceTable.attributes) {\n\t\t\tif (\n\t\t\t\tattribute.is_primary_key || attribute.attribute === '__createdtime__'\n\t\t\t\t|| attribute.attribute === '__updatedtime__'\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tsample[attribute.attribute] = defaultByAttributeType(attribute.type);\n\t\t}\n\t\treturn JSON.stringify(sample, null, 4);\n\t}, [instanceTable]);\n\n\tconst onValidate = useCallback((markers: unknown[]) => {\n\t\tsetMadeChanges(true);\n\t\tsetIsValidJSON(markers.length === 0);\n\t}, [setIsValidJSON]);\n\n\tconst onSubmitClick = useCallback(() => {\n\t\tif (addTableRecordData && isValidJSON) {\n\t\t\tconst data = JSON.parse(addTableRecordData);\n\t\t\tconst records = Array.isArray(data) ? data : [data];\n\t\t\tconst toastId = toast.loading(`Adding ${records.length} records...`);\n\t\t\taddTableRecords(\n\t\t\t\t{\n\t\t\t\t\t...instanceParams,\n\t\t\t\t\tdatabaseName: instanceTable.schema,\n\t\t\t\t\ttableName: instanceTable.name,\n\t\t\t\t\trecords,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tonSuccess: (response) => {\n\t\t\t\t\t\tvoid refreshTable();\n\t\t\t\t\t\tif (!response.skipped_hashes?.length) {\n\t\t\t\t\t\t\tsetIsModalOpen(false);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsetSkippedHashes(response.skipped_hashes);\n\t\t\t\t\t\t(response.skipped_hashes?.length > 0 ? toast.warning : toast.success)(\n\t\t\t\t\t\t\tresponse.skipped_hashes?.length > 0 ? 'Warning!' : 'Success!',\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tid: toastId,\n\t\t\t\t\t\t\t\tdescription: (\n\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t{response.inserted_hashes.length > 0\n\t\t\t\t\t\t\t\t\t\t\t&& <p>Added {pluralize(response.inserted_hashes.length, 'record', 'records')}</p>}\n\t\t\t\t\t\t\t\t\t\t{response.skipped_hashes.length > 0\n\t\t\t\t\t\t\t\t\t\t\t&& <p>Skipped {pluralize(response.skipped_hashes.length, 'record', 'records')}</p>}\n\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}, [\n\t\taddTableRecordData,\n\t\taddTableRecords,\n\t\tinstanceParams,\n\t\tinstanceTable.name,\n\t\tinstanceTable.schema,\n\t\tisValidJSON,\n\t\trefreshTable,\n\t\tsetIsModalOpen,\n\t]);\n\n\tconst handleEditorDidMount: EditorProps['onMount'] = useCallback<OnMount>((editor) => {\n\t\teditor?.focus();\n\t}, []);\n\n\treturn (\n\t\t<Dialog onOpenChange={setIsModalOpen} open={isModalOpen}>\n\t\t\t{/* NOTE - Is this okay to do for the aria describedby? */}\n\t\t\t<DialogContent\n\t\t\t\taria-describedby={undefined}\n\t\t\t\tonEscapeKeyDown={(event) => {\n\t\t\t\t\tif (madeChanges) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<DialogHeader>\n\t\t\t\t\t<DialogTitle>Add New {instanceTable.name}</DialogTitle>\n\t\t\t\t</DialogHeader>\n\t\t\t\t{(instanceTable?.primary_key ?? instanceTable?.hash_attribute)\n\t\t\t\t\t&& (\n\t\t\t\t\t\t<div className=\"text-sm text-gray-500\">\n\t\t\t\t\t\t\tThe primary key for this table is{' '}\n\t\t\t\t\t\t\t<strong>“{instanceTable.primary_key ?? instanceTable.hash_attribute}”</strong>, and will\n\t\t\t\t\t\t\tauto-generate. You may manually add it if you want to specify its value.\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t<Editor\n\t\t\t\t\tclassName=\"w-full h-96\"\n\t\t\t\t\tlanguage=\"json\"\n\t\t\t\t\ttheme=\"vs-dark\"\n\t\t\t\t\tvalue={sampleJSON}\n\t\t\t\t\tonValidate={onValidate}\n\t\t\t\t\tonChange={setAddTableRecordData}\n\t\t\t\t\toptions={{ minimap: { enabled: false } }}\n\t\t\t\t\tonMount={handleEditorDidMount}\n\t\t\t\t/>\n\t\t\t\t<div className=\"text-sm text-gray-500\">\n\t\t\t\t\t<strong>Provide an [array]</strong> if you want to add more than one record at a time.\n\t\t\t\t</div>\n\n\t\t\t\t{skippedHashes.length > 0 && (\n\t\t\t\t\t<Alert className=\"mt-2\">\n\t\t\t\t\t\t<TerminalIcon className=\"w-4 h-4\" />\n\t\t\t\t\t\t<AlertTitle>\n\t\t\t\t\t\t\tSkipped {skippedHashes.length === 1 ? 'Hash' : 'Hashes'} Detected\n\t\t\t\t\t\t</AlertTitle>\n\t\t\t\t\t\t<AlertDescription className=\"max-h-36 overflow-auto\">\n\t\t\t\t\t\t\t<ol>\n\t\t\t\t\t\t\t\t{skippedHashes.map(hash => <li key={hash}>{hash}</li>)}\n\t\t\t\t\t\t\t</ol>\n\t\t\t\t\t\t</AlertDescription>\n\t\t\t\t\t</Alert>\n\t\t\t\t)}\n\n\t\t\t\t<DialogFooter>\n\t\t\t\t\t<div className=\"flex justify-between w-full\">\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"submit\"\n\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\tonClick={onSubmitClick}\n\t\t\t\t\t\t\taccessKey=\"s\"\n\t\t\t\t\t\t\tdisabled={!addTableRecordData || !isValidJSON || isAddTableRecordsPending}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Save />{' '}\n\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t<u>S</u>ave Changes\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t</DialogFooter>\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n\nfunction defaultByAttributeType(type: InstanceAttribute['type']) {\n\tswitch (type) {\n\t\tcase 'Date':\n\t\t\treturn new Date().toISOString();\n\t\tcase 'Id':\n\t\tcase 'ID':\n\t\tcase 'String':\n\t\t\treturn '';\n\t\tcase 'Boolean':\n\t\t\treturn false;\n\t\tcase 'Int':\n\t\tcase 'Long':\n\t\tcase 'Float':\n\t\tcase 'BigInt':\n\t\t\treturn 0;\n\t\tdefault:\n\t\t\treturn null;\n\t}\n}\n","import { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { ReplicatedResponse } from '@/integrations/api/replication';\nimport { useMutation } from '@tanstack/react-query';\n\ninterface DeleteDatabaseParams extends InstanceClientConfig {\n\tdatabaseName: string;\n\treplicated: boolean;\n}\n\nasync function onDeleteDatabase(\n\t{ databaseName, replicated, instanceClient }: DeleteDatabaseParams,\n): Promise<ReplicatedResponse> {\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation: 'drop_database',\n\t\tdatabase: databaseName,\n\t\treplicated,\n\t});\n\treturn data;\n}\n\nexport function useDeleteDatabaseMutation() {\n\treturn useMutation({\n\t\tmutationFn: onDeleteDatabase,\n\t});\n}\n","import { ConfirmDeletionModal } from '@/components/ConfirmDeletionModal';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { useInstanceBrowseManagePermission } from '@/hooks/usePermissions';\nimport { useDeleteDatabaseMutation } from '@/integrations/api/instance/database/deleteDatabase';\nimport { attemptToRestoreFocus } from '@/lib/attemptToRestoreFocus';\nimport { setWatchedValue, useWatchedValue } from '@/lib/events/watcher';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useRouter } from '@tanstack/react-router';\nimport { useCallback } from 'react';\nimport { toast } from 'sonner';\n\nexport function DeleteDatabaseModal({ databaseName, onDeleted }: {\n\treadonly databaseName: string;\n\treadonly onDeleted: (deleted: 'table' | 'database') => void;\n}) {\n\tconst { value: isModalOpen, trigger } = useWatchedValue('ShowDeleteDatabase', false);\n\tconst closeModal = useCallback(() => {\n\t\tsetWatchedValue('ShowDeleteDatabase', false);\n\t\tattemptToRestoreFocus(trigger);\n\t}, [trigger]);\n\n\tconst canManageBrowseInstance = useInstanceBrowseManagePermission();\n\tconst queryClient = useQueryClient();\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst router = useRouter();\n\tconst { mutate: deleteDatabase, isPending: isDeletingDatabase } = useDeleteDatabaseMutation();\n\n\tconst onDeleteDatabase = useCallback(() => {\n\t\tdeleteDatabase({\n\t\t\tdatabaseName,\n\t\t\t...instanceParams,\n\t\t\treplicated: instanceParams.entityType === 'cluster',\n\t\t}, {\n\t\t\tonSuccess: async () => {\n\t\t\t\tcloseModal();\n\t\t\t\tawait queryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: [instanceParams.entityId, 'describe_all'],\n\t\t\t\t\trefetchType: 'all',\n\t\t\t\t});\n\t\t\t\tawait router.invalidate();\n\t\t\t\ttoast.success(`Database ${databaseName} dropped successfully`);\n\t\t\t\tonDeleted('database');\n\t\t\t},\n\t\t});\n\t}, [closeModal, databaseName, deleteDatabase, instanceParams, onDeleted, queryClient, router]);\n\n\tif (!canManageBrowseInstance || !databaseName) {\n\t\treturn <></>;\n\t}\n\n\treturn (\n\t\t<ConfirmDeletionModal\n\t\t\ttypeOfThingBeingDeleted=\"database\"\n\t\t\tnameOfThingBeingDeleted={databaseName}\n\t\t\ttransitiveVerb=\"Drop\"\n\t\t\tpresentParticiple=\"Dropping\"\n\t\t\tisModalOpen={isModalOpen}\n\t\t\tsetIsModalOpen={closeModal}\n\t\t\tdeletionConfirmed={onDeleteDatabase}\n\t\t\tdeletionPending={isDeletingDatabase}\n\t\t/>\n\t);\n}\n","import { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { ReplicatedResponse } from '@/integrations/api/replication';\nimport { useMutation } from '@tanstack/react-query';\n\ninterface DeleteTableData extends InstanceClientConfig {\n\tdatabaseName: string;\n\ttableName: string;\n\treplicated: boolean;\n}\n\nasync function onDeleteTable(\n\t{ databaseName, tableName, replicated, instanceClient }: DeleteTableData,\n): Promise<ReplicatedResponse> {\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation: 'drop_table',\n\t\tdatabase: databaseName,\n\t\ttable: tableName,\n\t\treplicated,\n\t});\n\treturn data;\n}\n\nexport function useDeleteTableMutation() {\n\treturn useMutation({\n\t\tmutationFn: onDeleteTable,\n\t});\n}\n","import { ConfirmDeletionModal } from '@/components/ConfirmDeletionModal';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { useInstanceBrowseManagePermission } from '@/hooks/usePermissions';\nimport { useDeleteTableMutation } from '@/integrations/api/instance/database/deleteTable';\nimport { attemptToRestoreFocus } from '@/lib/attemptToRestoreFocus';\nimport { setWatchedValue, useWatchedValue } from '@/lib/events/watcher';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useRouter } from '@tanstack/react-router';\nimport { useCallback } from 'react';\nimport { toast } from 'sonner';\n\nexport function DeleteTableModal({ databaseName, tableName, onDeleted }: {\n\treadonly databaseName: string;\n\treadonly tableName: string;\n\treadonly onDeleted: (deleted: 'table' | 'database') => void;\n}) {\n\tconst { value: isModalOpen, trigger } = useWatchedValue('ShowDeleteTable', false);\n\tconst closeModal = useCallback(() => {\n\t\tsetWatchedValue('ShowDeleteTable', false);\n\t\tattemptToRestoreFocus(trigger);\n\t}, [trigger]);\n\n\tconst canManageBrowseInstance = useInstanceBrowseManagePermission();\n\tconst queryClient = useQueryClient();\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst router = useRouter();\n\tconst { mutate: deleteTable, isPending: isDeletingTable } = useDeleteTableMutation();\n\n\tconst onDeleteTable = useCallback(() => {\n\t\tdeleteTable(\n\t\t\t{\n\t\t\t\tdatabaseName,\n\t\t\t\ttableName,\n\t\t\t\t...instanceParams,\n\t\t\t\treplicated: instanceParams.entityType === 'cluster',\n\t\t\t},\n\t\t\t{\n\t\t\t\tonSuccess: async () => {\n\t\t\t\t\tcloseModal();\n\t\t\t\t\tawait queryClient.invalidateQueries({\n\t\t\t\t\t\tqueryKey: [instanceParams.entityId, 'describe_all'],\n\t\t\t\t\t\trefetchType: 'all',\n\t\t\t\t\t});\n\t\t\t\t\tawait router.invalidate();\n\t\t\t\t\ttoast.success(`Table ${tableName} dropped successfully`);\n\t\t\t\t\tonDeleted('table');\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}, [closeModal, databaseName, deleteTable, instanceParams, onDeleted, queryClient, router, tableName]);\n\n\tif (!canManageBrowseInstance || !databaseName) {\n\t\treturn <></>;\n\t}\n\n\treturn (\n\t\t<ConfirmDeletionModal\n\t\t\ttypeOfThingBeingDeleted=\"table\"\n\t\t\tnameOfThingBeingDeleted={`${databaseName} > ${tableName}`}\n\t\t\ttransitiveVerb=\"Drop\"\n\t\t\tpresentParticiple=\"Dropping\"\n\t\t\tisModalOpen={isModalOpen}\n\t\t\tsetIsModalOpen={closeModal}\n\t\t\tdeletionConfirmed={onDeleteTable}\n\t\t\tdeletionPending={isDeletingTable}\n\t\t/>\n\t);\n}\n","import { Loading } from '@/components/Loading';\nimport { Button } from '@/components/ui/button';\nimport { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';\nimport Editor from '@monaco-editor/react';\nimport { Save, Trash } from 'lucide-react';\nimport { useCallback, useMemo, useState } from 'react';\n\nexport function EditTableRowModal({\n\tcanEditRecords,\n\tcanDeleteRecords,\n\tsetIsModalOpen,\n\tisModalOpen,\n\tprimaryKey,\n\tdata,\n\tonSaveChanges,\n\tonDeleteRecord,\n\tisUpdateTableRecordsPending,\n\tisDeleteTableRecordsPending,\n}: {\n\tcanEditRecords: boolean;\n\tcanDeleteRecords: boolean;\n\tsetIsModalOpen: (open: boolean) => void;\n\tisModalOpen: boolean;\n\tprimaryKey: string;\n\tdata: { __createdtime__?: number; __updatedtime__?: number; [record: string]: unknown }[];\n\tonSaveChanges: (data: Record<string, unknown>[]) => void;\n\tonDeleteRecord: (data: unknown[]) => void;\n\tisUpdateTableRecordsPending: boolean;\n\tisDeleteTableRecordsPending: boolean;\n}) {\n\tconst [isValidJSON, setIsValidJSON] = useState(true);\n\tconst [madeChanges, setMadeChanges] = useState(false);\n\tconst [updatedTableRecordData, setUpdatedTableRecordData] = useState<string>();\n\n\tconst value = useMemo(() => {\n\t\tconst dataWithoutTimes = data?.map(({ __createdtime__, __updatedtime__, ...rowWithoutTime }) => rowWithoutTime);\n\t\treturn JSON.stringify(dataWithoutTimes, null, 4);\n\t}, [data]);\n\tconst onValidate = useCallback((markers: unknown[]) => {\n\t\tsetMadeChanges(true);\n\t\tsetIsValidJSON(markers.length === 0);\n\t}, [setIsValidJSON]);\n\n\treturn (\n\t\t<Dialog onOpenChange={setIsModalOpen} open={isModalOpen}>\n\t\t\t{/* NOTE - Is this okay to do for the aria describedby? */}\n\t\t\t<DialogContent\n\t\t\t\taria-describedby={undefined}\n\t\t\t\tautoFocus={canEditRecords}\n\t\t\t\tonEscapeKeyDown={canEditRecords\n\t\t\t\t\t? (event) => {\n\t\t\t\t\t\tif (madeChanges) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t: undefined}\n\t\t\t>\n\t\t\t\t<DialogHeader>\n\t\t\t\t\t<DialogTitle>{canEditRecords ? 'Edit' : 'View'} Row</DialogTitle>\n\t\t\t\t</DialogHeader>\n\t\t\t\t{data\n\t\t\t\t\t? (\n\t\t\t\t\t\t<Editor\n\t\t\t\t\t\t\tclassName=\"w-full h-96\"\n\t\t\t\t\t\t\tlanguage=\"json\"\n\t\t\t\t\t\t\ttheme=\"vs-dark\"\n\t\t\t\t\t\t\toptions={canEditRecords ? undefined : { readOnly: true }}\n\t\t\t\t\t\t\tvalue={value}\n\t\t\t\t\t\t\tonValidate={onValidate}\n\t\t\t\t\t\t\tonChange={(updatedValue) => {\n\t\t\t\t\t\t\t\tsetUpdatedTableRecordData(updatedValue);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)\n\t\t\t\t\t: <Loading />}\n\t\t\t\t<DialogFooter>\n\t\t\t\t\t<div className=\"flex justify-between w-full\">\n\t\t\t\t\t\t{canDeleteRecords && (\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tvariant=\"destructive\"\n\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tautoFocus={false}\n\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\tconst primaryKeyValue = data[0]?.[primaryKey];\n\t\t\t\t\t\t\t\t\tif (primaryKeyValue) {\n\t\t\t\t\t\t\t\t\t\tonDeleteRecord([primaryKeyValue]);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tdisabled={isDeleteTableRecordsPending}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Trash /> Delete Row\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{canEditRecords && (\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tvariant=\"submit\"\n\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\tautoFocus={true}\n\t\t\t\t\t\t\t\taccessKey=\"s\"\n\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\tif (updatedTableRecordData && isValidJSON) {\n\t\t\t\t\t\t\t\t\t\tonSaveChanges(JSON.parse(updatedTableRecordData));\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tsetIsModalOpen(false);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tdisabled={!isValidJSON || isUpdateTableRecordsPending}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Save />{' '}\n\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t<u>S</u>ave Changes\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t</DialogFooter>\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { useMutation } from '@tanstack/react-query';\n\nexport interface AddCSVDataFormData {\n\tdatabase: string;\n\ttable: string;\n\tfileData: string;\n}\nexport interface AddCSVDataResponse {\n\tmessage: string;\n\tjob_id: string;\n}\n\nexport async function onAddCSVDataSubmit(formData: AddCSVDataFormData & InstanceClientConfig) {\n\tconst { database, table, fileData, instanceClient } = formData;\n\tconst { data } = await instanceClient.post(\n\t\t'/',\n\t\t{\n\t\t\toperation: 'csv_data_load',\n\t\t\tdatabase,\n\t\t\taction: 'insert',\n\t\t\ttable,\n\t\t\tdata: fileData,\n\t\t},\n\t);\n\treturn data;\n}\n\nexport function useAddCSVDataMutation() {\n\treturn useMutation<AddCSVDataResponse, Error, AddCSVDataFormData & InstanceClientConfig>({\n\t\tmutationFn: onAddCSVDataSubmit,\n\t});\n}\n","import { z } from 'zod';\n\nexport const AddCSVDataFormSchema = z.object({\n\tfileData: z.string(),\n\tdatabase: z.string(),\n\ttable: z.string(),\n});\n","import { Button } from '@/components/ui/button';\nimport {\n\tDialog,\n\tDialogContent,\n\tDialogDescription,\n\tDialogFooter,\n\tDialogHeader,\n\tDialogTitle,\n} from '@/components/ui/dialog';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { AddCSVDataFormData, useAddCSVDataMutation } from '@/integrations/api/instance/database/addCSVData';\nimport { AddCSVDataFormSchema } from '@/integrations/api/instance/database/addCSVDataFormSchema';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { CloudUploadIcon, Save } from 'lucide-react';\nimport { useState } from 'react';\nimport { useForm } from 'react-hook-form';\n\nexport function ImportCSVModal({\n\tsetIsModalOpen,\n\tisModalOpen,\n\tonSaveChanges,\n\tdatabase,\n\ttable,\n}: {\n\tsetIsModalOpen: (open: boolean) => void;\n\tisModalOpen: boolean;\n\tonSaveChanges: (message: string) => void;\n\tdatabase: string;\n\ttable: string;\n}) {\n\tconst [selectedCSVFile, setSelectedCSVFile] = useState<File | null>(null);\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst { mutate: addCSVData, isPending: isAddCSVDataPending } = useAddCSVDataMutation();\n\n\tconst onFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n\t\tif (!e.target.files) { return; }\n\t\tconst file = e.target.files[0];\n\t\tif (file) {\n\t\t\tconst reader = new FileReader();\n\t\t\treader.onload = (event) => {\n\t\t\t\tconst text = event.target?.result;\n\t\t\t\tif (typeof text === 'string') {\n\t\t\t\t\tsetSelectedCSVFile(file);\n\t\t\t\t\tform.setValue('fileData', text);\n\t\t\t\t}\n\t\t\t};\n\t\t\treader.readAsText(file);\n\t\t}\n\t};\n\n\tconst form = useForm({\n\t\tresolver: zodResolver(AddCSVDataFormSchema),\n\t\tdefaultValues: {\n\t\t\tdatabase,\n\t\t\ttable,\n\t\t\tfileData: '',\n\t\t},\n\t});\n\n\tconst submitForm = (formData: AddCSVDataFormData) => {\n\t\taddCSVData(\n\t\t\t{\n\t\t\t\tfileData: formData.fileData,\n\t\t\t\tdatabase,\n\t\t\t\ttable,\n\t\t\t\t...instanceParams,\n\t\t\t},\n\t\t\t{\n\t\t\t\tonSuccess: ({ message }: { message: string }) => {\n\t\t\t\t\tform.reset();\n\t\t\t\t\tsetSelectedCSVFile(null);\n\t\t\t\t\tonSaveChanges(message);\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t};\n\n\treturn (\n\t\t<Dialog\n\t\t\tonOpenChange={() => {\n\t\t\t\tsetIsModalOpen(false);\n\t\t\t\tform.reset();\n\t\t\t}}\n\t\t\topen={isModalOpen}\n\t\t>\n\t\t\t<DialogContent>\n\t\t\t\t<DialogHeader>\n\t\t\t\t\t<DialogTitle>Import CSV</DialogTitle>\n\t\t\t\t\t<DialogDescription>Upload a CSV file to import data into the table.</DialogDescription>\n\t\t\t\t</DialogHeader>\n\t\t\t\t<Form {...form}>\n\t\t\t\t\t<form\n\t\t\t\t\t\tid=\"instance-import-csv-form\"\n\t\t\t\t\t\tname=\"instance-import-csv-form\"\n\t\t\t\t\t\tonSubmit={form.handleSubmit(submitForm)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div className=\"w-full\">\n\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\t\t\tname=\"fileData\"\n\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t<FormItem className=\"relative\">\n\t\t\t\t\t\t\t\t\t\t<FormLabel\n\t\t\t\t\t\t\t\t\t\t\thtmlFor=\"dropzone-file\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"flex flex-col items-center justify-center w-full h-64 border-2 border-grey border-dashed rounded-lg cursor-pointer bg-grey-700 hover:bg-grey-700/80\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"flex flex-col items-center justify-center pt-5 pb-6\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<CloudUploadIcon className=\"text-white\" size={48} />\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<p className=\"mb-2 text-sm text-white\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{selectedCSVFile\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tselectedCSVFile.name\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"font-semibold\">Click to upload</span> or drag and drop a CSV File\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tid=\"dropzone-file\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"file\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"opacity-0 w-full h-full absolute left-0 top-0 cursor-pointer\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\taccept=\".csv\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tname={field.name}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tref={field.ref}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonBlur={field.onBlur}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={field.disabled}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonChange={onFileChange}\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t</FormLabel>\n\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<DialogFooter className=\"mt-4\">\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tvariant=\"submit\"\n\t\t\t\t\t\t\t\tclassName=\"rounded-full\"\n\t\t\t\t\t\t\t\taccessKey=\"u\"\n\t\t\t\t\t\t\t\tdisabled={!selectedCSVFile || isAddCSVDataPending}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Save />\n\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t<u>U</u>pload CSV\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</DialogFooter>\n\t\t\t\t\t</form>\n\t\t\t\t</Form>\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { ReplicatedResponse } from '@/integrations/api/replication';\nimport { useMutation } from '@tanstack/react-query';\n\ninterface CleanupOrphanBlobsParams extends InstanceClientConfig {\n\tdatabaseName: string;\n}\n\nasync function onCleanupOrphanBlobs(\n\t{ databaseName, instanceClient }: CleanupOrphanBlobsParams,\n): Promise<ReplicatedResponse> {\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation: 'cleanup_orphan_blobs',\n\t\tdatabase: databaseName,\n\t});\n\treturn data;\n}\n\nexport function useCleanupOrphanBlobsMutation() {\n\treturn useMutation({\n\t\tmutationFn: onCleanupOrphanBlobs,\n\t});\n}\n","import { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { useMutation } from '@tanstack/react-query';\n\ninterface DeleteTableRecordsData extends InstanceClientConfig {\n\tdatabaseName: string;\n\ttableName: string;\n\thashValues: unknown[];\n}\n\nexport async function deleteTableRecords(\n\t{ databaseName, tableName, hashValues, instanceClient }: DeleteTableRecordsData,\n) {\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation: 'delete',\n\t\tdatabase: databaseName,\n\t\ttable: tableName,\n\t\thash_values: hashValues,\n\t});\n\treturn data;\n}\n\nexport function useDeleteTableRecords() {\n\treturn useMutation({\n\t\tmutationFn: deleteTableRecords,\n\t});\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { InstanceTable } from '@/integrations/api/api.patch';\nimport { queryOptions } from '@tanstack/react-query';\n\ninterface GetDescribeTableParams extends InstanceClientIdConfig {\n\tdatabaseName: string;\n\ttableName: string;\n}\n\nexport async function getDescribeTable({ databaseName, tableName, instanceClient }: GetDescribeTableParams) {\n\tconst { data } = await instanceClient.post<InstanceTable>('/', {\n\t\toperation: 'describe_table',\n\t\tdatabase: databaseName,\n\t\ttable: tableName,\n\t});\n\treturn data;\n}\n\nexport function getDescribeTableQueryOptions(params: GetDescribeTableParams) {\n\treturn queryOptions({\n\t\tqueryKey: [params.entityId, params.databaseName, params.tableName, 'describe_table'] as const,\n\t\tqueryFn: () => getDescribeTable(params),\n\t\tstaleTime: 60_000,\n\t\tgcTime: 5_000,\n\t\tenabled: !!params.databaseName && !!params.tableName,\n\t\tretry: false,\n\t});\n}\n","const acceptedTrueValues = [\n\t'1',\n\t'bet',\n\t'k',\n\t'ok',\n\t'si',\n\t'tru',\n\t'true',\n\t'yes',\n\t'yup',\n];\n\nexport function translateKnownBooleanTypedValue(value: string): boolean {\n\tconst lowerValue = value.toLowerCase().trim();\n\treturn acceptedTrueValues.includes(lowerValue);\n}\n","export function isNumber(str: string): boolean {\n\treturn !isNaN(str as unknown as number)\n\t\t&& !isNaN(parseFloat(str));\n}\n","import { isNumber } from '@/lib/numbers/isNumber';\n\n/**\n * function to check if a string is a number based on the rules used by our autocaster\n */\nexport function autoCasterIsNumberCheck(data: string): boolean {\n\tif (data.startsWith('0.') && isNumber(data)) {\n\t\treturn true;\n\t}\n\n\tconst containsE = data.toUpperCase().includes('E');\n\tconst startsWithZero = data !== '0' && data.startsWith('0');\n\treturn !startsWithZero && !containsE && isNumber(data);\n}\n","import { autoCasterIsNumberCheck } from '@/lib/numbers/autoCasterIsNumberCheck';\n\nconst autoCastCommonStringsMap: Record<string, boolean | null | number> = {\n\ttrue: true,\n\tTRUE: true,\n\tfalse: false,\n\tFALSE: false,\n\tundefined: null,\n\tnull: null,\n\tNULL: null,\n\tNaN: NaN,\n};\nconst isoDateRegex =\n\t/^((\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d:[0-5]\\d|Z))|(\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d([+-][0-2]\\d:[0-5]\\d|Z))|(\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d([+-][0-2]\\d:[0-5]\\d|Z)))$/;\n\n/**\n * Takes a raw string value and casts it to a potentially correct data type.\n * @param data\n * @returns\n */\nexport function autoCast(data: unknown) {\n\tif (data === null || data === undefined || data === '') {\n\t\treturn data;\n\t}\n\n\t// if this is already typed other than string, return data\n\tif (typeof data !== 'string') {\n\t\treturn data;\n\t}\n\n\t// Try to make it a common string\n\tif (autoCastCommonStringsMap[data] !== undefined) {\n\t\treturn autoCastCommonStringsMap[data];\n\t}\n\n\tif (autoCasterIsNumberCheck(data)) {\n\t\treturn Number(data);\n\t}\n\n\tif (isoDateRegex.test(data)) { return new Date(data); }\n\n\treturn data;\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { InstanceAttribute } from '@/integrations/api/api.patch';\nimport { translateKnownBooleanTypedValue } from '@/lib/boolean/translateKnownBooleanTypedValue';\nimport { autoCast } from '@/lib/casting/autoCast';\nimport { queryOptions } from '@tanstack/react-query';\n\ninterface GetSearchByConditionsParams extends InstanceClientIdConfig {\n\tenabled: boolean;\n\tdatabaseName: string;\n\ttableName: string;\n\tconditions: SearchCondition[] | null;\n\tsort: { attribute: string; descending: boolean };\n\tpageIndex: number;\n\tpageSize: number;\n\tonlyIfCached: boolean;\n\theaders?: Record<string, any>;\n}\n\ntype Comparator =\n\t| 'between'\n\t// | 'contains' // Turned off for performance reasons until we add warnings for the user.\n\t// | 'ends_with' // Turned off for performance reasons until we add warnings for the user.\n\t| 'eq'\n\t| 'equals'\n\t| 'greater_than'\n\t| 'greater_than_equal'\n\t| 'less_than'\n\t| 'less_than_equal'\n\t| 'ne'\n\t| 'not_equal'\n\t| 'starts_with';\n\nexport interface SearchCondition {\n\tsearch_attribute: string;\n\tsearch_type: Comparator;\n\tsearch_value: unknown;\n}\n\ninterface SearchByConditionsRequest {\n\toperation: 'search_by_conditions';\n\tdatabase: string;\n\ttable: string;\n\tconditions: SearchCondition[];\n\tsort?: { attribute: string; descending: boolean };\n\toffset: number;\n\tlimit: number;\n\tget_attributes?: string[];\n\tonlyIfCached: boolean;\n\tnoCacheStore: boolean;\n}\n\nexport function getSearchByConditionsOptions(params: GetSearchByConditionsParams) {\n\tconst {\n\t\tenabled,\n\t\tentityId,\n\t\tdatabaseName,\n\t\ttableName,\n\t\tconditions,\n\t\tsort,\n\t\tpageIndex,\n\t\tpageSize,\n\t\tonlyIfCached,\n\t} = params;\n\t// starts_with, equals, etc\n\treturn queryOptions({\n\t\tenabled: enabled && !!conditions,\n\t\tqueryKey: [\n\t\t\tentityId,\n\t\t\tdatabaseName,\n\t\t\ttableName,\n\t\t\t'search_by_conditions',\n\t\t\tconditions,\n\t\t\tsort.attribute || 'default',\n\t\t\tsort.descending || false,\n\t\t\tpageIndex || 0,\n\t\t\tpageSize || 0,\n\t\t\tonlyIfCached,\n\t\t] as const,\n\t\tstaleTime: 60_000,\n\t\tgcTime: 5_000,\n\t\tretry: false,\n\t\tqueryFn: () => getSearchByConditions(params),\n\t});\n}\n\nexport function getSearchByConditions<T = Record<string, unknown>>({\n\tinstanceClient,\n\tdatabaseName,\n\ttableName,\n\tconditions,\n\tsort,\n\tpageIndex,\n\tpageSize,\n\tonlyIfCached,\n\theaders,\n}: Omit<GetSearchByConditionsParams, 'enabled'>) {\n\treturn instanceClient.post<T[]>(\n\t\t'/',\n\t\t{\n\t\t\toperation: 'search_by_conditions',\n\t\t\tget_attributes: ['*'],\n\t\t\tdatabase: databaseName,\n\t\t\ttable: tableName,\n\t\t\tconditions: conditions!,\n\t\t\tsort: sort.attribute.length ? sort : undefined,\n\t\t\toffset: pageIndex * pageSize,\n\t\t\tlimit: pageSize,\n\t\t\tonlyIfCached: onlyIfCached,\n\t\t\tnoCacheStore: onlyIfCached,\n\t\t} satisfies SearchByConditionsRequest,\n\t\t{ timeout: 0, headers },\n\t);\n}\n\nexport function translateColumnFilterToSearchConditions(\n\tkey: string,\n\trawValues: string,\n\tattribute: InstanceAttribute | undefined,\n): SearchCondition[] {\n\tconst split = rawValues.split(/ & /);\n\treturn split.map(rawValue => translateColumnFilterToSearchCondition(key, rawValue, attribute));\n}\n\nexport function translateColumnFilterToSearchCondition(\n\tkey: string,\n\trawValue: string,\n\tattribute: InstanceAttribute | undefined,\n): SearchCondition {\n\tif (rawValue.startsWith(key)) {\n\t\trawValue = rawValue.substring(key.length);\n\t}\n\tconst { comparator, value } = parseComparator(rawValue);\n\tswitch (attribute?.type) {\n\t\tcase 'ID':\n\t\tcase 'String': {\n\t\t\treturn {\n\t\t\t\tsearch_attribute: key,\n\t\t\t\tsearch_type: comparator,\n\t\t\t\tsearch_value: value,\n\t\t\t};\n\t\t}\n\t\tcase 'Int':\n\t\tcase 'BigInt':\n\t\tcase 'Long':\n\t\tcase 'Float': {\n\t\t\tconst parsed = attribute.type.includes('Int') ? parseInt(value, 10) : parseFloat(value);\n\t\t\tif (isNaN(parsed)) {\n\t\t\t\tthrow new Error(`${value} does not appear to be a valid number.`);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tsearch_attribute: key,\n\t\t\t\tsearch_type: comparator,\n\t\t\t\tsearch_value: parsed,\n\t\t\t};\n\t\t}\n\t\tcase 'Date': {\n\t\t\tconst parsed = new Date(value).toISOString();\n\t\t\treturn {\n\t\t\t\tsearch_attribute: key,\n\t\t\t\tsearch_type: comparator,\n\t\t\t\tsearch_value: parsed,\n\t\t\t};\n\t\t}\n\t\tcase 'Boolean': {\n\t\t\treturn {\n\t\t\t\tsearch_attribute: key,\n\t\t\t\tsearch_type: comparator,\n\t\t\t\tsearch_value: translateKnownBooleanTypedValue(value),\n\t\t\t};\n\t\t}\n\t\tcase 'Blob':\n\t\tcase 'Bytes':\n\t\t\treturn {\n\t\t\t\tsearch_attribute: key,\n\t\t\t\tsearch_type: comparator,\n\t\t\t\tsearch_value: value,\n\t\t\t};\n\t\tcase 'Any':\n\t\tdefault:\n\t\t\treturn {\n\t\t\t\tsearch_attribute: key,\n\t\t\t\tsearch_type: comparator,\n\t\t\t\tsearch_value: autoCast(value),\n\t\t\t};\n\t}\n}\n\nconst comparatorEqualityPrefixMappings: Record<string, Comparator> = {\n\t// equals\n\t'=== ': 'equals',\n\t'== ': 'eq',\n\t'equals ': 'equals',\n\t'equal ': 'equals',\n\t'eq ': 'eq',\n\n\t// not equals\n\t'!== ': 'not_equal',\n\t'!= ': 'ne',\n\t'notequals ': 'not_equal',\n\t'notequal ': 'not_equal',\n\t'ne ': 'ne',\n};\n\nconst comparatorNumericalPrefixMappings: Record<string, Comparator> = {\n\t// greater than\n\t'>': 'greater_than',\n\t'g': 'greater_than',\n\t'gt': 'greater_than',\n\t'=gt': 'greater_than',\n\t'greater': 'greater_than',\n\t'greaterthan': 'greater_than',\n\n\t// greater than or equals\n\t'>=': 'greater_than_equal',\n\t'ge': 'greater_than_equal',\n\t'=ge': 'greater_than_equal',\n\t'gte': 'greater_than_equal',\n\t'greaterorequal': 'greater_than_equal',\n\t'greaterthanequal': 'greater_than_equal',\n\t'greaterthanorequal': 'greater_than_equal',\n\n\t// less than\n\t'<': 'less_than',\n\t'l': 'less_than',\n\t'lt': 'less_than',\n\t'=lt': 'less_than',\n\t'less': 'less_than',\n\t'lessthan': 'less_than',\n\n\t// less than or equals\n\t'<=': 'less_than_equal',\n\t'lte': 'less_than_equal',\n\t'le': 'less_than_equal',\n\t'=le': 'less_than_equal',\n\t'lessorequal': 'less_than_equal',\n\t'lessthanequal': 'less_than_equal',\n\t'lessthanorequal': 'less_than_equal',\n};\n\nexport function parseComparator(value: string): { comparator: Comparator; value: string } {\n\tconst lowered = value.toLowerCase();\n\n\tconst numericalComparator = lowered.match(/^([>=<a-z_ ]+)([\\d._TZ-]+)$/);\n\tif (numericalComparator) {\n\t\tconst prefix = numericalComparator[1]\n\t\t\t.replace(/[_ ]+/g, '')\n\t\t\t.replace(/^([a-z]+)=$/g, '$1');\n\t\tconst number = numericalComparator[2];\n\t\tconst mappedComparator = comparatorNumericalPrefixMappings[prefix];\n\t\tif (mappedComparator) {\n\t\t\treturn {\n\t\t\t\tcomparator: mappedComparator,\n\t\t\t\tvalue: number,\n\t\t\t};\n\t\t}\n\t}\n\n\tfor (const equalityPrefix in comparatorEqualityPrefixMappings) {\n\t\tif (lowered.startsWith(equalityPrefix)) {\n\t\t\tconst equalityComparator = comparatorEqualityPrefixMappings[equalityPrefix];\n\t\t\treturn {\n\t\t\t\tcomparator: equalityComparator,\n\t\t\t\tvalue: value.slice(equalityPrefix.length),\n\t\t\t};\n\t\t}\n\t}\n\n\tif (lowered.endsWith('*')) {\n\t\treturn {\n\t\t\tcomparator: 'starts_with',\n\t\t\tvalue: value.slice(0, -1),\n\t\t};\n\t}\n\n\treturn {\n\t\tcomparator: 'equals',\n\t\tvalue: value,\n\t};\n}\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { queryOptions } from '@tanstack/react-query';\n\ninterface SearchByIdParams extends InstanceClientIdConfig {\n\tenabled: boolean;\n\tdatabaseName: string;\n\ttableName: string;\n\tids: unknown[] | null;\n}\n\nexport function getSearchByIdOptions(\n\t{ enabled, entityId, instanceClient, databaseName, tableName, ids }: SearchByIdParams,\n) {\n\treturn queryOptions({\n\t\tqueryKey: [entityId, 'search_by_id', databaseName, tableName, ids] as const,\n\t\tqueryFn: () =>\n\t\t\tinstanceClient.post('/', {\n\t\t\t\tget_attributes: ['*'],\n\t\t\t\tids,\n\t\t\t\tnoCacheStore: true,\n\t\t\t\tonlyIfCached: true,\n\t\t\t\toperation: 'search_by_id',\n\t\t\t\tdatabase: databaseName,\n\t\t\t\ttable: tableName,\n\t\t\t}),\n\t\tenabled: enabled && !!ids?.length,\n\t\tretry: false,\n\t});\n}\n","import { InstanceClientConfig } from '@/config/instanceClientConfig';\nimport { useMutation } from '@tanstack/react-query';\n\ninterface UpdateTableRecordsParams extends InstanceClientConfig {\n\tdatabaseName: string;\n\ttableName: string;\n\trecords: object[];\n}\n\nexport async function updateTableRecords(recordsData: UpdateTableRecordsParams) {\n\tconst { databaseName, tableName, records, instanceClient } = recordsData;\n\tconst { data } = await instanceClient.post('/', {\n\t\toperation: 'update',\n\t\tdatabase: databaseName,\n\t\ttable: tableName,\n\t\trecords: records,\n\t});\n\treturn data;\n}\n\nexport function useUpdateTableRecords() {\n\treturn useMutation({\n\t\tmutationFn: updateTableRecords,\n\t});\n}\n","import { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { TableCell, TableHeader, TableRow } from '@/components/ui/table';\nimport { HeaderGroup } from '@tanstack/react-table';\nimport { KeyboardEvent, useCallback } from 'react';\nimport { UseFormReturn } from 'react-hook-form';\nimport { z } from 'zod';\n\nexport const ColumnFiltersSchema = z.record(z.string(), z.string());\n\nexport function ColumnFilters<TData>({\n\tapplyFilters,\n\tcolumnFiltersForm,\n\theaderGroups,\n}: {\n\tapplyFilters: () => void;\n\tcolumnFiltersForm: UseFormReturn<z.infer<typeof ColumnFiltersSchema>>;\n\theaderGroups: HeaderGroup<TData>[];\n}) {\n\tconst handleSubmit = useCallback((e: KeyboardEvent) => {\n\t\tif (e.key === 'Enter') {\n\t\t\te.preventDefault();\n\t\t\tapplyFilters();\n\t\t\treturn false;\n\t\t}\n\t}, [applyFilters]);\n\treturn (\n\t\t<TableHeader>\n\t\t\t<Form {...columnFiltersForm}>\n\t\t\t\t{headerGroups.map((headerGroup) => (\n\t\t\t\t\t<TableRow key={headerGroup.id} className=\"border-none\">\n\t\t\t\t\t\t{headerGroup.headers.map((header) => (\n\t\t\t\t\t\t\t<TableCell key={header.id} style={{ width: `${header.column.getSize()}px` }}>\n\t\t\t\t\t\t\t\t{header.column.columnDef.enableColumnFilter && (\n\t\t\t\t\t\t\t\t\t<FormField\n\t\t\t\t\t\t\t\t\t\tcontrol={columnFiltersForm.control}\n\t\t\t\t\t\t\t\t\t\tname={header.id}\n\t\t\t\t\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t\t\t\t\t<FormItem className=\"border-r-1 border-r-black\">\n\t\t\t\t\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tautoCapitalize=\"none\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"rounded-none\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonKeyDown={handleSubmit}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue={field.value ?? ''}\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</TableRow>\n\t\t\t\t))}\n\t\t\t</Form>\n\t\t</TableHeader>\n\t);\n}\n","import { Button } from '@/components/ui/button';\nimport {\n\tDropdownMenu,\n\tDropdownMenuCheckboxItem,\n\tDropdownMenuContent,\n\tDropdownMenuTrigger,\n} from '@/components/ui/dropdownMenu';\nimport { formatBrowseDataTableHeader } from '@/features/instance/databases/functions/formatBrowseDataTableHeader';\nimport { useToggler } from '@/hooks/useToggler';\nimport { excludeFalsy } from '@/lib/arrays/excludeFalsy';\nimport { VisibilityState } from '@tanstack/react-table';\nimport { Columns3CogIcon } from 'lucide-react';\nimport { useEffect, useMemo } from 'react';\n\nexport function PickColumnsDropdown({\n\tcolumns,\n\tcolumnVisibility,\n\tsetColumnVisibility,\n}: {\n\tcolumns: ReturnType<typeof formatBrowseDataTableHeader>['dataTableColumns'];\n\tcolumnVisibility: VisibilityState;\n\tsetColumnVisibility: (columnVisibility: VisibilityState) => void;\n}) {\n\tconst columnHeaders = useMemo(() => {\n\t\treturn columns\n\t\t\t.map(c => c.header as string)\n\t\t\t.filter(excludeFalsy);\n\t}, [columns]);\n\treturn (\n\t\t<DropdownMenu>\n\t\t\t<DropdownMenuTrigger asChild>\n\t\t\t\t<Button variant=\"ghost\">\n\t\t\t\t\t<Columns3CogIcon className=\"inline-block \" />\n\t\t\t\t\tColumns\n\t\t\t\t</Button>\n\t\t\t</DropdownMenuTrigger>\n\t\t\t<DropdownMenuContent>\n\t\t\t\t{columnHeaders.map(columnHeader => (\n\t\t\t\t\t<ColumnPicker\n\t\t\t\t\t\tkey={columnHeader}\n\t\t\t\t\t\tcolumnHeader={columnHeader}\n\t\t\t\t\t\tcolumnVisibility={columnVisibility}\n\t\t\t\t\t\tsetColumnVisibility={setColumnVisibility}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\t\t\t</DropdownMenuContent>\n\t\t</DropdownMenu>\n\t);\n}\n\nfunction ColumnPicker({\n\tcolumnHeader,\n\tcolumnVisibility,\n\tsetColumnVisibility,\n}: {\n\tcolumnHeader: string;\n\tcolumnVisibility: VisibilityState;\n\tsetColumnVisibility: (columnVisibility: VisibilityState) => void;\n}) {\n\tconst { toggled: isChecked, toggle: onCheckedChanged } = useToggler(columnVisibility[columnHeader] ?? true);\n\tuseEffect(() => {\n\t\tif (columnVisibility[columnHeader] !== isChecked) {\n\t\t\tsetColumnVisibility({\n\t\t\t\t...columnVisibility,\n\t\t\t\t[columnHeader]: isChecked,\n\t\t\t});\n\t\t}\n\t}, [columnHeader, columnVisibility, isChecked, setColumnVisibility]);\n\treturn (\n\t\t<DropdownMenuCheckboxItem key={columnHeader} checked={isChecked} onClick={onCheckedChanged}>\n\t\t\t{columnHeader}\n\t\t</DropdownMenuCheckboxItem>\n\t);\n}\n","import { cx } from 'class-variance-authority';\nimport { LoaderCircleIcon } from 'lucide-react';\nimport { ComponentProps } from 'react';\n\nexport function LoadingSubtle({ className }: ComponentProps<'div'>) {\n\treturn <LoaderCircleIcon className={cx('animate-spin', className)} />;\n}\n","'use client';\n\nimport { LoadingSubtle } from '@/components/LoadingSubtle';\nimport { TextLoadingSkeleton } from '@/components/TextLoadingSkeleton';\nimport { Button } from '@/components/ui/button';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';\nimport { Table, TableBody, TableCell, TableHeader, TableHeadSortable, TableRow } from '@/components/ui/table';\nimport { addCommasToNumbers } from '@/lib/addCommasToNumbers';\nimport { cn } from '@/lib/cn';\nimport {\n\tCell,\n\tColumnDef,\n\tflexRender,\n\tgetCoreRowModel,\n\tgetPaginationRowModel,\n\tRow,\n\tuseReactTable,\n\tVisibilityState,\n} from '@tanstack/react-table';\nimport { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react';\nimport { Dispatch, SetStateAction, useCallback, useMemo } from 'react';\nimport { UseFormReturn } from 'react-hook-form';\nimport { z } from 'zod';\nimport { ColumnFilters, ColumnFiltersSchema } from './ColumnFilters';\n\ninterface BrowseDataTableProps<TData, TValue> {\n\tapplyFilters: () => void;\n\tcolumnFiltersForm: UseFormReturn<z.infer<typeof ColumnFiltersSchema>>;\n\tcolumns: ColumnDef<TData, TValue>[];\n\tcolumnVisibility: VisibilityState;\n\tdata?: TData[];\n\tisFetching?: boolean;\n\tonColumnClick?: (accessorKey: string, isDescending: boolean) => void;\n\tfiltersToggled: boolean;\n\tonRowClick?: (row: Row<TData>) => void;\n\tpageIndex: number;\n\tpageSize: number;\n\tprimaryKey: string;\n\tsetPageIndex: Dispatch<SetStateAction<number>>;\n\tsetPageSize: Dispatch<SetStateAction<number>>;\n\ttotalPages?: number;\n\ttotalRecords?: number;\n}\n\nexport function TableView<TData, TValue>({\n\tapplyFilters,\n\tcolumnFiltersForm,\n\tcolumns,\n\tcolumnVisibility,\n\tdata,\n\tisFetching,\n\tonColumnClick,\n\tonRowClick,\n\tpageIndex,\n\tpageSize,\n\tprimaryKey,\n\tsetPageIndex,\n\tsetPageSize,\n\tfiltersToggled,\n\ttotalPages,\n\ttotalRecords,\n}: BrowseDataTableProps<TData, TValue>) {\n\tconst table = useReactTable({\n\t\tdata: data || [],\n\t\tcolumns,\n\t\tmanualPagination: true,\n\t\tenableColumnResizing: true,\n\t\tcolumnResizeMode: 'onEnd',\n\t\tpageCount: totalPages,\n\t\tdefaultColumn: {\n\t\t\tminSize: 1,\n\t\t},\n\t\tstate: {\n\t\t\tcolumnVisibility,\n\t\t},\n\t\trowCount: totalRecords,\n\t\tgetCoreRowModel: getCoreRowModel(),\n\t\tgetPaginationRowModel: getPaginationRowModel(),\n\t});\n\n\tconst previousPage = useCallback(() => {\n\t\tsetPageIndex(pageIndex - 1);\n\t}, [pageIndex, setPageIndex]);\n\tconst nextPage = useCallback(() => {\n\t\tsetPageIndex(pageIndex + 1);\n\t}, [pageIndex, setPageIndex]);\n\n\treturn (\n\t\t<>\n\t\t\t<Table containerClassName=\"rounded-md bg-black-dark grow max-h-[calc(100vh-128px-16px-112px-80px)]\">\n\t\t\t\t<TableHeader>\n\t\t\t\t\t{table.getHeaderGroups().map((headerGroup) => (\n\t\t\t\t\t\t<TableRow key={headerGroup.id} className=\"border-none\">\n\t\t\t\t\t\t\t{headerGroup.headers.map((header) => (\n\t\t\t\t\t\t\t\t<TableHeadSortable key={header.id} header={header} onColumnClick={onColumnClick} />\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t))}\n\t\t\t\t</TableHeader>\n\t\t\t\t{filtersToggled && (\n\t\t\t\t\t<ColumnFilters\n\t\t\t\t\t\tapplyFilters={applyFilters}\n\t\t\t\t\t\tcolumnFiltersForm={columnFiltersForm}\n\t\t\t\t\t\theaderGroups={table.getHeaderGroups()}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t<TableBody className=\"bg-black border border-grey-700\">\n\t\t\t\t\t{table.getRowModel().rows?.length\n\t\t\t\t\t\t? (table.getRowModel().rows.map((row) => (\n\t\t\t\t\t\t\t<TableBodyRow key={row.id} row={row} onRowClick={onRowClick} primaryKey={primaryKey} />\n\t\t\t\t\t\t)))\n\t\t\t\t\t\t: (\n\t\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t\t<TableCell colSpan={columns.length} className=\"h-24 text-center\">\n\t\t\t\t\t\t\t\t\t{isFetching || data === undefined\n\t\t\t\t\t\t\t\t\t\t? <LoadingSubtle className=\"opacity-50 inline-block\" />\n\t\t\t\t\t\t\t\t\t\t: <span>No results.</span>}\n\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t\t)}\n\t\t\t\t</TableBody>\n\t\t\t</Table>\n\t\t\t<div className=\"flex items-center justify-end py-4 space-x-2 pr-4\">\n\t\t\t\t<Button\n\t\t\t\t\tvariant=\"defaultOutline\"\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\tonClick={previousPage}\n\t\t\t\t\tclassName=\"select-none\"\n\t\t\t\t\tdisabled={pageIndex === 0}\n\t\t\t\t>\n\t\t\t\t\t<ArrowLeftIcon />\n\t\t\t\t\tPrevious\n\t\t\t\t</Button>\n\n\t\t\t\t<div className=\"grow\"></div>\n\n\t\t\t\t<div className=\"text-center\">\n\t\t\t\t\t<dt className=\"font-medium text-gray-500 text-sm/6 dark:text-gray-400\">Records</dt>\n\t\t\t\t\t<dd className=\"font-semibold tracking-tight\">\n\t\t\t\t\t\t{totalRecords === undefined\n\t\t\t\t\t\t\t? <TextLoadingSkeleton />\n\t\t\t\t\t\t\t: addCommasToNumbers(totalRecords)}\n\t\t\t\t\t</dd>\n\t\t\t\t</div>\n\t\t\t\t{totalRecords !== undefined && totalRecords > 0 && (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\t\tdefaultValue={pageSize.toString()}\n\t\t\t\t\t\t\t\tonValueChange={(value) => {\n\t\t\t\t\t\t\t\t\tsetPageSize(Number(value));\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<SelectTrigger className=\"h-10 w-20\">\n\t\t\t\t\t\t\t\t\t<SelectValue />\n\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t<SelectContent side=\"top\">\n\t\t\t\t\t\t\t\t\t{[20, 50, 100, 250].map((pageSize) => (\n\t\t\t\t\t\t\t\t\t\t<SelectItem key={pageSize} value={`${pageSize}`}>\n\t\t\t\t\t\t\t\t\t\t\t{pageSize}\n\t\t\t\t\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t{totalPages !== undefined && totalPages > 1 && (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<div className=\"text-center\">\n\t\t\t\t\t\t\t\t\t<dt className=\"font-medium text-gray-500 text-sm/6 dark:text-gray-400\">Pages</dt>\n\t\t\t\t\t\t\t\t\t<dd className=\"font-semibold tracking-tight\">{addCommasToNumbers(totalPages)}</dd>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"text-center\">\n\t\t\t\t\t\t\t\t\t<dt className=\"font-medium text-gray-500 text-sm/6 dark:text-gray-400\">Page</dt>\n\t\t\t\t\t\t\t\t\t<dd className=\"font-semibold tracking-tight\">{addCommasToNumbers(pageIndex + 1)}</dd>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</>\n\t\t\t\t)}\n\n\t\t\t\t<div className=\"grow\"></div>\n\n\t\t\t\t<Button\n\t\t\t\t\tvariant=\"defaultOutline\"\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\tonClick={nextPage}\n\t\t\t\t\tclassName=\"select-none\"\n\t\t\t\t\tdisabled={totalPages === undefined || pageIndex === totalPages - 1}\n\t\t\t\t>\n\t\t\t\t\tNext\n\t\t\t\t\t<ArrowRightIcon />\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t</>\n\t);\n}\n\nfunction TableBodyRow<TData>(\n\t{ row, primaryKey, onRowClick }: { row: Row<TData>; primaryKey?: string; onRowClick?: (row: Row<TData>) => void },\n) {\n\tconst cells = useMemo(() => {\n\t\tconst original = row.original as Record<string, unknown>;\n\t\tconst isExpired = original && original.message === 'This entry has expired';\n\t\tconst visibleCells = row.getVisibleCells();\n\n\t\tconsole.log('primaryKey, visibleCells', primaryKey, visibleCells);\n\n\t\tif (isExpired) {\n\t\t\tif (visibleCells[0]?.column?.id === primaryKey) {\n\t\t\t\treturn [\n\t\t\t\t\t<TableBodyRowCell key={visibleCells[0].id} cell={visibleCells[0]} />,\n\t\t\t\t\t<TableBodyRowExpiredSpan key=\"expired\" colSpan={visibleCells.length - 1} />,\n\t\t\t\t];\n\t\t\t}\n\t\t\treturn [\n\t\t\t\t<TableBodyRowExpiredSpan key=\"expired\" colSpan={visibleCells.length} />,\n\t\t\t];\n\t\t}\n\t\treturn visibleCells.map((cell) => <TableBodyRowCell key={cell.id} cell={cell} />);\n\t}, [row, primaryKey]);\n\n\treturn (\n\t\t<TableRow\n\t\t\tdata-state={row.getIsSelected() && 'selected'}\n\t\t\tonClick={() => onRowClick?.(row)}\n\t\t\tclassName={cn('hover:bg-muted/10 data-[state=selected]:bg-muted', onRowClick && 'cursor-pointer')}\n\t\t>\n\t\t\t{cells}\n\t\t</TableRow>\n\t);\n}\n\nfunction TableBodyRowCell<TData>({ cell }: { cell: Cell<TData, unknown> }) {\n\treturn (\n\t\t<TableCell\n\t\t\tstyle={{ width: `${cell.column.getSize()}px` }}\n\t\t\tclassName=\"px-2 py-2 overflow-x-hidden max-w-32 text-ellipsis whitespace-nowrap\"\n\t\t>\n\t\t\t{cell.getValue() == '[object Object]'\n\t\t\t\t? JSON.stringify(cell.getValue())\n\t\t\t\t: flexRender(cell.column.columnDef.cell, cell.getContext())}\n\t\t</TableCell>\n\t);\n}\n\nfunction TableBodyRowExpiredSpan({ colSpan }: { colSpan: number }) {\n\treturn (\n\t\t<TableCell\n\t\t\tcolSpan={colSpan}\n\t\t\tclassName=\"px-2 py-2 overflow-x-hidden max-w-32 text-ellipsis whitespace-nowrap\"\n\t\t>\n\t\t\t<span className=\"text-muted-foreground\">This entry has expired</span>\n\t\t</TableCell>\n\t);\n}\n","import { Button } from '@/components/ui/button';\nimport { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdownMenu';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { formatBrowseDataTableHeader } from '@/features/instance/databases/functions/formatBrowseDataTableHeader';\nimport { AddTableRowModal } from '@/features/instance/databases/modals/AddTableRowModal';\nimport { DeleteDatabaseModal } from '@/features/instance/databases/modals/DeleteDatabaseModal';\nimport { DeleteTableModal } from '@/features/instance/databases/modals/DeleteTableModal';\nimport { EditTableRowModal } from '@/features/instance/databases/modals/EditTableRowModal';\nimport { ImportCSVModal } from '@/features/instance/databases/modals/ImportCSVModal';\nimport { useAdminMode } from '@/hooks/useAuth';\nimport { useEffectedState } from '@/hooks/useEffectedState';\nimport { useInstanceBrowseManagePermission, useInstanceSchemaTablePermission } from '@/hooks/usePermissions';\nimport { useRefreshClick } from '@/hooks/useRefreshClick';\nimport { useSessionStorage } from '@/hooks/useSessionStorage';\nimport { useToggler } from '@/hooks/useToggler';\nimport { InstanceDatabaseMap } from '@/integrations/api/api.patch';\nimport { useCleanupOrphanBlobsMutation } from '@/integrations/api/instance/database/cleanupOrphanBlobs';\nimport { useDeleteTableRecords } from '@/integrations/api/instance/database/deleteTableRecords';\nimport { getDescribeTableQueryOptions } from '@/integrations/api/instance/database/getDescribeTable';\nimport {\n\tgetSearchByConditions,\n\tgetSearchByConditionsOptions,\n\tSearchCondition,\n\ttranslateColumnFilterToSearchConditions,\n} from '@/integrations/api/instance/database/getSearchByConditions';\nimport { getSearchByIdOptions } from '@/integrations/api/instance/database/getSearchById';\nimport { getSearchByValue, getSearchByValueOptions } from '@/integrations/api/instance/database/getSearchByValue';\nimport { useUpdateTableRecords } from '@/integrations/api/instance/database/updateTableRecords';\nimport { useSetWatchedValue } from '@/lib/events/watcher';\nimport { keyBy } from '@/lib/keyBy';\nimport { onClickStopPropagation } from '@/lib/onClickStopPropagation';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useQuery, useQueryClient } from '@tanstack/react-query';\nimport { Link, useNavigate, useParams } from '@tanstack/react-router';\nimport { Row, VisibilityState } from '@tanstack/react-table';\nimport {\n\tBrushCleaningIcon,\n\tCircleCheckBigIcon,\n\tCircleIcon,\n\tCloudDownloadIcon,\n\tCloudUploadIcon,\n\tEllipsisIcon,\n\tExternalLinkIcon,\n\tFunnelIcon,\n\tFunnelPlusIcon,\n\tFunnelXIcon,\n\tPlusIcon,\n\tRefreshCwIcon,\n\tTrash2Icon,\n\tTrashIcon,\n} from 'lucide-react';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { ColumnFiltersSchema } from './ColumnFilters';\nimport { PickColumnsDropdown } from './PickColumnsDropdown';\nimport { TableView } from './TableView';\n\nexport function DatabaseTableView({ instanceDatabaseMap, databaseName, tableName }: {\n\tinstanceDatabaseMap?: InstanceDatabaseMap;\n\tdatabaseName: string;\n\ttableName: string;\n}) {\n\tconst allParams: {\n\t\tclusterId?: string;\n\t\tinstanceId?: string;\n\t} = useParams({ strict: false });\n\n\tconst navigate = useNavigate();\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst { clusterId, instanceId } = allParams;\n\n\tconst { toggled: onlyIfCached, toggle: toggleOnlyCached } = useToggler(true);\n\n\tconst adminMode = useAdminMode();\n\tconst canAddRecords = useInstanceSchemaTablePermission(instanceId ?? clusterId, databaseName, tableName, 'insert');\n\tconst canEditRecords = useInstanceSchemaTablePermission(instanceId ?? clusterId, databaseName, tableName, 'update');\n\tconst canDeleteRecords = useInstanceSchemaTablePermission(instanceId ?? clusterId, databaseName, tableName, 'delete');\n\tconst canManageBrowseInstance = useInstanceBrowseManagePermission();\n\n\tconst { data: describeTableData } = useQuery(\n\t\tgetDescribeTableQueryOptions({\n\t\t\t...instanceParams,\n\t\t\tdatabaseName,\n\t\t\ttableName,\n\t\t}),\n\t);\n\tconst attributesMap = useMemo(() => keyBy(describeTableData?.attributes ?? [], 'attribute'), [describeTableData]);\n\tconst [selectedIds, setSelectedIds] = useEffectedState<null | unknown[]>(null, allParams);\n\tconst [isEditModalOpen, setIsEditModalOpen] = useState(false);\n\n\tconst isLastTableInDatabase = useMemo(() => {\n\t\tconst tableNames = databaseName ? Object.keys(instanceDatabaseMap?.[databaseName] || []).sort() : [];\n\t\treturn tableNames.length === 1;\n\t}, [instanceDatabaseMap, databaseName]);\n\n\tconst { toggled: filtersToggled, toggleOn: showFilters, toggleOff: hideFilters } = useToggler(false);\n\tconst columnFiltersForm = useForm({\n\t\tresolver: zodResolver(ColumnFiltersSchema),\n\t});\n\tconst { reset: resetFiltersForm } = columnFiltersForm;\n\tconst columnFiltersValues = columnFiltersForm.watch();\n\n\tconst [appliedSearchConditions, setAppliedSearchConditions] = useEffectedState<SearchCondition[] | null>(null, [\n\t\tallParams.clusterId,\n\t\tallParams.instanceId,\n\t\tdatabaseName,\n\t\ttableName,\n\t]);\n\n\tconst applyFilters = useCallback(() => {\n\t\tconst conditions: SearchCondition[] = [];\n\t\tfor (const key in columnFiltersValues) {\n\t\t\tif (columnFiltersValues[key]?.length) {\n\t\t\t\ttry {\n\t\t\t\t\tconditions.push(\n\t\t\t\t\t\t...translateColumnFilterToSearchConditions(key, columnFiltersValues[key], attributesMap[key]),\n\t\t\t\t\t);\n\t\t\t\t} catch (err) {\n\t\t\t\t\ttoast.error(String(err));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tsetAppliedSearchConditions(conditions.length ? conditions : null);\n\t\tresetFiltersForm({ ...columnFiltersValues });\n\t}, [attributesMap, resetFiltersForm, columnFiltersValues]);\n\tconst clearFilters = useCallback(() => {\n\t\t// Note sure why we need to resetFiltersForm twice here...\n\t\tresetFiltersForm({}, { keepValues: false, keepDirtyValues: false, keepDefaultValues: false });\n\t\tresetFiltersForm();\n\t\tsetAppliedSearchConditions(null);\n\t\thideFilters();\n\t}, [hideFilters, resetFiltersForm]);\n\n\tuseEffect(function clearFiltersWhenParamsChange() {\n\t\treturn clearFilters();\n\t}, [allParams, clearFilters]);\n\n\tconst { dataTableColumns, primaryKey } = formatBrowseDataTableHeader(describeTableData);\n\tconst [isAddModalOpen, setIsAddModalOpen] = useState(false);\n\tconst [isImportCSVModalOpen, setIsImportCSVModalOpen] = useState(false);\n\tconst [sort, setSort] = useEffectedState(\n\t\t{\n\t\t\tattribute: primaryKey,\n\t\t\tdescending: false,\n\t\t},\n\t\tallParams,\n\t);\n\n\tconst [pageIndex, setPageIndex] = useEffectedState(0, [databaseName, tableName]);\n\tconst [pageSize, setPageSize] = useState(20);\n\n\tconst totalRecords = describeTableData?.record_count;\n\tconst totalPages = describeTableData?.record_count ? Math.ceil(describeTableData.record_count / pageSize) : 0;\n\n\tconst useFilteredList = filtersToggled && !!appliedSearchConditions;\n\n\t// Full list\n\tconst searchByValueParams = {\n\t\t...instanceParams,\n\t\tenabled: !useFilteredList && !!primaryKey,\n\t\tdatabaseName,\n\t\ttableName,\n\t\tsearchAttribute: primaryKey,\n\t\tsort,\n\t\tpageSize,\n\t\tpageIndex,\n\t\tonlyIfCached,\n\t};\n\tconst searchByValueOptions = getSearchByValueOptions(searchByValueParams);\n\tconst { data: fullTableData, isFetching: tableDataFetching } = useQuery(searchByValueOptions);\n\n\t// Filtered list\n\tconst searchByConditionsParams = {\n\t\t...instanceParams,\n\t\tenabled: useFilteredList && !!primaryKey,\n\t\tdatabaseName,\n\t\ttableName,\n\t\tconditions: appliedSearchConditions,\n\t\tsort,\n\t\tpageSize,\n\t\tpageIndex,\n\t\tonlyIfCached,\n\t};\n\tconst searchByConditionsOptions = getSearchByConditionsOptions(searchByConditionsParams);\n\tconst { data: filteredTableData, isFetching: tableConditionsDataFetching } = useQuery(searchByConditionsOptions);\n\n\tconst tableData = useFilteredList ? filteredTableData : fullTableData;\n\tconst isFetching = tableDataFetching || tableConditionsDataFetching;\n\n\t// One by id\n\tconst { data: searchByIdData } = useQuery(getSearchByIdOptions({\n\t\t...instanceParams,\n\t\tenabled: isEditModalOpen,\n\t\tdatabaseName: databaseName,\n\t\ttableName: tableName,\n\t\tids: selectedIds,\n\t}));\n\n\tconst { mutate: updateTableRecords, isPending: isUpdateTableRecordsPending } = useUpdateTableRecords();\n\tconst { mutate: deleteTableRecords, isPending: isDeleteTableRecordsPending } = useDeleteTableRecords();\n\tconst { mutate: cleanupOrphanBlobs, isPending: isCleanupOrphanBlobsPending } = useCleanupOrphanBlobsMutation();\n\n\tconst queryClient = useQueryClient();\n\tconst refreshTable = useCallback(\n\t\t() => queryClient.invalidateQueries({ queryKey: [instanceParams.entityId, databaseName, tableName] }),\n\t\t[queryClient, instanceParams.entityId, databaseName, tableName],\n\t);\n\n\tconst onCleanupOrphanBlobs = useCallback(async () => {\n\t\tif (!confirm(`Are you sure you want to cleanup orphan blobs for database \"${databaseName}\"?`)) {\n\t\t\treturn;\n\t\t}\n\n\t\tcleanupOrphanBlobs({\n\t\t\t...instanceParams,\n\t\t\tdatabaseName,\n\t\t}, {\n\t\t\tonSuccess: (data) => {\n\t\t\t\ttoast.success(data.message || 'Orphan blobs cleanup started successfully');\n\t\t\t\trefreshTable();\n\t\t\t},\n\t\t\tonError: (error) => {\n\t\t\t\ttoast.error(error instanceof Error ? error.message : 'Failed to cleanup orphan blobs');\n\t\t\t},\n\t\t});\n\t}, [cleanupOrphanBlobs, databaseName, instanceParams, refreshTable]);\n\n\tconst [isExportingCSV, setisExportingCSV] = useState(false);\n\tconst onExportCSVClicked = useCallback(async () => {\n\t\tif (!primaryKey) {\n\t\t\treturn;\n\t\t}\n\t\tconst id = toast.loading('Loading CSV...');\n\t\tsetisExportingCSV(true);\n\t\tconst allResultsAsCSV = {\n\t\t\tpageIndex: 0,\n\t\t\tpageSize: 1_000_000,\n\t\t\theaders: {\n\t\t\t\tAccept: 'text/csv',\n\t\t\t},\n\t\t};\n\t\tconst response = await (\n\t\t\tuseFilteredList\n\t\t\t\t? getSearchByConditions({ ...searchByConditionsParams, ...allResultsAsCSV })\n\t\t\t\t: getSearchByValue({ ...searchByValueParams, ...allResultsAsCSV })\n\t\t);\n\t\ttoast.loading('Preparing CSV...', { id });\n\t\tconst content = response.data as unknown as string;\n\t\tconst blob = new Blob([content], { type: 'text/csv' });\n\t\tconst url = URL.createObjectURL(blob);\n\t\tconst downloadLink = document.createElement('a');\n\t\tdownloadLink.href = url;\n\t\tdownloadLink.setAttribute('download', `${databaseName}.${tableName}.${new Date().toISOString()}.csv`);\n\t\tdownloadLink.click();\n\t\ttoast.success('CSV Exported!', { id });\n\t\tsetisExportingCSV(false);\n\t}, [databaseName, tableName, searchByValueOptions, searchByConditionsOptions]);\n\n\tconst onRecordUpdate = useCallback((data: Record<string, unknown>[]) => {\n\t\tupdateTableRecords(\n\t\t\t{\n\t\t\t\t...instanceParams,\n\t\t\t\tdatabaseName,\n\t\t\t\ttableName,\n\t\t\t\trecords: data,\n\t\t\t},\n\t\t\t{\n\t\t\t\tonSuccess: () => {\n\t\t\t\t\tvoid refreshTable();\n\t\t\t\t\tsetIsEditModalOpen(false);\n\t\t\t\t\ttoast.success('Record updated successfully');\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}, [updateTableRecords, instanceParams, databaseName, tableName, refreshTable]);\n\n\tconst onDeleteRecord = useCallback((hashes: unknown[]) => {\n\t\tdeleteTableRecords(\n\t\t\t{\n\t\t\t\t...instanceParams,\n\t\t\t\tdatabaseName,\n\t\t\t\ttableName,\n\t\t\t\thashValues: hashes,\n\t\t\t},\n\t\t\t{\n\t\t\t\tonSuccess: () => {\n\t\t\t\t\tvoid refreshTable();\n\t\t\t\t\tsetIsEditModalOpen(false);\n\t\t\t\t\ttoast.success('Record deleted successfully');\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}, [deleteTableRecords, instanceParams, databaseName, tableName, refreshTable]);\n\n\tconst onCSVDataAdded = useCallback((message: string) => {\n\t\tvoid refreshTable();\n\t\tsetIsImportCSVModalOpen(false);\n\t\ttoast.success(`${message}. Please wait a few moments then refresh the table.`);\n\t}, [refreshTable]);\n\n\tconst onRowClick = (rowData: Row<Record<string, unknown>>) => {\n\t\tsetSelectedIds([rowData.original[primaryKey]]);\n\t\tsetIsEditModalOpen(!isEditModalOpen);\n\t};\n\tconst onColumnClick = (accessorKey: string, isAscending: boolean) => {\n\t\tsetSort({\n\t\t\tattribute: accessorKey,\n\t\t\tdescending: !isAscending,\n\t\t});\n\t};\n\tconst onRefreshClick = useRefreshClick(refreshTable);\n\n\tconst onAddClicked = useCallback(() => {\n\t\tsetIsAddModalOpen(true);\n\t}, [setIsAddModalOpen]);\n\n\tconst onImportCSVClicked = useCallback(() => {\n\t\tsetIsImportCSVModalOpen(true);\n\t}, [setIsImportCSVModalOpen]);\n\n\tconst onDeleted = useCallback(\n\t\t(deleted: 'table' | 'database') => void navigate({ to: deleted === 'table' ? '../' : '../../' }),\n\t\t[navigate],\n\t);\n\n\tconst [columnVisibility, setColumnVisibility] = useSessionStorage(\n\t\t`ColumnDisplayed/${databaseName}}/${tableName}` as 'ColumnDisplayed/{database}/{table}',\n\t\t{} satisfies VisibilityState,\n\t);\n\n\tconst openDeleteTable = useSetWatchedValue('ShowDeleteTable', true);\n\tconst openDeleteDatabase = useSetWatchedValue('ShowDeleteDatabase', true);\n\n\treturn (\n\t\t<>\n\t\t\t<div className=\"flex flex-col md:flex-row items-center justify-between space-y-3 md:space-y-0 md:space-x-3 pt-15 pb-4 pr-4\">\n\t\t\t\t<div className=\"flex space-x-2\">\n\t\t\t\t\t{canAddRecords && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"positiveOutline\"\n\t\t\t\t\t\t\tonClick={onAddClicked}\n\t\t\t\t\t\t\tdisabled={isAddModalOpen}\n\t\t\t\t\t\t\taccessKey=\"n\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<PlusIcon />\n\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\tAdd <u>N</u>ew Record(s)\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t\t{canAddRecords && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"positiveOutline\"\n\t\t\t\t\t\t\tonClick={onImportCSVClicked}\n\t\t\t\t\t\t\tdisabled={isImportCSVModalOpen}\n\t\t\t\t\t\t\taccessKey=\"c\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<CloudUploadIcon />\n\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\tImport <u>C</u>SV\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"positiveOutline\"\n\t\t\t\t\t\tonClick={onExportCSVClicked}\n\t\t\t\t\t\tdisabled={isExportingCSV}\n\t\t\t\t\t\taccessKey=\"e\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<CloudDownloadIcon />\n\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t<u>E</u>xport CSV\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\n\t\t\t\t<div className=\"flex space-x-2\">\n\t\t\t\t\t{filtersToggled && appliedSearchConditions && (\n\t\t\t\t\t\t<Button type=\"button\" variant=\"ghost\" onClick={clearFilters} accessKey=\"f\">\n\t\t\t\t\t\t\t<FunnelXIcon className=\"inline-block \" />\n\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\tClear <u>F</u>ilters\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t\t{filtersToggled && columnFiltersForm.formState.isDirty && (\n\t\t\t\t\t\t<Button variant=\"default\" onClick={applyFilters}>\n\t\t\t\t\t\t\t<FunnelPlusIcon className=\"inline-block \" />\n\t\t\t\t\t\t\tApply Filters\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t\t{filtersToggled && !appliedSearchConditions && (\n\t\t\t\t\t\t<Button variant=\"ghost\" onClick={hideFilters} accessKey=\"f\">\n\t\t\t\t\t\t\t<FunnelXIcon className=\"inline-block \" />\n\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\tHide <u>F</u>ilters\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{!filtersToggled && (\n\t\t\t\t\t\t<Button variant=\"ghost\" onClick={showFilters} accessKey=\"f\">\n\t\t\t\t\t\t\t<FunnelIcon className=\"inline-block \" />\n\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\tShow <u>F</u>ilters\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"defaultOutline\"\n\t\t\t\t\t\tonClick={onRefreshClick}\n\t\t\t\t\t\tdisabled={isFetching}\n\t\t\t\t\t>\n\t\t\t\t\t\t<RefreshCwIcon />\n\t\t\t\t\t</Button>\n\n\t\t\t\t\t<PickColumnsDropdown\n\t\t\t\t\t\tcolumns={dataTableColumns}\n\t\t\t\t\t\tcolumnVisibility={columnVisibility}\n\t\t\t\t\t\tsetColumnVisibility={setColumnVisibility}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<DropdownMenu>\n\t\t\t\t\t\t<DropdownMenuTrigger disabled={!instanceDatabaseMap}>\n\t\t\t\t\t\t\t<EllipsisIcon aria-label=\"Table options\" color={!instanceDatabaseMap ? 'gray' : 'white'} />\n\t\t\t\t\t\t</DropdownMenuTrigger>\n\t\t\t\t\t\t<DropdownMenuContent side=\"bottom\" align=\"end\">\n\t\t\t\t\t\t\t<DropdownMenuItem className=\"focus:bg-primary/70 focus:text-white\" onClick={toggleOnlyCached}>\n\t\t\t\t\t\t\t\t{onlyIfCached ? <CircleCheckBigIcon className=\"text-green\" /> : <CircleIcon />}\n\t\t\t\t\t\t\t\tOnly If Cached\n\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\tto=\"https://docs.harperdb.io/docs/developers/applications/caching#cache-control-header\"\n\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\t\tonClick={onClickStopPropagation}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<ExternalLinkIcon />\n\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t\t{canManageBrowseInstance\n\t\t\t\t\t\t\t\t&& adminMode\n\t\t\t\t\t\t\t\t&& !!instanceId && (\n\t\t\t\t\t\t\t\t<DropdownMenuItem\n\t\t\t\t\t\t\t\t\tclassName=\"focus:bg-yellow/70 focus:text-white\"\n\t\t\t\t\t\t\t\t\tonClick={onCleanupOrphanBlobs}\n\t\t\t\t\t\t\t\t\tdisabled={isCleanupOrphanBlobsPending}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<BrushCleaningIcon className=\"text-yellow \" />\n\t\t\t\t\t\t\t\t\tCleanup Orphan Blobs\n\t\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{canManageBrowseInstance && !isLastTableInDatabase && (\n\t\t\t\t\t\t\t\t<DropdownMenuItem className=\"focus:bg-red/70 focus:text-white\" onClick={openDeleteTable}>\n\t\t\t\t\t\t\t\t\t<TrashIcon className=\"inline-block \" />\n\t\t\t\t\t\t\t\t\tDrop Table\n\t\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{canManageBrowseInstance\n\t\t\t\t\t\t\t\t&& (\n\t\t\t\t\t\t\t\t\t<DropdownMenuItem className=\"focus:bg-red/70 focus:text-white\" onClick={openDeleteDatabase}>\n\t\t\t\t\t\t\t\t\t\t<Trash2Icon />\n\t\t\t\t\t\t\t\t\t\tDrop Database\n\t\t\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</DropdownMenuContent>\n\t\t\t\t\t</DropdownMenu>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<TableView<Record<string, unknown>, unknown>\n\t\t\t\tprimaryKey={primaryKey}\n\t\t\t\tdata={tableData?.data}\n\t\t\t\tisFetching={isFetching}\n\t\t\t\tfiltersToggled={filtersToggled}\n\t\t\t\tcolumns={dataTableColumns}\n\t\t\t\tcolumnVisibility={columnVisibility}\n\t\t\t\tonRowClick={onRowClick}\n\t\t\t\tonColumnClick={onColumnClick}\n\t\t\t\ttotalPages={totalPages}\n\t\t\t\ttotalRecords={totalRecords}\n\t\t\t\tpageIndex={pageIndex}\n\t\t\t\tpageSize={pageSize}\n\t\t\t\tcolumnFiltersForm={columnFiltersForm}\n\t\t\t\tapplyFilters={applyFilters}\n\t\t\t\tsetPageIndex={setPageIndex}\n\t\t\t\tsetPageSize={setPageSize}\n\t\t\t/>\n\t\t\t{canAddRecords && describeTableData && isAddModalOpen && (\n\t\t\t\t<AddTableRowModal\n\t\t\t\t\tinstanceTable={describeTableData}\n\t\t\t\t\tisModalOpen={isAddModalOpen}\n\t\t\t\t\trefreshTable={refreshTable}\n\t\t\t\t\tsetIsModalOpen={setIsAddModalOpen}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t<EditTableRowModal\n\t\t\t\tcanEditRecords={canEditRecords}\n\t\t\t\tcanDeleteRecords={canDeleteRecords}\n\t\t\t\tsetIsModalOpen={setIsEditModalOpen}\n\t\t\t\tisModalOpen={isEditModalOpen}\n\t\t\t\tprimaryKey={primaryKey}\n\t\t\t\tdata={searchByIdData?.data}\n\t\t\t\tonSaveChanges={onRecordUpdate}\n\t\t\t\tonDeleteRecord={onDeleteRecord}\n\t\t\t\tisUpdateTableRecordsPending={isUpdateTableRecordsPending}\n\t\t\t\tisDeleteTableRecordsPending={isDeleteTableRecordsPending}\n\t\t\t/>\n\n\t\t\t<DeleteDatabaseModal databaseName={databaseName} onDeleted={onDeleted} />\n\t\t\t<DeleteTableModal databaseName={databaseName} tableName={tableName} onDeleted={onDeleted} />\n\n\t\t\t<ImportCSVModal\n\t\t\t\tisModalOpen={isImportCSVModalOpen}\n\t\t\t\tsetIsModalOpen={setIsImportCSVModalOpen}\n\t\t\t\tonSaveChanges={onCSVDataAdded}\n\t\t\t\tdatabase={databaseName}\n\t\t\t\ttable={tableName}\n\t\t\t/>\n\t\t</>\n\t);\n}\n","import { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { getDescribeAllQueryOptions } from '@/integrations/api/instance/database/getDescribeAll';\nimport { buildAbsoluteLinkToDatabasePage } from '@/lib/urls/buildAbsoluteLinkToDatabasePage';\nimport { useQuery } from '@tanstack/react-query';\nimport { Navigate, useParams } from '@tanstack/react-router';\nimport { DatabasesSidebar } from './components/DatabasesSidebar';\nimport { DatabaseTableView } from './components/DatabaseTableView';\n\nexport function Databases() {\n\tconst params: {\n\t\tclusterId?: string;\n\t\tinstanceId?: string;\n\t\tdatabaseName?: string;\n\t\ttableName?: string;\n\t} = useParams({ strict: false });\n\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst { data: instanceDatabaseMap } = useQuery(getDescribeAllQueryOptions(instanceParams));\n\n\tlet newDatabaseName: string | undefined;\n\tlet newTableName: string | undefined;\n\tif (instanceDatabaseMap) {\n\t\tif (!params.databaseName) {\n\t\t\tnewDatabaseName = Object.keys(instanceDatabaseMap).sort()[0];\n\t\t}\n\t\tconst databaseName = params.databaseName ?? newDatabaseName;\n\t\tif (!params.tableName && databaseName && instanceDatabaseMap[databaseName]) {\n\t\t\tnewTableName = Object.keys(instanceDatabaseMap[databaseName]).sort()[0];\n\t\t}\n\t}\n\tif (newDatabaseName || newTableName) {\n\t\treturn (\n\t\t\t<Navigate\n\t\t\t\tto={buildAbsoluteLinkToDatabasePage({\n\t\t\t\t\t...params,\n\t\t\t\t\tdatabaseName: newDatabaseName ?? params.databaseName,\n\t\t\t\t\ttableName: newTableName,\n\t\t\t\t})}\n\t\t\t\treplace={true}\n\t\t\t/>\n\t\t);\n\t}\n\n\treturn (\n\t\t<main className=\"grid grid-cols-1 gap-4 md:grid-cols-12 min-h-[calc(100vh-(--spacing(36)))]\">\n\t\t\t<section className=\"col-span-1 text-white md:col-span-4 lg:col-span-3\">\n\t\t\t\t<DatabasesSidebar instanceDatabaseMap={instanceDatabaseMap} />\n\t\t\t</section>\n\t\t\t<section className=\"col-span-1 text-white md:col-span-8 lg:col-span-9 flex flex-col\">\n\t\t\t\t{params.databaseName && params.tableName && (\n\t\t\t\t\t<DatabaseTableView\n\t\t\t\t\t\tinstanceDatabaseMap={instanceDatabaseMap}\n\t\t\t\t\t\tdatabaseName={params.databaseName}\n\t\t\t\t\t\ttableName={params.tableName}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</section>\n\t\t</main>\n\t);\n}\n","import { createInstanceLayoutRoute } from '@/features/instance/instanceLayoutRoute';\nimport { createRoute } from '@tanstack/react-router';\nimport { Databases } from './index';\n\nexport function createBrowseRouteTree(instanceLayoutRoute: ReturnType<typeof createInstanceLayoutRoute>) {\n\treturn createRoute({\n\t\tgetParentRoute: () => instanceLayoutRoute,\n\t\tpath: '/databases/{-$databaseName}/{-$tableName}',\n\t\tcomponent: Databases,\n\t});\n}\n","import { Breadcrumbs } from '@/components/Breadcrumbs';\nimport { Button } from '@/components/ui/button';\nimport {\n\tDropdownMenu,\n\tDropdownMenuContent,\n\tDropdownMenuItem,\n\tDropdownMenuLabel,\n\tDropdownMenuSeparator,\n\tDropdownMenuTrigger,\n} from '@/components/ui/dropdownMenu';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { useInstanceManagePermission } from '@/hooks/usePermissions';\nimport { RegistrationInfoResponse } from '@/integrations/api/instance/status/getRegistrationInfo';\nimport { getStatusQueryOptions } from '@/integrations/api/instance/status/getStatus';\nimport { excludeFalsy } from '@/lib/arrays/excludeFalsy';\nimport { wasAReleasedBeforeB } from '@/lib/string/wasAReleasedBeforeB';\nimport { buildAbsoluteLinkToPage } from '@/lib/urls/buildAbsoluteLinkToPage';\nimport { useQuery } from '@tanstack/react-query';\nimport { Link, useLoaderData, useParams } from '@tanstack/react-router';\nimport { DatabaseIcon, GaugeIcon, Menu, NotepadTextIcon, PackageIcon, ServerIcon, SettingsIcon } from 'lucide-react';\nimport { ReactNode, useMemo } from 'react';\n\ninterface Link {\n\tto: string;\n\tname: string;\n\tshortName?: string;\n\ticon: ReactNode;\n}\n\nconst activeLinkProps = { className: 'text-white' };\n\nexport function InstanceNavBar() {\n\tconst canManage = useInstanceManagePermission();\n\tconst params = useParams({ strict: false });\n\n\tconst { version }: RegistrationInfoResponse = useLoaderData({ strict: false });\n\tconst statusAvailable = wasAReleasedBeforeB('4.6.0', version);\n\tconst apisAvailable = wasAReleasedBeforeB('4.7.0-beta.7', version);\n\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst { data: statusData } = useQuery(getStatusQueryOptions(instanceParams, statusAvailable));\n\tconst restartRequired = statusData?.restartRequired ?? false;\n\n\tconst links = useMemo(() =>\n\t\t[\n\t\t\t{\n\t\t\t\tto: buildAbsoluteLinkToPage(params),\n\t\t\t\tactiveOptions: { exact: true },\n\t\t\t\tname: 'Applications',\n\t\t\t\tshortName: 'Apps',\n\t\t\t\ticon: <PackageIcon className=\"inline-block\" />,\n\t\t\t},\n\t\t\t{\n\t\t\t\tto: buildAbsoluteLinkToPage(params, 'databases'),\n\t\t\t\ticon: <DatabaseIcon className=\"inline-block\" />,\n\t\t\t\tname: 'Databases',\n\t\t\t},\n\t\t\tcanManage && apisAvailable && {\n\t\t\t\tto: buildAbsoluteLinkToPage(params, 'apis'),\n\t\t\t\tname: 'APIs',\n\t\t\t\ticon: <ServerIcon className=\"inline-block\" />,\n\t\t\t},\n\t\t\tcanManage && statusAvailable && {\n\t\t\t\tto: buildAbsoluteLinkToPage(params, 'status'),\n\t\t\t\ticon: <GaugeIcon className=\"inline-block\" />,\n\t\t\t\tname: 'Status',\n\t\t\t},\n\t\t\tcanManage && {\n\t\t\t\tto: buildAbsoluteLinkToPage(params, 'logs'),\n\t\t\t\ticon: <NotepadTextIcon className=\"inline-block\" />,\n\t\t\t\tname: 'Logs',\n\t\t\t},\n\t\t\tcanManage && {\n\t\t\t\tto: buildAbsoluteLinkToPage(params, 'config'),\n\t\t\t\ticon: <SettingsIcon className=\"inline-block\" />,\n\t\t\t\tname: 'Config',\n\t\t\t},\n\t\t].filter(excludeFalsy) satisfies Link[], [canManage, params, apisAvailable, statusAvailable]);\n\treturn (\n\t\t<>\n\t\t\t<DesktopInstanceNavBar links={links} restartRequired={restartRequired} />\n\t\t\t<MobileInstanceNavBar links={links} restartRequired={restartRequired} />\n\t\t</>\n\t);\n}\n\nfunction DesktopInstanceNavBar({ links, restartRequired }: { links: Link[]; restartRequired: boolean }) {\n\treturn (\n\t\t<div className=\"hidden md:flex items-center justify-between h-full text-sm text-white\">\n\t\t\t<Breadcrumbs restartRequired={restartRequired} />\n\t\t\t<div className=\"flex space-x-2\">\n\t\t\t\t{links.map(({ shortName, ...link }) => (\n\t\t\t\t\t<Link\n\t\t\t\t\t\tkey={link.to}\n\t\t\t\t\t\tclassName=\"p-2 text-center text-gray-400 hover:text-white\"\n\t\t\t\t\t\tactiveProps={activeLinkProps}\n\t\t\t\t\t\t{...link}\n\t\t\t\t\t>\n\t\t\t\t\t\t{link.icon}\n\t\t\t\t\t\t<span className=\"hidden xl:inline-block ml-1\">{link.name}</span>\n\t\t\t\t\t\t{shortName && <span className=\"visible xl:hidden ml-1\">{shortName}</span>}\n\t\t\t\t\t</Link>\n\t\t\t\t))}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nfunction MobileInstanceNavBar({ links, restartRequired }: { links: Link[]; restartRequired: boolean }) {\n\treturn (\n\t\t<>\n\t\t\t<div className=\"flex md:hidden items-center justify-between h-full px-2 text-white\">\n\t\t\t\t<Breadcrumbs restartRequired={restartRequired} />\n\t\t\t\t<DropdownMenu>\n\t\t\t\t\t<DropdownMenuTrigger asChild>\n\t\t\t\t\t\t<Button variant=\"ghost\" className=\"p-0\">\n\t\t\t\t\t\t\t<Menu className=\"h-8 w-8\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</DropdownMenuTrigger>\n\t\t\t\t\t<DropdownMenuContent>\n\t\t\t\t\t\t<DropdownMenuLabel>Instance Menu</DropdownMenuLabel>\n\t\t\t\t\t\t<DropdownMenuSeparator />\n\n\t\t\t\t\t\t{links.map(link => (\n\t\t\t\t\t\t\t<DropdownMenuItem key={link.to} asChild>\n\t\t\t\t\t\t\t\t<Link to={link.to} activeProps={activeLinkProps}>{link.name}</Link>\n\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</DropdownMenuContent>\n\t\t\t\t</DropdownMenu>\n\t\t\t</div>\n\t\t</>\n\t);\n}\n","import { inputSchema } from '@harperfast/agent-tools/tools/collectFeedback/inputSchema';\nimport { serverSchema } from '@harperfast/agent-tools/tools/collectFeedback/serverSchema';\nimport { MessageSquareHeartIcon } from 'lucide-react';\nimport { z } from 'zod';\nimport type { ClientSideTool } from '../../types/clientSideTool';\nimport { execute } from './execute';\nimport { Output } from './output';\n\nexport const collectFeedback: ClientSideTool<z.infer<typeof inputSchema>, Output> = {\n\t...serverSchema,\n\ticon: MessageSquareHeartIcon,\n\texecute,\n};\n","import { inputSchema } from '@harperfast/agent-tools/tools/createApp/inputSchema';\nimport { serverSchema } from '@harperfast/agent-tools/tools/createApp/serverSchema';\nimport { PlusIcon } from 'lucide-react';\nimport { z } from 'zod';\nimport type { ClientSideTool } from '../../types/clientSideTool';\nimport { execute } from './execute';\nimport { Output } from './output';\n\nexport const createApp: ClientSideTool<z.infer<typeof inputSchema>, Output> = {\n\t...serverSchema,\n\ticon: PlusIcon,\n\texecute,\n\trequiresApproval: true,\n};\n","import { inputSchema } from '@harperfast/agent-tools/tools/deleteTableRecords/inputSchema';\nimport { serverSchema } from '@harperfast/agent-tools/tools/deleteTableRecords/serverSchema';\nimport { BetweenHorizonalStartIcon } from 'lucide-react';\nimport { z } from 'zod';\nimport type { ClientSideTool } from '../../types/clientSideTool';\nimport { execute } from './execute';\nimport { Output } from './output';\n\nexport const deleteTableRecords: ClientSideTool<z.infer<typeof inputSchema>, Output> = {\n\t...serverSchema,\n\ticon: BetweenHorizonalStartIcon,\n\texecute,\n\trequiresApproval: true,\n};\n","import { inputSchema } from '@harperfast/agent-tools/tools/dropComponentFile/inputSchema';\nimport { serverSchema } from '@harperfast/agent-tools/tools/dropComponentFile/serverSchema';\nimport { TrashIcon } from 'lucide-react';\nimport { z } from 'zod';\nimport type { ClientSideTool } from '../../types/clientSideTool';\nimport { execute } from './execute';\nimport { Output } from './output';\n\nexport const dropComponentFile: ClientSideTool<z.infer<typeof inputSchema>, Output> = {\n\t...serverSchema,\n\ticon: TrashIcon,\n\texecute,\n\trequiresApproval: true,\n};\n","import type { InstanceClientIdConfig, InstanceTypeConfig } from '@/config/instanceClientConfig.ts';\nimport type { Units } from '@/lib/units';\nimport { queryOptions } from '@tanstack/react-query';\n\nexport type MetricDataKey = 'count' | ((metric: Metric) => number);\nexport type MetricUnits = Units | 'reads' | 'writes' | 'messages';\nexport interface MetricConfig {\n\tid: string;\n\tname: 'db-read' | 'db-write' | 'db-message' | 'cpu-usage';\n\tlabel?: string;\n\tdataKey: MetricDataKey;\n\taggregator: (accumulator: number, current: number) => number;\n\tunits: MetricUnits;\n\tpath?: string;\n}\n\ninterface GetAnalyticsParams {\n\tmetricConfig: MetricConfig;\n\tstartTime: number;\n\tendTime: number;\n\tinstanceParams: InstanceClientIdConfig & InstanceTypeConfig;\n}\n\ninterface GetAnalyticsRequest {\n\toperation: 'get_analytics';\n\tmetric: string;\n\tstart_time: number;\n\tend_time: number;\n\tconditions?: {\n\t\tattribute: string;\n\t\tvalue: string | number | boolean;\n\t\tcomparator?: string;\n\t}[];\n}\n\nexport interface Metric {\n\tid: number;\n\tmetric: string;\n\tcount: number;\n\tmean: number;\n\tperiod: number;\n\tnode: string;\n\t[key: string]: string | number | boolean | null;\n}\n\ntype GetAnalyticsResponse = Metric[];\n\nexport function getAnalyticsQueryOptions(params: GetAnalyticsParams) {\n\tconst { metricConfig, startTime, endTime } = params;\n\treturn queryOptions({\n\t\tqueryKey: ['get_analytics', metricConfig.name, metricConfig.path, startTime, endTime] as const,\n\t\tqueryFn: () => getAnalytics(params),\n\t});\n}\n\nexport async function getAnalytics({ metricConfig, startTime, endTime, instanceParams }: GetAnalyticsParams) {\n\tconst req: GetAnalyticsRequest = {\n\t\toperation: 'get_analytics',\n\t\tmetric: metricConfig.name,\n\t\tstart_time: startTime,\n\t\tend_time: endTime,\n\t};\n\tif (metricConfig.path) {\n\t\treq.conditions = [{ attribute: 'path', value: metricConfig.path }];\n\t}\n\tconst { data } = await instanceParams.instanceClient.post<GetAnalyticsResponse>('/', req);\n\treturn data;\n}\n","import { inputSchema } from '@harperfast/agent-tools/tools/getAnalytics/inputSchema';\nimport { serverSchema } from '@harperfast/agent-tools/tools/getAnalytics/serverSchema';\nimport { ChartAreaIcon } from 'lucide-react';\nimport { z } from 'zod';\nimport type { ClientSideTool } from '../../types/clientSideTool';\nimport { execute } from './execute';\nimport { Output } from './output';\n\nexport const getAnalytics: ClientSideTool<z.infer<typeof inputSchema>, Output> = {\n\t...serverSchema,\n\ticon: ChartAreaIcon,\n\texecute,\n};\n","import { inputSchema } from '@harperfast/agent-tools/tools/getComponentFile/inputSchema';\nimport { serverSchema } from '@harperfast/agent-tools/tools/getComponentFile/serverSchema';\nimport { FileIcon } from 'lucide-react';\nimport { z } from 'zod';\nimport type { ClientSideTool } from '../../types/clientSideTool';\nimport { execute } from './execute';\nimport { Output } from './output';\n\nexport const getComponentFile: ClientSideTool<z.infer<typeof inputSchema>, Output> = {\n\t...serverSchema,\n\ticon: FileIcon,\n\texecute,\n};\n","import { inputSchema } from '@harperfast/agent-tools/tools/getComponents/inputSchema';\nimport { serverSchema } from '@harperfast/agent-tools/tools/getComponents/serverSchema';\nimport { FolderIcon } from 'lucide-react';\nimport { z } from 'zod';\nimport type { ClientSideTool } from '../../types/clientSideTool';\nimport { execute } from './execute';\nimport { Output } from './output';\n\nexport const getComponents: ClientSideTool<z.infer<typeof inputSchema>, Output> = {\n\t...serverSchema,\n\ticon: FolderIcon,\n\texecute,\n};\n","import { inputSchema } from '@harperfast/agent-tools/tools/getDescribeAll/inputSchema';\nimport { serverSchema } from '@harperfast/agent-tools/tools/getDescribeAll/serverSchema';\nimport { DatabaseIcon } from 'lucide-react';\nimport { z } from 'zod';\nimport type { ClientSideTool } from '../../types/clientSideTool';\nimport { execute } from './execute';\nimport { Output } from './output';\n\nexport const getDescribeAll: ClientSideTool<z.infer<typeof inputSchema>, Output> = {\n\t...serverSchema,\n\ticon: DatabaseIcon,\n\texecute,\n};\n","import { inputSchema } from '@harperfast/agent-tools/tools/getDescribeTable/inputSchema';\nimport { serverSchema } from '@harperfast/agent-tools/tools/getDescribeTable/serverSchema';\nimport { TableIcon } from 'lucide-react';\nimport { z } from 'zod';\nimport type { ClientSideTool } from '../../types/clientSideTool';\nimport { execute } from './execute';\nimport { Output } from './output';\n\nexport const getDescribeTable: ClientSideTool<z.infer<typeof inputSchema>, Output> = {\n\t...serverSchema,\n\ticon: TableIcon,\n\texecute,\n};\n","import { inputSchema } from '@harperfast/agent-tools/tools/getUserContext/inputSchema';\nimport { serverSchema } from '@harperfast/agent-tools/tools/getUserContext/serverSchema';\nimport { UserIcon } from 'lucide-react';\nimport { z } from 'zod';\nimport type { ClientSideTool } from '../../types/clientSideTool';\nimport { execute } from './execute';\nimport { Output } from './output';\n\nexport const getUserContext: ClientSideTool<z.infer<typeof inputSchema>, Output> = {\n\t...serverSchema,\n\ticon: UserIcon,\n\texecute,\n};\n","import { inputSchema } from '@harperfast/agent-tools/tools/insertTableRecords/inputSchema';\nimport { serverSchema } from '@harperfast/agent-tools/tools/insertTableRecords/serverSchema';\nimport { BetweenHorizonalStartIcon } from 'lucide-react';\nimport { z } from 'zod';\nimport type { ClientSideTool } from '../../types/clientSideTool';\nimport { execute } from './execute';\nimport { Output } from './output';\n\nexport const insertTableRecords: ClientSideTool<z.infer<typeof inputSchema>, Output> = {\n\t...serverSchema,\n\ticon: BetweenHorizonalStartIcon,\n\texecute,\n\trequiresApproval: true,\n};\n","import { inputSchema } from '@harperfast/agent-tools/tools/readHarperSkill/inputSchema';\nimport { serverSchema } from '@harperfast/agent-tools/tools/readHarperSkill/serverSchema';\nimport { BookIcon } from 'lucide-react';\nimport { z } from 'zod';\nimport type { ClientSideTool } from '../../types/clientSideTool';\nimport { execute } from './execute';\nimport { Output } from './output';\n\nexport const readHarperSkill: ClientSideTool<z.infer<typeof inputSchema>, Output> = {\n\t...serverSchema,\n\ticon: BookIcon,\n\texecute,\n};\n","import { InstanceClientIdConfig } from '@/config/instanceClientConfig';\nimport { LogFiltersFormSchema } from '@/integrations/api/instance/status/logFiltersFormSchema';\nimport { queryOptions } from '@tanstack/react-query';\nimport { z } from 'zod';\n\nexport interface ReadLogItem {\n\tlevel: 'notify' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'stderr' | 'stdout';\n\ttimestamp: string;\n\tthread: string;\n\ttags: string[];\n\tnode: string;\n\tmessage: string;\n}\n\ninterface GetReadLogParams {\n\tlogFilters: z.infer<typeof LogFiltersFormSchema>;\n\treplicated: boolean;\n\tisAutoRefreshEnabled: boolean;\n}\n\nexport async function getReadLog(\n\t{ instanceClient, logFilters, replicated }: Omit<GetReadLogParams, 'isAutoRefreshEnabled'> & InstanceClientIdConfig,\n): Promise<ReadLogItem[]> {\n\tconst { data } = await instanceClient.post<ReadLogItem[]>('/', {\n\t\toperation: 'read_log',\n\t\tstart: 0,\n\t\treplicated,\n\t\tlimit: logFilters.limit ? parseInt(logFilters.limit, 10) : undefined,\n\t\tlevel: logFilters.level !== 'undefined' ? logFilters.level : undefined,\n\t\tfrom: logFilters.from ? new Date(logFilters.from).toISOString() : undefined,\n\t\tuntil: logFilters.until ? new Date(logFilters.until).toISOString() : undefined,\n\t\torder: 'desc',\n\t});\n\treturn data;\n}\n\nexport function getReadLogQueryOptions(params: GetReadLogParams & InstanceClientIdConfig) {\n\tconst logFilters = params.logFilters;\n\treturn queryOptions({\n\t\tqueryKey: [\n\t\t\tparams.entityId,\n\t\t\t'read_log',\n\t\t\tlogFilters.limit,\n\t\t\tlogFilters.level,\n\t\t\tlogFilters.from,\n\t\t\tlogFilters.until,\n\t\t\tparams.replicated,\n\t\t] as const,\n\t\tqueryFn: () => getReadLog(params),\n\t\tretry: false,\n\t\trefetchInterval: params.isAutoRefreshEnabled ? 5000 : false,\n\t});\n}\n","import { inputSchema } from '@harperfast/agent-tools/tools/readLogs/inputSchema';\nimport { serverSchema } from '@harperfast/agent-tools/tools/readLogs/serverSchema';\nimport { LogsIcon } from 'lucide-react';\nimport { z } from 'zod';\nimport type { ClientSideTool } from '../../types/clientSideTool';\nimport { execute } from './execute';\nimport { Output } from './output';\n\nexport const readLogs: ClientSideTool<z.infer<typeof inputSchema>, Output> = {\n\t...serverSchema,\n\ticon: LogsIcon,\n\texecute,\n};\n","import { inputSchema } from '@harperfast/agent-tools/tools/readTableRecords/inputSchema';\nimport { serverSchema } from '@harperfast/agent-tools/tools/readTableRecords/serverSchema';\nimport { SearchIcon } from 'lucide-react';\nimport { z } from 'zod';\nimport type { ClientSideTool } from '../../types/clientSideTool';\nimport { execute } from './execute';\nimport { Output } from './output';\n\nexport const readTableRecords: ClientSideTool<z.infer<typeof inputSchema>, Output> = {\n\t...serverSchema,\n\ticon: SearchIcon,\n\texecute,\n};\n","import { inputSchema } from '@harperfast/agent-tools/tools/restartHTTPService/inputSchema';\nimport { serverSchema } from '@harperfast/agent-tools/tools/restartHTTPService/serverSchema';\nimport { RefreshCwIcon } from 'lucide-react';\nimport { z } from 'zod';\nimport type { ClientSideTool } from '../../types/clientSideTool';\nimport { execute } from './execute';\nimport { Output } from './output';\n\nexport const restartHTTPService: ClientSideTool<z.infer<typeof inputSchema>, Output> = {\n\t...serverSchema,\n\ticon: RefreshCwIcon,\n\texecute,\n\trequiresApproval: true,\n};\n","import { inputSchema } from '@harperfast/agent-tools/tools/setComponentFile/inputSchema';\nimport { serverSchema } from '@harperfast/agent-tools/tools/setComponentFile/serverSchema';\nimport { FilePenIcon } from 'lucide-react';\nimport { z } from 'zod';\nimport type { ClientSideTool } from '../../types/clientSideTool';\nimport { execute } from './execute';\nimport { Output } from './output';\n\nexport const setComponentFile: ClientSideTool<z.infer<typeof inputSchema>, Output> = {\n\t...serverSchema,\n\ticon: FilePenIcon,\n\texecute,\n\trequiresApproval: true,\n};\n","import { inputSchema } from '@harperfast/agent-tools/tools/updateTableRecords/inputSchema';\nimport { serverSchema } from '@harperfast/agent-tools/tools/updateTableRecords/serverSchema';\nimport { BetweenHorizonalStartIcon } from 'lucide-react';\nimport { z } from 'zod';\nimport type { ClientSideTool } from '../../types/clientSideTool';\nimport { execute } from './execute';\nimport { Output } from './output';\n\nexport const updateTableRecords: ClientSideTool<z.infer<typeof inputSchema>, Output> = {\n\t...serverSchema,\n\ticon: BetweenHorizonalStartIcon,\n\texecute,\n\trequiresApproval: true,\n};\n","import { isLocalStudio } from '@/config/constants';\nimport { InstanceNavBar } from '@/features/instance/InstanceNavBar';\nimport { Outlet } from '@tanstack/react-router';\nimport { FloatingChat } from './applications/components/Chat/FloatingChat';\n\nexport function InstanceLayout() {\n\treturn (\n\t\t<>\n\t\t\t<nav className=\"fixed top-20 w-full z-39 h-12 md:px-12 bg-grey-700\">\n\t\t\t\t<InstanceNavBar />\n\t\t\t</nav>\n\t\t\t<div className=\"mt-32 min-h-[calc(100vh-(--spacing(32)))]\">\n\t\t\t\t<Outlet />\n\t\t\t</div>\n\t\t\t{!isLocalStudio && <FloatingChat />}\n\t\t</>\n\t);\n}\n","import { getInstanceClient } from '@/config/getInstanceClient';\nimport {\n\tAuthenticatedCloudConnection,\n\tAuthenticatedConnection,\n\tauthStore,\n\tOverallAppSignIn,\n} from '@/features/auth/store/authStore';\nimport { clusterLayoutRoute } from '@/features/cluster/clusterLayoutRoute';\nimport { InstanceLayout } from '@/features/instance/InstanceLayout';\nimport { getOrganizationClusterInstancePermissions, getOrganizationClusterPermissions } from '@/hooks/usePermissions';\nimport { getInstanceUserInfo } from '@/integrations/api/instance/status/getInstanceUserInfo';\nimport { buildRedirectInSearch } from '@/lib/urls/buildRedirectInSearch';\nimport { dashboardLayout } from '@/router/dashboardRoute';\nimport { createRoute, redirect } from '@tanstack/react-router';\nimport { registrationInfoLoader } from './registrationInfoLoader';\n\nexport function createInstanceLayoutRoute(mode: 'local' | 'cluster' | 'instance') {\n\tswitch (mode) {\n\t\tcase 'local':\n\t\t\treturn createRoute({\n\t\t\t\tgetParentRoute: () => dashboardLayout,\n\t\t\t\tid: '_instanceLayout',\n\t\t\t\tcomponent: InstanceLayout,\n\t\t\t\tloader: registrationInfoLoader,\n\t\t\t});\n\t\tcase 'cluster':\n\t\t\treturn createRoute({\n\t\t\t\tgetParentRoute: () => clusterLayoutRoute,\n\t\t\t\tid: '_instanceLayout',\n\t\t\t\tcomponent: InstanceLayout,\n\t\t\t\tbeforeLoad: checkClusterInstanceAuthenticationBeforeLoad,\n\t\t\t\tloader: registrationInfoLoader,\n\t\t\t});\n\t\tcase 'instance':\n\t\t\treturn createRoute({\n\t\t\t\tgetParentRoute: () => clusterLayoutRoute,\n\t\t\t\tpath: 'instance/$instanceId',\n\t\t\t\tcomponent: InstanceLayout,\n\t\t\t\tbeforeLoad: checkClusterInstanceAuthenticationBeforeLoad,\n\t\t\t\tloader: registrationInfoLoader,\n\t\t\t});\n\t}\n}\n\nasync function checkClusterInstanceAuthenticationBeforeLoad({\n\tcontext,\n\tparams,\n}: {\n\tcontext: { authentication: Record<string, AuthenticatedConnection> };\n\tparams: { organizationId: string; clusterId: string; instanceId?: string };\n}) {\n\t// Are we already authenticated?\n\tconst auth = context.authentication[params.instanceId || params.clusterId];\n\tif (auth?.isLoading || auth?.user) {\n\t\treturn;\n\t}\n\n\t// See if we can Fabric Connect.\n\tconst overallAuth = context.authentication[OverallAppSignIn] as AuthenticatedCloudConnection;\n\tif (overallAuth?.isLoading) {\n\t\treturn;\n\t}\n\tconst { update } = params.instanceId\n\t\t? getOrganizationClusterInstancePermissions(overallAuth.user, params.organizationId, params.clusterId)\n\t\t: getOrganizationClusterPermissions(overallAuth.user, params.organizationId, params.clusterId);\n\tif (update) {\n\t\tconst entityId = params.instanceId || params.clusterId;\n\t\tconst instanceClient = getInstanceClient({\n\t\t\tid: entityId,\n\t\t\tforceFabricConnect: true,\n\t\t});\n\t\ttry {\n\t\t\tconst user = await getInstanceUserInfo({ instanceClient });\n\t\t\tauthStore.setUserForIdAndKey(\n\t\t\t\tentityId,\n\t\t\t\tinstanceClient.defaults.baseURL!,\n\t\t\t\tuser,\n\t\t\t);\n\t\t\tauthStore.flagForFabricConnect(entityId, true);\n\t\t\treturn;\n\t\t} catch (err) {\n\t\t\tconsole.error('Fabric Connect not established', err);\n\t\t}\n\t}\n\n\tconst to = `/${params.organizationId}/${params.clusterId}/`\n\t\t+ (params.instanceId ? `instance/${params.instanceId}` : '')\n\t\t+ `/sign-in`;\n\tthrow redirect({ to, search: buildRedirectInSearch() });\n}\n","import { cva } from 'class-variance-authority';\n\nexport const toggleVariants = cva(\n\t`inline-flex \n items-center \n justify-center \n gap-2 \n whitespace-nowrap \n rounded-lg \n text-sm \n transition-[color,box-shadow] \n disabled:pointer-events-none \n disabled:opacity-50 \n [&_svg]:pointer-events-none \n [&_svg:not([class*='size-'])]:size-4 \n [&_svg]:shrink-0 \n ring-ring/10 \n dark:ring-ring/20 \n dark:outline-ring/40 \n outline-ring/50 \n focus-visible:ring-1 \n focus-visible:outline-1 \n focus-visible:ring-purple-200 \n aria-invalid:focus-visible:ring-0`,\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: 'bg-primary text-primary-foreground shadow-sm hover:bg-primary/90',\n\t\t\t\toutline:\n\t\t\t\t\t'border bg-default border-primary border-2 text-white shadow-xs hover:-translate-y-1 transition duration-200 hover:bg-grey-700/40',\n\t\t\t},\n\t\t\tsize: {\n\t\t\t\tdefault: 'h-9 px-4 py-2 has-[>svg]:px-3',\n\t\t\t\tsm: 'h-8 px-1.5 min-w-8',\n\t\t\t\tlg: 'h-10 px-2.5 min-w-10',\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tvariant: 'default',\n\t\t\tsize: 'default',\n\t\t},\n\t},\n);\n","import { toggleVariants } from '@/components/ui/toggleVariants';\nimport { cn } from '@/lib/cn';\nimport * as TogglePrimitive from '@radix-ui/react-toggle';\nimport { type VariantProps } from 'class-variance-authority';\nimport * as React from 'react';\n\nexport function Toggle({\n\tclassName,\n\tvariant,\n\tsize,\n\t...props\n}: React.ComponentProps<typeof TogglePrimitive.Root> & VariantProps<typeof toggleVariants>) {\n\treturn (\n\t\t<TogglePrimitive.Root data-slot=\"toggle\" className={cn(toggleVariants({ variant, size, className }))} {...props} />\n\t);\n}\n","export type BadgeLogLevelVariant =\n\t| 'notify'\n\t| 'error'\n\t| 'warn'\n\t| 'info'\n\t| 'debug'\n\t| 'trace'\n\t| 'stderr'\n\t| 'stdout'\n\t| undefined;\n\ntype BadgeStatusVariantValues = 'warning' | 'success' | 'secondary' | 'destructive';\n\nexport function renderBadgeLogLevelVariant(value: BadgeLogLevelVariant): BadgeStatusVariantValues {\n\tswitch (value) {\n\t\tcase 'warn':\n\t\t\treturn 'warning';\n\t\tcase 'notify':\n\t\t\treturn 'success';\n\t\tcase 'info':\n\t\tcase 'debug':\n\t\tcase 'trace':\n\t\tcase undefined:\n\t\tcase 'stdout':\n\t\t\treturn 'secondary';\n\t\tcase 'stderr':\n\t\tcase 'error':\n\t\t\treturn 'destructive';\n\t\tdefault:\n\t\t\treturn value;\n\t}\n}\n","const nodeVariant = ['secondary', 'default', 'warning', 'outline', 'success', 'destructive'] as const;\n\nlet nodeEntries = 0;\nconst cache = new Map<string, BadgeNodeVariantValues>();\n\nconst memoizeNodeNames = (nodeName: string): BadgeNodeVariantValues => {\n\tif (cache.has(nodeName)) { return cache.get(nodeName)!; }\n\tnodeEntries++;\n\tconst nodeVariantIndex = nodeEntries % nodeVariant.length;\n\tconst memoized = nodeVariant[nodeVariantIndex] as BadgeNodeVariantValues;\n\tcache.set(nodeName, memoized);\n\treturn memoized;\n};\n\nexport type BadgeNodeVariantValues = (typeof nodeVariant)[number];\n\nexport { memoizeNodeNames, nodeVariant };\n","'use client';\n\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';\nimport { ReadLogItem } from '@/integrations/api/instance/status/getReadLog';\nimport { cn } from '@/lib/cn';\nimport { ColumnDef, flexRender, getCoreRowModel, Row, useReactTable } from '@tanstack/react-table';\n\ninterface DataTableProps<TData extends ReadLogItem, TValue> {\n\tcolumns: ColumnDef<ReadLogItem, TValue>[];\n\tdata: TData[];\n\tonRowClick?: (row: Row<TData>) => void;\n\tcontainerClassName?: string;\n}\n\nexport function LogsDataTable<TData extends ReadLogItem, TValue>({\n\tcolumns,\n\tdata,\n\tonRowClick,\n}: DataTableProps<TData, TValue>) {\n\tconst table = useReactTable({\n\t\tdata,\n\t\tcolumns,\n\t\tgetCoreRowModel: getCoreRowModel(),\n\t});\n\n\treturn (\n\t\t<div className=\"rounded-md bg-black-dark logsTable\">\n\t\t\t<Table className=\"text-xs\">\n\t\t\t\t<TableHeader>\n\t\t\t\t\t{table.getHeaderGroups().map((headerGroup) => (\n\t\t\t\t\t\t<TableRow key={headerGroup.id} className=\"border-none\">\n\t\t\t\t\t\t\t{headerGroup.headers.map((header) => {\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<TableHead key={header.id} className=\"p-4 max-w-96\">\n\t\t\t\t\t\t\t\t\t\t{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}\n\t\t\t\t\t\t\t\t\t</TableHead>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t))}\n\t\t\t\t</TableHeader>\n\t\t\t\t<TableBody className=\"bg-black\">\n\t\t\t\t\t{table.getRowModel().rows?.length\n\t\t\t\t\t\t? (\n\t\t\t\t\t\t\ttable.getRowModel().rows.map((row) => (\n\t\t\t\t\t\t\t\t<TableRow\n\t\t\t\t\t\t\t\t\tkey={row.id}\n\t\t\t\t\t\t\t\t\tdata-state={row.getIsSelected() && 'selected'}\n\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t'hover:bg-muted/10 data-[state=selected]:bg-muted max-w-full',\n\t\t\t\t\t\t\t\t\t\tonRowClick && 'cursor-pointer',\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\tonClick={() => onRowClick?.(row as Row<TData>)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{row.getVisibleCells().map((cell) => (\n\t\t\t\t\t\t\t\t\t\t<TableCell key={cell.id} className=\"p-1\">\n\t\t\t\t\t\t\t\t\t\t\t{flexRender(cell.column.columnDef.cell, cell.getContext())}\n\t\t\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t\t\t))\n\t\t\t\t\t\t)\n\t\t\t\t\t\t: (\n\t\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t\t<TableCell colSpan={columns.length} className=\"h-24 text-center\">\n\t\t\t\t\t\t\t\t\tNo results.\n\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t\t)}\n\t\t\t\t</TableBody>\n\t\t\t</Table>\n\t\t</div>\n\t);\n}\n","import { Loading } from '@/components/Loading';\nimport { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';\nimport { renderBadgeLogLevelVariant } from '@/components/ui/utils/badgeLogLevel';\nimport { BadgeNodeVariantValues, memoizeNodeNames } from '@/components/ui/utils/badgeNode';\nimport { ReadLogItem } from '@/integrations/api/instance/status/getReadLog';\nimport { capitalizeWords } from '@/lib/string/capitalizeWords';\nimport Editor from '@monaco-editor/react';\nimport { Save, Trash } from 'lucide-react';\n\nfunction isJsonString(str: string) {\n\ttry {\n\t\tJSON.parse(str);\n\t} catch {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nexport function ViewLogModal({\n\tsetIsModalOpen,\n\tisModalOpen,\n\tdata,\n}: {\n\tsetIsModalOpen: (open: boolean) => void;\n\tisModalOpen: boolean;\n\tdata: ReadLogItem | undefined;\n}) {\n\tconst variant: BadgeNodeVariantValues = data ? memoizeNodeNames(data.node) : 'default';\n\treturn (\n\t\t<Dialog onOpenChange={setIsModalOpen} open={isModalOpen}>\n\t\t\t{/* NOTE - Is this okay to do for the aria describedby? */}\n\t\t\t<DialogContent aria-describedby={undefined}>\n\t\t\t\t<DialogHeader>\n\t\t\t\t\t<DialogTitle>Edit Row</DialogTitle>\n\t\t\t\t</DialogHeader>\n\t\t\t\t{data\n\t\t\t\t\t? (\n\t\t\t\t\t\t// <Editor className=\"w-full h-96\" language=\"json\" theme=\"vs-dark\" value={JSON.stringify(data, null, 4)} />\n\t\t\t\t\t\t<div className=\"flex flex-col gap-3 text-white\">\n\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t<h3 className=\"inline-block pr-2\">Level:</h3>\n\t\t\t\t\t\t\t\t<Badge variant={renderBadgeLogLevelVariant(data.level)}>\n\t\t\t\t\t\t\t\t\t{capitalizeWords(data.level)}\n\t\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t<h3>Timestamp:</h3>\n\t\t\t\t\t\t\t\t<p className=\"text-sm\">{data.timestamp}</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t<h3>Thread:</h3>\n\t\t\t\t\t\t\t\t<p className=\"text-sm\">{data.thread}</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t<h3>Node:</h3>\n\t\t\t\t\t\t\t\t<Badge variant={variant}>{data.node}</Badge>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t<h3>Tags:</h3>\n\t\t\t\t\t\t\t\t<p className=\"text-sm\">{data.tags && data.tags.length > 0 ? <span>{data.tags}</span> : 'N/A'}</p>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t<h3 className=\"text-lg font-bold\">Message</h3>\n\t\t\t\t\t\t\t\t<Editor\n\t\t\t\t\t\t\t\t\tclassName=\"w-full h-72\"\n\t\t\t\t\t\t\t\t\tlanguage={isJsonString(data.message) ? 'json' : 'text'}\n\t\t\t\t\t\t\t\t\ttheme=\"vs-dark\"\n\t\t\t\t\t\t\t\t\tvalue={data.message}\n\t\t\t\t\t\t\t\t\toptions={{\n\t\t\t\t\t\t\t\t\t\treadOnly: true,\n\t\t\t\t\t\t\t\t\t\tminimap: {\n\t\t\t\t\t\t\t\t\t\t\tenabled: false,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tscrollBeyondLastLine: false,\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)\n\t\t\t\t\t: <Loading />}\n\t\t\t\t<DialogFooter>\n\t\t\t\t\t<div className=\"flex justify-between w-full\">\n\t\t\t\t\t\t<Button type=\"button\" variant=\"destructive\" className=\"rounded-full\">\n\t\t\t\t\t\t\t<Trash /> Delete Row\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t<Button variant=\"submit\" className=\"rounded-full\">\n\t\t\t\t\t\t\t<Save /> Save Changes\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t</DialogFooter>\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t);\n}\n","import { z } from 'zod';\n\nexport const LogFiltersFormSchema = z.object({\n\tlimit: z.string().or(z.undefined()).or(z.null()),\n\tlevel: z.enum(['notify', 'error', 'warn', 'info', 'debug', 'trace', 'undefined']).or(z.undefined()).or(z.null()),\n\tfrom: z.string().or(z.undefined()).or(z.null()).optional(),\n\tuntil: z.string().or(z.undefined()).or(z.null()).optional(),\n});\n","import { Button } from '@/components/ui/button';\nimport { Form } from '@/components/ui/form/Form';\nimport { FormControl } from '@/components/ui/form/FormControl';\nimport { FormField } from '@/components/ui/form/FormField';\nimport { FormItem } from '@/components/ui/form/FormItem';\nimport { FormLabel } from '@/components/ui/form/FormLabel';\nimport { FormMessage } from '@/components/ui/form/FormMessage';\nimport { Input } from '@/components/ui/input';\nimport { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';\nimport { LogFiltersFormSchema } from '@/integrations/api/instance/status/logFiltersFormSchema';\nimport { UseFormReturn } from 'react-hook-form';\nimport z from 'zod';\n\nexport function LogsFiltersForm({\n\tform,\n\tresetFilters,\n\tsubmitFilters,\n}: {\n\tform: UseFormReturn<z.infer<typeof LogFiltersFormSchema>>;\n\tresetFilters: () => void;\n\tsubmitFilters: (data: z.infer<typeof LogFiltersFormSchema>) => void;\n}) {\n\treturn (\n\t\t<div>\n\t\t\t<Form {...form}>\n\t\t\t\t<form\n\t\t\t\t\tid=\"instance-edit-log-filters-form\"\n\t\t\t\t\tname=\"instance-edit-log-filters-form\"\n\t\t\t\t\tonSubmit={form.handleSubmit(submitFilters)}\n\t\t\t\t\tclassName=\"flex-col space-y-5\"\n\t\t\t\t>\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\tname=\"limit\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel>Log Limit:</FormLabel>\n\t\t\t\t\t\t\t\t<Select onValueChange={field.onChange} value={field.value ?? undefined}>\n\t\t\t\t\t\t\t\t\t<SelectTrigger className=\"w-full\">\n\t\t\t\t\t\t\t\t\t\t<SelectValue placeholder=\"Select log limit\" />\n\t\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t\t\t<SelectGroup>\n\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"1000\">1000</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"500\">500</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"250\">250</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"100\">100</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"10\">10</SelectItem>\n\t\t\t\t\t\t\t\t\t\t</SelectGroup>\n\t\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\tname=\"level\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel>Log Level:</FormLabel>\n\t\t\t\t\t\t\t\t<Select onValueChange={field.onChange} value={field.value ?? undefined}>\n\t\t\t\t\t\t\t\t\t<SelectTrigger className=\"w-full\">\n\t\t\t\t\t\t\t\t\t\t<SelectValue placeholder=\"Select log level\" />\n\t\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t\t\t<SelectGroup>\n\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"undefined\">All</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"notify\">Notify</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"error\">Error</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"warn\">Warn</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"info\">Info</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"debug\">Debug</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"trace\">Trace</SelectItem>\n\t\t\t\t\t\t\t\t\t\t</SelectGroup>\n\t\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\tname=\"from\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel>Start Date:</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input type=\"datetime-local\" value={field.value ?? undefined} onChange={field.onChange} />\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t\t<FormField\n\t\t\t\t\t\tcontrol={form.control}\n\t\t\t\t\t\tname=\"until\"\n\t\t\t\t\t\trender={({ field }) => (\n\t\t\t\t\t\t\t<FormItem>\n\t\t\t\t\t\t\t\t<FormLabel>End Date:</FormLabel>\n\t\t\t\t\t\t\t\t<FormControl>\n\t\t\t\t\t\t\t\t\t<Input type=\"datetime-local\" value={field.value ?? undefined} onChange={field.onChange} />\n\t\t\t\t\t\t\t\t</FormControl>\n\t\t\t\t\t\t\t\t<FormMessage />\n\t\t\t\t\t\t\t</FormItem>\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<div className=\"flex items-center justify-between space-x-2 mt-2\">\n\t\t\t\t\t\t<Button type=\"submit\" variant=\"positiveOutline\" className=\"grow\">\n\t\t\t\t\t\t\tApply Filters\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t<Button type=\"reset\" variant=\"destructiveOutline\" onClick={resetFilters}>\n\t\t\t\t\t\t\tClear Filters\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t</form>\n\t\t\t</Form>\n\t\t</div>\n\t);\n}\n","import { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport { Toggle } from '@/components/ui/toggle';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';\nimport { renderBadgeLogLevelVariant } from '@/components/ui/utils/badgeLogLevel';\nimport { BadgeNodeVariantValues, memoizeNodeNames } from '@/components/ui/utils/badgeNode';\nimport { useInstanceClientIdParams } from '@/config/useInstanceClient';\nimport { LogsDataTable } from '@/features/instance/log/LogsDataTable';\nimport { ViewLogModal } from '@/features/instance/log/modals/ViewLogModal';\nimport { useRefreshClick } from '@/hooks/useRefreshClick';\nimport { getReadLogQueryOptions, ReadLogItem } from '@/integrations/api/instance/status/getReadLog';\nimport { LogFiltersFormSchema } from '@/integrations/api/instance/status/logFiltersFormSchema';\nimport { capitalizeWords } from '@/lib/string/capitalizeWords';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { useQuery } from '@tanstack/react-query';\nimport { ColumnDef } from '@tanstack/react-table';\nimport { RefreshCwIcon } from 'lucide-react';\nimport { useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { z } from 'zod';\nimport { LogsFiltersForm } from './components/LogsFiltersForm';\n\ntype RowData = {\n\toriginal: ReadLogItem;\n};\n\nconst defaultFormValues: z.infer<typeof LogFiltersFormSchema> = {\n\tlimit: '100',\n\tlevel: 'undefined',\n\tfrom: '',\n\tuntil: '',\n};\n\nconst columns: ColumnDef<ReadLogItem>[] = [\n\t{\n\t\taccessorKey: 'level',\n\t\theader: 'Status',\n\t\tcell: ({ row }) => {\n\t\t\tconst { level } = row.original;\n\t\t\treturn <Badge variant={renderBadgeLogLevelVariant(level)}>{capitalizeWords(level)}</Badge>;\n\t\t},\n\t},\n\t{\n\t\taccessorKey: 'timestamp',\n\t\theader: 'Date',\n\t\tcell: ({ row }) => {\n\t\t\tconst { timestamp } = row.original;\n\t\t\treturn <span>{new Date(timestamp).toLocaleDateString()}</span>;\n\t\t},\n\t},\n\t{\n\t\taccessorKey: 'time',\n\t\theader: 'Time',\n\t\tcell: ({ row }) => {\n\t\t\tconst { timestamp } = row.original;\n\t\t\treturn <span>{new Date(timestamp).toLocaleTimeString()}</span>;\n\t\t},\n\t},\n\t{\n\t\taccessorKey: 'thread',\n\t\theader: 'Thread',\n\t},\n\t{\n\t\taccessorKey: 'node',\n\t\theader: 'Node',\n\t\tcell: ({ row }) => {\n\t\t\tconst { node } = row.original;\n\t\t\tconst variant: BadgeNodeVariantValues = memoizeNodeNames(node);\n\t\t\treturn (\n\t\t\t\t<>\n\t\t\t\t\t{node\n\t\t\t\t\t\t? (\n\t\t\t\t\t\t\t<Tooltip>\n\t\t\t\t\t\t\t\t<TooltipTrigger asChild>\n\t\t\t\t\t\t\t\t\t<Badge variant={variant}>{node.split('.')[0]}...</Badge>\n\t\t\t\t\t\t\t\t</TooltipTrigger>\n\t\t\t\t\t\t\t\t<TooltipContent className=\"bg-grey-700\" arrowClassName=\"bg-grey-700 fill-grey-700\">\n\t\t\t\t\t\t\t\t\t{node}\n\t\t\t\t\t\t\t\t</TooltipContent>\n\t\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t\t)\n\t\t\t\t\t\t: null}\n\t\t\t\t</>\n\t\t\t);\n\t\t},\n\t},\n\t{\n\t\taccessorKey: 'tags',\n\t\theader: 'Tags',\n\t},\n\t{\n\t\taccessorKey: 'message',\n\t\theader: 'Message',\n\t\tcell: ({ row }) => {\n\t\t\tconst { message } = row.original;\n\t\t\trow.getIsSelected();\n\t\t\treturn (\n\t\t\t\t<pre>\n\t\t\t\t\t<code>{message}</code>\n\t\t\t\t</pre>\n\t\t\t);\n\t\t},\n\t},\n];\n\nconst isValidDateRange = (startDate?: string | null, endDate?: string | null) => {\n\tif (!startDate && !endDate) { return true; }\n\tif (!startDate || !endDate) { return true; }\n\n\tconst start = new Date(startDate);\n\tconst end = new Date(endDate);\n\treturn start <= end;\n};\n\nexport function Logs() {\n\tconst [logFilters, setLogFilters] = useState<z.infer<typeof LogFiltersFormSchema>>(defaultFormValues);\n\n\tconst [isViewLogModalOpen, setIsViewLogModalOpen] = useState(false);\n\tconst [selectedLogData, setSelectedLogData] = useState<ReadLogItem | undefined>();\n\tconst [isAutoRefreshEnabled, setIsAutoRefreshEnabled] = useState(false);\n\n\tconst instanceParams = useInstanceClientIdParams();\n\tconst {\n\t\tdata: instanceLogs,\n\t\tisLoading,\n\t\trefetch: refetchReadLogQueryOptions,\n\t\tisFetching: isFetchingInstanceLogs,\n\t} = useQuery(\n\t\tgetReadLogQueryOptions({\n\t\t\tlogFilters,\n\t\t\t...instanceParams,\n\t\t\treplicated: instanceParams.entityType === 'cluster',\n\t\t\tisAutoRefreshEnabled,\n\t\t}),\n\t);\n\n\tconst form = useForm({\n\t\tresolver: zodResolver(LogFiltersFormSchema),\n\t\tdefaultValues: defaultFormValues,\n\t\tmode: 'onChange',\n\t});\n\n\tconst onRowClick = (rowData: RowData): void => {\n\t\tsetSelectedLogData(rowData.original);\n\t\tsetIsViewLogModalOpen(true);\n\t};\n\n\tconst submitFilters = async (data: z.infer<typeof LogFiltersFormSchema>) => {\n\t\tif (!isValidDateRange(data.from, data.until)) {\n\t\t\tform.setError('from', {\n\t\t\t\ttype: 'onChange',\n\t\t\t\tmessage: 'Start date must be before end date',\n\t\t\t});\n\t\t\tform.setError('until', {\n\t\t\t\ttype: 'onChange',\n\t\t\t\tmessage: 'End date must be after start date',\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tsetLogFilters(data);\n\t};\n\n\tconst resetFilters = async () => {\n\t\tform.reset();\n\t\tsetLogFilters(defaultFormValues);\n\t};\n\n\tconst onRefreshClick = useRefreshClick(refetchReadLogQueryOptions);\n\n\treturn (\n\t\t<div className=\"grid grid-cols-1 gap-4 text-white md:grid-cols-12\">\n\t\t\t<section className=\"col-span-1 md:col-span-4 lg:col-span-3 px-2 pt-4 md:pt-12\">\n\t\t\t\t<LogsFiltersForm form={form} resetFilters={resetFilters} submitFilters={submitFilters} />\n\n\t\t\t\t<div className=\"flex items-center justify-between space-x-2 mt-2\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"defaultOutline\"\n\t\t\t\t\t\tonClick={onRefreshClick}\n\t\t\t\t\t\tdisabled={isFetchingInstanceLogs || isLoading || isAutoRefreshEnabled}\n\t\t\t\t\t\tclassName=\"grow\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<RefreshCwIcon />\n\t\t\t\t\t\tRefresh\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Toggle variant=\"outline\" aria-label=\"Toggle Auto Refresh\" onPressedChange={setIsAutoRefreshEnabled}>\n\t\t\t\t\t\t<RefreshCwIcon />\n\t\t\t\t\t\tAuto Refresh {isAutoRefreshEnabled ? 'On' : 'Off'}\n\t\t\t\t\t</Toggle>\n\t\t\t\t</div>\n\t\t\t</section>\n\t\t\t<section className=\"col-span-1 md:col-span-8 lg:col-span-9\">\n\t\t\t\t{isLoading ? <div>Loading...</div> : (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<LogsDataTable columns={columns} data={instanceLogs || []} onRowClick={onRowClick} />\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</section>\n\t\t\t<ViewLogModal isModalOpen={isViewLogModalOpen} setIsModalOpen={setIsViewLogModalOpen} data={selectedLogData} />\n\t\t</div>\n\t);\n}\n","import { createInstanceLayoutRoute } from '@/features/instance/instanceLayoutRoute';\nimport { Logs } from '@/features/instance/log/index';\nimport { createRoute } from '@tanstack/react-router';\n\nexport function createLogRouteTree(instanceLayoutRoute: ReturnType<typeof createInstanceLayoutRoute>) {\n\treturn createRoute({\n\t\tgetParentRoute: () => instanceLayoutRoute,\n\t\tpath: 'logs',\n\t\tcomponent: Logs,\n\t});\n}\n","import { createInstanceLayoutRoute } from '@/features/instance/instanceLayoutRoute';\nimport { createRoute, lazyRouteComponent } from '@tanstack/react-router';\n\nexport function createStatusRouteTree(instanceLayoutRoute: ReturnType<typeof createInstanceLayoutRoute>) {\n\tconst instanceConfigRoute = createRoute({\n\t\tgetParentRoute: () => instanceLayoutRoute,\n\t\tpath: 'status',\n\t\tcomponent: lazyRouteComponent(async () => import('@/features/instance/status/index'), 'StatusIndex'),\n\t});\n\treturn instanceConfigRoute;\n}\n","import { createAPIsRouteTree } from '@/features/instance/apis/routes';\nimport { createApplicationsRoutes } from '@/features/instance/applications/routes';\nimport { createConfigRouteTree } from '@/features/instance/config/routes';\nimport { createBrowseRouteTree } from '@/features/instance/databases/routes';\nimport { createInstanceLayoutRoute } from '@/features/instance/instanceLayoutRoute';\nimport { createLogRouteTree } from '@/features/instance/log/routes';\nimport { createStatusRouteTree } from '@/features/instance/status/routes';\n\nexport function createInstanceRouteTree(mode: 'local' | 'cluster' | 'instance') {\n\tconst instanceLayoutRoute = createInstanceLayoutRoute(mode);\n\n\tconst children = [\n\t\tcreateLogRouteTree(instanceLayoutRoute),\n\t\t...createApplicationsRoutes(instanceLayoutRoute),\n\t\tcreateAPIsRouteTree(instanceLayoutRoute),\n\t\tcreateStatusRouteTree(instanceLayoutRoute),\n\t\tcreateConfigRouteTree(instanceLayoutRoute),\n\t\tcreateBrowseRouteTree(instanceLayoutRoute),\n\t];\n\n\treturn instanceLayoutRoute.addChildren(children);\n}\n","import { dashboardLayout } from '@/router/dashboardRoute';\nimport { createRoute, lazyRouteComponent } from '@tanstack/react-router';\n\nconst profileRoute = createRoute({\n\tgetParentRoute: () => dashboardLayout,\n\tpath: 'profile',\n\tcomponent: lazyRouteComponent(async () => import('@/features/profile/index'), 'ProfileIndex'),\n});\n\nexport const profileRoutes = [profileRoute];\n","import { isLocalStudio } from '@/config/constants';\nimport { authRouteTree, localAuthRoutes } from '@/features/auth/routes';\nimport { clusterLayoutRoute } from '@/features/cluster/clusterLayoutRoute';\nimport { clusterRoutes } from '@/features/cluster/routes';\nimport { clustersLayoutRoute, clustersRoutes } from '@/features/clusters/routes';\nimport { createInstanceRouteTree } from '@/features/instance/routes';\nimport { orgLayoutRoute, orgRoutes } from '@/features/organization/routes';\nimport { orgsLayoutRoute, orgsRoutes } from '@/features/organizations/routes';\nimport { profileRoutes } from '@/features/profile/routes';\nimport { dashboardLayout } from '@/router/dashboardRoute';\nimport { rootRoute } from '@/router/rootRoute';\n\nexport const rootRouteTree = isLocalStudio\n\t? rootRoute.addChildren([\n\t\t...localAuthRoutes,\n\t\tdashboardLayout.addChildren([\n\t\t\tcreateInstanceRouteTree('local'),\n\t\t]),\n\t])\n\t: rootRoute.addChildren([\n\t\tauthRouteTree,\n\t\tdashboardLayout.addChildren([\n\t\t\t...profileRoutes,\n\t\t\torgsLayoutRoute.addChildren([\n\t\t\t\t...orgsRoutes,\n\t\t\t\torgLayoutRoute.addChildren([\n\t\t\t\t\t...orgRoutes,\n\t\t\t\t\tclustersLayoutRoute.addChildren([\n\t\t\t\t\t\t...clustersRoutes,\n\t\t\t\t\t\tcreateInstanceRouteTree('cluster'),\n\t\t\t\t\t\tclusterLayoutRoute.addChildren([\n\t\t\t\t\t\t\t...clusterRoutes,\n\t\t\t\t\t\t\tcreateInstanceRouteTree('instance'),\n\t\t\t\t\t\t]),\n\t\t\t\t\t]),\n\t\t\t\t]),\n\t\t\t]),\n\t\t]),\n\t]);\n","import { ErrorComponent } from '@/components/ErrorComponent';\nimport { NotFoundComponent } from '@/components/NotFoundComponent';\nimport { AuthenticatedConnection, EntityIds } from '@/features/auth/store/authStore';\nimport { browserIsTouchBased } from '@/lib/browserIsTouchBased';\nimport { queryClient } from '@/react-query/queryClient';\nimport { rootRouteTree } from '@/router/rootRouteTree';\nimport { createHashHistory, createRouter } from '@tanstack/react-router';\n\nexport function useNewRouter({ routeTree = rootRouteTree, authentication }: {\n\trouteTree?: typeof rootRouteTree;\n\tauthentication?: Record<EntityIds, AuthenticatedConnection>;\n}) {\n\tconst hashHistory = createHashHistory();\n\treturn createRouter({\n\t\trouteTree,\n\t\thistory: hashHistory,\n\t\tdefaultNotFoundComponent: NotFoundComponent,\n\t\tdefaultErrorComponent: ErrorComponent,\n\t\tdefaultPreload: browserIsTouchBased() ? false : 'intent',\n\t\ttrailingSlash: 'never',\n\t\t// Since we're using React Query, we don't want loader calls to ever be stale\n\t\t// This will ensure that the loader is always called when the route is preloaded or visited\n\t\tdefaultPreloadStaleTime: 0,\n\t\tscrollRestoration: true,\n\t\tcontext: {\n\t\t\tqueryClient,\n\t\t\tauthentication: authentication || {},\n\t\t},\n\t});\n}\n","import { useRootAuthenticationContext } from '@/hooks/useAuth';\nimport { useNewRouter } from '@/router/useNewRouter';\nimport { RouterProvider } from '@tanstack/react-router';\nimport { TanStackRouterDevtools } from '@tanstack/react-router-devtools';\n\nexport function AppRouted() {\n\tconst authentication = useRootAuthenticationContext();\n\tconst router = useNewRouter({ authentication });\n\treturn (\n\t\t<>\n\t\t\t<RouterProvider router={router} context={{ authentication }} />\n\t\t\t{!import.meta.env.VITE_DISABLE_DEVTOOLS && <TanStackRouterDevtools router={router} position=\"bottom-right\" />}\n\t\t</>\n\t);\n}\n","// import { useTheme } from 'next-themes';\nimport { Toaster as Sonner, ToasterProps } from 'sonner';\n\nconst Toaster = ({ ...props }: ToasterProps) => {\n\t// const { theme = 'system' } = useTheme();\n\n\treturn (\n\t\t<Sonner\n\t\t\t// theme={theme as ToasterProps['theme']}\n\t\t\tclassName=\"toaster group\"\n\t\t\ttoastOptions={{\n\t\t\t\tclassNames: {\n\t\t\t\t\ttoast:\n\t\t\t\t\t\t'group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg',\n\t\t\t\t\tdescription: 'group-[.toast]:text-muted-foreground',\n\t\t\t\t\tactionButton: 'group-[.toast]:bg-primary group-[.toast]:text-primary-foreground font-medium',\n\t\t\t\t\tcancelButton: 'group-[.toast]:bg-muted group-[.toast]:text-muted-foreground font-medium',\n\t\t\t\t},\n\t\t\t}}\n\t\t\t{...props}\n\t\t/>\n\t);\n};\n\nexport { Toaster };\n","import { isLocalStudio } from '@/config/constants';\nimport { useEffect } from 'react';\n\nlet initialized = false;\nconst enabled = !import.meta.env.DEV && !isLocalStudio;\n\nexport function useGTM() {\n\tuseEffect(() => {\n\t\tif (initialized) {\n\t\t\treturn;\n\t\t}\n\t\tinitialized = true;\n\t\tif (enabled) {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t(function(w: any, d: any, s, l, i) {\n\t\t\t\tw[l] = w[l] || [];\n\t\t\t\tw[l].push({\n\t\t\t\t\t'gtm.start': new Date().getTime(),\n\t\t\t\t\tevent: 'gtm.js',\n\t\t\t\t});\n\t\t\t\tconst f = d.getElementsByTagName(s)[0];\n\t\t\t\tconst j = d.createElement(s);\n\t\t\t\tconst dl = l !== 'dataLayer' ? `&l=${l}` : '';\n\t\t\t\tj.async = true;\n\t\t\t\tj.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;\n\t\t\t\tf.parentNode.insertBefore(j, f);\n\t\t\t})(window, document, 'script', 'dataLayer', 'GTM-5QQX432');\n\t\t}\n\t}, []);\n}\n","import { AppRouted } from '@/AppRouted';\nimport { Toaster } from '@/components/ui/sonner';\nimport { useDatadog } from '@/integrations/datadog/datadog';\nimport { useGTM } from '@/integrations/google/gtm';\nimport { useReo } from '@/integrations/reo/reo';\nimport { queryClient } from '@/react-query/queryClient';\nimport { QueryClientProvider } from '@tanstack/react-query';\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools';\n\nexport function App() {\n\tuseReo();\n\tuseDatadog();\n\tuseGTM();\n\treturn (\n\t\t<>\n\t\t\t<QueryClientProvider client={queryClient}>\n\t\t\t\t<AppRouted />\n\t\t\t\t{!import.meta.env.VITE_DISABLE_DEVTOOLS && <ReactQueryDevtools buttonPosition=\"bottom-right\" />}\n\t\t\t</QueryClientProvider>\n\t\t\t<Toaster richColors />\n\t\t</>\n\t);\n}\n","import { App } from '@/App';\nimport { addReactError } from '@datadog/browser-rum-react';\nimport { StrictMode } from 'react';\nimport { createRoot } from 'react-dom/client';\nimport './index.css';\n\ncreateRoot(\n\tdocument.getElementById('root')!,\n\t{\n\t\tonUncaughtError: (error, errorInfo) => {\n\t\t\t// Report uncaught errors to Datadog\n\t\t\taddReactError(error as Error, errorInfo);\n\t\t\tconsole.error('Uncaught error:', error, errorInfo);\n\t\t},\n\t\tonCaughtError: (error, errorInfo) => {\n\t\t\t// Report caught errors to Datadog\n\t\t\taddReactError(error as Error, errorInfo);\n\t\t\tconsole.error('Caught error:', error, errorInfo);\n\t\t},\n\t\tonRecoverableError: (error, errorInfo) => {\n\t\t\t// Report recoverable errors to Datadog\n\t\t\taddReactError(error as Error, errorInfo);\n\t\t\tconsole.warn('Recoverable error:', error, errorInfo);\n\t\t},\n\t},\n).render(\n\t<StrictMode>\n\t\t<App />\n\t</StrictMode>,\n);\n"],"file":"index-Dk_TRrUg.js"}
|