diff --git a/.changeset/nasty-mirrors-melt.md b/.changeset/nasty-mirrors-melt.md new file mode 100644 index 00000000..8d7441bb --- /dev/null +++ b/.changeset/nasty-mirrors-melt.md @@ -0,0 +1,5 @@ +--- +"@elasticpath/react-shopper-hooks": minor +--- + +add enhanced promotions details fns to cart object diff --git a/packages/react-shopper-hooks/example/App.tsx b/packages/react-shopper-hooks/example/App.tsx index e181cb80..6bbe5b28 100644 --- a/packages/react-shopper-hooks/example/App.tsx +++ b/packages/react-shopper-hooks/example/App.tsx @@ -1,12 +1,12 @@ import React from "react" import "./App.css" import CartExample from "./CartExample" -import { CartProvider } from "../src/cart" import { gateway as EPCCGateway } from "@moltin/sdk" import { StoreProvider } from "../src/store" import { ElasticPathProvider } from "../src" import { QueryClient } from "@tanstack/react-query" import { ProductListExample } from "./ProductListExample" +import { ReactQueryDevtools } from "@tanstack/react-query-devtools" const client = EPCCGateway({ name: "my_store", @@ -34,11 +34,10 @@ function App() { client={client} queryClientProviderProps={{ client: queryClient }} > - - - {activeItem === "cart" && } - {activeItem === "products" && } - + + + {activeItem === "cart" && } + {activeItem === "products" && } diff --git a/packages/react-shopper-hooks/example/CartExample.tsx b/packages/react-shopper-hooks/example/CartExample.tsx index 5b30d9cb..e575e0e4 100644 --- a/packages/react-shopper-hooks/example/CartExample.tsx +++ b/packages/react-shopper-hooks/example/CartExample.tsx @@ -1,13 +1,45 @@ import React from "react" -import { useCart, useCartAddBundleItem, useCartClear } from "../src/cart" +import { + useCart, + useCartAddBundleItem, + useCartAddProduct, + useCartAddPromotion, + useCartClear, +} from "../src/cart" +import ReactJson from "react-json-view" export default function CartExample(): JSX.Element { - const { state } = useCart() + const { data, isLoading } = useCart() const { mutate: addBundleProductToCart } = useCartAddBundleItem() + const { mutate: addProduct } = useCartAddProduct() const { mutate: emptyCart } = useCartClear() + const { mutate: addPromotion } = useCartAddPromotion() + + const itemDiscounts = data?.state.__extended.getItemDiscounts() + const allDiscounts = data?.state.__extended.getAllDiscounts() + return ( <> + + -
{JSON.stringify(state, null, 2)}
+ {data && ( +
+

Cart State

+ +
+ )} + {itemDiscounts && ( +
+

Item Discounts

+ +
+ )} + {allDiscounts && ( +
+

All discounts

+ +
+ )} ) } diff --git a/packages/react-shopper-hooks/package.json b/packages/react-shopper-hooks/package.json index b985a66d..61a1efec 100644 --- a/packages/react-shopper-hooks/package.json +++ b/packages/react-shopper-hooks/package.json @@ -40,6 +40,7 @@ "@storybook/react-vite": "^7.5.3", "@storybook/testing-library": "^0.2.2", "@tanstack/react-query": "^5.17.15", + "@tanstack/react-query-devtools": "^5.32.1", "@types/js-cookie": "^3.0.6", "@types/react": "^18.2.33", "@types/react-dom": "^18.2.14", @@ -62,7 +63,13 @@ "@moltin/sdk": "28.12.0", "@tanstack/react-query": "^5.8.4", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "rxjs": "7.5.7" + }, + "peerDependenciesMeta": { + "rxjs": { + "optional": true + } }, "publishConfig": { "access": "public" @@ -70,8 +77,7 @@ "dependencies": { "@elasticpath/shopper-common": "workspace:*", "js-cookie": "^3.0.5", - "jwt-decode": "^3.1.2", - "rxjs": "7.5.7" + "jwt-decode": "^3.1.2" }, "msw": { "workerDirectory": "public" diff --git a/packages/react-shopper-hooks/src/cart/cart-provider.tsx b/packages/react-shopper-hooks/src/cart/cart-provider.tsx deleted file mode 100644 index 1056e8b8..00000000 --- a/packages/react-shopper-hooks/src/cart/cart-provider.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import React, { createContext, ReactNode } from "react" -import { Cart, CartIncluded, ResourceIncluded, CartItem } from "@moltin/sdk" -import { CartState } from "./types/cart-types" -import { enhanceCartResponse } from "./util/enhance-cart-response" -import { StoreEvent } from "../shared" -import { useGetCart } from "./hooks/use-get-cart" -import { useElasticPath } from "../elasticpath" - -export const CartItemsContext = createContext< - | ({ - state: CartState | undefined - cartId: string - emit?: (event: StoreEvent) => void - } & Omit, "data">) - | undefined ->(undefined) - -export interface CartProviderProps { - children: ReactNode - cartId?: string - initialState?: { - cart?: ResourceIncluded - } - emit?: (event: StoreEvent) => void -} - -export function CartProvider({ - initialState, - children, - emit, - cartId: sourceCartId, -}: CartProviderProps) { - const { client } = useElasticPath() - - const cartId = sourceCartId ?? client.Cart().cartId - - const { data: rawCartData, ...rest } = useGetCart(cartId, { - initialData: initialState?.cart, - }) - - const state = - rawCartData && - enhanceCartResponse({ - data: rawCartData, - included: rest.included, - }) - - return ( - - {children} - - ) -} - -export function createCartItemsUpdater(updatedData: CartItem[]) { - return function cartItemsUpdater( - oldData: ResourceIncluded, - ) { - return { - ...oldData, - included: { - items: updatedData, - }, - } - } -} -export const useCart = () => { - const context = React.useContext(CartItemsContext) - if (!context) { - throw new Error("useCart must be used within a CartProvider") - } - return context -} diff --git a/packages/react-shopper-hooks/src/cart/hooks/index.ts b/packages/react-shopper-hooks/src/cart/hooks/index.ts index fefd2783..ba84a98a 100644 --- a/packages/react-shopper-hooks/src/cart/hooks/index.ts +++ b/packages/react-shopper-hooks/src/cart/hooks/index.ts @@ -15,3 +15,4 @@ export * from "./use-cart-add-bundle-item" export * from "./use-cart-clear" export * from "./use-cart-remove-promotion" export * from "./use-cart-remove-item" +export * from "./use-cart" diff --git a/packages/react-shopper-hooks/src/cart/hooks/use-cart-add-bundle-item.tsx b/packages/react-shopper-hooks/src/cart/hooks/use-cart-add-bundle-item.tsx index 8084f389..3ace74a2 100644 --- a/packages/react-shopper-hooks/src/cart/hooks/use-cart-add-bundle-item.tsx +++ b/packages/react-shopper-hooks/src/cart/hooks/use-cart-add-bundle-item.tsx @@ -1,11 +1,14 @@ -import { createCartItemsUpdater, useCart } from "../cart-provider" +import { createCartItemsUpdater, useCart } from "./use-cart" import { useQueryClient } from "@tanstack/react-query" import { cartQueryKeys } from "./use-get-cart" import { useAddBundleProductToCart } from "./use-add-bundle-product-to-cart" export function useCartAddBundleItem() { - const { cartId } = useCart() + const { data } = useCart() const queryClient = useQueryClient() + + const cartId = data?.cartId! + return useAddBundleProductToCart(cartId, { onSuccess: (updatedData) => { // Updates the cart items in the query cache diff --git a/packages/react-shopper-hooks/src/cart/hooks/use-cart-add-product.tsx b/packages/react-shopper-hooks/src/cart/hooks/use-cart-add-product.tsx index 203c05d6..b2501665 100644 --- a/packages/react-shopper-hooks/src/cart/hooks/use-cart-add-product.tsx +++ b/packages/react-shopper-hooks/src/cart/hooks/use-cart-add-product.tsx @@ -1,13 +1,16 @@ import { useAddProductToCart } from "./use-add-product" -import { createCartItemsUpdater, useCart } from "../cart-provider" +import { createCartItemsUpdater, useCart } from "./use-cart" import { useQueryClient } from "@tanstack/react-query" import { cartQueryKeys } from "./use-get-cart" export function useCartAddProduct() { - const { cartId } = useCart() + const { data } = useCart() const queryClient = useQueryClient() + + const cartId = data?.cartId! + return useAddProductToCart(cartId, { - onSuccess: (updatedData) => { + onSuccess: (updatedData, req) => { // Updates the cart items in the query cache queryClient.setQueryData( cartQueryKeys.detail(cartId), diff --git a/packages/react-shopper-hooks/src/cart/hooks/use-cart-add-promotion.tsx b/packages/react-shopper-hooks/src/cart/hooks/use-cart-add-promotion.tsx index 33a8be36..9a293bbe 100644 --- a/packages/react-shopper-hooks/src/cart/hooks/use-cart-add-promotion.tsx +++ b/packages/react-shopper-hooks/src/cart/hooks/use-cart-add-promotion.tsx @@ -1,11 +1,14 @@ -import { createCartItemsUpdater, useCart } from "../cart-provider" +import { createCartItemsUpdater, useCart } from "./use-cart" import { useQueryClient } from "@tanstack/react-query" import { cartQueryKeys } from "./use-get-cart" import { useAddPromotionToCart } from "./use-add-promotion" export function useCartAddPromotion() { - const { cartId } = useCart() + const { data } = useCart() const queryClient = useQueryClient() + + const cartId = data?.cartId! + return useAddPromotionToCart(cartId, { onSuccess: (updatedData) => { // Updates the cart items in the query cache diff --git a/packages/react-shopper-hooks/src/cart/hooks/use-cart-clear.tsx b/packages/react-shopper-hooks/src/cart/hooks/use-cart-clear.tsx index 2b26da8c..57e05cb1 100644 --- a/packages/react-shopper-hooks/src/cart/hooks/use-cart-clear.tsx +++ b/packages/react-shopper-hooks/src/cart/hooks/use-cart-clear.tsx @@ -1,11 +1,15 @@ -import { createCartItemsUpdater, useCart } from "../cart-provider" +import { createCartItemsUpdater, useCart } from "./use-cart" import { useQueryClient } from "@tanstack/react-query" import { cartQueryKeys } from "./use-get-cart" import { useDeleteCartItems } from "./use-delete-cart-items" export function useCartClear() { - const { cartId } = useCart() + const { data } = useCart() + + const cartId = data?.cartId! + const queryClient = useQueryClient() + return useDeleteCartItems(cartId, { onSuccess: (updatedData) => { // Updates the cart items in the query cache diff --git a/packages/react-shopper-hooks/src/cart/hooks/use-cart-remove-item.tsx b/packages/react-shopper-hooks/src/cart/hooks/use-cart-remove-item.tsx index bb77b723..2d97520c 100644 --- a/packages/react-shopper-hooks/src/cart/hooks/use-cart-remove-item.tsx +++ b/packages/react-shopper-hooks/src/cart/hooks/use-cart-remove-item.tsx @@ -1,11 +1,14 @@ -import { createCartItemsUpdater, useCart } from "../cart-provider" +import { createCartItemsUpdater, useCart } from "./use-cart" import { useQueryClient } from "@tanstack/react-query" import { cartQueryKeys } from "./use-get-cart" import { useRemoveCartItem } from "./use-remove-cart-item" export function useCartRemoveItem() { - const { cartId } = useCart() + const { data } = useCart() const queryClient = useQueryClient() + + const cartId = data?.cartId! + return useRemoveCartItem(cartId, { onSuccess: (updatedData) => { // Updates the cart items in the query cache diff --git a/packages/react-shopper-hooks/src/cart/hooks/use-cart-remove-promotion.tsx b/packages/react-shopper-hooks/src/cart/hooks/use-cart-remove-promotion.tsx index a4954792..d6f5a268 100644 --- a/packages/react-shopper-hooks/src/cart/hooks/use-cart-remove-promotion.tsx +++ b/packages/react-shopper-hooks/src/cart/hooks/use-cart-remove-promotion.tsx @@ -1,11 +1,14 @@ -import { createCartItemsUpdater, useCart } from "../cart-provider" +import { createCartItemsUpdater, useCart } from "./use-cart" import { useQueryClient } from "@tanstack/react-query" import { cartQueryKeys } from "./use-get-cart" import { useRemovePromotionCode } from "./use-remove-promotion" export function useCartRemovePromotion() { - const { cartId } = useCart() + const { data } = useCart() const queryClient = useQueryClient() + + const cartId = data?.cartId! + return useRemovePromotionCode(cartId, { onSuccess: (updatedData) => { // Updates the cart items in the query cache diff --git a/packages/react-shopper-hooks/src/cart/hooks/use-cart-update-item.tsx b/packages/react-shopper-hooks/src/cart/hooks/use-cart-update-item.tsx index a99d1022..50fe6953 100644 --- a/packages/react-shopper-hooks/src/cart/hooks/use-cart-update-item.tsx +++ b/packages/react-shopper-hooks/src/cart/hooks/use-cart-update-item.tsx @@ -1,11 +1,14 @@ -import { createCartItemsUpdater, useCart } from "../cart-provider" +import { createCartItemsUpdater, useCart } from "./use-cart" import { useQueryClient } from "@tanstack/react-query" import { cartQueryKeys } from "./use-get-cart" import { useUpdateCartItem } from "./use-update-cart-items" export function useCartUpdateItem() { - const { cartId } = useCart() + const { data } = useCart() const queryClient = useQueryClient() + + const cartId = data?.cartId! + return useUpdateCartItem(cartId, { onSuccess: (updatedData) => { // Updates the cart items in the query cache diff --git a/packages/react-shopper-hooks/src/cart/hooks/use-cart.tsx b/packages/react-shopper-hooks/src/cart/hooks/use-cart.tsx new file mode 100644 index 00000000..3339291c --- /dev/null +++ b/packages/react-shopper-hooks/src/cart/hooks/use-cart.tsx @@ -0,0 +1,61 @@ +import React from "react" +import { Cart, CartIncluded, ResourceIncluded, CartItem } from "@moltin/sdk" +import { CartState } from "../types/cart-types" +import { enhanceCartResponse } from "../util/enhance-cart-response" +import { StoreEvent } from "../../shared" +import { CartQueryKey, cartQueryKeys } from "./use-get-cart" +import { useElasticPath } from "../../elasticpath" +import { UseQueryOptionsWrapper } from "../../types" +import { UseQueryResult } from "@tanstack/react-query/build/modern/index" +import { useQuery } from "@tanstack/react-query" + +export type UseCartData = { + state: CartState + cartId: string + emit?: (event: StoreEvent) => void +} + +export function createCartItemsUpdater(updatedData: CartItem[]) { + return function cartItemsUpdater( + oldData: ResourceIncluded, + ) { + return { + ...oldData, + included: { + items: updatedData, + }, + } + } +} + +export function useCart( + id?: string, + options?: UseQueryOptionsWrapper< + ResourceIncluded, + Error, + ReturnType + >, +): UseQueryResult { + const { client } = useElasticPath() + const cartId = id ?? client.Cart().cartId + + return useQuery({ + queryKey: cartQueryKeys.detail(cartId), + queryFn: () => client.Cart(id).With("items").Get(), + ...options, + select: (data) => { + const transformedData = options?.select?.(data) ?? data + + const state = enhanceCartResponse({ + data: transformedData.data, + included: transformedData.included, + }) + + return { + state, + cartId, + // TODO: add event emitter + } + }, + }) +} diff --git a/packages/react-shopper-hooks/src/cart/hooks/use-get-cart.ts b/packages/react-shopper-hooks/src/cart/hooks/use-get-cart.ts index 98aa9fca..f84bbfb6 100644 --- a/packages/react-shopper-hooks/src/cart/hooks/use-get-cart.ts +++ b/packages/react-shopper-hooks/src/cart/hooks/use-get-cart.ts @@ -7,7 +7,7 @@ import { queryKeysFactory } from "../../shared/util/query-keys-factory" const CARTS_QUERY_KEY = "carts" as const export const cartQueryKeys = queryKeysFactory(CARTS_QUERY_KEY) -type CartQueryKey = typeof cartQueryKeys +export type CartQueryKey = typeof cartQueryKeys export function useGetCart( id: string, @@ -16,13 +16,12 @@ export function useGetCart( Error, ReturnType >, -): Partial> & - Omit, Error>, "data"> { +) { const { client } = useElasticPath() - const { data, ...rest } = useQuery({ + + return useQuery({ queryKey: cartQueryKeys.detail(id), queryFn: () => client.Cart(id).With("items").Get(), ...options, }) - return { ...data, ...rest } as const } diff --git a/packages/react-shopper-hooks/src/cart/index.ts b/packages/react-shopper-hooks/src/cart/index.ts index b6e71cd1..28c57f1a 100644 --- a/packages/react-shopper-hooks/src/cart/index.ts +++ b/packages/react-shopper-hooks/src/cart/index.ts @@ -1,4 +1,3 @@ -export * from "./cart-provider" export * from "./types/cart-types" export * from "./hooks" export * from "./util" diff --git a/packages/react-shopper-hooks/src/cart/types/cart-types.ts b/packages/react-shopper-hooks/src/cart/types/cart-types.ts index 1ad0b338..ee967be9 100644 --- a/packages/react-shopper-hooks/src/cart/types/cart-types.ts +++ b/packages/react-shopper-hooks/src/cart/types/cart-types.ts @@ -36,6 +36,29 @@ export interface GroupedCartItems { export type RefinedCartItem = RegularCartItem | CustomCartItem +export type ItemDiscount = { + id: string + promotion_source: "rule-promotion" + amount: { + amount: number + currency: string + includes_tax: boolean + } + code: string +} + +export type ItemDiscountWithMeta = ItemDiscount & { + __meta: { + display_price?: { + amount: number + currency: string + formatted: string + } + } +} + +export type Discount = ItemDiscountWithMeta | PromotionCartItem + /** * State of the cart. */ @@ -53,6 +76,16 @@ export type CartState = { * Cart items grouped by their respective types cart_item, custom_item, promotion_item */ readonly groupedItems: GroupedCartItems + /** + * Get all item level discounts - these are discounts applied to specific items in the cart. + * + * These have been deduped and are unique. + */ + readonly getItemDiscounts: () => ReadonlyArray + /** + * Get all discounts both item level and cart level. + */ + readonly getAllDiscounts: () => ReadonlyArray } } & Cart diff --git a/packages/react-shopper-hooks/src/cart/util/enhance-cart-response.ts b/packages/react-shopper-hooks/src/cart/util/enhance-cart-response.ts index bd02f4e5..0a7da9b9 100644 --- a/packages/react-shopper-hooks/src/cart/util/enhance-cart-response.ts +++ b/packages/react-shopper-hooks/src/cart/util/enhance-cart-response.ts @@ -1,6 +1,7 @@ import { Cart, CartIncluded, CartItem, ResourceIncluded } from "@moltin/sdk" import { CartState, RefinedCartItem } from "../../cart" import { groupCartItems } from "./group-cart-items" +import { resolveItemDiscounts } from "./resolve-item-discounts" export function enhanceCartResponse( cart: ResourceIncluded, @@ -15,11 +16,41 @@ export function enhanceCartResponse( items: items as ReadonlyArray, __extended: { groupedItems, + getItemDiscounts: () => getItemDiscounts(cart), + getAllDiscounts: () => [ + ...getItemDiscounts(cart), + ...groupedItems.promotion, + ], }, ...cart.data, } } +function getItemDiscounts(cart: ResourceIncluded) { + const itemDiscounts = resolveItemDiscounts(cart.included?.items ?? []) + + // TODO: update sdk to have the correct display price types + const discountsLookup = ( + cart.data.meta?.display_price as { + discounts: + | Record< + string, + { amount: number; currency: string; formatted: string } + > + | undefined + } + )?.discounts + + return itemDiscounts.map((discount) => ({ + ...discount, + __meta: { + ...(discountsLookup && { + display_price: discountsLookup?.[discount.id], + }), + }, + })) +} + function sortItemByCreatedAsc(a: CartItem, b: CartItem) { return ( new Date(a.meta.timestamps.created_at).getTime() - diff --git a/packages/react-shopper-hooks/src/cart/util/resolve-item-discounts.ts b/packages/react-shopper-hooks/src/cart/util/resolve-item-discounts.ts new file mode 100644 index 00000000..c5eddbe5 --- /dev/null +++ b/packages/react-shopper-hooks/src/cart/util/resolve-item-discounts.ts @@ -0,0 +1,17 @@ +import { CartItem } from "@moltin/sdk" +import { ItemDiscount } from "../../cart" + +function checkDiscounts( + item: CartItem, +): item is CartItem & { discounts: ItemDiscount } { + return !!item.discounts +} + +export function resolveItemDiscounts( + items: Array, +): Array { + const itemDiscounts = items + .filter(checkDiscounts) + .map((item) => item.discounts) + return Array.from(new Set(itemDiscounts)) +} diff --git a/packages/react-shopper-hooks/src/store/store-provider.tsx b/packages/react-shopper-hooks/src/store/store-provider.tsx index 9b36cc94..af591683 100644 --- a/packages/react-shopper-hooks/src/store/store-provider.tsx +++ b/packages/react-shopper-hooks/src/store/store-provider.tsx @@ -1,6 +1,4 @@ import { StoreProviderProps } from "./types/store-context-types" -import { emitter } from "../event/event-context" -import { CartProvider } from "../cart" import React, { createContext } from "react" import type { Moltin as EPCCClient } from "@moltin/sdk" import { NavigationNode } from "@elasticpath/shopper-common" @@ -16,21 +14,12 @@ export const StoreProviderContext = createContext(null) export const StoreProvider = ({ children, initialState, - cartId, }: StoreProviderProps) => { const { client } = useElasticPath() return ( - - {children} - + {children} ) } diff --git a/packages/react-shopper-hooks/src/store/types/store-context-types.ts b/packages/react-shopper-hooks/src/store/types/store-context-types.ts index afea61d4..897fd494 100644 --- a/packages/react-shopper-hooks/src/store/types/store-context-types.ts +++ b/packages/react-shopper-hooks/src/store/types/store-context-types.ts @@ -5,7 +5,6 @@ import { NavigationNode } from "@elasticpath/shopper-common" export interface StoreProviderProps { initialState?: InitialState children: ReactNode - cartId?: string } export interface InitialState { diff --git a/packages/react-shopper-hooks/src/stories/Cart.stories.tsx b/packages/react-shopper-hooks/src/stories/Cart.stories.tsx index 2c959280..1c1a212f 100644 --- a/packages/react-shopper-hooks/src/stories/Cart.stories.tsx +++ b/packages/react-shopper-hooks/src/stories/Cart.stories.tsx @@ -3,7 +3,7 @@ import React from "react" import Layout from "./components/Layout" import { useGetCart } from "../cart/hooks/use-get-cart" -import { CartProvider, useCart } from "../cart" +import { useCart } from "../cart" import { CartItem } from "@moltin/sdk" import { useCartUpdateItem } from "../cart/hooks/use-cart-update-item" import { useCartRemoveItem } from "../cart/hooks/use-cart-remove-item" @@ -13,7 +13,7 @@ const Cart = ({ showHookData, id }: { showHookData: boolean; id: string }) => { return (

Cart: {id}

-

{data?.id}

+

{data?.data.id}

) } @@ -102,23 +102,25 @@ const CartUsingProvider = ({ showHookData: boolean id: string }) => { - const { state } = useCart() + const { data } = useCart() return (

Cart: {id}

-
    - {(state as any)?.items?.map((item: CartItem) => { - return - })} -
+ {!data ? ( +

Loading...

+ ) : ( +
    + {data.state?.items.map((item: CartItem) => { + return + })}{" "} +
+ )}
) } export const CartProv = (args: { showHookData: boolean; id: string }) => ( - - - + ) CartProv.argTypes = { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d336a7a1..1def425c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1264,6 +1264,9 @@ importers: '@tanstack/react-query': specifier: ^5.17.15 version: 5.17.15(react@18.2.0) + '@tanstack/react-query-devtools': + specifier: ^5.32.1 + version: 5.32.1(@tanstack/react-query@5.17.15)(react@18.2.0) '@types/js-cookie': specifier: ^3.0.6 version: 3.0.6 @@ -1676,7 +1679,6 @@ packages: dependencies: '@babel/highlight': 7.23.4 chalk: 2.4.2 - dev: true /@babel/compat-data@7.23.2: resolution: {integrity: sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==} @@ -1685,7 +1687,6 @@ packages: /@babel/compat-data@7.23.5: resolution: {integrity: sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==} engines: {node: '>=6.9.0'} - dev: true /@babel/core@7.23.2: resolution: {integrity: sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==} @@ -1752,7 +1753,6 @@ packages: semver: 6.3.1 transitivePeerDependencies: - supports-color - dev: true /@babel/generator@7.23.0: resolution: {integrity: sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==} @@ -1780,7 +1780,6 @@ packages: '@jridgewell/gen-mapping': 0.3.3 '@jridgewell/trace-mapping': 0.3.21 jsesc: 2.5.2 - dev: true /@babel/helper-annotate-as-pure@7.22.5: resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} @@ -1813,7 +1812,6 @@ packages: browserslist: 4.22.2 lru-cache: 5.1.1 semver: 6.3.1 - dev: true /@babel/helper-create-class-features-plugin@7.22.15(@babel/core@7.23.2): resolution: {integrity: sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==} @@ -2038,7 +2036,6 @@ packages: '@babel/helper-simple-access': 7.22.5 '@babel/helper-split-export-declaration': 7.22.6 '@babel/helper-validator-identifier': 7.22.20 - dev: true /@babel/helper-optimise-call-expression@7.22.5: resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} @@ -2155,7 +2152,6 @@ packages: /@babel/helper-validator-option@7.23.5: resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} engines: {node: '>=6.9.0'} - dev: true /@babel/helper-wrap-function@7.22.20: resolution: {integrity: sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==} @@ -2194,7 +2190,6 @@ packages: '@babel/types': 7.23.6 transitivePeerDependencies: - supports-color - dev: true /@babel/highlight@7.22.20: resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==} @@ -2240,7 +2235,6 @@ packages: hasBin: true dependencies: '@babel/types': 7.23.6 - dev: true /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.22.15(@babel/core@7.23.2): resolution: {integrity: sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==} @@ -2822,7 +2816,6 @@ packages: dependencies: '@babel/core': 7.23.7 '@babel/helper-plugin-utils': 7.22.5 - dev: true /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.23.2): resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} @@ -3990,7 +3983,7 @@ packages: '@babel/core': 7.23.3 '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.23.3) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.23.7) /@babel/plugin-transform-optional-chaining@7.23.0(@babel/core@7.23.7): resolution: {integrity: sha512-sBBGXbLJjxTzLBF5rFWaikMnOGOk/BmK6vVByIdEggZ7Vn6CvWXZyRkkLFK6WE0IF8jSliyOkUN6SScFgzCM0g==} @@ -5097,7 +5090,6 @@ packages: globals: 11.12.0 transitivePeerDependencies: - supports-color - dev: true /@babel/types@7.22.19: resolution: {integrity: sha512-P7LAw/LbojPzkgp5oznjE6tQEIWbp4PkkfrZDINTro9zgBRtI324/EYsiSI7lhPbpIQ+DCeR2NNmMWANGGfZsg==} @@ -5131,7 +5123,6 @@ packages: '@babel/helper-string-parser': 7.23.4 '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 - dev: true /@base2/pretty-print-object@1.0.1: resolution: {integrity: sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==} @@ -8589,7 +8580,6 @@ packages: dependencies: '@jridgewell/resolve-uri': 3.1.1 '@jridgewell/sourcemap-codec': 1.4.15 - dev: true /@jridgewell/trace-mapping@0.3.9: resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} @@ -12703,6 +12693,21 @@ packages: /@tanstack/query-core@5.17.15: resolution: {integrity: sha512-QURxpu77/ICA4d61aPvV7EcJ2MwmksxUejKBaq/xLcO2TUJAlXf4PFKHC/WxnVFI/7F1jeLx85AO3Vpk0+uBXw==} + /@tanstack/query-devtools@5.32.1: + resolution: {integrity: sha512-7Xq57Ctopiy/4atpb0uNY5VRuCqRS/1fi/WBCKKX6jHMa6cCgDuV/AQuiwRXcKARbq2OkVAOrW2v4xK9nTbcCA==} + dev: true + + /@tanstack/react-query-devtools@5.32.1(@tanstack/react-query@5.17.15)(react@18.2.0): + resolution: {integrity: sha512-NjNRPgCReZxgY5f56gnoTCR47NznHlQR4w2cW/W8B0QY8afkbPPnRlfzofs2SwdFW7F37Ysgjm8jtolPTzfa2Q==} + peerDependencies: + '@tanstack/react-query': ^5.32.1 + react: ^18.0.0 + dependencies: + '@tanstack/query-devtools': 5.32.1 + '@tanstack/react-query': 5.17.15(react@18.2.0) + react: 18.2.0 + dev: true + /@tanstack/react-query@5.17.15(react@18.2.0): resolution: {integrity: sha512-9qur91mOihaUN7pXm6ioDtS+4qgkBcCiIaZyvi3lZNcQZsrMGCYZ+eP3hiFrV4khoJyJrFUX1W0NcCVlgwNZxQ==} peerDependencies: @@ -15435,7 +15440,6 @@ packages: electron-to-chromium: 1.4.637 node-releases: 2.0.14 update-browserslist-db: 1.0.13(browserslist@4.22.2) - dev: true /bs-logger@0.2.6: resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} @@ -15701,7 +15705,6 @@ packages: /caniuse-lite@1.0.30001579: resolution: {integrity: sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==} - dev: true /capital-case@1.0.4: resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==} @@ -17736,7 +17739,6 @@ packages: /electron-to-chromium@1.4.637: resolution: {integrity: sha512-G7j3UCOukFtxVO1vWrPQUoDk3kL70mtvjc/DC/k2o7lE0wAdq+Vwp1ipagOow+BH0uVztFysLWbkM/RTIrbK3w==} - dev: true /elegant-spinner@1.0.1: resolution: {integrity: sha512-B+ZM+RXvRqQaAmkMlO/oSe5nMUOaUnyfGYCEHoR8wrXsZR2mA0XVibsxV1bvTwxdRWah1PkQqso2EzhILGHtEQ==} @@ -25242,7 +25244,6 @@ packages: /node-releases@2.0.14: resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} - dev: true /node-source-walk@5.0.2: resolution: {integrity: sha512-Y4jr/8SRS5hzEdZ7SGuvZGwfORvNsSsNRwDXx5WisiqzsVfeftDvRgfeqWNgZvWSJbgubTRVRYBzK6UO+ErqjA==} @@ -26339,7 +26340,7 @@ packages: optional: true dependencies: lilconfig: 2.1.0 - ts-node: 10.9.1(@types/node@18.7.3)(typescript@4.9.5) + ts-node: 10.9.1(@types/node@18.7.3)(typescript@5.3.3) yaml: 1.10.2 dev: true @@ -31048,7 +31049,6 @@ packages: browserslist: 4.22.2 escalade: 3.1.1 picocolors: 1.0.0 - dev: true /update-notifier@6.0.2: resolution: {integrity: sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==}