From 2ec8032e2a9186c9fca46943d1cc77b6c94a94ba Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 14:17:21 +0000 Subject: [PATCH] chore(vendor): update @lightbase/internal-management _This PR is created by sync and will be force-pushed daily. Overwriting any manual changes done to this PR._ - chore: migrate to NPM (lightbasenl/frontend-components#94) (lightbasenl/frontend-components@b363957e314f98f953f40189a67d31178b57caf4) - chore(deps): bump the minor-prod group with 7 updates (lightbasenl/frontend-components#88) (lightbasenl/frontend-components@14e2493dbed067b85bbf6c03d246901ed2c0fb71) - feat(internal-management): FF support tenant specific settings (lightbasenl/frontend-components#82) (lightbasenl/frontend-components@adf918cf50c15831e92382002cdd59892fb62722) - chore(deps): bump the minor-prod group with 5 updates (lightbasenl/frontend-components#81) (lightbasenl/frontend-components@69e5fe9b25e477d7a96d76a4973d802b57cd4ea9) - chore(deps): bump the minor-prod group with 9 updates (lightbasenl/frontend-components#71) (lightbasenl/frontend-components@7eb3791ea9604a5bfb4e387143e8fee2b4a57635) - chore(deps): update dependencies (lightbasenl/frontend-components#57) (lightbasenl/frontend-components@0e1090041d1adbd7b5c7dfa3c299d963ca9dc97f) - chore(deps): update dependencies (lightbasenl/frontend-components#54) (lightbasenl/frontend-components@090296eb4107a326955f46428f07432c8fceb5a2) - chore(deps): update dependencies (lightbasenl/frontend-components#52) (lightbasenl/frontend-components@d4ae06224dabb61b59fa68d973faaa3b4cb8c5b6) - chore(deps): update dependencies (lightbasenl/frontend-components#51) (lightbasenl/frontend-components@b4b06009b1107217dcf04dd226bf5920bcaec9ed) - chore(deps): update dependencies (lightbasenl/frontend-components#48) (lightbasenl/frontend-components@19c4df157c32330214c5c8297ca219f7533c4c7d) - chore: test internal-management against the app router (lightbasenl/frontend-components#50) (lightbasenl/frontend-components@290efe6b56cb605643152485858d3c78f974c494) - chore(internal-management): make RQ5 compatible (lightbasenl/frontend-components#49) (lightbasenl/frontend-components@1998c93066c1f29f642e96b3a0b8c05578bf5da5) - chore(deps): update dependencies (lightbasenl/frontend-components#46) (lightbasenl/frontend-components@29ce2d6a4ddccaf10df12fd5a180b13b4c6ca450) - chore(deps): update dependencies (lightbasenl/frontend-components#44) (lightbasenl/frontend-components@4c3e68022d1bd0254832e16884bc4f9f55c2a759) - chore(deps): update dependencies (lightbasenl/frontend-components#35) (lightbasenl/frontend-components@d3f1651e3ae79d96f669f124f6a0873855183776) - chore(deps): update dependencies (lightbasenl/frontend-components#34) (lightbasenl/frontend-components@ae456c4e79c269d9216f1538532e5aa697503f29) - chore(deps): update dependencies (lightbasenl/frontend-components#32) (lightbasenl/frontend-components@c7b2f123a6a2dec2d597ad0c7d17b992d9aabe73) - chore(deps): update dependencies (lightbasenl/frontend-components#31) (lightbasenl/frontend-components@3ede89c53c6f9f568de9a0dc852b09ee27be473b) - chore(deps): update dependencies (lightbasenl/frontend-components#29) (lightbasenl/frontend-components@3e756c8eb6341edf144c45694041a0cef1a12574) - chore(deps): update dependencies (lightbasenl/frontend-components#28) (lightbasenl/frontend-components@15a6b9bb7d99b37714147d21f7d50294513d0685) - chore: update api spec & regenerate (lightbasenl/frontend-components#26) (lightbasenl/frontend-components@eb1193e35e00d359cb559c95b0dba7c8c9569748) - chore(deps): update dependencies (lightbasenl/frontend-components#25) (lightbasenl/frontend-components@57ebe6b06a7ac42d8ca1b58b447902c44873da14)- Failed to execute `npm run format`. Sync is not able to correct this, so human checks and fixes are necessary for this PR. --- vendor/internal-management/README.md | 6 +- vendor/internal-management/package.json | 18 +- .../internal-management/src/auth/cookies.ts | 2 +- .../src/components/Button.tsx | 2 +- ...agModal.tsx => EditDescriptionFFModal.tsx} | 20 +- .../components/EditTentantSettingsFFModal.tsx | 197 ++++++++++++ .../src/components/Router.tsx | 4 +- .../src/components/SideBar.tsx | 4 +- .../src/generated/auth/apiClient.ts | 21 ++ .../src/generated/auth/reactQueries.tsx | 300 ++++++++++++------ .../authAnonymousBased/reactQueries.tsx | 20 +- .../generated/common/api-client-wrapper.tsx | 1 + .../src/generated/common/types.d.ts | 51 ++- .../src/generated/management/reactQueries.tsx | 22 +- .../managementFeatureFlag/reactQueries.tsx | 229 ++++++++----- vendor/internal-management/src/index.tsx | 14 +- .../src/pages/FeatureFlags.tsx | 50 ++- .../internal-management/src/pages/Login.tsx | 2 +- 18 files changed, 718 insertions(+), 245 deletions(-) rename vendor/internal-management/src/components/{EditFeatureFlagModal.tsx => EditDescriptionFFModal.tsx} (86%) create mode 100644 vendor/internal-management/src/components/EditTentantSettingsFFModal.tsx diff --git a/vendor/internal-management/README.md b/vendor/internal-management/README.md index b0111f29..470f5407 100644 --- a/vendor/internal-management/README.md +++ b/vendor/internal-management/README.md @@ -16,7 +16,11 @@ Props: - `tenantOrigin`: optional tenant origin, to send to tenant aware backends. ```tsx -// In pages/_tenants/[tenant]/_lightbase/[...management].tsx +// In pages/_tenants/[tenant]/_lightbase/[[...management]].tsx +// Or in app/%5Flightbase/[[...management]]/page.tsx +// ^ _ directories are not turned in to routes by default + +"use client"; import { InternalManagement } from "@lightbase/internal-management"; diff --git a/vendor/internal-management/package.json b/vendor/internal-management/package.json index 722b4535..4b8f2383 100644 --- a/vendor/internal-management/package.json +++ b/vendor/internal-management/package.json @@ -5,19 +5,21 @@ "main": "./src/index.tsx", "dependencies": { "@emotion/hash": "^0.9.1", - "@emotion/react": "11.11.0", - "@headlessui/react": "1.7.14", - "@tanstack/react-query": "4.29.5", - "axios": "1.4.0", - "jwt-decode": "3.1.2", + "@emotion/react": "11.11.3", + "@headlessui/react": "1.7.17", + "axios": "1.6.5", + "jwt-decode": "4.0.0", "nookies": "^2.5.2", - "react-hook-form": "7.43.9", - "react-router-dom": "6.11.1", + "react-hook-form": "7.49.2", + "react-router-dom": "6.21.1", "twind": "0.16.19" }, + "peerDependencies": { + "@tanstack/react-query": "*" + }, "files": [ "README.md", "src" ], - "gitHead": "4dcfe0922a124f2c944f6dc24411c73dcdc2819b" + "gitHead": "4410a3e0201f455092576429e5e95e6ae20990b6" } diff --git a/vendor/internal-management/src/auth/cookies.ts b/vendor/internal-management/src/auth/cookies.ts index 3cc3789f..491460a4 100644 --- a/vendor/internal-management/src/auth/cookies.ts +++ b/vendor/internal-management/src/auth/cookies.ts @@ -1,4 +1,4 @@ -import jwtDecode from "jwt-decode"; +import { jwtDecode } from "jwt-decode"; import { destroyCookie, parseCookies, setCookie } from "nookies"; import type { AuthTokenPair } from "../generated/common/types"; diff --git a/vendor/internal-management/src/components/Button.tsx b/vendor/internal-management/src/components/Button.tsx index 7d50c50b..b452696c 100644 --- a/vendor/internal-management/src/components/Button.tsx +++ b/vendor/internal-management/src/components/Button.tsx @@ -9,7 +9,7 @@ const sizes = { const variants = { primary: "border-transparent text-white bg-blue-600 hover:bg-blue-700 focus:ring-blue-500", - default: "bg-gray-50", + default: "bg-gray-50 hover:bg-gray-100", }; export type ButtonProps = DetailedHTMLProps, HTMLButtonElement> & { diff --git a/vendor/internal-management/src/components/EditFeatureFlagModal.tsx b/vendor/internal-management/src/components/EditDescriptionFFModal.tsx similarity index 86% rename from vendor/internal-management/src/components/EditFeatureFlagModal.tsx rename to vendor/internal-management/src/components/EditDescriptionFFModal.tsx index c90a32b0..d17c3a04 100644 --- a/vendor/internal-management/src/components/EditFeatureFlagModal.tsx +++ b/vendor/internal-management/src/components/EditDescriptionFFModal.tsx @@ -1,4 +1,4 @@ -import { Transition, Dialog, Portal } from "@headlessui/react"; +import { Dialog, Portal, Transition } from "@headlessui/react"; import { Fragment } from "react"; import { useForm } from "react-hook-form"; import { tw } from "twind"; @@ -6,7 +6,7 @@ import Button from "../components/Button"; import type { ManagementFeatureFlagItem } from "../generated/common/types"; import { useManagementFeatureFlagUpdate } from "../generated/managementFeatureFlag/reactQueries"; -export default function EditFeatureFlagModal({ +export default function EditDescriptionFFModal({ show, onClose, flag, @@ -15,7 +15,7 @@ export default function EditFeatureFlagModal({ onClose: () => void; flag: ManagementFeatureFlagItem; }) { - const { mutate, isLoading, error } = useManagementFeatureFlagUpdate( + const { mutate, status, error } = useManagementFeatureFlagUpdate( { onSuccess: () => { onClose(); @@ -61,12 +61,13 @@ export default function EditFeatureFlagModal({ > { mutate({ featureFlagId: flag.id, description, globalValue: flag.globalValue, + tenantValues: flag.tenantValues, }); })} className={tw`relative w-full transform overflow-hidden rounded-lg bg-white text-left shadow-xl transition-all sm:my-8 sm:max-w-lg`} @@ -111,10 +112,17 @@ export default function EditFeatureFlagModal({
- -
diff --git a/vendor/internal-management/src/components/EditTentantSettingsFFModal.tsx b/vendor/internal-management/src/components/EditTentantSettingsFFModal.tsx new file mode 100644 index 00000000..239793bb --- /dev/null +++ b/vendor/internal-management/src/components/EditTentantSettingsFFModal.tsx @@ -0,0 +1,197 @@ +import { Dialog, Portal, Transition } from "@headlessui/react"; +import { Fragment, useState } from "react"; +import { tw } from "twind"; +import Button from "../components/Button"; +import type { ManagementFeatureFlagItem } from "../generated/common/types"; +import { useManagementFeatureFlagUpdate } from "../generated/managementFeatureFlag/reactQueries"; + +export default function EditTenantSettingsFFModal({ + show, + onClose, + flag, + tenants, +}: { + show: boolean; + onClose: () => void; + flag: ManagementFeatureFlagItem; + tenants: string[]; +}) { + const { mutate, status, error } = useManagementFeatureFlagUpdate( + { + onSuccess: () => { + onClose(); + }, + }, + { invalidateQueries: true }, + ); + + const [tenantValues, setTenantValues] = useState({ + ...(flag.tenantValues ?? {}), + }); + + return ( + + + + +
+ + +
+
+ + { + e.preventDefault(); + mutate({ + featureFlagId: flag.id, + tenantValues, + globalValue: flag.globalValue, + description: flag.description, + }); + }} + className={tw`relative w-full transform overflow-hidden rounded-lg bg-white text-left shadow-xl transition-all sm:my-8 sm:max-w-lg`} + > +
+
+ Edit feature flag +
+
+
+ {tenants.map((tenant, index) => ( +
+

{tenant}

+
    +
  • +
    + { + /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ + const { [tenant]: remove, ...rest } = tenantValues; + setTenantValues(rest); + }} + className={tw`w-4 h-4 text-blue-600 bg-gray-100 border-gray-300`} + /> + +
    +
  • +
  • +
    + setTenantValues({ ...tenantValues, [tenant]: true })} + className={tw`w-4 h-4 text-blue-600 bg-gray-100 border-gray-300`} + /> + +
    +
  • +
  • +
    + setTenantValues({ ...tenantValues, [tenant]: false })} + className={tw`w-4 h-4 text-blue-600 bg-gray-100 border-gray-300`} + /> + +
    +
  • +
+
+ ))} + {!!error && ( +
+

+ Something went wrong +

+ {!!error.response?.data && ( + + )} +
+ )} +
+
+
+
+ + +
+
+
+
+
+
+
+
+ ); +} diff --git a/vendor/internal-management/src/components/Router.tsx b/vendor/internal-management/src/components/Router.tsx index 4a3764b7..73dc02fc 100644 --- a/vendor/internal-management/src/components/Router.tsx +++ b/vendor/internal-management/src/components/Router.tsx @@ -4,7 +4,7 @@ import { FeatureFlags } from "../pages/FeatureFlags"; import { Login } from "../pages/Login"; import { TokenAuth } from "../pages/TokenAuth"; -export function Router() { +export function Router({ tenants }: { tenants?: string[] }) { const [isMounted, setIsMounted] = useState(false); useEffect(() => { @@ -19,7 +19,7 @@ export function Router() { [ { path: "/", - element: , + element: , errorElement: , }, { diff --git a/vendor/internal-management/src/components/SideBar.tsx b/vendor/internal-management/src/components/SideBar.tsx index 2ef02eb2..a6cbb448 100644 --- a/vendor/internal-management/src/components/SideBar.tsx +++ b/vendor/internal-management/src/components/SideBar.tsx @@ -10,8 +10,8 @@ export default function SideBar() { to="/" className={({ isActive }) => isActive - ? tw`block bg-[#f1f1f1] py-3 px-6 text-sm font-medium text-gray-800` - : tw`block py-3 px-6 text-sm font-medium text-gray-600 hover:text-gray-800` + ? tw`block bg-[#f1f1f1] px-6 py-3 text-sm font-medium text-gray-800` + : tw`block px-6 py-3 text-sm font-medium text-gray-600 hover:text-gray-800` } > Feature flags diff --git a/vendor/internal-management/src/generated/auth/apiClient.ts b/vendor/internal-management/src/generated/auth/apiClient.ts index 01d0201c..36611858 100644 --- a/vendor/internal-management/src/generated/auth/apiClient.ts +++ b/vendor/internal-management/src/generated/auth/apiClient.ts @@ -4,6 +4,7 @@ import type { AxiosInstance, AxiosRequestConfig } from "axios"; import type { AuthGetUserParams, AuthGetUserResponse, + AuthImpersonateStopSessionResponse, AuthLogoutResponse, AuthMeResponse, AuthRefreshTokensBody, @@ -39,6 +40,26 @@ export async function apiAuthGetUser( return response.data; } +/** + * Stop an impersonating session. Requires that the current session belongs to the impersonator. Impersonate sessions can only be started from the platform backends. + * + * Callers should bust all local caches and redirect the user to the correct location. + * + * Tags: [] + * + */ +export async function apiAuthImpersonateStopSession( + axiosInstance: AxiosInstance, + requestConfig?: AxiosRequestConfig, +): Promise { + const response = await axiosInstance.request({ + url: `auth/impersonate-stop-session`, + method: "POST", + ...requestConfig, + }); + return response.data; +} + /** * Destroy the current session. * diff --git a/vendor/internal-management/src/generated/auth/reactQueries.tsx b/vendor/internal-management/src/generated/auth/reactQueries.tsx index 24a9e4cb..d34617dc 100644 --- a/vendor/internal-management/src/generated/auth/reactQueries.tsx +++ b/vendor/internal-management/src/generated/auth/reactQueries.tsx @@ -3,6 +3,7 @@ import type { QueryClient, QueryKey, + Updater, UseMutationOptions, UseMutationResult, UseQueryOptions, @@ -10,10 +11,12 @@ import type { import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import type { AxiosInstance, AxiosRequestConfig } from "axios"; import type { AppErrorResponse } from "../common/api-client"; +import type { Pretty } from "../common/api-client-wrapper"; import { useApi } from "../common/api-client-wrapper"; import type { AuthGetUserParams, AuthGetUserResponse, + AuthImpersonateStopSessionResponse, AuthLogoutResponse, AuthMeResponse, AuthRefreshTokensBody, @@ -29,6 +32,7 @@ import type { } from "../common/types"; import { apiAuthGetUser, + apiAuthImpersonateStopSession, apiAuthLogout, apiAuthMe, apiAuthRefreshTokens, @@ -46,24 +50,38 @@ import { * */ export function useAuthGetUser( - opts: AuthGetUserParams & { requestConfig?: AxiosRequestConfig } & { - queryOptions?: UseQueryOptions; - }, + opts: Pretty< + Partial< + AuthGetUserParams & { requestConfig?: AxiosRequestConfig } & { + queryOptions?: Omit< + UseQueryOptions, + "queryFn" | "queryKey" + >; + } + > + >, ) { const axiosInstance = useApi(); const options = opts?.queryOptions ?? {}; options.enabled = - options.enabled === true || (options.enabled !== false && opts.user !== undefined && opts.user !== null); - return useQuery( - useAuthGetUser.queryKey(opts), - ({ signal }) => { + options.enabled === true || + (options.enabled !== false && opts["user"] !== undefined && opts["user"] !== null); + return useQuery({ + queryKey: useAuthGetUser.queryKey(opts), + queryFn: ({ signal }) => { + if (opts["user"] === undefined || opts["user"] === null) { + throw new Error( + "Not all required variables where provided to 'useAuthGetUser'. This happens when you manually set 'queryOptions.enabled' or when you use 'refetch'. Both skip the generated 'queryOptions.enabled'. Make sure that all necessary arguments are set.", + ); + } + opts.requestConfig ??= {}; opts.requestConfig.signal = signal; return apiAuthGetUser(axiosInstance, { user: opts["user"] }, opts?.requestConfig); }, - options, - ); + ...options, + }); } /** * Base key used by useAuthGetUser.queryKey() @@ -73,7 +91,7 @@ useAuthGetUser.baseKey = (): QueryKey => ["auth", "getUser"]; /** * Query key used by useAuthGetUser */ -useAuthGetUser.queryKey = (opts: AuthGetUserParams): QueryKey => [ +useAuthGetUser.queryKey = (opts: Pretty>): QueryKey => [ ...useAuthGetUser.baseKey(), { user: opts["user"] }, ]; @@ -84,11 +102,20 @@ useAuthGetUser.queryKey = (opts: AuthGetUserParams): QueryKey => [ useAuthGetUser.fetch = ( queryClient: QueryClient, axiosInstance: AxiosInstance, - opts: AuthGetUserParams & { requestConfig?: AxiosRequestConfig }, + opts: Pretty>, ) => { - return queryClient.fetchQuery(useAuthGetUser.queryKey(opts), () => - apiAuthGetUser(axiosInstance, { user: opts["user"] }, opts?.requestConfig), - ); + return queryClient.fetchQuery({ + queryKey: useAuthGetUser.queryKey(opts), + queryFn: () => { + if (opts["user"] === undefined || opts["user"] === null) { + throw new Error( + "Not all required variables where provided to 'useAuthGetUser.fetchQuery'. This happens when you manually set 'queryOptions.enabled' or when you use 'refetch'. Both skip the generated 'queryOptions.enabled'. Make sure that all necessary arguments are set.", + ); + } + + return apiAuthGetUser(axiosInstance, { user: opts["user"] }, opts?.requestConfig); + }, + }); }; /** @@ -97,39 +124,87 @@ useAuthGetUser.fetch = ( useAuthGetUser.prefetch = ( queryClient: QueryClient, axiosInstance: AxiosInstance, - opts: AuthGetUserParams & { requestConfig?: AxiosRequestConfig }, + opts: Pretty>, ) => { - return queryClient.prefetchQuery(useAuthGetUser.queryKey(opts), () => - apiAuthGetUser(axiosInstance, { user: opts["user"] }, opts?.requestConfig), - ); + return queryClient.prefetchQuery({ + queryKey: useAuthGetUser.queryKey(opts), + queryFn: () => { + if (opts["user"] === undefined || opts["user"] === null) { + throw new Error( + "Not all required variables where provided to 'useAuthGetUser.prefetchQuery'. This happens when you manually set 'queryOptions.enabled' or when you use 'refetch'. Both skip the generated 'queryOptions.enabled'. Make sure that all necessary arguments are set.", + ); + } + + return apiAuthGetUser(axiosInstance, { user: opts["user"] }, opts?.requestConfig); + }, + }); }; /** * Invalidate useAuthGetUser via the queryClient */ -useAuthGetUser.invalidate = (queryClient: QueryClient, opts: AuthGetUserParams) => - queryClient.invalidateQueries(useAuthGetUser.queryKey(opts)); +useAuthGetUser.invalidate = (queryClient: QueryClient, opts: Pretty>) => + queryClient.invalidateQueries({ queryKey: useAuthGetUser.queryKey(opts) }); /** * Set query data for useAuthGetUser via the queryClient */ useAuthGetUser.setQueryData = ( queryClient: QueryClient, - opts: AuthGetUserParams, - data: AuthGetUserResponse, -) => queryClient.setQueryData(useAuthGetUser.queryKey(opts), data); + opts: Pretty>, + data: Updater, +) => { + if (opts["user"] === undefined || opts["user"] === null) { + throw new Error( + "Not all required variables where provided to 'useAuthGetUser.setQueryData'. This happens when you manually set 'queryOptions.enabled' or when you use 'refetch'. Both skip the generated 'queryOptions.enabled'. Make sure that all necessary arguments are set.", + ); + } + + return queryClient.setQueryData(useAuthGetUser.queryKey(opts), data); +}; + +/** + * Stop an impersonating session. Requires that the current session belongs to the impersonator. Impersonate sessions can only be started from the platform backends. + * + * Callers should bust all local caches and redirect the user to the correct location. + * + */ +type UseAuthImpersonateStopSessionProps = Pretty<{ requestConfig?: AxiosRequestConfig }>; +export function useAuthImpersonateStopSession( + options: UseMutationOptions< + AuthImpersonateStopSessionResponse, + AppErrorResponse, + UseAuthImpersonateStopSessionProps, + Context + > = {}, +): UseMutationResult< + AuthImpersonateStopSessionResponse, + AppErrorResponse, + UseAuthImpersonateStopSessionProps, + Context +> { + const axiosInstance = useApi(); + const queryClient = useQueryClient(); + return useMutation({ + mutationFn: variables => apiAuthImpersonateStopSession(axiosInstance, variables?.requestConfig), + ...options, + }); +} /** * Destroy the current session. * */ -type UseAuthLogoutProps = { requestConfig?: AxiosRequestConfig }; -export function useAuthLogout( - options: UseMutationOptions = {}, -): UseMutationResult { +type UseAuthLogoutProps = Pretty<{ requestConfig?: AxiosRequestConfig }>; +export function useAuthLogout( + options: UseMutationOptions = {}, +): UseMutationResult { const axiosInstance = useApi(); const queryClient = useQueryClient(); - return useMutation(variables => apiAuthLogout(axiosInstance, variables?.requestConfig), options); + return useMutation({ + mutationFn: variables => apiAuthLogout(axiosInstance, variables?.requestConfig), + ...options, + }); } /** @@ -139,22 +214,24 @@ export function useAuthLogout( * */ export function useAuthMe( - opts: { requestConfig?: AxiosRequestConfig } & { - queryOptions?: UseQueryOptions; - } = {}, + opts: Pretty< + { requestConfig?: AxiosRequestConfig } & { + queryOptions?: Omit, "queryFn" | "queryKey">; + } + > = {}, ) { const axiosInstance = useApi(); const options = opts?.queryOptions ?? {}; - return useQuery( - useAuthMe.queryKey(), - ({ signal }) => { + return useQuery({ + queryKey: useAuthMe.queryKey(), + queryFn: ({ signal }) => { opts.requestConfig ??= {}; opts.requestConfig.signal = signal; return apiAuthMe(axiosInstance, opts?.requestConfig); }, - options, - ); + ...options, + }); } /** * Base key used by useAuthMe.queryKey() @@ -172,9 +249,14 @@ useAuthMe.queryKey = (): QueryKey => [...useAuthMe.baseKey()]; useAuthMe.fetch = ( queryClient: QueryClient, axiosInstance: AxiosInstance, - opts?: { requestConfig?: AxiosRequestConfig }, + opts?: Pretty<{ requestConfig?: AxiosRequestConfig }>, ) => { - return queryClient.fetchQuery(useAuthMe.queryKey(), () => apiAuthMe(axiosInstance, opts?.requestConfig)); + return queryClient.fetchQuery({ + queryKey: useAuthMe.queryKey(), + queryFn: () => { + return apiAuthMe(axiosInstance, opts?.requestConfig); + }, + }); }; /** @@ -183,15 +265,21 @@ useAuthMe.fetch = ( useAuthMe.prefetch = ( queryClient: QueryClient, axiosInstance: AxiosInstance, - opts?: { requestConfig?: AxiosRequestConfig }, + opts?: Pretty<{ requestConfig?: AxiosRequestConfig }>, ) => { - return queryClient.prefetchQuery(useAuthMe.queryKey(), () => apiAuthMe(axiosInstance, opts?.requestConfig)); + return queryClient.prefetchQuery({ + queryKey: useAuthMe.queryKey(), + queryFn: () => { + return apiAuthMe(axiosInstance, opts?.requestConfig); + }, + }); }; /** * Invalidate useAuthMe via the queryClient */ -useAuthMe.invalidate = (queryClient: QueryClient) => queryClient.invalidateQueries(useAuthMe.queryKey()); +useAuthMe.invalidate = (queryClient: QueryClient) => + queryClient.invalidateQueries({ queryKey: useAuthMe.queryKey() }); /** * Set query data for useAuthMe via the queryClient @@ -199,8 +287,10 @@ useAuthMe.invalidate = (queryClient: QueryClient) => queryClient.invalidateQueri useAuthMe.setQueryData = ( queryClient: QueryClient, - data: AuthMeResponse, -) => queryClient.setQueryData(useAuthMe.queryKey(), data); + data: Updater, +) => { + return queryClient.setQueryData(useAuthMe.queryKey(), data); +}; /** * Returns a new token pair based on the provided refresh token. @@ -209,21 +299,21 @@ useAuthMe.setQueryData = ( * - Inherits errors from [`sessionStoreRefreshTokens`](https://compasjs.com/features/session-handling.html#sessionstorerefreshtokens) * */ -type UseAuthRefreshTokensProps = AuthRefreshTokensBody & { requestConfig?: AxiosRequestConfig }; -export function useAuthRefreshTokens( - options: UseMutationOptions = {}, -): UseMutationResult { +type UseAuthRefreshTokensProps = Pretty; +export function useAuthRefreshTokens( + options: UseMutationOptions = {}, +): UseMutationResult { const axiosInstance = useApi(); const queryClient = useQueryClient(); - return useMutation( - variables => + return useMutation({ + mutationFn: variables => apiAuthRefreshTokens( axiosInstance, { refreshToken: variables["refreshToken"] }, variables?.requestConfig, ), - options, - ); + ...options, + }); } /** @@ -236,23 +326,29 @@ export function useAuthRefreshTokens( * Tags: ["auth:user:manage"] * */ -type UseAuthSetUserActiveProps = AuthSetUserActiveParams & - AuthSetUserActiveBody & { requestConfig?: AxiosRequestConfig }; -export function useAuthSetUserActive( - options: UseMutationOptions = {}, -): UseMutationResult { +type UseAuthSetUserActiveProps = Pretty< + AuthSetUserActiveParams & AuthSetUserActiveBody & { requestConfig?: AxiosRequestConfig } +>; +export function useAuthSetUserActive( + options: UseMutationOptions< + AuthSetUserActiveResponse, + AppErrorResponse, + UseAuthSetUserActiveProps, + Context + > = {}, +): UseMutationResult { const axiosInstance = useApi(); const queryClient = useQueryClient(); - return useMutation( - variables => + return useMutation({ + mutationFn: variables => apiAuthSetUserActive( axiosInstance, { user: variables["user"] }, { active: variables["active"] }, variables?.requestConfig, ), - options, - ); + ...options, + }); } /** @@ -264,23 +360,24 @@ export function useAuthSetUserActive( * Tags: ["auth:user:manage"] * */ -type UseAuthUpdateUserProps = AuthUpdateUserParams & - AuthUpdateUserBody & { requestConfig?: AxiosRequestConfig }; -export function useAuthUpdateUser( - options: UseMutationOptions = {}, -): UseMutationResult { +type UseAuthUpdateUserProps = Pretty< + AuthUpdateUserParams & AuthUpdateUserBody & { requestConfig?: AxiosRequestConfig } +>; +export function useAuthUpdateUser( + options: UseMutationOptions = {}, +): UseMutationResult { const axiosInstance = useApi(); const queryClient = useQueryClient(); - return useMutation( - variables => + return useMutation({ + mutationFn: variables => apiAuthUpdateUser( axiosInstance, { user: variables["user"] }, { name: variables["name"] }, variables?.requestConfig, ), - options, - ); + ...options, + }); } /** @@ -293,15 +390,20 @@ export function useAuthUpdateUser( * */ export function useAuthUserList( - opts: AuthUserListBody & { requestConfig?: AxiosRequestConfig } & { - queryOptions?: UseQueryOptions; - }, + opts: Pretty< + AuthUserListBody & { requestConfig?: AxiosRequestConfig } & { + queryOptions?: Omit< + UseQueryOptions, + "queryFn" | "queryKey" + >; + } + >, ) { const axiosInstance = useApi(); const options = opts?.queryOptions ?? {}; - return useQuery( - useAuthUserList.queryKey(opts), - ({ signal }) => { + return useQuery({ + queryKey: useAuthUserList.queryKey(opts), + queryFn: ({ signal }) => { opts.requestConfig ??= {}; opts.requestConfig.signal = signal; @@ -311,8 +413,8 @@ export function useAuthUserList( opts?.requestConfig, ); }, - options, - ); + ...options, + }); } /** * Base key used by useAuthUserList.queryKey() @@ -322,7 +424,7 @@ useAuthUserList.baseKey = (): QueryKey => ["auth", "userList"]; /** * Query key used by useAuthUserList */ -useAuthUserList.queryKey = (opts: AuthUserListBody): QueryKey => [ +useAuthUserList.queryKey = (opts: Pretty): QueryKey => [ ...useAuthUserList.baseKey(), { search: opts["search"] ?? null, filters: opts["filters"] ?? null }, ]; @@ -333,11 +435,18 @@ useAuthUserList.queryKey = (opts: AuthUserListBody): QueryKey => [ useAuthUserList.fetch = ( queryClient: QueryClient, axiosInstance: AxiosInstance, - opts: AuthUserListBody & { requestConfig?: AxiosRequestConfig }, + opts: Pretty, ) => { - return queryClient.fetchQuery(useAuthUserList.queryKey(opts), () => - apiAuthUserList(axiosInstance, { search: opts["search"], filters: opts["filters"] }, opts?.requestConfig), - ); + return queryClient.fetchQuery({ + queryKey: useAuthUserList.queryKey(opts), + queryFn: () => { + return apiAuthUserList( + axiosInstance, + { search: opts["search"], filters: opts["filters"] }, + opts?.requestConfig, + ); + }, + }); }; /** @@ -346,24 +455,33 @@ useAuthUserList.fetch = ( useAuthUserList.prefetch = ( queryClient: QueryClient, axiosInstance: AxiosInstance, - opts: AuthUserListBody & { requestConfig?: AxiosRequestConfig }, + opts: Pretty, ) => { - return queryClient.prefetchQuery(useAuthUserList.queryKey(opts), () => - apiAuthUserList(axiosInstance, { search: opts["search"], filters: opts["filters"] }, opts?.requestConfig), - ); + return queryClient.prefetchQuery({ + queryKey: useAuthUserList.queryKey(opts), + queryFn: () => { + return apiAuthUserList( + axiosInstance, + { search: opts["search"], filters: opts["filters"] }, + opts?.requestConfig, + ); + }, + }); }; /** * Invalidate useAuthUserList via the queryClient */ -useAuthUserList.invalidate = (queryClient: QueryClient, opts: AuthUserListBody) => - queryClient.invalidateQueries(useAuthUserList.queryKey(opts)); +useAuthUserList.invalidate = (queryClient: QueryClient, opts: Pretty) => + queryClient.invalidateQueries({ queryKey: useAuthUserList.queryKey(opts) }); /** * Set query data for useAuthUserList via the queryClient */ useAuthUserList.setQueryData = ( queryClient: QueryClient, - opts: AuthUserListBody, - data: AuthUserListResponse, -) => queryClient.setQueryData(useAuthUserList.queryKey(opts), data); + opts: Pretty, + data: Updater, +) => { + return queryClient.setQueryData(useAuthUserList.queryKey(opts), data); +}; diff --git a/vendor/internal-management/src/generated/authAnonymousBased/reactQueries.tsx b/vendor/internal-management/src/generated/authAnonymousBased/reactQueries.tsx index 93e2ab94..d241d1e6 100644 --- a/vendor/internal-management/src/generated/authAnonymousBased/reactQueries.tsx +++ b/vendor/internal-management/src/generated/authAnonymousBased/reactQueries.tsx @@ -4,6 +4,7 @@ import type { UseMutationOptions, UseMutationResult } from "@tanstack/react-quer import { useMutation, useQueryClient } from "@tanstack/react-query"; import type { AxiosRequestConfig } from "axios"; import type { AppErrorResponse } from "../common/api-client"; +import type { Pretty } from "../common/api-client-wrapper"; import { useApi } from "../common/api-client-wrapper"; import type { AuthAnonymousBasedLoginBody, AuthAnonymousBasedTokenPair } from "../common/types"; import { apiAuthAnonymousBasedLogin } from "./apiClient"; @@ -17,28 +18,31 @@ import { apiAuthAnonymousBasedLogin } from "./apiClient"; * log in. * */ -type UseAuthAnonymousBasedLoginProps = AuthAnonymousBasedLoginBody & { requestConfig?: AxiosRequestConfig }; -export function useAuthAnonymousBasedLogin( +type UseAuthAnonymousBasedLoginProps = Pretty< + AuthAnonymousBasedLoginBody & { requestConfig?: AxiosRequestConfig } +>; +export function useAuthAnonymousBasedLogin( options: UseMutationOptions< AuthAnonymousBasedTokenPair, AppErrorResponse, - UseAuthAnonymousBasedLoginProps + UseAuthAnonymousBasedLoginProps, + Context > = {}, ): UseMutationResult< AuthAnonymousBasedTokenPair, AppErrorResponse, UseAuthAnonymousBasedLoginProps, - unknown + Context > { const axiosInstance = useApi(); const queryClient = useQueryClient(); - return useMutation( - variables => + return useMutation({ + mutationFn: variables => apiAuthAnonymousBasedLogin( axiosInstance, { token: variables["token"], device: variables["device"] }, variables?.requestConfig, ), - options, - ); + ...options, + }); } diff --git a/vendor/internal-management/src/generated/common/api-client-wrapper.tsx b/vendor/internal-management/src/generated/common/api-client-wrapper.tsx index 3f160f3c..379d5af4 100644 --- a/vendor/internal-management/src/generated/common/api-client-wrapper.tsx +++ b/vendor/internal-management/src/generated/common/api-client-wrapper.tsx @@ -6,6 +6,7 @@ import type { AxiosInstance } from "axios"; import type { PropsWithChildren } from "react"; import React from "react"; import { createContext, useContext } from "react"; +export type Pretty = { [K in keyof T]: T[K] } & {}; const ApiContext = createContext(undefined); diff --git a/vendor/internal-management/src/generated/common/types.d.ts b/vendor/internal-management/src/generated/common/types.d.ts index 172064dc..3d02bf2d 100644 --- a/vendor/internal-management/src/generated/common/types.d.ts +++ b/vendor/internal-management/src/generated/common/types.d.ts @@ -65,6 +65,10 @@ export type AuthGetUserResponse = { user: AuthUserSummary; }; +export type AuthImpersonateStopSessionResponse = { + success: true; +}; + export type AuthLogoutResponse = { success: true; }; @@ -80,6 +84,7 @@ export type AuthSession = { loginType: AuthLoginType; twoStepType?: AuthTwoStepType | undefined; userId: string; + impersonatorUserId?: string | undefined; }; export type AuthMeResponse = { @@ -142,10 +147,22 @@ export type AuthUserListResponse = { users: AuthUserSummary[]; }; +/** + * Web push information object. This is the result of 'PushSubscription.toJSON()'. + */ +export type SessionWebPushInformation = { + endpoint: string; + keys: { + p256dh: string; + auth: string; + }; +}; + export type SessionLoginDevice = { platform: "apple" | "android" | "desktop" | "other"; name: string; notificationToken?: string | undefined; + webPushInformation?: SessionWebPushInformation | undefined; }; export type AuthAnonymousBasedLoginBody = { @@ -176,36 +193,30 @@ export type ManagementFeatureFlagListBody = { | { id?: string | undefined; idNotEqual?: string | undefined; - idIn?: string[] | string | undefined; - idNotIn?: string[] | string | undefined; + idIn?: string[] | undefined; + idNotIn?: string[] | undefined; name?: string | undefined; nameNotEqual?: string | undefined; - nameIn?: string[] | string | undefined; - nameNotIn?: string[] | string | undefined; + nameIn?: string[] | undefined; + nameNotIn?: string[] | undefined; nameLike?: string | undefined; nameILike?: string | undefined; nameNotLike?: string | undefined; createdAt?: Date | string | number | undefined; createdAtNotEqual?: Date | string | number | undefined; - createdAtIn?: (Date | string | number)[] | Date | string | number | undefined; - createdAtNotIn?: (Date | string | number)[] | Date | string | number | undefined; + createdAtIn?: (Date | string | number)[] | undefined; + createdAtNotIn?: (Date | string | number)[] | undefined; createdAtGreaterThan?: Date | string | number | undefined; createdAtLowerThan?: Date | string | number | undefined; updatedAt?: Date | string | number | undefined; updatedAtNotEqual?: Date | string | number | undefined; - updatedAtIn?: (Date | string | number)[] | Date | string | number | undefined; - updatedAtNotIn?: (Date | string | number)[] | Date | string | number | undefined; + updatedAtIn?: (Date | string | number)[] | undefined; + updatedAtNotIn?: (Date | string | number)[] | undefined; updatedAtGreaterThan?: Date | string | number | undefined; updatedAtLowerThan?: Date | string | number | undefined; } | undefined; - orderBy?: - | ("id" | "name" | "createdAt" | "updatedAt")[] - | "id" - | "name" - | "createdAt" - | "updatedAt" - | undefined; + orderBy?: ("id" | "name" | "createdAt" | "updatedAt")[] | undefined; orderBySpec?: | { id?: "ASC" | "DESC" | undefined; @@ -225,6 +236,11 @@ export type ManagementFeatureFlagItem = { description: string; name: string; + /** + * Specific settings for a tenant. We map the value based on the tenant name. If there is no specific setting for the tenant the globalValue is used. + */ + tenantValues?: { [key: string]: boolean } | undefined; + /** * Automatically generated 'createdAt', containing an ISO timestamp. */ @@ -262,6 +278,11 @@ export type ManagementFeatureFlagUpdateParams = { export type ManagementFeatureFlagItemWrite = { globalValue?: boolean | "true" | "false" | undefined; description?: string | undefined; + + /** + * Specific settings for a tenant. We map the value based on the tenant name. If there is no specific setting for the tenant the globalValue is used. + */ + tenantValues?: { [key: string]: boolean | "true" | "false" } | undefined; }; export type ManagementFeatureFlagUpdateResponse = { diff --git a/vendor/internal-management/src/generated/management/reactQueries.tsx b/vendor/internal-management/src/generated/management/reactQueries.tsx index b6740e89..69d47c33 100644 --- a/vendor/internal-management/src/generated/management/reactQueries.tsx +++ b/vendor/internal-management/src/generated/management/reactQueries.tsx @@ -4,6 +4,7 @@ import type { UseMutationOptions, UseMutationResult } from "@tanstack/react-quer import { useMutation, useQueryClient } from "@tanstack/react-query"; import type { AxiosRequestConfig } from "axios"; import type { AppErrorResponse } from "../common/api-client"; +import type { Pretty } from "../common/api-client-wrapper"; import { useApi } from "../common/api-client-wrapper"; import type { ManagementRequestMagicLinkBody, ManagementRequestMagicLinkResponse } from "../common/types"; import { apiManagementRequestMagicLink } from "./apiClient"; @@ -11,30 +12,31 @@ import { apiManagementRequestMagicLink } from "./apiClient"; * Sends a magic link via Slack. Locally it directly returns the url. * */ -type UseManagementRequestMagicLinkProps = ManagementRequestMagicLinkBody & { - requestConfig?: AxiosRequestConfig; -}; -export function useManagementRequestMagicLink( +type UseManagementRequestMagicLinkProps = Pretty< + ManagementRequestMagicLinkBody & { requestConfig?: AxiosRequestConfig } +>; +export function useManagementRequestMagicLink( options: UseMutationOptions< ManagementRequestMagicLinkResponse, AppErrorResponse, - UseManagementRequestMagicLinkProps + UseManagementRequestMagicLinkProps, + Context > = {}, ): UseMutationResult< ManagementRequestMagicLinkResponse, AppErrorResponse, UseManagementRequestMagicLinkProps, - unknown + Context > { const axiosInstance = useApi(); const queryClient = useQueryClient(); - return useMutation( - variables => + return useMutation({ + mutationFn: variables => apiManagementRequestMagicLink( axiosInstance, { slackUserId: variables["slackUserId"] }, variables?.requestConfig, ), - options, - ); + ...options, + }); } diff --git a/vendor/internal-management/src/generated/managementFeatureFlag/reactQueries.tsx b/vendor/internal-management/src/generated/managementFeatureFlag/reactQueries.tsx index bdfb1738..c11ae4f5 100644 --- a/vendor/internal-management/src/generated/managementFeatureFlag/reactQueries.tsx +++ b/vendor/internal-management/src/generated/managementFeatureFlag/reactQueries.tsx @@ -3,6 +3,7 @@ import type { QueryClient, QueryKey, + Updater, UseMutationOptions, UseMutationResult, UseQueryOptions, @@ -10,6 +11,7 @@ import type { import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import type { AxiosInstance, AxiosRequestConfig } from "axios"; import type { AppErrorResponse } from "../common/api-client"; +import type { Pretty } from "../common/api-client-wrapper"; import { useApi } from "../common/api-client-wrapper"; import type { ManagementFeatureFlagItemWrite, @@ -31,16 +33,21 @@ import { * */ export function useManagementFeatureFlagList( - opts: ManagementFeatureFlagListQuery & - ManagementFeatureFlagListBody & { requestConfig?: AxiosRequestConfig } & { - queryOptions?: UseQueryOptions; - }, + opts: Pretty< + ManagementFeatureFlagListQuery & + ManagementFeatureFlagListBody & { requestConfig?: AxiosRequestConfig } & { + queryOptions?: Omit< + UseQueryOptions, + "queryFn" | "queryKey" + >; + } + >, ) { const axiosInstance = useApi(); const options = opts?.queryOptions ?? {}; - return useQuery( - useManagementFeatureFlagList.queryKey(opts), - ({ signal }) => { + return useQuery({ + queryKey: useManagementFeatureFlagList.queryKey(opts), + queryFn: ({ signal }) => { opts.requestConfig ??= {}; opts.requestConfig.signal = signal; @@ -51,8 +58,8 @@ export function useManagementFeatureFlagList ["managementFeatureFlag", * Query key used by useManagementFeatureFlagList */ useManagementFeatureFlagList.queryKey = ( - opts: ManagementFeatureFlagListQuery & ManagementFeatureFlagListBody, + opts: Pretty, ): QueryKey => [ ...useManagementFeatureFlagList.baseKey(), { offset: opts["offset"] ?? null, limit: opts["limit"] ?? null }, @@ -80,17 +87,21 @@ useManagementFeatureFlagList.queryKey = ( useManagementFeatureFlagList.fetch = ( queryClient: QueryClient, axiosInstance: AxiosInstance, - opts: ManagementFeatureFlagListQuery & - ManagementFeatureFlagListBody & { requestConfig?: AxiosRequestConfig }, + opts: Pretty< + ManagementFeatureFlagListQuery & ManagementFeatureFlagListBody & { requestConfig?: AxiosRequestConfig } + >, ) => { - return queryClient.fetchQuery(useManagementFeatureFlagList.queryKey(opts), () => - apiManagementFeatureFlagList( - axiosInstance, - { offset: opts["offset"], limit: opts["limit"] }, - { where: opts["where"], orderBy: opts["orderBy"], orderBySpec: opts["orderBySpec"] }, - opts?.requestConfig, - ), - ); + return queryClient.fetchQuery({ + queryKey: useManagementFeatureFlagList.queryKey(opts), + queryFn: () => { + return apiManagementFeatureFlagList( + axiosInstance, + { offset: opts["offset"], limit: opts["limit"] }, + { where: opts["where"], orderBy: opts["orderBy"], orderBySpec: opts["orderBySpec"] }, + opts?.requestConfig, + ); + }, + }); }; /** @@ -99,17 +110,21 @@ useManagementFeatureFlagList.fetch = ( useManagementFeatureFlagList.prefetch = ( queryClient: QueryClient, axiosInstance: AxiosInstance, - opts: ManagementFeatureFlagListQuery & - ManagementFeatureFlagListBody & { requestConfig?: AxiosRequestConfig }, + opts: Pretty< + ManagementFeatureFlagListQuery & ManagementFeatureFlagListBody & { requestConfig?: AxiosRequestConfig } + >, ) => { - return queryClient.prefetchQuery(useManagementFeatureFlagList.queryKey(opts), () => - apiManagementFeatureFlagList( - axiosInstance, - { offset: opts["offset"], limit: opts["limit"] }, - { where: opts["where"], orderBy: opts["orderBy"], orderBySpec: opts["orderBySpec"] }, - opts?.requestConfig, - ), - ); + return queryClient.prefetchQuery({ + queryKey: useManagementFeatureFlagList.queryKey(opts), + queryFn: () => { + return apiManagementFeatureFlagList( + axiosInstance, + { offset: opts["offset"], limit: opts["limit"] }, + { where: opts["where"], orderBy: opts["orderBy"], orderBySpec: opts["orderBySpec"] }, + opts?.requestConfig, + ); + }, + }); }; /** @@ -117,35 +132,50 @@ useManagementFeatureFlagList.prefetch = ( */ useManagementFeatureFlagList.invalidate = ( queryClient: QueryClient, - opts: ManagementFeatureFlagListQuery & ManagementFeatureFlagListBody, -) => queryClient.invalidateQueries(useManagementFeatureFlagList.queryKey(opts)); + opts: Pretty, +) => queryClient.invalidateQueries({ queryKey: useManagementFeatureFlagList.queryKey(opts) }); /** * Set query data for useManagementFeatureFlagList via the queryClient */ useManagementFeatureFlagList.setQueryData = ( queryClient: QueryClient, - opts: ManagementFeatureFlagListQuery & ManagementFeatureFlagListBody, - data: ManagementFeatureFlagListResponse, -) => queryClient.setQueryData(useManagementFeatureFlagList.queryKey(opts), data); + opts: Pretty, + data: Updater, +) => { + return queryClient.setQueryData(useManagementFeatureFlagList.queryKey(opts), data); +}; /** * Generated single route for 'featureFlag'. * */ export function useManagementFeatureFlagSingle( - opts: ManagementFeatureFlagSingleParams & { requestConfig?: AxiosRequestConfig } & { - queryOptions?: UseQueryOptions; - }, + opts: Pretty< + Partial< + ManagementFeatureFlagSingleParams & { requestConfig?: AxiosRequestConfig } & { + queryOptions?: Omit< + UseQueryOptions, + "queryFn" | "queryKey" + >; + } + > + >, ) { const axiosInstance = useApi(); const options = opts?.queryOptions ?? {}; options.enabled = options.enabled === true || - (options.enabled !== false && opts.featureFlagId !== undefined && opts.featureFlagId !== null); - return useQuery( - useManagementFeatureFlagSingle.queryKey(opts), - ({ signal }) => { + (options.enabled !== false && opts["featureFlagId"] !== undefined && opts["featureFlagId"] !== null); + return useQuery({ + queryKey: useManagementFeatureFlagSingle.queryKey(opts), + queryFn: ({ signal }) => { + if (opts["featureFlagId"] === undefined || opts["featureFlagId"] === null) { + throw new Error( + "Not all required variables where provided to 'useManagementFeatureFlagSingle'. This happens when you manually set 'queryOptions.enabled' or when you use 'refetch'. Both skip the generated 'queryOptions.enabled'. Make sure that all necessary arguments are set.", + ); + } + opts.requestConfig ??= {}; opts.requestConfig.signal = signal; @@ -155,8 +185,8 @@ export function useManagementFeatureFlagSingle ["managementFeatureFlag /** * Query key used by useManagementFeatureFlagSingle */ -useManagementFeatureFlagSingle.queryKey = (opts: ManagementFeatureFlagSingleParams): QueryKey => [ - ...useManagementFeatureFlagSingle.baseKey(), - { featureFlagId: opts["featureFlagId"] }, -]; +useManagementFeatureFlagSingle.queryKey = ( + opts: Pretty>, +): QueryKey => [...useManagementFeatureFlagSingle.baseKey(), { featureFlagId: opts["featureFlagId"] }]; /** * Fetch useManagementFeatureFlagSingle via the queryClient and return the result @@ -177,15 +206,24 @@ useManagementFeatureFlagSingle.queryKey = (opts: ManagementFeatureFlagSinglePara useManagementFeatureFlagSingle.fetch = ( queryClient: QueryClient, axiosInstance: AxiosInstance, - opts: ManagementFeatureFlagSingleParams & { requestConfig?: AxiosRequestConfig }, + opts: Pretty>, ) => { - return queryClient.fetchQuery(useManagementFeatureFlagSingle.queryKey(opts), () => - apiManagementFeatureFlagSingle( - axiosInstance, - { featureFlagId: opts["featureFlagId"] }, - opts?.requestConfig, - ), - ); + return queryClient.fetchQuery({ + queryKey: useManagementFeatureFlagSingle.queryKey(opts), + queryFn: () => { + if (opts["featureFlagId"] === undefined || opts["featureFlagId"] === null) { + throw new Error( + "Not all required variables where provided to 'useManagementFeatureFlagSingle.fetchQuery'. This happens when you manually set 'queryOptions.enabled' or when you use 'refetch'. Both skip the generated 'queryOptions.enabled'. Make sure that all necessary arguments are set.", + ); + } + + return apiManagementFeatureFlagSingle( + axiosInstance, + { featureFlagId: opts["featureFlagId"] }, + opts?.requestConfig, + ); + }, + }); }; /** @@ -194,15 +232,24 @@ useManagementFeatureFlagSingle.fetch = ( useManagementFeatureFlagSingle.prefetch = ( queryClient: QueryClient, axiosInstance: AxiosInstance, - opts: ManagementFeatureFlagSingleParams & { requestConfig?: AxiosRequestConfig }, + opts: Pretty>, ) => { - return queryClient.prefetchQuery(useManagementFeatureFlagSingle.queryKey(opts), () => - apiManagementFeatureFlagSingle( - axiosInstance, - { featureFlagId: opts["featureFlagId"] }, - opts?.requestConfig, - ), - ); + return queryClient.prefetchQuery({ + queryKey: useManagementFeatureFlagSingle.queryKey(opts), + queryFn: () => { + if (opts["featureFlagId"] === undefined || opts["featureFlagId"] === null) { + throw new Error( + "Not all required variables where provided to 'useManagementFeatureFlagSingle.prefetchQuery'. This happens when you manually set 'queryOptions.enabled' or when you use 'refetch'. Both skip the generated 'queryOptions.enabled'. Make sure that all necessary arguments are set.", + ); + } + + return apiManagementFeatureFlagSingle( + axiosInstance, + { featureFlagId: opts["featureFlagId"] }, + opts?.requestConfig, + ); + }, + }); }; /** @@ -210,61 +257,73 @@ useManagementFeatureFlagSingle.prefetch = ( */ useManagementFeatureFlagSingle.invalidate = ( queryClient: QueryClient, - opts: ManagementFeatureFlagSingleParams, -) => queryClient.invalidateQueries(useManagementFeatureFlagSingle.queryKey(opts)); + opts: Pretty>, +) => queryClient.invalidateQueries({ queryKey: useManagementFeatureFlagSingle.queryKey(opts) }); /** * Set query data for useManagementFeatureFlagSingle via the queryClient */ useManagementFeatureFlagSingle.setQueryData = ( queryClient: QueryClient, - opts: ManagementFeatureFlagSingleParams, - data: ManagementFeatureFlagSingleResponse, -) => queryClient.setQueryData(useManagementFeatureFlagSingle.queryKey(opts), data); + opts: Pretty>, + data: Updater, +) => { + if (opts["featureFlagId"] === undefined || opts["featureFlagId"] === null) { + throw new Error( + "Not all required variables where provided to 'useManagementFeatureFlagSingle.setQueryData'. This happens when you manually set 'queryOptions.enabled' or when you use 'refetch'. Both skip the generated 'queryOptions.enabled'. Make sure that all necessary arguments are set.", + ); + } + + return queryClient.setQueryData(useManagementFeatureFlagSingle.queryKey(opts), data); +}; /** * Generated update route for 'featureFlag'. * */ -type UseManagementFeatureFlagUpdateProps = ManagementFeatureFlagUpdateParams & - ManagementFeatureFlagItemWrite & { requestConfig?: AxiosRequestConfig }; -export function useManagementFeatureFlagUpdate( +type UseManagementFeatureFlagUpdateProps = Pretty< + ManagementFeatureFlagUpdateParams & ManagementFeatureFlagItemWrite & { requestConfig?: AxiosRequestConfig } +>; +export function useManagementFeatureFlagUpdate( options: UseMutationOptions< ManagementFeatureFlagUpdateResponse, AppErrorResponse, - UseManagementFeatureFlagUpdateProps + UseManagementFeatureFlagUpdateProps, + Context > = {}, hookOptions: { invalidateQueries?: boolean } = {}, ): UseMutationResult< ManagementFeatureFlagUpdateResponse, AppErrorResponse, UseManagementFeatureFlagUpdateProps, - unknown + Context > { const axiosInstance = useApi(); const queryClient = useQueryClient(); if (hookOptions.invalidateQueries) { const originalOnSuccess = options.onSuccess; options.onSuccess = async (data, variables, context) => { - queryClient.invalidateQueries(["managementFeatureFlag", "list"]); - queryClient.invalidateQueries([ - "managementFeatureFlag", - "single", - { featureFlagId: variables.featureFlagId }, - ]); + queryClient.invalidateQueries({ queryKey: ["managementFeatureFlag", "list"] }); + queryClient.invalidateQueries({ + queryKey: ["managementFeatureFlag", "single", { featureFlagId: variables.featureFlagId }], + }); if (typeof originalOnSuccess === "function") { return await originalOnSuccess(data, variables, context); } }; } - return useMutation( - variables => + return useMutation({ + mutationFn: variables => apiManagementFeatureFlagUpdate( axiosInstance, { featureFlagId: variables["featureFlagId"] }, - { globalValue: variables["globalValue"], description: variables["description"] }, + { + globalValue: variables["globalValue"], + description: variables["description"], + tenantValues: variables["tenantValues"], + }, variables?.requestConfig, ), - options, - ); + ...options, + }); } diff --git a/vendor/internal-management/src/index.tsx b/vendor/internal-management/src/index.tsx index 93d5c200..2b121bf7 100644 --- a/vendor/internal-management/src/index.tsx +++ b/vendor/internal-management/src/index.tsx @@ -1,5 +1,5 @@ import hash from "@emotion/hash"; -import { Global, css } from "@emotion/react"; +import { css, Global } from "@emotion/react"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import axios, { AxiosError } from "axios"; import Head from "next/head"; @@ -22,7 +22,15 @@ setup({ * Includes its own QueryClient and Axios instance, and is not dependant on the auth setup of * the host. */ -export function InternalManagement({ apiUrl, tenantOrigin }: { apiUrl: string; tenantOrigin?: string }) { +export function InternalManagement({ + apiUrl, + tenantOrigin, + tenants, +}: { + apiUrl: string; + tenantOrigin?: string; + tenants?: string[]; +}) { const [queryClient] = useState( () => new QueryClient({ @@ -83,7 +91,7 @@ export function InternalManagement({ apiUrl, tenantOrigin }: { apiUrl: string; t - + diff --git a/vendor/internal-management/src/pages/FeatureFlags.tsx b/vendor/internal-management/src/pages/FeatureFlags.tsx index 24d1c8da..26f55da1 100644 --- a/vendor/internal-management/src/pages/FeatureFlags.tsx +++ b/vendor/internal-management/src/pages/FeatureFlags.tsx @@ -2,7 +2,8 @@ import React, { useState } from "react"; import { tw } from "twind"; import useAuthenticate from "../auth/useAuthenticate"; import Button from "../components/Button"; -import EditFeatureFlagModal from "../components/EditFeatureFlagModal"; +import EditDescriptionFFModal from "../components/EditDescriptionFFModal"; +import EditTenantSettingsFFModal from "../components/EditTentantSettingsFFModal"; import SideBar from "../components/SideBar"; import TopBar from "../components/TopBar"; import type { ManagementFeatureFlagItem } from "../generated/common/types"; @@ -11,7 +12,7 @@ import { useManagementFeatureFlagUpdate, } from "../generated/managementFeatureFlag/reactQueries"; -export function FeatureFlags() { +export function FeatureFlags({ tenants }: { tenants?: string[] }) { useAuthenticate({ enforceLoginType: "anonymousBased", enforceSessionType: "user", @@ -32,12 +33,12 @@ export function FeatureFlags() {
-
+

Feature flags

-
+
{(featureFlags ?? []).map(it => ( - + ))} @@ -81,10 +82,11 @@ export function FeatureFlags() { ); } -function FeatureFlag({ flag }: { flag: ManagementFeatureFlagItem }) { +function FeatureFlag({ flag, tenants }: { flag: ManagementFeatureFlagItem; tenants?: string[] }) { const { mutate } = useManagementFeatureFlagUpdate({}, { invalidateQueries: true }); - const [mode, setMode] = useState<"default" | "edit">("default"); + const [modeDescription, setModeDescription] = useState<"default" | "edit">("default"); + const [modeTenantSettings, setModeTenantSettings] = useState<"default" | "edit">("default"); return ( <> @@ -104,7 +106,7 @@ function FeatureFlag({ flag }: { flag: ManagementFeatureFlagItem }) { {flag.description ? flag.description : "No description provided"} + {tenants && tenants.length > 0 && ( + + )} - { - setMode("default"); + setModeDescription("default"); }} /> + + {tenants && tenants.length > 0 && ( + { + setModeTenantSettings("default"); + }} + /> + )} ); } diff --git a/vendor/internal-management/src/pages/Login.tsx b/vendor/internal-management/src/pages/Login.tsx index 61595599..2926e74c 100644 --- a/vendor/internal-management/src/pages/Login.tsx +++ b/vendor/internal-management/src/pages/Login.tsx @@ -92,7 +92,7 @@ export function Login() {
- +

How to find your Slack User ID