@ic-reactor/react 2.0.1 → 3.0.0-beta.2
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 +283 -87
- package/dist/createActorHooks.d.ts +39 -0
- package/dist/createActorHooks.d.ts.map +1 -0
- package/dist/createActorHooks.js +30 -0
- package/dist/createActorHooks.js.map +1 -0
- package/dist/createAuthHooks.d.ts +37 -0
- package/dist/createAuthHooks.d.ts.map +1 -0
- package/dist/createAuthHooks.js +94 -0
- package/dist/createAuthHooks.js.map +1 -0
- package/dist/createInfiniteQuery.d.ts +129 -0
- package/dist/createInfiniteQuery.d.ts.map +1 -0
- package/dist/createInfiniteQuery.js +160 -0
- package/dist/createInfiniteQuery.js.map +1 -0
- package/dist/createMutation.d.ts +19 -0
- package/dist/createMutation.d.ts.map +1 -0
- package/dist/createMutation.js +98 -0
- package/dist/createMutation.js.map +1 -0
- package/dist/createQuery.d.ts +20 -0
- package/dist/createQuery.d.ts.map +1 -0
- package/dist/createQuery.js +111 -0
- package/dist/createQuery.js.map +1 -0
- package/dist/createSuspenseInfiniteQuery.d.ts +122 -0
- package/dist/createSuspenseInfiniteQuery.d.ts.map +1 -0
- package/dist/createSuspenseInfiniteQuery.js +160 -0
- package/dist/createSuspenseInfiniteQuery.js.map +1 -0
- package/dist/createSuspenseQuery.d.ts +25 -0
- package/dist/createSuspenseQuery.d.ts.map +1 -0
- package/dist/createSuspenseQuery.js +116 -0
- package/dist/createSuspenseQuery.js.map +1 -0
- package/dist/hooks/index.d.ts +6 -2
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +6 -18
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/useActorInfiniteQuery.d.ts +37 -0
- package/dist/hooks/useActorInfiniteQuery.d.ts.map +1 -0
- package/dist/hooks/useActorInfiniteQuery.js +33 -0
- package/dist/hooks/useActorInfiniteQuery.js.map +1 -0
- package/dist/hooks/useActorMutation.d.ts +23 -0
- package/dist/hooks/useActorMutation.d.ts.map +1 -0
- package/dist/hooks/useActorMutation.js +39 -0
- package/dist/hooks/useActorMutation.js.map +1 -0
- package/dist/hooks/useActorQuery.d.ts +32 -0
- package/dist/hooks/useActorQuery.d.ts.map +1 -0
- package/dist/hooks/useActorQuery.js +35 -0
- package/dist/hooks/useActorQuery.js.map +1 -0
- package/dist/hooks/useActorSuspenseInfiniteQuery.d.ts +36 -0
- package/dist/hooks/useActorSuspenseInfiniteQuery.d.ts.map +1 -0
- package/dist/hooks/useActorSuspenseInfiniteQuery.js +33 -0
- package/dist/hooks/useActorSuspenseInfiniteQuery.js.map +1 -0
- package/dist/hooks/useActorSuspenseQuery.d.ts +32 -0
- package/dist/hooks/useActorSuspenseQuery.d.ts.map +1 -0
- package/dist/hooks/useActorSuspenseQuery.js +36 -0
- package/dist/hooks/useActorSuspenseQuery.js.map +1 -0
- package/dist/index.d.ts +11 -8
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -49
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +232 -13
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -22
- package/dist/types.js.map +1 -0
- package/dist/validation.d.ts +131 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +125 -0
- package/dist/validation.js.map +1 -0
- package/package.json +70 -35
- package/LICENSE.md +0 -8
- package/dist/context/actor/create.d.ts +0 -63
- package/dist/context/actor/create.js +0 -119
- package/dist/context/actor/hooks/useActorInterface.d.ts +0 -4
- package/dist/context/actor/hooks/useActorInterface.js +0 -10
- package/dist/context/actor/hooks/useActorState.d.ts +0 -21
- package/dist/context/actor/hooks/useActorState.js +0 -25
- package/dist/context/actor/hooks/useActorStore.d.ts +0 -32
- package/dist/context/actor/hooks/useActorStore.js +0 -36
- package/dist/context/actor/hooks/useInitializeActor.d.ts +0 -6
- package/dist/context/actor/hooks/useInitializeActor.js +0 -10
- package/dist/context/actor/hooks/useMethod.d.ts +0 -29
- package/dist/context/actor/hooks/useMethod.js +0 -34
- package/dist/context/actor/hooks/useMethodAttributes.d.ts +0 -7
- package/dist/context/actor/hooks/useMethodAttributes.js +0 -11
- package/dist/context/actor/hooks/useMethodNames.d.ts +0 -7
- package/dist/context/actor/hooks/useMethodNames.js +0 -11
- package/dist/context/actor/hooks/useQueryCall.d.ts +0 -28
- package/dist/context/actor/hooks/useQueryCall.js +0 -33
- package/dist/context/actor/hooks/useUpdateCall.d.ts +0 -29
- package/dist/context/actor/hooks/useUpdateCall.js +0 -34
- package/dist/context/actor/hooks/useVisitMethod.d.ts +0 -8
- package/dist/context/actor/hooks/useVisitMethod.js +0 -13
- package/dist/context/actor/hooks/useVisitService.d.ts +0 -8
- package/dist/context/actor/hooks/useVisitService.js +0 -13
- package/dist/context/actor/index.d.ts +0 -16
- package/dist/context/actor/index.js +0 -33
- package/dist/context/actor/provider.d.ts +0 -71
- package/dist/context/actor/provider.js +0 -75
- package/dist/context/actor/types.d.ts +0 -35
- package/dist/context/actor/types.js +0 -2
- package/dist/context/adapter/create.d.ts +0 -2
- package/dist/context/adapter/create.js +0 -102
- package/dist/context/adapter/hooks/useCandidAdapter.d.ts +0 -23
- package/dist/context/adapter/hooks/useCandidAdapter.js +0 -27
- package/dist/context/adapter/hooks/useCandidEvaluation.d.ts +0 -5
- package/dist/context/adapter/hooks/useCandidEvaluation.js +0 -9
- package/dist/context/adapter/index.d.ts +0 -6
- package/dist/context/adapter/index.js +0 -24
- package/dist/context/adapter/provider.d.ts +0 -23
- package/dist/context/adapter/provider.js +0 -27
- package/dist/context/adapter/types.d.ts +0 -52
- package/dist/context/adapter/types.js +0 -2
- package/dist/context/agent/create.d.ts +0 -74
- package/dist/context/agent/create.js +0 -104
- package/dist/context/agent/hooks/useAgent.d.ts +0 -14
- package/dist/context/agent/hooks/useAgent.js +0 -18
- package/dist/context/agent/hooks/useAgentManager.d.ts +0 -14
- package/dist/context/agent/hooks/useAgentManager.js +0 -18
- package/dist/context/agent/hooks/useAgentState.d.ts +0 -21
- package/dist/context/agent/hooks/useAgentState.js +0 -25
- package/dist/context/agent/hooks/useAuth.d.ts +0 -57
- package/dist/context/agent/hooks/useAuth.js +0 -61
- package/dist/context/agent/hooks/useAuthState.d.ts +0 -19
- package/dist/context/agent/hooks/useAuthState.js +0 -23
- package/dist/context/agent/hooks/useUserPrincipal.d.ts +0 -17
- package/dist/context/agent/hooks/useUserPrincipal.js +0 -21
- package/dist/context/agent/index.d.ts +0 -12
- package/dist/context/agent/index.js +0 -29
- package/dist/context/agent/provider.d.ts +0 -28
- package/dist/context/agent/provider.js +0 -32
- package/dist/context/agent/types.d.ts +0 -17
- package/dist/context/agent/types.js +0 -2
- package/dist/core.d.ts +0 -1
- package/dist/core.js +0 -9
- package/dist/createReactor.d.ts +0 -49
- package/dist/createReactor.js +0 -69
- package/dist/helpers/actorHooks.d.ts +0 -18
- package/dist/helpers/actorHooks.js +0 -283
- package/dist/helpers/agentHooks.d.ts +0 -3
- package/dist/helpers/agentHooks.js +0 -22
- package/dist/helpers/authHooks.d.ts +0 -2
- package/dist/helpers/authHooks.js +0 -120
- package/dist/helpers/extractActorContext.d.ts +0 -4
- package/dist/helpers/extractActorContext.js +0 -44
- package/dist/helpers/extractAgentContext.d.ts +0 -28
- package/dist/helpers/extractAgentContext.js +0 -59
- package/dist/helpers/index.d.ts +0 -5
- package/dist/helpers/index.js +0 -21
- package/dist/helpers/types.d.ts +0 -222
- package/dist/helpers/types.js +0 -2
- package/dist/hooks/types.d.ts +0 -22
- package/dist/hooks/types.js +0 -2
- package/dist/hooks/useActor.d.ts +0 -67
- package/dist/hooks/useActor.js +0 -197
- package/dist/hooks/useActorManager.d.ts +0 -68
- package/dist/hooks/useActorManager.js +0 -75
- package/dist/utils.d.ts +0 -1
- package/dist/utils.js +0 -17
package/README.md
CHANGED
|
@@ -1,121 +1,317 @@
|
|
|
1
|
-
|
|
1
|
+
# @ic-reactor/react
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
<strong>The Ultimate React Hooks for the Internet Computer.</strong>
|
|
5
|
+
<br><br>
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@ic-reactor/react)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
[](https://www.typescriptlang.org/)
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
Connect your React application to the Internet Computer Blockchain with full [TanStack Query](https://tanstack.com/query) integration for caching, suspense, and infinite queries.
|
|
2
15
|
|
|
3
16
|
## Features
|
|
4
17
|
|
|
5
|
-
- **
|
|
6
|
-
- **
|
|
7
|
-
- **
|
|
8
|
-
- **
|
|
9
|
-
- **Authentication
|
|
10
|
-
- **
|
|
18
|
+
- ⚛️ **TanStack Query Integration** — Full power of React Query (caching, refetching, suspense, infinite queries)
|
|
19
|
+
- � **End-to-End Type Safety** — Automatic type inference from your Candid files
|
|
20
|
+
- � **Auto Transformations** — `DisplayReactor` converts BigInt to string, Principal to text, and more
|
|
21
|
+
- 📦 **Result Unwrapping** — Automatic `Ok`/`Err` handling from Candid Result types
|
|
22
|
+
- 🔐 **Authentication** — Easy-to-use hooks with Internet Identity integration
|
|
23
|
+
- 🏗️ **Multi-Actor Support** — Manage multiple canisters with shared authentication
|
|
11
24
|
|
|
12
25
|
## Installation
|
|
13
26
|
|
|
14
|
-
Install the package using npm:
|
|
15
|
-
|
|
16
27
|
```bash
|
|
17
|
-
|
|
18
|
-
|
|
28
|
+
# With npm
|
|
29
|
+
npm install @ic-reactor/react @tanstack/react-query @icp-sdk/core
|
|
19
30
|
|
|
20
|
-
|
|
31
|
+
# With pnpm
|
|
32
|
+
pnpm add @ic-reactor/react @tanstack/react-query @icp-sdk/core
|
|
21
33
|
|
|
22
|
-
|
|
23
|
-
|
|
34
|
+
# Optional: For Internet Identity authentication
|
|
35
|
+
npm install @icp-sdk/auth
|
|
24
36
|
```
|
|
25
37
|
|
|
26
|
-
##
|
|
38
|
+
## Quick Start
|
|
27
39
|
|
|
28
|
-
|
|
40
|
+
### 1. Setup ClientManager and Reactor
|
|
29
41
|
|
|
30
|
-
|
|
42
|
+
```typescript
|
|
43
|
+
// src/reactor.ts
|
|
44
|
+
import { ClientManager, Reactor } from "@ic-reactor/react"
|
|
45
|
+
import { QueryClient } from "@tanstack/react-query"
|
|
46
|
+
import { idlFactory, type _SERVICE } from "./declarations/my_canister"
|
|
31
47
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
import { canisterId, idlFactory, actor } from "declaration/actor"
|
|
35
|
-
import { createReactor } from "@ic-reactor/react"
|
|
48
|
+
// Create query client for caching
|
|
49
|
+
export const queryClient = new QueryClient()
|
|
36
50
|
|
|
37
|
-
|
|
51
|
+
// Create client manager (handles identity and agent)
|
|
52
|
+
export const clientManager = new ClientManager({
|
|
53
|
+
queryClient,
|
|
54
|
+
withProcessEnv: true, // Reads DFX_NETWORK from environment
|
|
55
|
+
})
|
|
38
56
|
|
|
39
|
-
|
|
40
|
-
|
|
57
|
+
// Create reactor for your canister
|
|
58
|
+
export const backend = new Reactor<_SERVICE>({
|
|
59
|
+
clientManager,
|
|
41
60
|
idlFactory,
|
|
42
|
-
|
|
61
|
+
canisterId: "rrkah-fqaaa-aaaaa-aaaaq-cai",
|
|
43
62
|
})
|
|
44
63
|
```
|
|
45
64
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
```
|
|
49
|
-
//
|
|
50
|
-
import {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
65
|
+
### 2. Create Hooks
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
// src/hooks.ts
|
|
69
|
+
import { createActorHooks, createAuthHooks } from "@ic-reactor/react"
|
|
70
|
+
import { backend, clientManager } from "./reactor"
|
|
71
|
+
|
|
72
|
+
// Create actor hooks for queries and mutations
|
|
73
|
+
export const { useActorQuery, useActorMutation, useActorSuspenseQuery } =
|
|
74
|
+
createActorHooks(backend)
|
|
75
|
+
|
|
76
|
+
// Create auth hooks for login/logout
|
|
77
|
+
export const { useAuth, useUserPrincipal } = createAuthHooks(clientManager)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 3. Setup Provider (not required) and Use in Components
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
// src/App.tsx
|
|
84
|
+
import { QueryClientProvider } from "@tanstack/react-query"
|
|
85
|
+
import { queryClient } from "./reactor"
|
|
86
|
+
import { useAuth, useActorQuery, useActorMutation } from "./hooks"
|
|
62
87
|
|
|
88
|
+
function App() {
|
|
63
89
|
return (
|
|
64
|
-
<
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
{loading && <p>Loading...</p>}
|
|
69
|
-
{data && <p>Balance: {data}</p>}
|
|
70
|
-
{error && <p>Error: {error}</p>}
|
|
71
|
-
</div>
|
|
90
|
+
<QueryClientProvider client={queryClient}>
|
|
91
|
+
<AuthButton />
|
|
92
|
+
<Greeting />
|
|
93
|
+
</QueryClientProvider>
|
|
72
94
|
)
|
|
73
95
|
}
|
|
74
96
|
|
|
75
|
-
|
|
97
|
+
function AuthButton() {
|
|
98
|
+
const { login, logout, isAuthenticated, principal } = useAuth()
|
|
99
|
+
|
|
100
|
+
return isAuthenticated ? (
|
|
101
|
+
<button onClick={() => logout()}>
|
|
102
|
+
Logout {principal?.toText().slice(0, 8)}...
|
|
103
|
+
</button>
|
|
104
|
+
) : (
|
|
105
|
+
<button onClick={() => login()}>Login with Internet Identity</button>
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function Greeting() {
|
|
110
|
+
// Query: Fetch data (auto-cached!)
|
|
111
|
+
const { data, isPending, error } = useActorQuery({
|
|
112
|
+
functionName: "greet",
|
|
113
|
+
args: ["World"],
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
if (isPending) return <div>Loading...</div>
|
|
117
|
+
if (error) return <div>Error: {error.message}</div>
|
|
118
|
+
|
|
119
|
+
return <h1>{data}</h1>
|
|
120
|
+
}
|
|
76
121
|
```
|
|
77
122
|
|
|
78
|
-
##
|
|
123
|
+
## Core Concepts
|
|
79
124
|
|
|
80
|
-
|
|
125
|
+
### Reactor vs DisplayReactor
|
|
81
126
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
127
|
+
| Feature | `Reactor` | `DisplayReactor` |
|
|
128
|
+
| ------------- | ---------------- | --------------------------- |
|
|
129
|
+
| Types | Raw Candid types | Display-friendly types |
|
|
130
|
+
| BigInt | `bigint` | `string` |
|
|
131
|
+
| Principal | `Principal` | `string` |
|
|
132
|
+
| Vec nat8 | `Uint8Array` | <= 96 bytes: `string` (hex) |
|
|
133
|
+
| Result | Unwrapped | Unwrapped |
|
|
134
|
+
| Form-friendly | No | Yes |
|
|
85
135
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
login,
|
|
89
|
-
logout,
|
|
90
|
-
loginLoading,
|
|
91
|
-
loginError,
|
|
92
|
-
identity,
|
|
93
|
-
authenticating,
|
|
94
|
-
authenticated,
|
|
95
|
-
} = useAuth()
|
|
136
|
+
```typescript
|
|
137
|
+
import { DisplayReactor } from "@ic-reactor/react"
|
|
96
138
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
139
|
+
// DisplayReactor for form-friendly UI work
|
|
140
|
+
const backend = new DisplayReactor<_SERVICE>({
|
|
141
|
+
clientManager,
|
|
142
|
+
idlFactory,
|
|
143
|
+
canisterId: "rrkah-fqaaa-aaaaa-aaaaq-cai",
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
// Now hooks return strings instead of bigint/Principal
|
|
147
|
+
const { data } = useActorQuery({
|
|
148
|
+
functionName: "icrc1_balance_of",
|
|
149
|
+
args: [{ owner: "aaaaa-aa", subaccount: [] }], // strings!
|
|
150
|
+
})
|
|
151
|
+
// data is "100000000" instead of 100000000n
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Hooks Reference
|
|
155
|
+
|
|
156
|
+
### Actor Hooks (from `createActorHooks`)
|
|
157
|
+
|
|
158
|
+
| Hook | Description |
|
|
159
|
+
| ------------------------------- | ---------------------------------------------- |
|
|
160
|
+
| `useActorQuery` | Standard queries with loading states |
|
|
161
|
+
| `useActorSuspenseQuery` | Suspense-enabled queries (data always defined) |
|
|
162
|
+
| `useActorInfiniteQuery` | Paginated/infinite scroll queries |
|
|
163
|
+
| `useActorSuspenseInfiniteQuery` | Suspense infinite queries |
|
|
164
|
+
| `useActorMutation` | State-changing operations |
|
|
165
|
+
|
|
166
|
+
### Auth Hooks (from `createAuthHooks`)
|
|
167
|
+
|
|
168
|
+
| Hook | Description |
|
|
169
|
+
| ------------------ | ----------------------------------- |
|
|
170
|
+
| `useAuth` | Login, logout, authentication state |
|
|
171
|
+
| `useAgentState` | Agent initialization state |
|
|
172
|
+
| `useUserPrincipal` | Current user's Principal |
|
|
173
|
+
|
|
174
|
+
## Query Examples
|
|
175
|
+
|
|
176
|
+
### Standard Query
|
|
177
|
+
|
|
178
|
+
```tsx
|
|
179
|
+
const { data, isPending, error } = useActorQuery({
|
|
180
|
+
functionName: "get_user",
|
|
181
|
+
args: ["user-123"],
|
|
182
|
+
staleTime: 5 * 60 * 1000, // 5 minutes
|
|
183
|
+
})
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Suspense Query
|
|
187
|
+
|
|
188
|
+
```tsx
|
|
189
|
+
// Parent must have <Suspense> boundary
|
|
190
|
+
function UserProfile() {
|
|
191
|
+
// data is never undefined with suspense!
|
|
192
|
+
const { data } = useActorSuspenseQuery({
|
|
193
|
+
functionName: "get_user",
|
|
194
|
+
args: ["user-123"],
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
return <div>{data.name}</div>
|
|
118
198
|
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Infinite Query
|
|
202
|
+
|
|
203
|
+
```tsx
|
|
204
|
+
const { data, fetchNextPage, hasNextPage } = useActorInfiniteQuery({
|
|
205
|
+
functionName: "get_posts",
|
|
206
|
+
initialPageParam: 0,
|
|
207
|
+
getNextPageParam: (lastPage, pages) => pages.length * 10,
|
|
208
|
+
args: (pageParam) => [{ offset: pageParam, limit: 10 }],
|
|
209
|
+
})
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Mutation Examples
|
|
213
|
+
|
|
214
|
+
### Basic Mutation
|
|
215
|
+
|
|
216
|
+
```tsx
|
|
217
|
+
const { mutate, isPending, error } = useActorMutation({
|
|
218
|
+
functionName: "update_profile",
|
|
219
|
+
onSuccess: (result) => {
|
|
220
|
+
console.log("Profile updated!", result)
|
|
221
|
+
},
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
// Call the mutation
|
|
225
|
+
mutate([{ name: "Alice", bio: "Hello IC!" }])
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Query Factories
|
|
229
|
+
|
|
230
|
+
Create reusable query configurations with factory functions:
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
import {
|
|
234
|
+
createQuery,
|
|
235
|
+
createSuspenseQuery,
|
|
236
|
+
createMutation,
|
|
237
|
+
} from "@ic-reactor/react"
|
|
238
|
+
|
|
239
|
+
// Static query (no args at call time)
|
|
240
|
+
export const tokenNameQuery = createSuspenseQuery(backend, {
|
|
241
|
+
functionName: "icrc1_name",
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
// In component:
|
|
245
|
+
const { data } = tokenNameQuery.useSuspenseQuery()
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Factory with Dynamic Args
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
import { createSuspenseQueryFactory } from "@ic-reactor/react"
|
|
252
|
+
|
|
253
|
+
// Factory for balance queries
|
|
254
|
+
export const getBalance = createSuspenseQueryFactory(backend, {
|
|
255
|
+
functionName: "icrc1_balance_of",
|
|
256
|
+
select: (balance) => `${balance} tokens`,
|
|
257
|
+
})
|
|
119
258
|
|
|
120
|
-
|
|
259
|
+
// In component - pass args at call time
|
|
260
|
+
const { data } = getBalance.useSuspenseQuery({
|
|
261
|
+
args: [{ owner: userPrincipal, subaccount: [] }],
|
|
262
|
+
})
|
|
121
263
|
```
|
|
264
|
+
|
|
265
|
+
## Advanced: Direct Reactor Usage
|
|
266
|
+
|
|
267
|
+
Access reactor methods directly for manual cache management:
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
// Fetch and cache
|
|
271
|
+
await backend.fetchQuery({
|
|
272
|
+
functionName: "get_user",
|
|
273
|
+
args: ["user-123"],
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
// Get cached data (no fetch)
|
|
277
|
+
const cached = backend.getQueryData({
|
|
278
|
+
functionName: "get_user",
|
|
279
|
+
args: ["user-123"],
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
// Invalidate cache to trigger refetch
|
|
283
|
+
backend.invalidateQueries({
|
|
284
|
+
functionName: "get_user",
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
// Direct call without caching
|
|
288
|
+
const result = await backend.callMethod({
|
|
289
|
+
functionName: "update_user",
|
|
290
|
+
args: [{ name: "Alice" }],
|
|
291
|
+
})
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Re-exports
|
|
295
|
+
|
|
296
|
+
`@ic-reactor/react` re-exports everything from `@ic-reactor/core`, so you typically only need one import:
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
// Everything from one package
|
|
300
|
+
import {
|
|
301
|
+
ClientManager,
|
|
302
|
+
Reactor,
|
|
303
|
+
DisplayReactor,
|
|
304
|
+
createActorHooks,
|
|
305
|
+
createAuthHooks,
|
|
306
|
+
createQuery,
|
|
307
|
+
CanisterError,
|
|
308
|
+
} from "@ic-reactor/react"
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## Documentation
|
|
312
|
+
|
|
313
|
+
For comprehensive guides and API reference, visit the [documentation site](https://b3pay.github.io/ic-reactor/v3).
|
|
314
|
+
|
|
315
|
+
## License
|
|
316
|
+
|
|
317
|
+
MIT © [Behrad Deylami](https://github.com/b3hr4d)
|
|
@@ -0,0 +1,39 @@
|
|
|
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 { Reactor, DisplayReactor, ReactorReturnErr, ReactorReturnOk, BaseActor, FunctionName, TransformKey } from "@ic-reactor/core";
|
|
20
|
+
import { UseQueryResult, UseSuspenseQueryResult, UseInfiniteQueryResult, UseSuspenseInfiniteQueryResult, UseMutationResult, InfiniteData } from "@tanstack/react-query";
|
|
21
|
+
import { InfiniteQueryConfig } from "./createInfiniteQuery";
|
|
22
|
+
import { SuspenseInfiniteQueryConfig } from "./createSuspenseInfiniteQuery";
|
|
23
|
+
import { QueryConfig, SuspenseQueryConfig, MutationConfig } from "./types";
|
|
24
|
+
export type ActorHooks<A, T extends TransformKey> = {
|
|
25
|
+
useActorQuery: {
|
|
26
|
+
<M extends FunctionName<A>>(config: QueryConfig<A, M, T, ReactorReturnOk<A, M, T>>): UseQueryResult<ReactorReturnOk<A, M, T>, ReactorReturnErr<A, M, T>>;
|
|
27
|
+
<M extends FunctionName<A>, TData>(config: QueryConfig<A, M, T, TData>): UseQueryResult<TData, ReactorReturnErr<A, M, T>>;
|
|
28
|
+
};
|
|
29
|
+
useActorSuspenseQuery: {
|
|
30
|
+
<M extends FunctionName<A>>(config: SuspenseQueryConfig<A, M, T, ReactorReturnOk<A, M, T>>): UseSuspenseQueryResult<ReactorReturnOk<A, M, T>, ReactorReturnErr<A, M, T>>;
|
|
31
|
+
<M extends FunctionName<A>, TData>(config: SuspenseQueryConfig<A, M, T, TData>): UseSuspenseQueryResult<TData, ReactorReturnErr<A, M, T>>;
|
|
32
|
+
};
|
|
33
|
+
useActorInfiniteQuery: <M extends FunctionName<A>, TPageParam = unknown>(config: InfiniteQueryConfig<A, M, T, TPageParam>) => UseInfiniteQueryResult<InfiniteData<ReactorReturnOk<A, M, T>, TPageParam>, ReactorReturnErr<A, M, T>>;
|
|
34
|
+
useActorSuspenseInfiniteQuery: <M extends FunctionName<A>, TPageParam = unknown>(config: SuspenseInfiniteQueryConfig<A, M, T, TPageParam>) => UseSuspenseInfiniteQueryResult<InfiniteData<ReactorReturnOk<A, M, T>, TPageParam>, ReactorReturnErr<A, M, T>>;
|
|
35
|
+
useActorMutation: <M extends FunctionName<A>>(config: MutationConfig<A, M, T>) => UseMutationResult<ReactorReturnOk<A, M, T>, ReactorReturnErr<A, M, T>>;
|
|
36
|
+
};
|
|
37
|
+
export declare function createActorHooks<A>(reactor: DisplayReactor<A>): ActorHooks<A, "display">;
|
|
38
|
+
export declare function createActorHooks<A = BaseActor, T extends TransformKey = "candid">(reactor: Reactor<A, T>): ActorHooks<A, T>;
|
|
39
|
+
//# sourceMappingURL=createActorHooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createActorHooks.d.ts","sourceRoot":"","sources":["../src/createActorHooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createQuery } from "./createQuery";
|
|
2
|
+
import { createSuspenseQuery } from "./createSuspenseQuery";
|
|
3
|
+
import { createInfiniteQuery } from "./createInfiniteQuery";
|
|
4
|
+
import { createSuspenseInfiniteQuery, } from "./createSuspenseInfiniteQuery";
|
|
5
|
+
import { createMutation } from "./createMutation";
|
|
6
|
+
export function createActorHooks(reactor) {
|
|
7
|
+
return {
|
|
8
|
+
useActorQuery: ((config) => {
|
|
9
|
+
const { select, ...options } = config;
|
|
10
|
+
return createQuery(reactor, config).useQuery(options);
|
|
11
|
+
}),
|
|
12
|
+
useActorSuspenseQuery: ((config) => {
|
|
13
|
+
const { select, ...options } = config;
|
|
14
|
+
return createSuspenseQuery(reactor, config).useSuspenseQuery(options);
|
|
15
|
+
}),
|
|
16
|
+
useActorInfiniteQuery: ((config) => {
|
|
17
|
+
const { select, ...options } = config;
|
|
18
|
+
return createInfiniteQuery(reactor, config).useInfiniteQuery(options);
|
|
19
|
+
}),
|
|
20
|
+
useActorSuspenseInfiniteQuery: ((config) => {
|
|
21
|
+
const { select, ...options } = config;
|
|
22
|
+
return createSuspenseInfiniteQuery(reactor, config).useSuspenseInfiniteQuery(options);
|
|
23
|
+
}),
|
|
24
|
+
useActorMutation: ((config) => {
|
|
25
|
+
const { onSuccess, refetchQueries, ...options } = config;
|
|
26
|
+
return createMutation(reactor, config).useMutation(options);
|
|
27
|
+
}),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=createActorHooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createActorHooks.js","sourceRoot":"","sources":["../src/createActorHooks.ts"],"names":[],"mappings":"AAmCA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAC3D,OAAO,EAAE,mBAAmB,EAAuB,MAAM,uBAAuB,CAAA;AAChF,OAAO,EACL,2BAA2B,GAE5B,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAwDjD,MAAM,UAAU,gBAAgB,CAC9B,OAAsB;IAEtB,OAAO;QACL,aAAa,EAAE,CAAC,CAAC,MAAW,EAAE,EAAE;YAC9B,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,GAAG,MAAM,CAAA;YACrC,OAAO,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QACvD,CAAC,CAAsC;QAEvC,qBAAqB,EAAE,CAAC,CAAC,MAAW,EAAE,EAAE;YACtC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,GAAG,MAAM,CAAA;YACrC,OAAO,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAA;QACvE,CAAC,CAA8C;QAE/C,qBAAqB,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;YACjC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,GAAG,MAAM,CAAA;YACrC,OAAO,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAA;QACvE,CAAC,CAA8C;QAE/C,6BAA6B,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;YACzC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,GAAG,MAAM,CAAA;YACrC,OAAO,2BAA2B,CAChC,OAAO,EACP,MAAM,CACP,CAAC,wBAAwB,CAAC,OAAO,CAAC,CAAA;QACrC,CAAC,CAAsD;QAEvD,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;YAC5B,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,OAAO,EAAE,GAAG,MAAM,CAAA;YACxD,OAAO,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;QAC7D,CAAC,CAAyC;KAC3C,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ClientManager, AgentState } from "@ic-reactor/core";
|
|
2
|
+
import { Principal } from "@icp-sdk/core/principal";
|
|
3
|
+
import { Identity } from "@icp-sdk/core/agent";
|
|
4
|
+
import { AuthClientLoginOptions } from "@icp-sdk/auth/client";
|
|
5
|
+
export interface UseAuthReturn {
|
|
6
|
+
authenticate: () => Promise<Identity | undefined>;
|
|
7
|
+
login: (options?: AuthClientLoginOptions) => Promise<void>;
|
|
8
|
+
logout: (options?: {
|
|
9
|
+
returnTo?: string;
|
|
10
|
+
}) => Promise<void>;
|
|
11
|
+
isAuthenticated: boolean;
|
|
12
|
+
isAuthenticating: boolean;
|
|
13
|
+
principal: Principal | null;
|
|
14
|
+
identity: Identity | null;
|
|
15
|
+
error: Error | undefined;
|
|
16
|
+
}
|
|
17
|
+
export interface CreateAuthHooksReturn {
|
|
18
|
+
useAgentState: () => AgentState;
|
|
19
|
+
useUserPrincipal: () => Principal | null;
|
|
20
|
+
useAuth: () => UseAuthReturn;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Create authentication hooks for managing user sessions with Internet Identity.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* const { useAuth, useUserPrincipal, useAgentState } = createAuthHooks(clientManager)
|
|
27
|
+
*
|
|
28
|
+
* function App() {
|
|
29
|
+
* const { login, logout, principal, isAuthenticated } = useAuth()
|
|
30
|
+
*
|
|
31
|
+
* return isAuthenticated
|
|
32
|
+
* ? <button onClick={logout}>Logout {principal?.toText()}</button>
|
|
33
|
+
* : <button onClick={login}>Login with II</button>
|
|
34
|
+
* }
|
|
35
|
+
*/
|
|
36
|
+
export declare const createAuthHooks: (clientManager: ClientManager) => CreateAuthHooksReturn;
|
|
37
|
+
//# sourceMappingURL=createAuthHooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createAuthHooks.d.ts","sourceRoot":"","sources":["../src/createAuthHooks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAa,MAAM,kBAAkB,CAAA;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAE7D,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAA;IACjD,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,sBAAsB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1D,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1D,eAAe,EAAE,OAAO,CAAA;IACxB,gBAAgB,EAAE,OAAO,CAAA;IACzB,SAAS,EAAE,SAAS,GAAG,IAAI,CAAA;IAC3B,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAA;IACzB,KAAK,EAAE,KAAK,GAAG,SAAS,CAAA;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,MAAM,UAAU,CAAA;IAC/B,gBAAgB,EAAE,MAAM,SAAS,GAAG,IAAI,CAAA;IACxC,OAAO,EAAE,MAAM,aAAa,CAAA;CAC7B;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,eAAe,GAC1B,eAAe,aAAa,KAC3B,qBAiGF,CAAA"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { useSyncExternalStore, useEffect, useRef, useMemo } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Create authentication hooks for managing user sessions with Internet Identity.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const { useAuth, useUserPrincipal, useAgentState } = createAuthHooks(clientManager)
|
|
7
|
+
*
|
|
8
|
+
* function App() {
|
|
9
|
+
* const { login, logout, principal, isAuthenticated } = useAuth()
|
|
10
|
+
*
|
|
11
|
+
* return isAuthenticated
|
|
12
|
+
* ? <button onClick={logout}>Logout {principal?.toText()}</button>
|
|
13
|
+
* : <button onClick={login}>Login with II</button>
|
|
14
|
+
* }
|
|
15
|
+
*/
|
|
16
|
+
export const createAuthHooks = (clientManager) => {
|
|
17
|
+
/**
|
|
18
|
+
* Subscribe to agent state changes.
|
|
19
|
+
* Returns the current agent state (agent, isInitialized, etc.)
|
|
20
|
+
*/
|
|
21
|
+
const useAgentState = () => useSyncExternalStore((callback) => clientManager.subscribeAgentState(callback), () => clientManager.agentState,
|
|
22
|
+
// Server snapshot - provide initial state for SSR
|
|
23
|
+
() => clientManager.agentState);
|
|
24
|
+
/**
|
|
25
|
+
* Subscribe to authentication state changes.
|
|
26
|
+
* Returns auth state (isAuthenticated, isAuthenticating, identity, error)
|
|
27
|
+
*/
|
|
28
|
+
const useAuthState = () => useSyncExternalStore((callback) => clientManager.subscribeAuthState(callback), () => clientManager.authState,
|
|
29
|
+
// Server snapshot - provide initial state for SSR
|
|
30
|
+
() => clientManager.authState);
|
|
31
|
+
/**
|
|
32
|
+
* Main authentication hook that provides login/logout methods and auth state.
|
|
33
|
+
* Automatically initializes the session on first use, restoring any previous session.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* function AuthButton() {
|
|
37
|
+
* const { login, logout, isAuthenticated, isAuthenticating } = useAuth()
|
|
38
|
+
*
|
|
39
|
+
* if (isAuthenticated) {
|
|
40
|
+
* return <button onClick={logout}>Logout</button>
|
|
41
|
+
* }
|
|
42
|
+
* return (
|
|
43
|
+
* <button onClick={login} disabled={isAuthenticating}>
|
|
44
|
+
* {isAuthenticating ? "Connecting..." : "Login"}
|
|
45
|
+
* </button>
|
|
46
|
+
* )
|
|
47
|
+
* }
|
|
48
|
+
*/
|
|
49
|
+
const useAuth = () => {
|
|
50
|
+
const { login, logout, authenticate } = clientManager;
|
|
51
|
+
const { isAuthenticated, isAuthenticating, identity, error } = useAuthState();
|
|
52
|
+
// Track if we've already initialized to avoid duplicate calls
|
|
53
|
+
const initializedRef = useRef(false);
|
|
54
|
+
// Auto-initialize on first mount to restore previous session
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
if (!initializedRef.current) {
|
|
57
|
+
initializedRef.current = true;
|
|
58
|
+
clientManager.initialize();
|
|
59
|
+
}
|
|
60
|
+
}, []);
|
|
61
|
+
const principal = useMemo(() => (identity ? identity.getPrincipal() : null), [identity]);
|
|
62
|
+
return {
|
|
63
|
+
authenticate,
|
|
64
|
+
login,
|
|
65
|
+
logout,
|
|
66
|
+
isAuthenticated,
|
|
67
|
+
isAuthenticating,
|
|
68
|
+
principal,
|
|
69
|
+
identity,
|
|
70
|
+
error,
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Get the current user's Principal.
|
|
75
|
+
* Returns null if not authenticated.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* function UserInfo() {
|
|
79
|
+
* const principal = useUserPrincipal()
|
|
80
|
+
* if (!principal) return null
|
|
81
|
+
* return <span>Logged in as: {principal.toText()}</span>
|
|
82
|
+
* }
|
|
83
|
+
*/
|
|
84
|
+
const useUserPrincipal = () => {
|
|
85
|
+
const { identity } = useAuthState();
|
|
86
|
+
return identity ? identity.getPrincipal() : null;
|
|
87
|
+
};
|
|
88
|
+
return {
|
|
89
|
+
useAuth,
|
|
90
|
+
useAgentState,
|
|
91
|
+
useUserPrincipal,
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
//# sourceMappingURL=createAuthHooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createAuthHooks.js","sourceRoot":"","sources":["../src/createAuthHooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAuBxE;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,aAA4B,EACL,EAAE;IACzB;;;OAGG;IACH,MAAM,aAAa,GAAG,GAAe,EAAE,CACrC,oBAAoB,CAClB,CAAC,QAAQ,EAAE,EAAE,CAAC,aAAa,CAAC,mBAAmB,CAAC,QAAQ,CAAC,EACzD,GAAG,EAAE,CAAC,aAAa,CAAC,UAAU;IAC9B,kDAAkD;IAClD,GAAG,EAAE,CAAC,aAAa,CAAC,UAAU,CAC/B,CAAA;IAEH;;;OAGG;IACH,MAAM,YAAY,GAAG,GAAc,EAAE,CACnC,oBAAoB,CAClB,CAAC,QAAQ,EAAE,EAAE,CAAC,aAAa,CAAC,kBAAkB,CAAC,QAAQ,CAAC,EACxD,GAAG,EAAE,CAAC,aAAa,CAAC,SAAS;IAC7B,kDAAkD;IAClD,GAAG,EAAE,CAAC,aAAa,CAAC,SAAS,CAC9B,CAAA;IAEH;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,OAAO,GAAG,GAAkB,EAAE;QAClC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,aAAa,CAAA;QACrD,MAAM,EAAE,eAAe,EAAE,gBAAgB,EAAE,QAAQ,EAAE,KAAK,EAAE,GAC1D,YAAY,EAAE,CAAA;QAEhB,8DAA8D;QAC9D,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;QAEpC,6DAA6D;QAC7D,SAAS,CAAC,GAAG,EAAE;YACb,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;gBAC5B,cAAc,CAAC,OAAO,GAAG,IAAI,CAAA;gBAC7B,aAAa,CAAC,UAAU,EAAE,CAAA;YAC5B,CAAC;QACH,CAAC,EAAE,EAAE,CAAC,CAAA;QAEN,MAAM,SAAS,GAAG,OAAO,CACvB,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EACjD,CAAC,QAAQ,CAAC,CACX,CAAA;QAED,OAAO;YACL,YAAY;YACZ,KAAK;YACL,MAAM;YACN,eAAe;YACf,gBAAgB;YAChB,SAAS;YACT,QAAQ;YACR,KAAK;SACN,CAAA;IACH,CAAC,CAAA;IAED;;;;;;;;;;OAUG;IACH,MAAM,gBAAgB,GAAG,GAAqB,EAAE;QAC9C,MAAM,EAAE,QAAQ,EAAE,GAAG,YAAY,EAAE,CAAA;QACnC,OAAO,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;IAClD,CAAC,CAAA;IAED,OAAO;QACL,OAAO;QACP,aAAa;QACb,gBAAgB;KACjB,CAAA;AACH,CAAC,CAAA"}
|