Updated types for hooks now using the API

This commit is contained in:
Luis Alvarez 2021-03-29 11:25:21 -06:00
parent d3fe16e1d7
commit 8ad6a34175
5 changed files with 67 additions and 69 deletions

View File

@ -1,17 +1,12 @@
import { useMemo } from 'react' import { useMemo } from 'react'
import { SWRHook } from '@commerce/utils/types' import { SWRHook } from '@commerce/utils/types'
import useCart, { UseCart, FetchCartInput } from '@commerce/cart/use-cart' import useCart, { UseCart } from '@commerce/cart/use-cart'
import { normalizeCart } from '../lib/normalize' import { normalizeCart } from '../lib/normalize'
import type { Cart } from '../types' import type { GetCartHook } from '../types/cart'
export default useCart as UseCart<typeof handler> export default useCart as UseCart<typeof handler>
export const handler: SWRHook< export const handler: SWRHook<GetCartHook> = {
Cart | null,
{},
FetchCartInput,
{ isEmpty?: boolean }
> = {
fetchOptions: { fetchOptions: {
url: '/api/bigcommerce/cart', url: '/api/bigcommerce/cart',
method: 'GET', method: 'GET',

View File

@ -1,17 +1,14 @@
import { useHook, useMutationHook } from '../utils/use-hook' import { useHook, useMutationHook } from '../utils/use-hook'
import { mutationFetcher } from '../utils/default-fetcher' import { mutationFetcher } from '../utils/default-fetcher'
import type { HookFetcherFn, MutationHook } from '../utils/types' import type { HookFetcherFn, MutationHook } from '../utils/types'
import type { Cart, CartItemBody, AddCartItemBody } from '../types' import type { AddItemHook } from '../types/cart'
import type { Provider } from '..' import type { Provider } from '..'
export type UseAddItem< export type UseAddItem<
H extends MutationHook<any, any, any> = MutationHook<Cart, {}, CartItemBody> H extends MutationHook<AddItemHook> = MutationHook<AddItemHook>
> = ReturnType<H['useHook']> > = ReturnType<H['useHook']>
export const fetcher: HookFetcherFn< export const fetcher: HookFetcherFn<AddItemHook> = mutationFetcher
Cart,
AddCartItemBody<CartItemBody>
> = mutationFetcher
const fn = (provider: Provider) => provider.cart?.useAddItem! const fn = (provider: Provider) => provider.cart?.useAddItem!

View File

@ -1,23 +1,14 @@
import Cookies from 'js-cookie' import Cookies from 'js-cookie'
import { useHook, useSWRHook } from '../utils/use-hook' import { useHook, useSWRHook } from '../utils/use-hook'
import type { HookFetcherFn, SWRHook } from '../utils/types' import type { SWRHook, HookFetcherFn } from '../utils/types'
import type { Cart } from '../types/cart' import type { GetCartHook } from '../types/cart'
import { Provider, useCommerce } from '..' import { Provider, useCommerce } from '..'
export type FetchCartInput = {
cartId?: Cart['id']
}
export type UseCart< export type UseCart<
H extends SWRHook<any, any, any> = SWRHook< H extends SWRHook<GetCartHook> = SWRHook<GetCartHook>
Cart | null,
{},
FetchCartInput,
{ isEmpty?: boolean }
>
> = ReturnType<H['useHook']> > = ReturnType<H['useHook']>
export const fetcher: HookFetcherFn<Cart | null, FetchCartInput> = async ({ export const fetcher: HookFetcherFn<GetCartHook> = async ({
options, options,
input: { cartId }, input: { cartId },
fetch, fetch,

View File

@ -94,11 +94,16 @@ export type CartHooks = {
export type GetCartHook = { export type GetCartHook = {
data: Cart | null data: Cart | null
input: {}
fetchInput: { cartId?: string }
swrState: { isEmpty: boolean }
} }
export type AddItemHook = { export type AddItemHook = {
data: Cart data: Cart
body: { item: CartItemBody } body: { item: CartItemBody }
input: CartItemBody
fetchInput: { item: CartItemBody }
} }
export type UpdateItemHook = { export type UpdateItemHook = {

View File

@ -36,9 +36,13 @@ export type HookFetcher<Data, Input = null, Result = any> = (
fetch: <T = Result, Body = any>(options: FetcherOptions<Body>) => Promise<T> fetch: <T = Result, Body = any>(options: FetcherOptions<Body>) => Promise<T>
) => Data | Promise<Data> ) => Data | Promise<Data>
export type HookFetcherFn<Data, Input = undefined, Result = any, Body = any> = ( export type HookFetcherFn<
context: HookFetcherContext<Input, Result, Body> H extends HookSchemaBase,
) => Data | Promise<Data> Result = any,
Body = any
> = (
context: HookFetcherContext<H['fetchInput'], Result, Body>
) => H['data'] | Promise<H['data']>
export type HookFetcherContext<Input = undefined, Result = any, Body = any> = { export type HookFetcherContext<Input = undefined, Result = any, Body = any> = {
options: HookFetcherOptions options: HookFetcherOptions
@ -58,7 +62,7 @@ export type HookSWRInput = [string, HookInputValue][]
export type HookFetchInput = { [k: string]: HookInputValue } export type HookFetchInput = { [k: string]: HookInputValue }
export type HookFunction< export type HookFunction<
Input extends { [k: string]: unknown } | null, Input extends { [k: string]: unknown } | undefined,
T T
> = keyof Input extends never > = keyof Input extends never
? () => T ? () => T
@ -66,62 +70,68 @@ export type HookFunction<
? (input?: Input) => T ? (input?: Input) => T
: (input: Input) => T : (input: Input) => T
export type SWRHook< export type HookSchemaBase = {
// Data obj returned by the hook and fetch operation // Data obj returned by the hook and fetch operation
Data, data: any
// Input expected by the hook // Input expected by the hook
Input extends { [k: string]: unknown } = {}, input: {}
// Input expected before doing a fetch operation // Input expected before doing a fetch operation
FetchInput extends HookFetchInput = {}, fetchInput?: {}
}
export type SWRHookSchemaBase = HookSchemaBase & {
// Custom state added to the response object of SWR // Custom state added to the response object of SWR
State = {} swrState: {}
> = { }
export type MutationSchemaBase = HookSchemaBase & {
// Input expected by the action returned by the hook
actionInput?: {}
}
/**
* Generates a SWR hook handler based on the schema of a hook
*/
export type SWRHook<H extends SWRHookSchemaBase> = {
useHook( useHook(
context: SWRHookContext<Data, FetchInput> context: SWRHookContext<H>
): HookFunction< ): HookFunction<
Input & { swrOptions?: SwrOptions<Data, FetchInput> }, H['input'] & { swrOptions?: SwrOptions<H['data'], H['fetchInput']> },
ResponseState<Data> & State ResponseState<H['data']> & H['swrState']
> >
fetchOptions: HookFetcherOptions fetchOptions: HookFetcherOptions
fetcher?: HookFetcherFn<Data, FetchInput> fetcher?: HookFetcherFn<H>
} }
export type SWRHookContext< type X = {} & undefined
Data,
FetchInput extends { [k: string]: unknown } = {} export type SWRHookContext<H extends SWRHookSchemaBase> = {
> = {
useData(context?: { useData(context?: {
input?: HookFetchInput | HookSWRInput input?: HookFetchInput | HookSWRInput
swrOptions?: SwrOptions<Data, FetchInput> swrOptions?: SwrOptions<H['data'], H['fetchInput']>
}): ResponseState<Data> }): ResponseState<H['data']>
} }
export type MutationHook< /**
// Data obj returned by the hook and fetch operation * Generates a mutation hook handler based on the schema of a hook
Data, */
// Input expected by the hook export type MutationHook<H extends MutationSchemaBase> = {
Input extends { [k: string]: unknown } = {},
// Input expected by the action returned by the hook
ActionInput extends { [k: string]: unknown } = {},
// Input expected before doing a fetch operation
FetchInput extends { [k: string]: unknown } = ActionInput
> = {
useHook( useHook(
context: MutationHookContext<Data, FetchInput> context: MutationHookContext<H>
): HookFunction<Input, HookFunction<ActionInput, Data | Promise<Data>>> ): HookFunction<
H['input'],
HookFunction<H['actionInput'], H['data'] | Promise<H['data']>>
>
fetchOptions: HookFetcherOptions fetchOptions: HookFetcherOptions
fetcher?: HookFetcherFn<Data, FetchInput> fetcher?: HookFetcherFn<H['data'], H['fetchInput']>
} }
export type MutationHookContext< export type MutationHookContext<H extends MutationSchemaBase> = {
Data, fetch: keyof H['fetchInput'] extends never
FetchInput extends { [k: string]: unknown } | null = {} ? () => H['data'] | Promise<H['data']>
> = { : Partial<H['fetchInput']> extends H['fetchInput']
fetch: keyof FetchInput extends never ? (context?: { input?: H['fetchInput'] }) => H['data'] | Promise<H['data']>
? () => Data | Promise<Data> : (context: { input: H['fetchInput'] }) => H['data'] | Promise<H['data']>
: Partial<FetchInput> extends FetchInput
? (context?: { input?: FetchInput }) => Data | Promise<Data>
: (context: { input: FetchInput }) => Data | Promise<Data>
} }
export type SwrOptions<Data, Input = null, Result = any> = ConfigInterface< export type SwrOptions<Data, Input = null, Result = any> = ConfigInterface<