Skip to content

Commit

Permalink
Update React package
Browse files Browse the repository at this point in the history
  • Loading branch information
b3hr4d committed Feb 16, 2024
1 parent 17bc5f2 commit 6f7ec5e
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 239 deletions.
21 changes: 0 additions & 21 deletions packages/react/src/context/actor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,20 +89,9 @@ export const createReActorContext: CreateReActorContext = <
args: ActorUseMethodCallArg<Actor, T>
) => useActor().useMethodCall(args)

const useServiceFields = () => useActor().useServiceFields()

const useMethodFields = () => useActor().useMethodFields()

const useMethodField = (functionName: keyof Actor & string) =>
useActor().useMethodField(functionName)

const useServiceDetails = () => useActor().useServiceDetails()

const useMethodDetails = () => useActor().useMethodDetails()

const useMethodDetail = (functionName: keyof Actor & string) =>
useActor().useMethodDetail(functionName)

return {
ActorContext,
ActorProvider,
Expand All @@ -111,12 +100,7 @@ export const createReActorContext: CreateReActorContext = <
useQueryCall,
useUpdateCall,
useMethodCall,
useServiceFields,
useMethodFields,
useMethodField,
useServiceDetails,
useMethodDetails,
useMethodDetail,
} as any
}

Expand All @@ -128,10 +112,5 @@ export const {
useQueryCall,
useUpdateCall,
useMethodCall,
useServiceFields,
useMethodFields,
useMethodField,
useServiceDetails,
useMethodDetails,
useMethodDetail,
} = createReActorContext()
54 changes: 11 additions & 43 deletions packages/react/src/context/actor/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React, { PropsWithChildren } from "react"
import { IDL } from "@dfinity/candid"
import {
ActorSubclass,
Expand All @@ -10,55 +9,25 @@ import { ActorHooks } from "../../types"

export type ActorContextType<
Actor = ActorSubclass<any>,
F extends boolean = true,
D extends boolean = true
> = ActorHooks<Actor, F, D> & {
ActorContext: React.Context<ActorContextType<Actor, F, D> | null>
useActor: <A extends ActorSubclass<any> = Actor>() => ActorContextType<
A,
F,
D
>
ActorProvider: React.FC<
ActorProviderProps & {
withServiceFields?: F
withServiceDetails?: D
}
>
F extends boolean = true
> = ActorHooks<Actor, F> & {
ActorContext: React.Context<ActorContextType<Actor, F> | null>
useActor: <A extends ActorSubclass<any> = Actor>() => ActorContextType<A>
ActorProvider: React.FC<ActorProviderProps>
}

export type CreateReActorContext = {
// When both withServiceFields and withServiceDetails are true
<A extends ActorSubclass<any> = DefaultActorType>(
options?: Partial<CreateActorOptions> & {
withServiceFields: true
withServiceDetails: true
}
): ActorContextType<A, true, true>

// When withServiceFields is true and withServiceDetails is false or undefined
<A extends ActorSubclass<any> = DefaultActorType>(
options?: Partial<CreateActorOptions> & {
withServiceFields: true
withServiceDetails?: false | undefined
}
): ActorContextType<A, true, false>

// When withServiceFields is false or undefined and withServiceDetails is true
<A extends ActorSubclass<any> = DefaultActorType>(
options?: Partial<CreateActorOptions> & {
withServiceFields?: false | undefined
withServiceDetails: true
withVisitor: true
}
): ActorContextType<A, false, true>
): ActorContextType<A, true>

// When both withServiceFields and withServiceDetails are false or undefined
<A extends ActorSubclass<any> = DefaultActorType>(
options?: Partial<CreateActorOptions> & {
withServiceFields?: false | undefined
withServiceDetails?: false | undefined
withVisitor?: false | undefined
}
): ActorContextType<A, false, false>
): ActorContextType<A, false>
}

export interface CreateActorOptions
Expand All @@ -73,8 +42,7 @@ export interface CreateActorOptions
loadingComponent?: React.ReactNode
}

export interface ActorProviderProps
extends PropsWithChildren,
CreateActorOptions {
export interface ActorProviderProps extends CreateActorOptions {
children?: React.ReactNode | undefined
loadingComponent?: React.ReactNode
}
203 changes: 62 additions & 141 deletions packages/react/src/hooks/actor.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,17 @@
import {
type ExtractedServiceFields,
type MethodFields,
type ExtractedServiceDetails,
type ServiceDetails,
type MethodDetails,
ExtractRandomArgs,
ExtractRandomReturns,
} from "@ic-reactor/candid"
import { useCallback, useEffect, useMemo, useRef, useState } from "react"
import {
ActorHookState,
type ActorCall,
type ActorHooks,
type ActorUseMethodCallArg,
type ActorUseMethodCallReturn,
type UseActorStoreReturn,
ActorQueryCall,
ActorUpdateCall,
ActorHooks,
ActorUseMethodCallReturn,
ActorUseMethodCallArg,
} from "../types"
import { useStore } from "zustand"
import { ActorCandidManager } from "@ic-reactor/candid"
import {
ExtractActorMethodArgs,
FunctionName,
FunctionType,
} from "@ic-reactor/store"
import { ActorManager, ExtractedService, FunctionType } from "@ic-reactor/store"
import { ExtractActorMethodArgs, FunctionName } from "@ic-reactor/store"

const DEFAULT_STATE = {
data: undefined,
Expand All @@ -34,76 +21,29 @@ const DEFAULT_STATE = {

export const getActorHooks = <A>({
initialize,
serviceFields,
serviceDetails,
withServiceFields,
withServiceDetails,
visitFunction,
canisterId,
actorStore,
callMethod,
transformResult,
}: ActorCandidManager<A>): ActorHooks<
A,
typeof withServiceFields,
typeof withServiceDetails
> => {
type F = typeof withServiceFields
type D = typeof withServiceDetails

}: ActorManager<A>): ActorHooks<A, true> => {
const useActorStore = (): UseActorStoreReturn<A> => {
const actorState = useStore(actorStore, (state) => state)

return { ...actorState, canisterId } as UseActorStoreReturn<A>
}

const useServiceFields = (): ExtractedServiceFields<A> => {
if (!withServiceFields || !serviceFields) {
throw new Error(
"Service fields not initialized. Pass `withServiceFields` to initialize service fields."
)
}

return serviceFields
}

const useMethodFields = (): MethodFields<A>[] => {
const serviceFields = useServiceFields()

return useMemo(() => {
return Object.values(serviceFields.methodFields)
}, [serviceFields])
const useVisitFunction = (): ExtractedService<A> => {
return visitFunction
}

const useMethodField = (functionName: FunctionName<A>): MethodFields<A> => {
const serviceMethod = useServiceFields()
const useMethodField = <M extends FunctionName<A>>(
functionName: M
): ExtractedService<A>[M] => {
const serviceFields = useVisitFunction()

return useMemo(() => {
return serviceMethod.methodFields[functionName]
}, [functionName, serviceMethod])
}

const useServiceDetails = (): ExtractedServiceDetails<A> => {
if (!withServiceDetails || !serviceDetails) {
throw new Error(
"Service details not initialized. Pass `withServiceDetails` to initialize service fields."
)
}

return serviceDetails
}

const useMethodDetails = (): ServiceDetails<A> => {
const serviceFields = useServiceDetails()

return serviceFields.methodDetails
}

const useMethodDetail = (functionName: FunctionName<A>): MethodDetails<A> => {
const serviceMethod = useServiceDetails()

return useMemo(() => {
return serviceMethod.methodDetails[functionName]
}, [functionName, serviceMethod])
return serviceFields[functionName]
}, [functionName, serviceFields])
}

const useReActorCall: ActorCall<A> = ({
Expand All @@ -112,7 +52,6 @@ export const getActorHooks = <A>({
onLoading,
args = [] as unknown as ExtractActorMethodArgs<A[any]>,
functionName,
withTransform,
throwOnError = false,
}) => {
type M = typeof functionName
Expand Down Expand Up @@ -141,17 +80,10 @@ export const getActorHooks = <A>({
: undefined
: undefined

const result = await callMethod(
functionName,
...(replaceArgs ?? args)
)

const data = withTransform
? transformResult(functionName, result)
: result
const data = await callMethod(functionName, ...(replaceArgs ?? args))

onLoading?.(false)
onSuccess?.(result)
onSuccess?.(data)
setState((prevState) => ({ ...prevState, data, loading: false }))

return data
Expand Down Expand Up @@ -210,68 +142,57 @@ export const getActorHooks = <A>({

const useMethodCall = <M extends FunctionName<A>, T extends FunctionType>(
args: ActorUseMethodCallArg<A, T>
): ActorUseMethodCallReturn<A, M, F, D> => {
const { functionName } = args

const field = useMemo(
() => serviceFields?.methodFields[functionName],
[functionName]
) as MethodFields<A>

const detail = useMemo(
() => serviceDetails?.methodDetails[functionName],
[functionName]
) as MethodDetails<A>

const generateArgs = useCallback(() => {
const randomClass = new ExtractRandomArgs()
return randomClass.generate(field.argTypes, functionName)
}, [field, functionName])

const generateReturns = useCallback(() => {
const randomClass = new ExtractRandomReturns()
const data = randomClass.generate(field.returnTypes)
console.log("generateReturns", data, field.returnTypes)
return transformResult(functionName, data.length > 1 ? data : data[0])
}, [field, functionName])

const type = field.functionType ?? detail.functionType

switch (type) {
case "query":
return {
field,
detail,
generateArgs,
generateReturns,
...useQueryCall<M>(args as any),
}
case "update":
return {
field,
detail,
generateArgs,
generateReturns,
...useUpdateCall<M>(args as any),
}
default:
throw new Error(`Invalid type: ${type}`)
}
): ActorUseMethodCallReturn<A, M, true> => {
// const { functionName } = args
// const field = useMemo(
// () => serviceFields?.methodFields[functionName],
// [functionName]
// ) as MethodFields<A>
// const detail = useMemo(
// () => serviceDetails?.methodDetails[functionName],
// [functionName]
// ) as MethodDetails<A>
// const generateArgs = useCallback(() => {
// const randomClass = new ExtractRandomArgs()
// return randomClass.generate(field.argTypes, functionName)
// }, [field, functionName])
// const generateReturns = useCallback(() => {
// const randomClass = new ExtractRandomReturns()
// const data = randomClass.generate(field.returnTypes)
// console.log("generateReturns", data, field.returnTypes)
// return transformResult(functionName, data.length > 1 ? data : data[0])
// }, [field, functionName])
// const type = field.functionType ?? detail.functionType
// switch (type) {
// case "query":
// return {
// field,
// detail,
// generateArgs,
// generateReturns,
// ...useQueryCall<M>(args as any),
// }
// case "update":
// return {
// field,
// detail,
// generateArgs,
// generateReturns,
// ...useUpdateCall<M>(args as any),
// }
// default:
// throw new Error(`Invalid type: ${type}`)
// }

return { args } as any
}

return {
initialize,
useQueryCall,
useUpdateCall,
useMethodCall,
useActorStore,
// __Details
useServiceDetails,
useMethodDetails,
useMethodDetail,
// __Fields
useServiceFields,
useMethodFields,
useMethodField,
useActorStore,
useMethodCall,
}
}
Loading

0 comments on commit 6f7ec5e

Please sign in to comment.