diff --git a/packages/api-v4/src/iam/delegation.ts b/packages/api-v4/src/iam/delegation.ts index 8f6b736a819..18f439153d3 100644 --- a/packages/api-v4/src/iam/delegation.ts +++ b/packages/api-v4/src/iam/delegation.ts @@ -81,11 +81,13 @@ export const updateChildAccountDelegates = ({ export const getMyDelegatedChildAccounts = ({ params, + filter, }: GetMyDelegatedChildAccountsParams) => Request>( setURL(`${BETA_API_ROOT}/iam/delegation/profile/child-accounts`), setMethod('GET'), setParams(params), + setXFilter(filter), ); export const getDelegatedChildAccount = ({ euuid }: { euuid: string }) => diff --git a/packages/api-v4/src/iam/delegation.types.ts b/packages/api-v4/src/iam/delegation.types.ts index 08d884733e9..953ca57c467 100644 --- a/packages/api-v4/src/iam/delegation.types.ts +++ b/packages/api-v4/src/iam/delegation.types.ts @@ -17,6 +17,7 @@ export interface ChildAccountWithDelegates extends ChildAccount { } export interface GetMyDelegatedChildAccountsParams { + filter?: Filter; params?: Params; } diff --git a/packages/manager/.changeset/pr-13318-upcoming-features-1769436050647.md b/packages/manager/.changeset/pr-13318-upcoming-features-1769436050647.md new file mode 100644 index 00000000000..d888868ee63 --- /dev/null +++ b/packages/manager/.changeset/pr-13318-upcoming-features-1769436050647.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +IAM Parent/Child - Enable server side filters on Switch Account drawer ([#13318](https://github.com/linode/manager/pull/13318)) diff --git a/packages/manager/package.json b/packages/manager/package.json index 20510a085fa..0c1ba8ef9d3 100644 --- a/packages/manager/package.json +++ b/packages/manager/package.json @@ -45,7 +45,7 @@ "@tanstack/react-query-devtools": "5.51.24", "@tanstack/react-router": "^1.111.11", "@xterm/xterm": "^5.5.0", - "akamai-cds-react-components": "0.0.1-alpha.19", + "akamai-cds-react-components": "0.1.0", "algoliasearch": "^4.14.3", "axios": "~1.12.0", "braintree-web": "^3.92.2", diff --git a/packages/manager/src/features/Account/SwitchAccountDrawer.test.tsx b/packages/manager/src/features/Account/SwitchAccountDrawer.test.tsx index b4fa59ab5f8..36f4e9fcd7b 100644 --- a/packages/manager/src/features/Account/SwitchAccountDrawer.test.tsx +++ b/packages/manager/src/features/Account/SwitchAccountDrawer.test.tsx @@ -9,7 +9,7 @@ import { SwitchAccountDrawer } from './SwitchAccountDrawer'; const queryMocks = vi.hoisted(() => ({ useProfile: vi.fn().mockReturnValue({}), - useAllListMyDelegatedChildAccountsQuery: vi.fn().mockReturnValue({}), + useGetListMyDelegatedChildAccountsQuery: vi.fn().mockReturnValue({}), })); vi.mock('@linode/queries', async () => { @@ -17,8 +17,8 @@ vi.mock('@linode/queries', async () => { return { ...actual, useProfile: queryMocks.useProfile, - useAllListMyDelegatedChildAccountsQuery: - queryMocks.useAllListMyDelegatedChildAccountsQuery, + useGetListMyDelegatedChildAccountsQuery: + queryMocks.useGetListMyDelegatedChildAccountsQuery, }; }); @@ -31,7 +31,7 @@ const props = { describe('SwitchAccountDrawer', () => { beforeEach(() => { queryMocks.useProfile.mockReturnValue({}); - queryMocks.useAllListMyDelegatedChildAccountsQuery.mockReturnValue({ + queryMocks.useGetListMyDelegatedChildAccountsQuery.mockReturnValue({ data: accountFactory.buildList(5, { company: 'Test Account 1', euuid: '123', diff --git a/packages/manager/src/features/Account/SwitchAccountDrawer.tsx b/packages/manager/src/features/Account/SwitchAccountDrawer.tsx index d8be164ba46..d18e6f105f1 100644 --- a/packages/manager/src/features/Account/SwitchAccountDrawer.tsx +++ b/packages/manager/src/features/Account/SwitchAccountDrawer.tsx @@ -1,10 +1,19 @@ import { - useAllListMyDelegatedChildAccountsQuery, useChildAccountsInfiniteQuery, + useMyDelegatedChildAccountsQuery, } from '@linode/queries'; -import { Drawer, LinkButton, Notice, Typography } from '@linode/ui'; +import { + Button, + Drawer, + LinkButton, + Notice, + Stack, + Typography, + useTheme, +} from '@linode/ui'; import React, { useMemo, useState } from 'react'; +import ErrorStateCloud from 'src/assets/icons/error-state-cloud.svg'; import { DebouncedSearchTextField } from 'src/components/DebouncedSearchTextField'; import { useParentChildAuthentication } from 'src/features/Account/SwitchAccounts/useParentChildAuthentication'; import { useSwitchToParentAccount } from 'src/features/Account/SwitchAccounts/useSwitchToParentAccount'; @@ -14,6 +23,7 @@ import { sendSwitchToParentAccountEvent } from 'src/utilities/analytics/customEv import { getStorage, storage } from 'src/utilities/storage'; import { ChildAccountList } from './SwitchAccounts/ChildAccountList'; +import { ChildAccountsTable } from './SwitchAccounts/ChildAccountsTable'; import { updateParentTokenInLocalStorage } from './SwitchAccounts/utils'; import type { APIError, Filter, UserType } from '@linode/api-v4'; @@ -34,10 +44,13 @@ interface HandleSwitchToChildAccountProps { export const SwitchAccountDrawer = (props: Props) => { const { onClose, open, userType } = props; + const theme = useTheme(); const [isParentTokenError, setIsParentTokenError] = React.useState< APIError[] >([]); const [searchQuery, setSearchQuery] = React.useState(''); + const [page, setPage] = useState(1); + const [pageSize, setPageSize] = useState(25); const { isIAMDelegationEnabled } = useIsIAMDelegationEnabled(); const isParentUserType = userType === 'parent'; const isProxyUserType = userType === 'proxy'; @@ -94,20 +107,20 @@ export const SwitchAccountDrawer = (props: Props) => { ); const { - data: allChildAccounts, - error: allChildAccountsError, - isLoading: allChildAccountsLoading, - isRefetching: allChildAccountsIsRefetching, - refetch: refetchAllChildAccounts, - } = useAllListMyDelegatedChildAccountsQuery({ - params: {}, + data: delegatedChildAccounts, + error: delegatedChildAccountsError, + isLoading: delegatedChildAccountsLoading, + isRefetching: delegatedChildAccountsIsRefetching, + refetch: refetchDelegatedChildAccounts, + } = useMyDelegatedChildAccountsQuery({ + params: { + page, + page_size: pageSize, + }, + filter, enabled: isIAMDelegationEnabled && isParentUserType, }); - const refetchFn = isIAMDelegationEnabled - ? refetchAllChildAccounts - : refetchChildAccounts; - const handleSwitchToChildAccount = React.useCallback( async ({ currentTokenWithBearer, @@ -147,35 +160,57 @@ export const SwitchAccountDrawer = (props: Props) => { }); onClose(event); location.reload(); - } catch (error) { + } catch { // Error is handled by createTokenError. } }, - [createToken, updateCurrentToken, revokeToken] + [createToken, isProxyUserType, updateCurrentToken, revokeToken] ); const [isSwitchingChildAccounts, setIsSwitchingChildAccounts] = useState(false); + const isLoading = + isInitialLoading || + isSubmitting || + isSwitchingChildAccounts || + isRefetching || + delegatedChildAccountsLoading || + delegatedChildAccountsIsRefetching; + + const refetchFn = isIAMDelegationEnabled + ? refetchDelegatedChildAccounts + : refetchChildAccounts; const handleClose = () => { setIsSwitchingChildAccounts(false); + setSearchQuery(''); onClose(); }; const childAccounts = useMemo(() => { if (isIAMDelegationEnabled) { - if (searchQuery && allChildAccounts) { - // Client-side filter: match company field with searchQuery (case-insensitive, contains) - const normalizedQuery = searchQuery.toLowerCase(); - return allChildAccounts.filter((account) => - account.company?.toLowerCase().includes(normalizedQuery) - ); - } - return allChildAccounts; + return delegatedChildAccounts?.data || []; } return data?.pages.flatMap((page) => page.data); - }, [isIAMDelegationEnabled, searchQuery, allChildAccounts, data]); + }, [isIAMDelegationEnabled, delegatedChildAccounts, data]); + + const handlePageChange = (newPage: number) => { + setPage(newPage); + }; + const handlePageSizeChange = (newPageSize: number) => { + setPageSize(newPageSize); + setPage(1); // Reset to first page when page size changes + }; + + const handleSearchQueryChange = (query: string) => { + setSearchQuery(query); + setPage(1); // Reset to first page when search query changes + }; + + const hasError = isIAMDelegationEnabled + ? delegatedChildAccountsError + : childAccountInfiniteError; return ( {createTokenErrorReason && ( @@ -207,69 +242,95 @@ export const SwitchAccountDrawer = (props: Props) => { )} . - {isIAMDelegationEnabled && - allChildAccounts && - allChildAccounts.length !== 0 && ( - <> - - {searchQuery && childAccounts && childAccounts.length === 0 && ( - + + {hasError && ( + + + Unable to load data. + + Try again or contact support if the issue persists. + + + + )} + {!hasError && ( + <> + + {searchQuery && + childAccounts && + childAccounts.length === 0 && + !isLoading && ( + No search results )} - - )} + + )} + {isIAMDelegationEnabled && ( + + )} {!isIAMDelegationEnabled && ( - )} - ); }; diff --git a/packages/manager/src/features/Account/SwitchAccounts/ChildAccountList.test.tsx b/packages/manager/src/features/Account/SwitchAccounts/ChildAccountList.test.tsx index 4e62477a014..8c4db5fe0da 100644 --- a/packages/manager/src/features/Account/SwitchAccounts/ChildAccountList.test.tsx +++ b/packages/manager/src/features/Account/SwitchAccounts/ChildAccountList.test.tsx @@ -26,10 +26,6 @@ const props: ChildAccountListProps = { onClose: vi.fn(), onSwitchAccount: vi.fn(), userType: undefined, - errors: { - childAccountInfiniteError: false, - allChildAccountsError: null, - }, fetchNextPage: vi.fn(), filter: {}, hasNextPage: false, diff --git a/packages/manager/src/features/Account/SwitchAccounts/ChildAccountList.tsx b/packages/manager/src/features/Account/SwitchAccounts/ChildAccountList.tsx index d0994f51578..5b93722145e 100644 --- a/packages/manager/src/features/Account/SwitchAccounts/ChildAccountList.tsx +++ b/packages/manager/src/features/Account/SwitchAccounts/ChildAccountList.tsx @@ -1,16 +1,7 @@ -import { - Box, - Button, - CircleProgress, - LinkButton, - Notice, - Stack, - Typography, -} from '@linode/ui'; +import { Box, CircleProgress, LinkButton, Notice, Stack } from '@linode/ui'; import React from 'react'; import { Waypoint } from 'react-waypoint'; -import ErrorStateCloud from 'src/assets/icons/error-state-cloud.svg'; import { useIsIAMDelegationEnabled } from 'src/features/IAM/hooks/useIsIAMEnabled'; import type { ChildAccount, Filter, UserType } from '@linode/api-v4'; @@ -18,10 +9,6 @@ import type { ChildAccount, Filter, UserType } from '@linode/api-v4'; export interface ChildAccountListProps { childAccounts: ChildAccount[] | undefined; currentTokenWithBearer: string; - errors: { - allChildAccountsError: Error | null; - childAccountInfiniteError: boolean; - }; fetchNextPage: () => void; filter: Filter; hasNextPage: boolean; @@ -52,39 +39,12 @@ export const ChildAccountList = React.memo( onClose, onSwitchAccount, userType, - refetchFn, - errors, hasNextPage, fetchNextPage, isFetchingNextPage, }: ChildAccountListProps) => { const { isIAMDelegationEnabled } = useIsIAMDelegationEnabled(); - const hasError = isIAMDelegationEnabled - ? errors.allChildAccountsError - : errors.childAccountInfiniteError; - - if (hasError) { - return ( - - - Unable to load data. - - Try again or contact support if the issue persists. - - - - ); - } - if (isLoading) { return ( diff --git a/packages/manager/src/features/Account/SwitchAccounts/ChildAccountsTable.tsx b/packages/manager/src/features/Account/SwitchAccounts/ChildAccountsTable.tsx new file mode 100644 index 00000000000..1f4c316003d --- /dev/null +++ b/packages/manager/src/features/Account/SwitchAccounts/ChildAccountsTable.tsx @@ -0,0 +1,129 @@ +import { Box, CircleProgress, LinkButton, useTheme } from '@linode/ui'; +import { Pagination } from 'akamai-cds-react-components/Pagination'; +import { + Table, + TableBody, + TableCell, + TableRow, +} from 'akamai-cds-react-components/Table'; +import React from 'react'; + +import { MIN_PAGE_SIZE } from 'src/components/PaginationFooter/PaginationFooter.constants'; + +import type { Account, UserType } from '@linode/api-v4'; + +interface ChildAccountsTableProps { + childAccounts?: Account[]; + currentTokenWithBearer?: string; + isLoading: boolean; + isSwitchingChildAccounts: boolean; + onClose: () => void; + onPageChange: (page: number) => void; + onPageSizeChange: (pageSize: number) => void; + onSwitchAccount: ({ + currentTokenWithBearer, + euuid, + event, + onClose, + userType, + }: { + currentTokenWithBearer?: string; + euuid: string; + event: React.MouseEvent; + onClose: (e: React.SyntheticEvent) => void; + userType: undefined | UserType; + }) => void; + page: number; + pageSize: number; + setIsSwitchingChildAccounts: (value: boolean) => void; + totalResults: number; + userType: undefined | UserType; +} + +export const ChildAccountsTable = (props: ChildAccountsTableProps) => { + const { + childAccounts, + currentTokenWithBearer, + isLoading, + isSwitchingChildAccounts, + onClose, + onSwitchAccount, + setIsSwitchingChildAccounts, + userType, + page, + pageSize, + totalResults, + onPageChange, + onPageSizeChange, + } = props; + + const theme = useTheme(); + const handlePageChange = (newPage: number) => { + onPageChange(newPage); + }; + + const handlePageSizeChange = (newPageSize: number) => { + onPageSizeChange(newPageSize); + }; + + if (isLoading) { + return ( + + + + ); + } + + return ( + <> + + + {childAccounts?.map((childAccount, idx) => ( + + + { + setIsSwitchingChildAccounts(true); + onSwitchAccount({ + currentTokenWithBearer, + euuid: childAccount.euuid, + event, + onClose, + userType, + }); + }} + sx={{ + textOverflow: 'ellipsis', + overflow: 'hidden', + textAlign: 'left', + whiteSpace: 'nowrap', + }} + > + {childAccount.company} + + + + ))} + +
+ {totalResults > MIN_PAGE_SIZE && ( + ) => + handlePageChange(Number(e.detail)) + } + onPageSizeChange={( + e: CustomEvent<{ page: number; pageSize: number }> + ) => handlePageSizeChange(Number(e.detail.pageSize))} + page={page} + pageSize={pageSize} + pageSizes={[25, 50, 75, 100]} + style={{ marginTop: theme.spacingFunction(12) }} + /> + )} + + ); +}; diff --git a/packages/queries/src/iam/delegation.ts b/packages/queries/src/iam/delegation.ts index efb447e1c77..ceed9d79255 100644 --- a/packages/queries/src/iam/delegation.ts +++ b/packages/queries/src/iam/delegation.ts @@ -9,7 +9,6 @@ import { updateChildAccountDelegates, updateDefaultDelegationAccess, } from '@linode/api-v4'; -import { getAll } from '@linode/utilities'; import { createQueryKeys } from '@lukemorales/query-key-factory'; import { keepPreviousData, @@ -26,8 +25,8 @@ import type { GetChildAccountDelegatesParams, GetChildAccountsIamParams, GetDelegatedChildAccountsForUserParams, + GetMyDelegatedChildAccountsParams, IamUserRoles, - Params, ResourcePage, Token, UpdateChildAccountDelegatesParams, @@ -61,19 +60,17 @@ export const delegationQueries = createQueryKeys('delegation', { queryFn: () => getChildAccountDelegates({ euuid, params }), queryKey: [euuid, params], }), - myDelegatedChildAccounts: { - contextQueries: { - all: (params: Params) => ({ - queryFn: () => getAllMyDelegatedChildAccounts(params), - queryKey: [params], - }), - paginated: (params: Params) => ({ - queryFn: () => getMyDelegatedChildAccounts({ params }), - queryKey: [params], + myDelegatedChildAccounts: ({ + params, + filter = {}, + }: GetMyDelegatedChildAccountsParams) => ({ + queryFn: () => + getMyDelegatedChildAccounts({ + params, + filter, }), - }, - queryKey: null, - }, + queryKey: [params, filter], + }), delegatedChildAccount: (euuid: string) => ({ queryFn: () => getDelegatedChildAccount({ euuid }), queryKey: [euuid], @@ -190,7 +187,7 @@ export const useUpdateChildAccountDelegatesQuery = (): UseMutationResult< }); // Invalidate all my delegated child accounts since delegation may have changed queryClient.invalidateQueries({ - queryKey: delegationQueries.myDelegatedChildAccounts._ctx.all._def, + queryKey: delegationQueries.myDelegatedChildAccounts._def, }); }, }); @@ -198,34 +195,21 @@ export const useUpdateChildAccountDelegatesQuery = (): UseMutationResult< /** * List my delegated child accounts (gets child accounts where user has view_child_account permission). - * - Purpose: Get child accounts that the current authenticated user can manage via delegation. + * - Purpose: Get child accounts that the current authenticated user can manage via delegation with pagination. * - Scope: Only child accounts where the caller has an active delegate and required view permission. - * - Audience: Needing to return accounts the caller can actually access. + * - Audience: Needing to return accounts the caller can actually access with pagination. * - CRUD: GET /iam/delegation/profile/child-accounts */ -export const useGetMyDelegatedChildAccountsQuery = ( - params: Params, -): UseQueryResult, APIError[]> => { - return useQuery({ - ...delegationQueries.myDelegatedChildAccounts._ctx.paginated(params), - }); -}; - -/** - * List all my delegated child accounts (fetches all pages of child accounts where user has view_child_account permission) - * - Purpose: Retrieve the full list of child accounts the current caller can manage via delegation, across all pages. - * - Scope: Only child accounts where the caller has an active delegate and required view permission; returns all results, not paginated. - * - Audience: Callers needing the complete set of accessible accounts for the current user. - * - Data: Account[] (limited profile fields) for `GET /iam/delegation/profile/child-accounts` (all pages). - * - Usage: Pass `enabled` to control query activation (e.g., only if IAM Delegation is enabled). - */ -export const useAllListMyDelegatedChildAccountsQuery = ({ +export const useMyDelegatedChildAccountsQuery = ({ params = {}, + filter = {}, enabled = true, -}) => { +}: GetMyDelegatedChildAccountsParams & { + enabled?: boolean; +}): UseQueryResult, APIError[]> => { return useQuery({ enabled, - ...delegationQueries.myDelegatedChildAccounts._ctx.all(params), + ...delegationQueries.myDelegatedChildAccounts({ params, filter }), }); }; @@ -297,11 +281,3 @@ export const useUpdateDefaultDelegationAccessQuery = (): UseMutationResult< }, }); }; - -/** - * Fetches all my delegated child accounts for the current user (all pages). - */ -const getAllMyDelegatedChildAccounts = (_params: Params = {}) => - getAll((params) => - getMyDelegatedChildAccounts({ params: { ...params, ..._params } }), - )().then((data) => data.data); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 68da9ff2003..d86446c627a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -215,8 +215,8 @@ importers: specifier: ^5.5.0 version: 5.5.0 akamai-cds-react-components: - specifier: 0.0.1-alpha.19 - version: 0.0.1-alpha.19(@linode/design-language-system@5.3.2)(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: 0.1.0 + version: 0.1.0(@linode/design-language-system@5.3.2)(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) algoliasearch: specifier: ^4.14.3 version: 4.24.0 @@ -1823,16 +1823,16 @@ packages: peerDependencies: eslint: ^9 - '@lit-labs/ssr-dom-shim@1.4.0': - resolution: {integrity: sha512-ficsEARKnmmW5njugNYKipTm4SFnbik7CXtoencDZzmzo/dQ+2Q0bgkzJuoJP20Aj0F+izzJjOqsnkd6F/o1bw==} + '@lit-labs/ssr-dom-shim@1.5.1': + resolution: {integrity: sha512-Aou5UdlSpr5whQe8AA/bZG0jMj96CoJIWbGfZ91qieWu5AWUMKw8VR/pAkQkJYvBNhmCcWnZlyyk5oze8JIqYA==} '@lit/react@1.0.8': resolution: {integrity: sha512-p2+YcF+JE67SRX3mMlJ1TKCSTsgyOVdAwd/nxp3NuV1+Cb6MWALbN6nT7Ld4tpmYofcE5kcaSY1YBB9erY+6fw==} peerDependencies: '@types/react': 17 || 18 || 19 - '@lit/reactive-element@2.1.1': - resolution: {integrity: sha512-N+dm5PAYdQ8e6UlywyyrgI2t++wFGXfHx+dSJ1oBrg6FAxUj40jId++EaRm80MKX5JnlH1sBsyZ5h0bcZKemCg==} + '@lit/reactive-element@2.1.2': + resolution: {integrity: sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==} '@lukemorales/query-key-factory@1.3.4': resolution: {integrity: sha512-A3frRDdkmaNNQi6mxIshsDk4chRXWoXa05US8fBo4kci/H+lVmujS6QrwQLLGIkNIRFGjMqp2uKjC4XsLdydRw==} @@ -3340,16 +3340,16 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - akamai-cds-react-components@0.0.1-alpha.19: - resolution: {integrity: sha512-YNQPeP4i65qKA5bjOb4ti0ciwQOYZqsKlJ9f14g7xeJCHamyqxPuHIGsOTvykhKyFoXLL8+kejDS52H5vLvVug==} + akamai-cds-react-components@0.1.0: + resolution: {integrity: sha512-3j4RUS2gsEvTvGVihG48oxfZ+sFRGM+6zfB04UNIVrxsIa5QLYhA4C6RKqmuEqKlsQhgSeg/XkcKJh4vKmW3Qw==} peerDependencies: react: ^18.0.0 react-dom: ^18.0.0 - akamai-cds-web-components@0.0.1-alpha.19: - resolution: {integrity: sha512-8xzQjUtNgpbmINt72deakR96vWDJekfjWMt7DJ3DWumlhXDzekf2hm3Q8++hObjKVx6KgXpUDOGzAdU5yMKeiQ==} + akamai-cds-web-components@0.1.0: + resolution: {integrity: sha512-Ia8JIqr0dV1yuFAaEiP1KfTOZVNLIc0OhWIcnmPb7lnUUOtKfLSB3bbUyYhcm0xag+hLCBxo+Ds+axE9ZL55uw==} peerDependencies: - '@linode/design-language-system': ^5.2.0 + '@linode/design-language-system': ^5.3.2 algoliasearch@4.24.0: resolution: {integrity: sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g==} @@ -4600,16 +4600,17 @@ packages: glob@10.5.0: resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me glob@8.1.0: resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} engines: {node: '>=12'} - deprecated: Glob versions prior to v9 are no longer supported + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me global-dirs@3.0.1: resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==} @@ -5173,14 +5174,14 @@ packages: resolution: {integrity: sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==} engines: {node: '>=18.0.0'} - lit-element@4.2.1: - resolution: {integrity: sha512-WGAWRGzirAgyphK2urmYOV72tlvnxw7YfyLDgQ+OZnM9vQQBQnumQ7jUJe6unEzwGU3ahFOjuz1iz1jjrpCPuw==} + lit-element@4.2.2: + resolution: {integrity: sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==} - lit-html@3.3.1: - resolution: {integrity: sha512-S9hbyDu/vs1qNrithiNyeyv64c9yqiW9l+DBgI18fL+MTvOtWoFR0FWiyq1TxaYef5wNlpEmzlXoBlZEO+WjoA==} + lit-html@3.3.2: + resolution: {integrity: sha512-Qy9hU88zcmaxBXcc10ZpdK7cOLXvXpRoBxERdtqV9QOrfpMZZ6pSYP91LhpPtap3sFMUiL7Tw2RImbe0Al2/kw==} - lit@3.3.1: - resolution: {integrity: sha512-Ksr/8L3PTapbdXJCk+EJVB78jDodUMaP54gD24W186zGRARvwrsPfS60wae/SSCTCNZVPd1chXqio1qHQmu4NA==} + lit@3.3.2: + resolution: {integrity: sha512-NF9zbsP79l4ao2SNrH3NkfmFgN/hBYSQo90saIVI1o5GpjAdCPVstVzO1MrLOakHoEhYkrtRjPK6Ob521aoYWQ==} load-tsconfig@0.2.5: resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} @@ -6879,6 +6880,7 @@ packages: whatwg-encoding@3.1.1: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} engines: {node: '>=18'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation whatwg-mimetype@4.0.0: resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} @@ -7953,15 +7955,15 @@ snapshots: dependencies: eslint: 9.31.0(jiti@2.4.2) - '@lit-labs/ssr-dom-shim@1.4.0': {} + '@lit-labs/ssr-dom-shim@1.5.1': {} '@lit/react@1.0.8(@types/react@19.1.6)': dependencies: '@types/react': 19.1.6 - '@lit/reactive-element@2.1.1': + '@lit/reactive-element@2.1.2': dependencies: - '@lit-labs/ssr-dom-shim': 1.4.0 + '@lit-labs/ssr-dom-shim': 1.5.1 '@lukemorales/query-key-factory@1.3.4(@tanstack/query-core@5.51.24)(@tanstack/react-query@5.51.24(react@19.1.0))': dependencies: @@ -9407,18 +9409,6 @@ snapshots: tinyrainbow: 3.0.3 vitest: 4.0.10(@types/debug@4.1.12)(@types/node@22.18.1)(@vitest/ui@4.0.10)(jiti@2.4.2)(jsdom@24.1.3)(msw@2.6.5(@types/node@22.18.1)(typescript@5.7.3))(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) - '@vitest/ui@4.0.10(vitest@4.0.16)': - dependencies: - '@vitest/utils': 4.0.10 - fflate: 0.8.2 - flatted: 3.3.3 - pathe: 2.0.3 - sirv: 3.0.2 - tinyglobby: 0.2.15 - tinyrainbow: 3.0.3 - vitest: 4.0.16(@types/node@22.18.1)(@vitest/ui@4.0.10)(jiti@2.4.2)(jsdom@24.1.3)(msw@2.6.5(@types/node@22.18.1)(typescript@5.9.3))(terser@5.36.0)(tsx@4.19.3)(yaml@2.6.1) - optional: true - '@vitest/utils@3.2.4': dependencies: '@vitest/pretty-format': 3.2.4 @@ -9473,20 +9463,20 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - akamai-cds-react-components@0.0.1-alpha.19(@linode/design-language-system@5.3.2)(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + akamai-cds-react-components@0.1.0(@linode/design-language-system@5.3.2)(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: '@lit/react': 1.0.8(@types/react@19.1.6) - akamai-cds-web-components: 0.0.1-alpha.19(@linode/design-language-system@5.3.2) + akamai-cds-web-components: 0.1.0(@linode/design-language-system@5.3.2) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) transitivePeerDependencies: - '@linode/design-language-system' - '@types/react' - akamai-cds-web-components@0.0.1-alpha.19(@linode/design-language-system@5.3.2): + akamai-cds-web-components@0.1.0(@linode/design-language-system@5.3.2): dependencies: '@linode/design-language-system': 5.3.2 - lit: 3.3.1 + lit: 3.3.2 algoliasearch@4.24.0: dependencies: @@ -11588,21 +11578,21 @@ snapshots: rfdc: 1.4.1 wrap-ansi: 9.0.0 - lit-element@4.2.1: + lit-element@4.2.2: dependencies: - '@lit-labs/ssr-dom-shim': 1.4.0 - '@lit/reactive-element': 2.1.1 - lit-html: 3.3.1 + '@lit-labs/ssr-dom-shim': 1.5.1 + '@lit/reactive-element': 2.1.2 + lit-html: 3.3.2 - lit-html@3.3.1: + lit-html@3.3.2: dependencies: '@types/trusted-types': 2.0.7 - lit@3.3.1: + lit@3.3.2: dependencies: - '@lit/reactive-element': 2.1.1 - lit-element: 4.2.1 - lit-html: 3.3.1 + '@lit/reactive-element': 2.1.2 + lit-element: 4.2.2 + lit-html: 3.3.2 load-tsconfig@0.2.5: {} @@ -13467,7 +13457,7 @@ snapshots: why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.18.1 - '@vitest/ui': 4.0.10(vitest@4.0.16) + '@vitest/ui': 4.0.10(vitest@4.0.10) jsdom: 24.1.3 transitivePeerDependencies: - jiti