@ic-reactor/cli 0.0.0-dev

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 ADDED
@@ -0,0 +1,267 @@
1
+ # @ic-reactor/cli
2
+
3
+ > 🔧 Generate shadcn-style React hooks for ICP canisters
4
+
5
+ The `@ic-reactor/cli` generates **customizable, user-owned** React hooks for interacting with Internet Computer canisters. Unlike build-time code generation, you get full control over the generated code.
6
+
7
+ ## Philosophy
8
+
9
+ Like [shadcn/ui](https://ui.shadcn.com/), this CLI generates code **into your project** rather than hiding it in `node_modules`. This means:
10
+
11
+ - ✅ **Full control** - Customize hooks to your needs
12
+ - ✅ **No magic** - See exactly what's happening
13
+ - ✅ **Version controlled** - Hooks are part of your codebase
14
+ - ✅ **Framework agnostic** - Works with any React setup
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install -D @ic-reactor/cli
20
+ # or
21
+ pnpm add -D @ic-reactor/cli
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ ### 1. Initialize your project
27
+
28
+ ```bash
29
+ npx @ic-reactor/cli init
30
+ ```
31
+
32
+ This creates:
33
+
34
+ - `reactor.config.json` - Configuration file
35
+ - `src/lib/client.ts` - Client manager (optional)
36
+ - `src/canisters/` - Output directory for hooks
37
+
38
+ ### 2. Add hooks for a canister
39
+
40
+ ```bash
41
+ npx @ic-reactor/cli add
42
+ ```
43
+
44
+ Interactive prompts will guide you through:
45
+
46
+ 1. Selecting a canister
47
+ 2. Choosing methods to generate hooks for
48
+ 3. Selecting hook types (Query, Suspense Query, Infinite Query, Mutation)
49
+
50
+ ### 3. Use the hooks
51
+
52
+ ```tsx
53
+ import { useGetMessageQuery, getMessageQuery } from "./canisters/backend/hooks"
54
+
55
+ function MyComponent() {
56
+ // Use the React hook
57
+ const { data, isLoading } = useGetMessageQuery()
58
+
59
+ // Or fetch directly (for loaders, etc.)
60
+ await getMessageQuery.fetch()
61
+
62
+ // Invalidate cache
63
+ await getMessageQuery.invalidate()
64
+ }
65
+ ```
66
+
67
+ ## Commands
68
+
69
+ ### `init`
70
+
71
+ Initialize ic-reactor in your project.
72
+
73
+ ```bash
74
+ npx @ic-reactor/cli init [options]
75
+
76
+ Options:
77
+ -y, --yes Skip prompts and use defaults
78
+ -o, --out-dir <path> Output directory for generated hooks
79
+ ```
80
+
81
+ ### `add`
82
+
83
+ Add hooks for canister methods (from local .did file).
84
+
85
+ ```bash
86
+ npx @ic-reactor/cli add [options]
87
+
88
+ Options:
89
+ -c, --canister <name> Canister to add hooks for
90
+ -m, --methods <methods...> Specific methods to generate
91
+ -a, --all Add hooks for all methods
92
+ ```
93
+
94
+ ### `fetch`
95
+
96
+ **Fetch Candid from a live canister** and generate hooks. No local .did file needed!
97
+
98
+ ```bash
99
+ npx @ic-reactor/cli fetch [options]
100
+
101
+ Options:
102
+ -i, --canister-id <id> Canister ID to fetch from
103
+ -n, --network <network> Network: 'ic' or 'local' (default: ic)
104
+ --name <name> Name for the canister in generated code
105
+ -m, --methods <methods...> Specific methods to generate
106
+ -a, --all Add hooks for all methods
107
+ ```
108
+
109
+ **Example:**
110
+
111
+ ```bash
112
+ # Fetch from IC mainnet
113
+ npx @ic-reactor/cli fetch -i ryjl3-tyaaa-aaaaa-aaaba-cai
114
+
115
+ # Fetch from local replica
116
+ npx @ic-reactor/cli fetch -i bkyz2-fmaaa-aaaaa-qaaaq-cai -n local
117
+ ```
118
+
119
+ ### `list`
120
+
121
+ List available methods from a canister.
122
+
123
+ ```bash
124
+ npx @ic-reactor/cli list [options]
125
+
126
+ Options:
127
+ -c, --canister <name> Canister to list methods from
128
+ ```
129
+
130
+ ### `sync`
131
+
132
+ Regenerate hooks after DID file changes.
133
+
134
+ ```bash
135
+ npx @ic-reactor/cli sync [options]
136
+
137
+ Options:
138
+ -c, --canister <name> Canister to sync (default: all)
139
+ ```
140
+
141
+ ## Configuration
142
+
143
+ ### reactor.config.json
144
+
145
+ ```json
146
+ {
147
+ "$schema": "https://raw.githubusercontent.com/B3Pay/ic-reactor/main/packages/cli/schema.json",
148
+ "outDir": "src/canisters",
149
+ "canisters": {
150
+ "backend": {
151
+ "didFile": "./backend.did",
152
+ "clientManagerPath": "../../lib/client",
153
+ "useDisplayReactor": true
154
+ }
155
+ },
156
+ "generatedHooks": {
157
+ "backend": ["get_message", "set_message"]
158
+ }
159
+ }
160
+ ```
161
+
162
+ ### Configuration Options
163
+
164
+ | Option | Description |
165
+ | ------------------------------------ | ----------------------------------------- |
166
+ | `outDir` | Directory where hooks are generated |
167
+ | `canisters` | Canister configurations |
168
+ | `canisters.<name>.didFile` | Path to the `.did` file |
169
+ | `canisters.<name>.clientManagerPath` | Import path to client manager |
170
+ | `canisters.<name>.useDisplayReactor` | Use DisplayReactor for type transforms |
171
+ | `generatedHooks` | Tracks which methods have hooks generated |
172
+
173
+ ## Generated File Structure
174
+
175
+ ```
176
+ src/canisters/
177
+ ├── backend/
178
+ │ ├── reactor.ts # Shared reactor instance
179
+ │ └── hooks/
180
+ │ ├── index.ts # Barrel exports
181
+ │ ├── getMessageQuery.ts # Query hook
182
+ │ ├── setMessageMutation.ts # Mutation hook
183
+ │ └── getPostsInfiniteQuery.ts # Infinite query
184
+ ```
185
+
186
+ ## Hook Types
187
+
188
+ ### Query (methods without side effects)
189
+
190
+ ```typescript
191
+ // For methods WITH arguments - factory pattern
192
+ export const getUserQuery = createQueryFactory(reactor, {
193
+ functionName: "get_user",
194
+ })
195
+
196
+ // Usage
197
+ const query = getUserQuery([userId])
198
+ const { data } = query.useQuery()
199
+
200
+ // For methods WITHOUT arguments - static instance
201
+ export const getConfigQuery = createQuery(reactor, {
202
+ functionName: "get_config",
203
+ })
204
+
205
+ // Usage
206
+ const { data } = getConfigQuery.useQuery()
207
+ await getConfigQuery.fetch()
208
+ ```
209
+
210
+ ### Mutation (methods with side effects)
211
+
212
+ ```typescript
213
+ export const setMessageMutation = createMutation(reactor, {
214
+ functionName: "set_message",
215
+ invalidateQueries: [getMessageQuery.getQueryKey()],
216
+ })
217
+
218
+ // Usage
219
+ const { mutate, isPending } = setMessageMutation.useMutation()
220
+ mutate(["Hello, ICP!"])
221
+ ```
222
+
223
+ ### Infinite Query (paginated data)
224
+
225
+ ```typescript
226
+ export const getPostsInfiniteQuery = createInfiniteQuery(reactor, {
227
+ functionName: "get_posts",
228
+ initialPageParam: 0,
229
+ getArgs: (cursor) => [{ cursor, limit: 10 }],
230
+ getNextPageParam: (lastPage) => lastPage.nextCursor ?? undefined,
231
+ })
232
+
233
+ // Usage
234
+ const { data, fetchNextPage, hasNextPage } =
235
+ getPostsInfiniteQuery.useInfiniteQuery()
236
+ const allPosts = data?.pages.flatMap((page) => page.items) ?? []
237
+ ```
238
+
239
+ ## Customization
240
+
241
+ Since the code is generated into your project, you can:
242
+
243
+ 1. **Modify hook options** - Change staleTime, select transforms, etc.
244
+ 2. **Add custom logic** - Error handling, optimistic updates
245
+ 3. **Combine hooks** - Create composite hooks
246
+ 4. **Type overrides** - Adjust TypeScript types
247
+
248
+ Example customization:
249
+
250
+ ```typescript
251
+ // getMessageQuery.ts (generated, then customized)
252
+ export const getMessageQuery = createQuery(reactor, {
253
+ functionName: "get_message",
254
+ staleTime: 30 * 1000, // Custom: 30 seconds
255
+ select: (data) => data.message.toUpperCase(), // Custom transform
256
+ })
257
+ ```
258
+
259
+ ## Requirements
260
+
261
+ - Node.js 18+
262
+ - @ic-reactor/react 3.x
263
+ - React 18+
264
+
265
+ ## License
266
+
267
+ MIT