Skip to content

Commit

Permalink
Update imports and configurations
Browse files Browse the repository at this point in the history
  • Loading branch information
b3hr4d committed Feb 18, 2024
1 parent 0e3991f commit 0ee8ef9
Show file tree
Hide file tree
Showing 30 changed files with 406 additions and 289 deletions.
6 changes: 1 addition & 5 deletions packages/core/babel.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
module.exports = {
presets: [
"@babel/preset-env",
["@babel/preset-react", { runtime: "automatic" }],
"@babel/preset-typescript",
],
presets: ["@babel/preset-env", "@babel/preset-typescript"],
}
2 changes: 1 addition & 1 deletion packages/core/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module.exports = {
transform: {
"^.+\\.[t|j]sx?$": "babel-jest",
"^.+\\.[t|j]s": "babel-jest",
},
preset: "ts-jest",
testEnvironment: "node",
Expand Down
12 changes: 7 additions & 5 deletions packages/core/jest.setup.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import fetch from "node-fetch"

if (!globalThis.fetch) {
globalThis.fetch = fetch
}
import { Crypto } from "@peculiar/webcrypto"
import "fake-indexeddb/auto"
global.crypto = new Crypto()
global.TextEncoder = require("text-encoding").TextEncoder
global.TextDecoder = require("text-encoding").TextDecoder
require("whatwg-fetch")
global.XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest
84 changes: 39 additions & 45 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/* eslint-disable no-console */
import type {
ActorMethodState,
ActorSubclass,
CreateReActorOptions,
FunctionName,
DefaultActorType,
BaseActor,
ActorMethodArgs,
} from "@ic-reactor/store"
import { createReActorStore, generateRequestHash } from "@ic-reactor/store"
import {
Expand All @@ -15,51 +16,43 @@ import {
ActorUpdate,
} from "./types"

export const createReActor = <A extends ActorSubclass<any> = DefaultActorType>(
options: CreateReActorOptions
) => {
export const createReActor = <A = BaseActor>(options: CreateReActorOptions) => {
const { agentManager, callMethod, actorStore, ...rest } =
createReActorStore<A>(options)

const { authStore, ...agentRest } = agentManager

const updateMethodState = <M extends FunctionName<A>>(
method: M,
args: any[] = [],
newState?: Partial<ActorMethodState<A, M>[string]>
args: ActorMethodArgs<A[M]>,
newState: Partial<ActorMethodState<A, M>[string]> = {}
) => {
const hash = generateRequestHash(args)

actorStore.setState((state) => {
if (!state.methodState) {
console.error("Actor not initialized")
return state
}

if (!state.methodState[method]) {
console.error(`Method ${String(method)} not found`)
return state
}

const currentMethodState = state.methodState[method][hash] || {
// Initialize method state if not already present
const methodState = state.methodState[method] || {}
// Initialize specific hash state if not already present
const hashState = methodState[hash] || {
loading: false,
data: undefined,
error: undefined,
}

return {
// Update the state with newState values
const updatedHashState = { ...hashState, ...newState }

// Construct the updated state to return
const updatedState = {
...state,
methodState: {
...state.methodState,
[method]: {
...state.methodState[method],
[hash]: {
...currentMethodState,
...newState,
},
...methodState,
[hash]: updatedHashState,
},
},
}

return updatedState
})

return hash
Expand All @@ -70,9 +63,7 @@ export const createReActor = <A extends ActorSubclass<any> = DefaultActorType>(
try {
const requestHash = updateMethodState(functionName, args)

const getState: ActorGetStateFunction<A, M> = (
key?: "data" | "loading" | "error"
) => {
const getState = ((key?: "data" | "loading" | "error") => {
const state =
actorStore.getState().methodState[functionName][requestHash]

Expand All @@ -84,9 +75,9 @@ export const createReActor = <A extends ActorSubclass<any> = DefaultActorType>(
case "error":
return state.error
default:
return state as any
return state
}
}
}) as ActorGetStateFunction<A, M>

const subscribe: ActorSubscribeFunction<A, M> = (callback) => {
const unsubscribe = actorStore.subscribe((state) => {
Expand Down Expand Up @@ -118,8 +109,7 @@ export const createReActor = <A extends ActorSubclass<any> = DefaultActorType>(
error: error as Error,
loading: false,
})

console.error(error)
throw error
}
}

Expand All @@ -142,35 +132,39 @@ export const createReActor = <A extends ActorSubclass<any> = DefaultActorType>(
const queryCall: ActorQuery<A> = ({
functionName,
args = [],
callOnMount = false,
autoRefresh = false,
refreshInterval = 5000,
refetchOnMount = true,
refetchInterval = false,
}) => {
let intervalId: NodeJS.Timeout | null = null
const { call, ...rest } = reActorMethod(functionName, ...(args as any))
const { call, ...rest } = reActorMethod(
functionName,
...(args as ActorMethodArgs<A[typeof functionName]>)
)

if (autoRefresh) {
if (refetchInterval) {
intervalId = setInterval(() => {
call()
}, refreshInterval)
}, refetchInterval)
}

let initialData = Promise.resolve() as ReturnType<typeof call>
if (callOnMount) initialData = call()
let dataPromise = Promise.resolve() as ReturnType<typeof call>
if (refetchOnMount) dataPromise = call()

return { ...rest, call, initialData, intervalId }
return { ...rest, call, dataPromise, intervalId }
}

const updateCall: ActorUpdate<A> = ({ functionName, args = [] }) => {
return reActorMethod(functionName, ...(args as any))
return reActorMethod(
functionName,
...(args as ActorMethodArgs<A[typeof functionName]>)
)
}

return {
actorStore,
authStore,
queryCall,
updateCall,
...agentRest,
agentManager,
...rest,
}
}
23 changes: 11 additions & 12 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import type {
ActorMethod,
ExtractActorMethodArgs,
ExtractActorMethodReturnType,
ActorMethodArgs,
ActorMethodReturnType,
ActorMethodState,
FunctionName,
} from "@ic-reactor/store"

export type ActorGetStateFunction<A, M extends FunctionName<A>> = {
(key: "data"): ExtractActorMethodReturnType<A[M]> | undefined
(key: "data"): ActorMethodReturnType<A[M]>
(key: "loading"): boolean
(key: "error"): Error | undefined
(): ActorMethodState<A, M>[string]
Expand All @@ -18,8 +18,8 @@ export type ActorSubscribeFunction<A, M extends FunctionName<A>> = (
) => () => void

export type ActorCallFunction<A, M extends FunctionName<A>> = (
replaceArgs?: ExtractActorMethodArgs<A[M]>
) => Promise<ExtractActorMethodReturnType<A[M]> | undefined>
replaceArgs?: ActorMethodArgs<A[M]>
) => Promise<ActorMethodReturnType<A[M]>>

// Type for the return value of a Actor call
export type ActorQueryReturn<A, M extends FunctionName<A>> = {
Expand All @@ -28,7 +28,7 @@ export type ActorQueryReturn<A, M extends FunctionName<A>> = {
getState: ActorGetStateFunction<A, M>
subscribe: ActorSubscribeFunction<A, M>
call: ActorCallFunction<A, M>
initialData: Promise<ExtractActorMethodReturnType<A[M]> | undefined>
dataPromise: Promise<ActorMethodReturnType<A[M]>>
}

export type ActorUpdateReturn<A, M extends FunctionName<A>> = {
Expand All @@ -40,23 +40,22 @@ export type ActorUpdateReturn<A, M extends FunctionName<A>> = {

export type ActorQueryArgs<A, M extends FunctionName<A>> = {
functionName: M
args?: ExtractActorMethodArgs<A[M]>
callOnMount?: boolean
autoRefresh?: boolean
refreshInterval?: number
args?: ActorMethodArgs<A[M]>
refetchOnMount?: boolean
refetchInterval?: number | false
}

export type ActorUpdateArgs<A, M extends FunctionName<A>> = {
functionName: M
args?: ExtractActorMethodArgs<A[M]>
args?: ActorMethodArgs<A[M]>
}

// Function type for calling a Actor method
export type ActorMethodCall<A = Record<string, ActorMethod>> = <
M extends FunctionName<A>
>(
functionName: M,
...args: ExtractActorMethodArgs<A[M]>
...args: ActorMethodArgs<A[M]>
) => ActorUpdateReturn<A, M>

export type ActorQuery<A = Record<string, ActorMethod>> = <
Expand Down
16 changes: 9 additions & 7 deletions packages/core/test/actor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Cbor } from "@dfinity/agent"
import { IDL } from "@dfinity/candid"
import fetchMock from "jest-fetch-mock"
import { createReActor } from "../src"
import { idlFactory, canisterId } from "./candid/hello"
import { hello, idlFactory } from "./candid/hello"

fetchMock.enableMocks()

Expand Down Expand Up @@ -32,9 +32,11 @@ fetchMock.mockResponse(async (req) => {
describe("Initialize", () => {
const callback = jest.fn()

const { initialize, actorStore, updateCall, queryCall } = createReActor({
const { initialize, actorStore, updateCall, queryCall } = createReActor<
typeof hello
>({
idlFactory,
canisterId,
canisterId: "aaaaa-aa",
initializeOnCreate: false,
verifyQuerySignatures: false,
host: "https://local-mock",
Expand All @@ -53,15 +55,15 @@ describe("Initialize", () => {
})

it("should queryCall the query method", async () => {
const { requestHash, initialData, call, getState } = queryCall({
const { requestHash, dataPromise, call, getState } = queryCall({
functionName: "greet",
args: ["World"],
})
expect(requestHash).toEqual(
"c102685369c5e29182d7457bd5af52486928280f000dfe641db598b82c5753e0"
"0xc102685369c5e29182d7457bd5af52486928280f000dfe641db598b82c5753e0"
)

const data = await initialData
const data = await dataPromise
expect(data).toEqual(canisterDecodedReturnValue)

expect(getState()).toEqual({
Expand All @@ -85,7 +87,7 @@ describe("Initialize", () => {
})

expect(requestHash).toEqual(
"c102685369c5e29182d7457bd5af52486928280f000dfe641db598b82c5753e0"
"0xc102685369c5e29182d7457bd5af52486928280f000dfe641db598b82c5753e0"
)

const loadingBefore = getState("loading")
Expand Down
66 changes: 66 additions & 0 deletions packages/core/test/candid/backend/backend.did
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
type AnonymousUserData = record {
texts : vec nat64;
created_at : nat64;
decryption_key : opt vec nat8
};
type AuthenticatedSignature = record {
signature : vec nat8;
created_at : nat64
};
type LogEntry = record {
counter : nat64;
file : text;
line : nat32;
cycle : opt nat;
version : text;
message : text;
timestamp : nat64;
"variant" : LogVariant
};
type LogVariant = variant { info; warn; error };
type OneTimeKey = record {
tries : nat8;
time_lock : nat64;
public_key : vec nat8
};
type PartitionDetail = record { id : nat8; name : text; size : nat64 };
type Result = variant { Ok : record { vec nat8; vec nat8 }; Err : text };
type Task = variant {
CleanUpKeys;
SendText : record { body : text; phone_number : text };
CleanUpAnonymousUsers;
SendEmail : record { subject : text; body : text; email : text };
Initialize
};
type TaskTimerEntry = record { task : Task; time : nat64 };
type UserData = record {
texts : vec nat64;
signature : opt AuthenticatedSignature;
public_key : vec nat8
};
type UserText = record { id : text; "text" : vec nat8 };
service : () -> {
anonymous_user : (vec nat8) -> (AnonymousUserData) query;
anonymous_user_notes : (vec nat8) -> (vec UserText) query;
anonymous_users : () -> (vec record { vec nat8; AnonymousUserData }) query;
edit_encrypted_text : (nat64, vec nat8, opt vec nat8) -> ();
encrypted_ibe_decryption_key_for_caller : (vec nat8) -> (vec nat8);
encrypted_symmetric_key_for_caller : (vec nat8) -> (vec nat8);
encrypted_texts : () -> (vec UserText) query;
get_one_time_key : (nat64) -> (vec nat8) query;
get_one_time_key_details : (nat64) -> (OneTimeKey) query;
ibe_encryption_key : () -> (vec nat8) query;
partition_details : () -> (vec PartitionDetail) query;
print_log_entries : () -> (vec LogEntry) query;
print_log_entries_page : (nat64, opt nat64) -> (vec text) query;
read_with_one_time_key : (nat64, vec nat8, vec nat8) -> (Result);
request_two_factor_authentication : (vec nat8) -> (text);
save_encrypted_text : (vec nat8, opt vec nat8) -> (nat64);
set_one_time_key : (nat64, vec nat8) -> ();
symmetric_key_verification_key : () -> (vec nat8) query;
timers : () -> (vec TaskTimerEntry) query;
two_factor_verification_key : () -> (text);
user_data : () -> (UserData) query;
user_notes : (opt vec nat8) -> (nat64, vec UserText) query;
version : () -> (text) query
}
Loading

0 comments on commit 0ee8ef9

Please sign in to comment.