go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/milo/ui/src/common/hooks/legacy_prpc_query/use_prpc_queries.ts (about)

     1  // Copyright 2023 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  import { UseQueryOptions, useQueries } from '@tanstack/react-query';
    16  
    17  import {
    18    useAuthState,
    19    useGetAccessToken,
    20  } from '@/common/components/auth_state_provider';
    21  import { PrpcClientExt } from '@/generic_libs/tools/prpc_client_ext';
    22  
    23  import {
    24    PrpcQueryBaseOptions,
    25    PrpcMethod,
    26    genPrpcQueryKey,
    27    PrpcServiceMethodKeys,
    28    PrpcMethodResponse,
    29    PrpcMethodRequest,
    30  } from './common';
    31  
    32  export interface UsePrpcQueriesOptions<S, MK, Req, Res, TError, TData>
    33    extends Omit<PrpcQueryBaseOptions<S, MK, Req>, 'request'> {
    34    readonly requests: readonly Req[];
    35    readonly options?: Omit<
    36      UseQueryOptions<Res, TError, TData, readonly unknown[]>,
    37      'queryKey' | 'queryFn' | 'context'
    38    >;
    39    readonly context?: UseQueryOptions['context'];
    40  }
    41  
    42  /**
    43   * @deprecated use `usePrpcQueries` from `@common/hooks/prpc_query` instead.
    44   *
    45   * Call a pRPC method via `@tanstack/react-query`.
    46   *
    47   * This hook
    48   *  * reduces boilerplate, and
    49   *  * ensures the `queryKey` is populated correctly.
    50   */
    51  export function usePrpcQueries<
    52    S extends object,
    53    MK extends PrpcServiceMethodKeys<S>,
    54    TError = unknown,
    55    TData = PrpcMethodResponse<S[MK]>,
    56  >(
    57    opts: UsePrpcQueriesOptions<
    58      S,
    59      MK,
    60      PrpcMethodRequest<S[MK]>,
    61      PrpcMethodResponse<S[MK]>,
    62      TError,
    63      TData
    64    >,
    65  ) {
    66    const { host, insecure, Service, method, requests, options, context } = opts;
    67  
    68    const { identity } = useAuthState();
    69    const getAccessToken = useGetAccessToken();
    70    const service = new Service(
    71      new PrpcClientExt({ host, insecure }, getAccessToken),
    72    );
    73    const m =
    74      // `method` is constrained to be a key that has an associated property of
    75      // type `PrpcMethod` in a `Service`. Therefore `service[method]` is
    76      // guaranteed to be a `PrpcMethod`. TSC isn't smart enough to know that,
    77      // so we need to use type casting.
    78      (
    79        service[method] as PrpcMethod<
    80          PrpcMethodRequest<S[MK]>,
    81          PrpcMethodResponse<S[MK]>
    82        >
    83      ).bind(service);
    84  
    85    type Query = Omit<
    86      UseQueryOptions<
    87        PrpcMethodResponse<S[MK]>,
    88        TError,
    89        TData,
    90        ReadonlyArray<unknown>
    91      >,
    92      'context'
    93    >;
    94  
    95    return useQueries({
    96      queries: requests.map<Query>((request) => ({
    97        queryKey: genPrpcQueryKey(identity, {
    98          host,
    99          insecure,
   100          Service,
   101          method,
   102          request,
   103        }),
   104        queryFn: async () => {
   105          return await m(
   106            request,
   107            // Let react-query handle caching.
   108            {
   109              acceptCache: false,
   110              skipUpdate: true,
   111            },
   112          );
   113        },
   114        ...options,
   115      })),
   116      context,
   117    });
   118  }