@ic-reactor/react 3.0.0-beta.8 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -10
- package/dist/createActorHooks.d.ts +2 -0
- package/dist/createActorHooks.d.ts.map +1 -1
- package/dist/createActorHooks.js +2 -0
- package/dist/createActorHooks.js.map +1 -1
- package/dist/createMutation.d.ts.map +1 -1
- package/dist/createMutation.js +4 -0
- package/dist/createMutation.js.map +1 -1
- package/dist/hooks/index.d.ts +18 -5
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +15 -5
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/useActorInfiniteQuery.d.ts +13 -11
- package/dist/hooks/useActorInfiniteQuery.d.ts.map +1 -1
- package/dist/hooks/useActorInfiniteQuery.js.map +1 -1
- package/dist/hooks/useActorMethod.d.ts +105 -0
- package/dist/hooks/useActorMethod.d.ts.map +1 -0
- package/dist/hooks/useActorMethod.js +192 -0
- package/dist/hooks/useActorMethod.js.map +1 -0
- package/dist/hooks/useActorSuspenseInfiniteQuery.d.ts +13 -10
- package/dist/hooks/useActorSuspenseInfiniteQuery.d.ts.map +1 -1
- package/dist/hooks/useActorSuspenseInfiniteQuery.js.map +1 -1
- package/package.json +7 -6
- package/src/createActorHooks.ts +146 -0
- package/src/createAuthHooks.ts +137 -0
- package/src/createInfiniteQuery.ts +471 -0
- package/src/createMutation.ts +163 -0
- package/src/createQuery.ts +197 -0
- package/src/createSuspenseInfiniteQuery.ts +478 -0
- package/src/createSuspenseQuery.ts +215 -0
- package/src/hooks/index.ts +93 -0
- package/src/hooks/useActorInfiniteQuery.test.tsx +457 -0
- package/src/hooks/useActorInfiniteQuery.ts +134 -0
- package/src/hooks/useActorMethod.test.tsx +798 -0
- package/src/hooks/useActorMethod.ts +397 -0
- package/src/hooks/useActorMutation.test.tsx +220 -0
- package/src/hooks/useActorMutation.ts +124 -0
- package/src/hooks/useActorQuery.test.tsx +287 -0
- package/src/hooks/useActorQuery.ts +110 -0
- package/src/hooks/useActorSuspenseInfiniteQuery.test.tsx +472 -0
- package/src/hooks/useActorSuspenseInfiniteQuery.ts +137 -0
- package/src/hooks/useActorSuspenseQuery.test.tsx +254 -0
- package/src/hooks/useActorSuspenseQuery.ts +112 -0
- package/src/index.ts +21 -0
- package/src/types.ts +435 -0
- package/src/validation.ts +202 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useActorSuspenseInfiniteQuery.d.ts","sourceRoot":"","sources":["../../src/hooks/useActorSuspenseInfiniteQuery.ts"],"names":[],"mappings":"AACA,OAAO,EACL,QAAQ,EAER,8BAA8B,EAC9B,YAAY,EACb,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,WAAW,EACX,eAAe,EACf,gBAAgB,EACjB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAEhD,MAAM,WAAW,uCAAuC,CACtD,CAAC,EACD,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,EACzB,CAAC,SAAS,YAAY,GAAG,QAAQ,EACjC,UAAU,GAAG,OAAO
|
|
1
|
+
{"version":3,"file":"useActorSuspenseInfiniteQuery.d.ts","sourceRoot":"","sources":["../../src/hooks/useActorSuspenseInfiniteQuery.ts"],"names":[],"mappings":"AACA,OAAO,EACL,QAAQ,EAER,8BAA8B,EAC9B,+BAA+B,EAC/B,YAAY,EACb,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,WAAW,EACX,eAAe,EACf,gBAAgB,EACjB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAEhD;;;GAGG;AACH,MAAM,WAAW,uCAAuC,CACtD,CAAC,EACD,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,EACzB,CAAC,SAAS,YAAY,GAAG,QAAQ,EACjC,UAAU,GAAG,OAAO,EACpB,SAAS,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,CAC9D,SAAQ,IAAI,CACZ,+BAA+B,CAC7B,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EACxB,gBAAgB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EACzB,SAAS,EACT,QAAQ,EACR,UAAU,CACX,EACD,UAAU,GAAG,SAAS,GAAG,kBAAkB,GAAG,kBAAkB,CACjE;IACC,mDAAmD;IACnD,OAAO,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACtB,8CAA8C;IAC9C,YAAY,EAAE,CAAC,CAAA;IACf,+CAA+C;IAC/C,OAAO,EAAE,CAAC,SAAS,EAAE,UAAU,KAAK,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IACxD,2DAA2D;IAC3D,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,6BAA6B;IAC7B,gBAAgB,EAAE,UAAU,CAAA;IAC5B,gDAAgD;IAChD,gBAAgB,EAAE,CAChB,QAAQ,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAClC,QAAQ,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EACpC,aAAa,EAAE,UAAU,EACzB,aAAa,EAAE,UAAU,EAAE,KACxB,UAAU,GAAG,SAAS,GAAG,IAAI,CAAA;CACnC;AAED,MAAM,MAAM,mCAAmC,CAC7C,CAAC,EACD,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,EACzB,CAAC,SAAS,YAAY,GAAG,QAAQ,EACjC,UAAU,GAAG,OAAO,IAClB,IAAI,CACN,uCAAuC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,EAC5D,SAAS,CACV,CAAA;AAED,MAAM,MAAM,mCAAmC,CAC7C,CAAC,EACD,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,EACzB,CAAC,SAAS,YAAY,GAAG,QAAQ,EACjC,UAAU,GAAG,OAAO,IAClB,8BAA8B,CAChC,YAAY,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,EAClD,gBAAgB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAC1B,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,6BAA6B,GACxC,CAAC,EACD,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,EACzB,CAAC,SAAS,YAAY,GAAG,QAAQ,EACjC,UAAU,GAAG,OAAO,EACpB,sEAOC,uCAAuC,CACxC,CAAC,EACD,CAAC,EACD,CAAC,EACD,UAAU,CACX,KAAG,mCAAmC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU,CA4B1D,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useActorSuspenseInfiniteQuery.js","sourceRoot":"","sources":["../../src/hooks/useActorSuspenseInfiniteQuery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAC5C,OAAO,EAEL,wBAAwB,
|
|
1
|
+
{"version":3,"file":"useActorSuspenseInfiniteQuery.js","sourceRoot":"","sources":["../../src/hooks/useActorSuspenseInfiniteQuery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAC5C,OAAO,EAEL,wBAAwB,GAIzB,MAAM,uBAAuB,CAAA;AAwE9B;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAK3C,EACA,OAAO,EACP,YAAY,EACZ,OAAO,EACP,UAAU,EACV,QAAQ,EACR,GAAG,OAAO,EAMX,EAA4D,EAAE;IAC7D,0DAA0D;IAC1D,MAAM,YAAY,GAAG,OAAO,CAC1B,GAAG,EAAE,CAAC,QAAQ,IAAI,OAAO,CAAC,gBAAgB,CAAC,EAAE,YAAY,EAAE,CAAC,EAC5D,CAAC,QAAQ,EAAE,OAAO,EAAE,YAAY,CAAC,CAClC,CAAA;IAED,wDAAwD;IACxD,MAAM,OAAO,GAAG,WAAW,CACzB,KAAK,EAAE,EAAE,SAAS,EAA6B,EAAE,EAAE;QACjD,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA;QAC/B,OAAO,OAAO,CAAC,UAAU,CAAC;YACxB,YAAY;YACZ,IAAI;YACJ,UAAU;SACX,CAAC,CAAA;IACJ,CAAC,EACD,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,CAAC,CAC7C,CAAA;IAED,OAAO,wBAAwB,CAC7B;QACE,QAAQ,EAAE,YAAY;QACtB,OAAO;QACP,GAAG,OAAO;KACJ,EACR,OAAO,CAAC,WAAW,CACwC,CAAA;AAC/D,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ic-reactor/react",
|
|
3
|
-
"version": "3.0.0
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "IC Reactor React Library",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"files": [
|
|
18
18
|
"dist",
|
|
19
|
+
"src",
|
|
19
20
|
"README.md"
|
|
20
21
|
],
|
|
21
22
|
"repository": {
|
|
@@ -41,7 +42,7 @@
|
|
|
41
42
|
"author": "Behrad Deylami",
|
|
42
43
|
"license": "MIT",
|
|
43
44
|
"dependencies": {
|
|
44
|
-
"@ic-reactor/core": "^3.0.0
|
|
45
|
+
"@ic-reactor/core": "^3.0.0"
|
|
45
46
|
},
|
|
46
47
|
"peerDependencies": {
|
|
47
48
|
"react": ">=18.0.0",
|
|
@@ -55,15 +56,15 @@
|
|
|
55
56
|
"@tanstack/react-query": "^5.90",
|
|
56
57
|
"@testing-library/dom": "^10.4.1",
|
|
57
58
|
"@testing-library/jest-dom": "^6.9.1",
|
|
58
|
-
"@testing-library/react": "^16.3.
|
|
59
|
-
"@types/react": "^19.2.
|
|
59
|
+
"@testing-library/react": "^16.3.2",
|
|
60
|
+
"@types/react": "^19.2.10",
|
|
60
61
|
"@types/react-dom": "^19.2.3",
|
|
61
62
|
"fake-indexeddb": "^6.2.5",
|
|
62
|
-
"jsdom": "^
|
|
63
|
+
"jsdom": "^28.0.0",
|
|
63
64
|
"react": "^19.2.3",
|
|
64
65
|
"react-dom": "^19.2.3",
|
|
65
66
|
"size-limit": "^12.0.0",
|
|
66
|
-
"vitest": "^4.0.
|
|
67
|
+
"vitest": "^4.0.17"
|
|
67
68
|
},
|
|
68
69
|
"size-limit": [
|
|
69
70
|
{
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Actor Hooks Factory - Creates a full set of React hooks for a reactor instance.
|
|
3
|
+
*
|
|
4
|
+
* This is the primary entry point for using the library in React applications.
|
|
5
|
+
* It generates type-safe hooks for:
|
|
6
|
+
* - Queries (useActorQuery)
|
|
7
|
+
* - Suspense Queries (useActorSuspenseQuery)
|
|
8
|
+
* - Infinite Queries (useActorInfiniteQuery)
|
|
9
|
+
* - Suspense Infinite Queries (useActorSuspenseInfiniteQuery)
|
|
10
|
+
* - Mutations (useActorMutation)
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const { useActorQuery, useActorMutation } = createActorHooks(reactor)
|
|
14
|
+
*
|
|
15
|
+
* // In component
|
|
16
|
+
* const { data } = useActorQuery({ functionName: 'get_user' })
|
|
17
|
+
* const { mutate } = useActorMutation({ functionName: 'update_user' })
|
|
18
|
+
*/
|
|
19
|
+
import {
|
|
20
|
+
Reactor,
|
|
21
|
+
DisplayReactor,
|
|
22
|
+
ReactorReturnErr,
|
|
23
|
+
ReactorReturnOk,
|
|
24
|
+
BaseActor,
|
|
25
|
+
FunctionName,
|
|
26
|
+
TransformKey,
|
|
27
|
+
} from "@ic-reactor/core"
|
|
28
|
+
import {
|
|
29
|
+
UseQueryResult,
|
|
30
|
+
UseSuspenseQueryResult,
|
|
31
|
+
UseInfiniteQueryResult,
|
|
32
|
+
UseSuspenseInfiniteQueryResult,
|
|
33
|
+
UseMutationResult,
|
|
34
|
+
InfiniteData,
|
|
35
|
+
} from "@tanstack/react-query"
|
|
36
|
+
import { createQuery } from "./createQuery"
|
|
37
|
+
import { createSuspenseQuery } from "./createSuspenseQuery"
|
|
38
|
+
import { createInfiniteQuery, InfiniteQueryConfig } from "./createInfiniteQuery"
|
|
39
|
+
import {
|
|
40
|
+
createSuspenseInfiniteQuery,
|
|
41
|
+
SuspenseInfiniteQueryConfig,
|
|
42
|
+
} from "./createSuspenseInfiniteQuery"
|
|
43
|
+
import { createMutation } from "./createMutation"
|
|
44
|
+
import {
|
|
45
|
+
useActorMethod,
|
|
46
|
+
UseActorMethodParameters,
|
|
47
|
+
} from "./hooks/useActorMethod"
|
|
48
|
+
import { QueryConfig, SuspenseQueryConfig, MutationConfig } from "./types"
|
|
49
|
+
|
|
50
|
+
export type ActorHooks<A, T extends TransformKey> = {
|
|
51
|
+
useActorQuery: {
|
|
52
|
+
<M extends FunctionName<A>>(
|
|
53
|
+
config: QueryConfig<A, M, T, ReactorReturnOk<A, M, T>>
|
|
54
|
+
): UseQueryResult<ReactorReturnOk<A, M, T>, ReactorReturnErr<A, M, T>>
|
|
55
|
+
<M extends FunctionName<A>, TData>(
|
|
56
|
+
config: QueryConfig<A, M, T, TData>
|
|
57
|
+
): UseQueryResult<TData, ReactorReturnErr<A, M, T>>
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
useActorSuspenseQuery: {
|
|
61
|
+
<M extends FunctionName<A>>(
|
|
62
|
+
config: SuspenseQueryConfig<A, M, T, ReactorReturnOk<A, M, T>>
|
|
63
|
+
): UseSuspenseQueryResult<
|
|
64
|
+
ReactorReturnOk<A, M, T>,
|
|
65
|
+
ReactorReturnErr<A, M, T>
|
|
66
|
+
>
|
|
67
|
+
<M extends FunctionName<A>, TData>(
|
|
68
|
+
config: SuspenseQueryConfig<A, M, T, TData>
|
|
69
|
+
): UseSuspenseQueryResult<TData, ReactorReturnErr<A, M, T>>
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
useActorInfiniteQuery: <M extends FunctionName<A>, TPageParam = unknown>(
|
|
73
|
+
config: InfiniteQueryConfig<A, M, T, TPageParam>
|
|
74
|
+
) => UseInfiniteQueryResult<
|
|
75
|
+
InfiniteData<ReactorReturnOk<A, M, T>, TPageParam>,
|
|
76
|
+
ReactorReturnErr<A, M, T>
|
|
77
|
+
>
|
|
78
|
+
|
|
79
|
+
useActorSuspenseInfiniteQuery: <
|
|
80
|
+
M extends FunctionName<A>,
|
|
81
|
+
TPageParam = unknown,
|
|
82
|
+
>(
|
|
83
|
+
config: SuspenseInfiniteQueryConfig<A, M, T, TPageParam>
|
|
84
|
+
) => UseSuspenseInfiniteQueryResult<
|
|
85
|
+
InfiniteData<ReactorReturnOk<A, M, T>, TPageParam>,
|
|
86
|
+
ReactorReturnErr<A, M, T>
|
|
87
|
+
>
|
|
88
|
+
|
|
89
|
+
useActorMutation: <M extends FunctionName<A>>(
|
|
90
|
+
config: MutationConfig<A, M, T>
|
|
91
|
+
) => UseMutationResult<ReactorReturnOk<A, M, T>, ReactorReturnErr<A, M, T>>
|
|
92
|
+
|
|
93
|
+
useActorMethod: <M extends FunctionName<A>>(
|
|
94
|
+
config: Omit<UseActorMethodParameters<A, M, T>, "reactor">
|
|
95
|
+
) => ReturnType<typeof useActorMethod<A, M, T>>
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function createActorHooks<A>(
|
|
99
|
+
reactor: DisplayReactor<A>
|
|
100
|
+
): ActorHooks<A, "display">
|
|
101
|
+
|
|
102
|
+
export function createActorHooks<
|
|
103
|
+
A = BaseActor,
|
|
104
|
+
T extends TransformKey = "candid",
|
|
105
|
+
>(reactor: Reactor<A, T>): ActorHooks<A, T>
|
|
106
|
+
|
|
107
|
+
export function createActorHooks<A, T extends TransformKey>(
|
|
108
|
+
reactor: Reactor<A, T>
|
|
109
|
+
): ActorHooks<A, T> {
|
|
110
|
+
return {
|
|
111
|
+
useActorQuery: ((config: any) => {
|
|
112
|
+
const { select, ...options } = config
|
|
113
|
+
return createQuery(reactor, config).useQuery(options)
|
|
114
|
+
}) as ActorHooks<A, T>["useActorQuery"],
|
|
115
|
+
|
|
116
|
+
useActorSuspenseQuery: ((config: any) => {
|
|
117
|
+
const { select, ...options } = config
|
|
118
|
+
return createSuspenseQuery(reactor, config).useSuspenseQuery(options)
|
|
119
|
+
}) as ActorHooks<A, T>["useActorSuspenseQuery"],
|
|
120
|
+
|
|
121
|
+
useActorInfiniteQuery: ((config) => {
|
|
122
|
+
const { select, ...options } = config
|
|
123
|
+
return createInfiniteQuery(reactor, config).useInfiniteQuery(options)
|
|
124
|
+
}) as ActorHooks<A, T>["useActorInfiniteQuery"],
|
|
125
|
+
|
|
126
|
+
useActorSuspenseInfiniteQuery: ((config) => {
|
|
127
|
+
const { select, ...options } = config
|
|
128
|
+
return createSuspenseInfiniteQuery(
|
|
129
|
+
reactor,
|
|
130
|
+
config
|
|
131
|
+
).useSuspenseInfiniteQuery(options)
|
|
132
|
+
}) as ActorHooks<A, T>["useActorSuspenseInfiniteQuery"],
|
|
133
|
+
|
|
134
|
+
useActorMutation: ((config) => {
|
|
135
|
+
const { onSuccess, invalidateQueries, ...options } = config
|
|
136
|
+
return createMutation(reactor, config).useMutation(options)
|
|
137
|
+
}) as ActorHooks<A, T>["useActorMutation"],
|
|
138
|
+
|
|
139
|
+
useActorMethod: (config) =>
|
|
140
|
+
useActorMethod({ ...config, reactor } as UseActorMethodParameters<
|
|
141
|
+
A,
|
|
142
|
+
any,
|
|
143
|
+
T
|
|
144
|
+
>),
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { useSyncExternalStore, useEffect, useRef, useMemo } from "react"
|
|
2
|
+
import { ClientManager, AgentState, AuthState } from "@ic-reactor/core"
|
|
3
|
+
import { Principal } from "@icp-sdk/core/principal"
|
|
4
|
+
import { Identity } from "@icp-sdk/core/agent"
|
|
5
|
+
import { AuthClientLoginOptions } from "@icp-sdk/auth/client"
|
|
6
|
+
|
|
7
|
+
export interface UseAuthReturn {
|
|
8
|
+
authenticate: () => Promise<Identity | undefined>
|
|
9
|
+
login: (options?: AuthClientLoginOptions) => Promise<void>
|
|
10
|
+
logout: (options?: { returnTo?: string }) => Promise<void>
|
|
11
|
+
isAuthenticated: boolean
|
|
12
|
+
isAuthenticating: boolean
|
|
13
|
+
principal: Principal | null
|
|
14
|
+
identity: Identity | null
|
|
15
|
+
error: Error | undefined
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface CreateAuthHooksReturn {
|
|
19
|
+
useAgentState: () => AgentState
|
|
20
|
+
useUserPrincipal: () => Principal | null
|
|
21
|
+
useAuth: () => UseAuthReturn
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Create authentication hooks for managing user sessions with Internet Identity.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* const { useAuth, useUserPrincipal, useAgentState } = createAuthHooks(clientManager)
|
|
29
|
+
*
|
|
30
|
+
* function App() {
|
|
31
|
+
* const { login, logout, principal, isAuthenticated } = useAuth()
|
|
32
|
+
*
|
|
33
|
+
* return isAuthenticated
|
|
34
|
+
* ? <button onClick={logout}>Logout {principal?.toText()}</button>
|
|
35
|
+
* : <button onClick={login}>Login with II</button>
|
|
36
|
+
* }
|
|
37
|
+
*/
|
|
38
|
+
export const createAuthHooks = (
|
|
39
|
+
clientManager: ClientManager
|
|
40
|
+
): CreateAuthHooksReturn => {
|
|
41
|
+
/**
|
|
42
|
+
* Subscribe to agent state changes.
|
|
43
|
+
* Returns the current agent state (agent, isInitialized, etc.)
|
|
44
|
+
*/
|
|
45
|
+
const useAgentState = (): AgentState =>
|
|
46
|
+
useSyncExternalStore(
|
|
47
|
+
(callback) => clientManager.subscribeAgentState(callback),
|
|
48
|
+
() => clientManager.agentState,
|
|
49
|
+
// Server snapshot - provide initial state for SSR
|
|
50
|
+
() => clientManager.agentState
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Subscribe to authentication state changes.
|
|
55
|
+
* Returns auth state (isAuthenticated, isAuthenticating, identity, error)
|
|
56
|
+
*/
|
|
57
|
+
const useAuthState = (): AuthState =>
|
|
58
|
+
useSyncExternalStore(
|
|
59
|
+
(callback) => clientManager.subscribeAuthState(callback),
|
|
60
|
+
() => clientManager.authState,
|
|
61
|
+
// Server snapshot - provide initial state for SSR
|
|
62
|
+
() => clientManager.authState
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Main authentication hook that provides login/logout methods and auth state.
|
|
67
|
+
* Automatically initializes the session on first use, restoring any previous session.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* function AuthButton() {
|
|
71
|
+
* const { login, logout, isAuthenticated, isAuthenticating } = useAuth()
|
|
72
|
+
*
|
|
73
|
+
* if (isAuthenticated) {
|
|
74
|
+
* return <button onClick={logout}>Logout</button>
|
|
75
|
+
* }
|
|
76
|
+
* return (
|
|
77
|
+
* <button onClick={login} disabled={isAuthenticating}>
|
|
78
|
+
* {isAuthenticating ? "Connecting..." : "Login"}
|
|
79
|
+
* </button>
|
|
80
|
+
* )
|
|
81
|
+
* }
|
|
82
|
+
*/
|
|
83
|
+
const useAuth = (): UseAuthReturn => {
|
|
84
|
+
const { login, logout, authenticate } = clientManager
|
|
85
|
+
const { isAuthenticated, isAuthenticating, identity, error } =
|
|
86
|
+
useAuthState()
|
|
87
|
+
|
|
88
|
+
// Track if we've already initialized to avoid duplicate calls
|
|
89
|
+
const initializedRef = useRef(false)
|
|
90
|
+
|
|
91
|
+
// Auto-initialize on first mount to restore previous session
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
if (!initializedRef.current) {
|
|
94
|
+
initializedRef.current = true
|
|
95
|
+
clientManager.initialize()
|
|
96
|
+
}
|
|
97
|
+
}, [])
|
|
98
|
+
|
|
99
|
+
const principal = useMemo(
|
|
100
|
+
() => (identity ? identity.getPrincipal() : null),
|
|
101
|
+
[identity]
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
authenticate,
|
|
106
|
+
login,
|
|
107
|
+
logout,
|
|
108
|
+
isAuthenticated,
|
|
109
|
+
isAuthenticating,
|
|
110
|
+
principal,
|
|
111
|
+
identity,
|
|
112
|
+
error,
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Get the current user's Principal.
|
|
118
|
+
* Returns null if not authenticated.
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* function UserInfo() {
|
|
122
|
+
* const principal = useUserPrincipal()
|
|
123
|
+
* if (!principal) return null
|
|
124
|
+
* return <span>Logged in as: {principal.toText()}</span>
|
|
125
|
+
* }
|
|
126
|
+
*/
|
|
127
|
+
const useUserPrincipal = (): Principal | null => {
|
|
128
|
+
const { identity } = useAuthState()
|
|
129
|
+
return identity ? identity.getPrincipal() : null
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
useAuth,
|
|
134
|
+
useAgentState,
|
|
135
|
+
useUserPrincipal,
|
|
136
|
+
}
|
|
137
|
+
}
|