@ic-reactor/vite-plugin 0.1.0 → 0.3.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 CHANGED
@@ -24,15 +24,11 @@ Automatically generate type-safe React hooks for your Internet Computer canister
24
24
  ## Installation
25
25
 
26
26
  ```bash
27
- # With npm
28
- npm install -D @ic-reactor/vite-plugin
29
-
30
27
  # With pnpm
31
28
  pnpm add -D @ic-reactor/vite-plugin
32
29
 
33
30
  # Required peer dependencies
34
- npm install @ic-reactor/react @tanstack/react-query @icp-sdk/core
35
- npm install -D @icp-sdk/bindgen
31
+ pnpm add @ic-reactor/react @tanstack/react-query @icp-sdk/core
36
32
  ```
37
33
 
38
34
  ## Quick Start
@@ -62,52 +58,30 @@ export default defineConfig({
62
58
 
63
59
  ### 2. Create Your ClientManager
64
60
 
65
- The plugin expects you to have a `ClientManager` exported from a file. By default, it looks for `./src/lib/client.ts`:
61
+ The plugin expects you to have a `ClientManager` exported from a file. By default, it looks for `./src/lib/clients.ts`:
66
62
 
67
63
  ```typescript
68
- // src/lib/client.ts
64
+ // src/lib/clients.ts
69
65
  import { ClientManager } from "@ic-reactor/react"
70
66
  import { QueryClient } from "@tanstack/react-query"
71
67
 
72
68
  export const queryClient = new QueryClient()
73
-
74
- export const clientManager = new ClientManager({
75
- queryClient,
76
- withCanisterEnv: true, // Enable environment-based canister ID resolution
77
- })
69
+ export const clientManager = new ClientManager({ queryClient })
78
70
  ```
79
71
 
80
72
  ### 3. Use Generated Hooks
81
73
 
82
- The plugin generates hooks in `./src/canisters/<name>/index.ts`:
74
+ The plugin generates an `index.ts` file in your canister folder (default: `./src/lib/canisters/<name>/index.ts`):
83
75
 
84
76
  ```tsx
85
- // Generated at: ./src/canisters/backend/index.ts
86
- import {
87
- backendReactor,
88
- useBackendQuery,
89
- useBackendMutation,
90
- useBackendSuspenseQuery,
91
- } from "./canisters/backend"
77
+ import { useActorQuery, useActorMutation } from "./canisters/backend"
92
78
 
93
79
  function MyComponent() {
94
- // Query data
95
- const { data, isPending } = useBackendQuery({
80
+ const { data, isPending } = useActorQuery({
96
81
  functionName: "get_message",
97
82
  })
98
83
 
99
- // Mutate data
100
- const { mutate } = useBackendMutation({
101
- functionName: "set_message",
102
- onSuccess: () => console.log("Message updated!"),
103
- })
104
-
105
- return (
106
- <div>
107
- <p>{isPending ? "Loading..." : data}</p>
108
- <button onClick={() => mutate(["Hello IC!"])}>Update</button>
109
- </div>
110
- )
84
+ return <p>{isPending ? "Loading..." : data}</p>
111
85
  }
112
86
  ```
113
87
 
@@ -115,123 +89,30 @@ function MyComponent() {
115
89
 
116
90
  ### Plugin Options
117
91
 
118
- ```typescript
119
- interface IcReactorPluginOptions {
120
- /** List of canisters to generate hooks for */
121
- canisters: CanisterConfig[]
122
- /** Base output directory (default: "./src/canisters") */
123
- outDir?: string
124
- /** Path to import ClientManager from (default: "../../lib/client") */
125
- clientManagerPath?: string
126
- }
127
-
128
- interface CanisterConfig {
129
- /** Name of the canister (used for variable naming) */
130
- name: string
131
- /** Path to the .did file */
132
- didFile: string
133
- /** Output directory (default: ./src/canisters/<name>) */
134
- outDir?: string
135
- /** Use DisplayReactor for React-friendly types (default: true) */
136
- useDisplayReactor?: boolean
137
- /** Path to import ClientManager from (relative to generated file) */
138
- clientManagerPath?: string
139
- }
140
- ```
141
-
142
- ### Example: Multiple Canisters
143
-
144
- ```typescript
145
- // vite.config.ts
146
- import { icReactorPlugin } from "@ic-reactor/vite-plugin"
147
-
148
- export default defineConfig({
149
- plugins: [
150
- icReactorPlugin({
151
- clientManagerPath: "@/lib/client", // Global default
152
- canisters: [
153
- {
154
- name: "backend",
155
- didFile: "./backend/backend.did",
156
- },
157
- {
158
- name: "ledger",
159
- didFile: "./ledger/ledger.did",
160
- useDisplayReactor: true, // BigInt → string, etc.
161
- },
162
- {
163
- name: "nft",
164
- didFile: "./nft/nft.did",
165
- outDir: "./src/services/nft", // Custom output
166
- clientManagerPath: "@/lib/nft-client", // Custom client
167
- },
168
- ],
169
- }),
170
- ],
171
- })
172
- ```
173
-
174
- ## Advanced Plugin
92
+ | Option | Type | Description | Default |
93
+ | :------------------ | :----------------- | :--------------------------------------------------- | :---------------------- |
94
+ | `canisters` | `CanisterConfig[]` | List of canisters to generate hooks for. | `[]` |
95
+ | `outDir` | `string` | Base output directory for generated files. | `"./src/lib/canisters"` |
96
+ | `injectEnvironment` | `boolean` | Whether to inject canister IDs into `ic_env` cookie. | `true` |
97
+ | `clientManagerPath` | `string` | Path to a custom `ClientManager` instance. | `"../../clients"` |
175
98
 
176
- For more granular control, use `icReactorAdvancedPlugin` which generates individual hooks per method:
99
+ ### Canister Config
177
100
 
178
- ```typescript
179
- import { icReactorAdvancedPlugin } from "@ic-reactor/vite-plugin"
180
-
181
- export default defineConfig({
182
- plugins: [
183
- icReactorAdvancedPlugin({
184
- canisters: [
185
- {
186
- name: "backend",
187
- didFile: "./backend/backend.did",
188
- },
189
- ],
190
- }),
191
- ],
192
- })
193
- ```
194
-
195
- This generates method-specific hooks:
196
-
197
- ```tsx
198
- import {
199
- useGetMessageQuery,
200
- useSetMessageMutation,
201
- getMessageQuery, // Static query for no-arg methods
202
- } from "./canisters/backend"
203
-
204
- function MyComponent() {
205
- // Method-specific hook
206
- const { data } = useGetMessageQuery([], { staleTime: 5000 })
207
-
208
- // Static query usage
209
- const { data: cached } = getMessageQuery.useQuery()
210
-
211
- const { mutate } = useSetMessageMutation()
212
-
213
- return <div>{data}</div>
214
- }
215
- ```
216
-
217
- ## Generated File Structure
218
-
219
- ```
220
- src/
221
- ├── canisters/
222
- │ └── backend/
223
- │ ├── index.ts # Reactor + hooks
224
- │ └── declarations/
225
- │ └── backend.did.ts # Type declarations
226
- ├── lib/
227
- │ └── client.ts # Your ClientManager (not generated)
228
- ```
101
+ | Option | Type | Description | Required |
102
+ | :------------------ | :-------- | :-------------------------------------------------- | :------- |
103
+ | `name` | `string` | Name of the canister (used in generated code). | Yes |
104
+ | `didFile` | `string` | Path to the `.did` file. | Yes |
105
+ | `outDir` | `string` | Override output directory for this canister. | No |
106
+ | `useDisplayReactor` | `boolean` | Use `DisplayReactor` instead of standard `Reactor`. | `true` |
107
+ | `clientManagerPath` | `string` | Override client manager path for this canister. | No |
229
108
 
230
109
  ## How It Works
231
110
 
232
- 1. **Build Start**: The plugin reads your `.did` files and uses `@icp-sdk/bindgen` to generate TypeScript declarations
233
- 2. **Code Generation**: Creates a reactor instance and typed hooks for each canister
234
- 3. **Hot Reload**: Watches for `.did` file changes and regenerates hooks automatically
111
+ 1. **Build Start**: The plugin reads your `.did` files and generates TypeScript declarations (`.js` and `.d.ts`).
112
+ 2. **Code Generation**: Creates a reactor instance and typed hooks (using `createActorHooks`) for each canister in `index.ts`.
113
+ 3. **Hot Reload**: Watches for `.did` file changes and regenerates everything automatically.
114
+ 4. **Local Proxy**: Configures a Vite proxy to redirect `/api` calls to your local replica.
115
+ 5. **Environment Detection**: Automatically injects canister IDs from `icp-cli` or `dfx` cache into your session.
235
116
 
236
117
  ## DisplayReactor vs Reactor
237
118
 
@@ -260,27 +141,28 @@ icReactorPlugin({
260
141
 
261
142
  ## Integration with ICP CLI
262
143
 
263
- If you're using [icp-cli](https://github.com/AstroxNetwork/icp-cli), configure your `vite.config.ts` to pass canister IDs via the `ic_env` cookie:
144
+ `@ic-reactor/vite-plugin` now supports **zero-config local `icp-cli` canister env injection** during `vite dev`.
145
+
146
+ When dev server starts, the plugin automatically tries to read:
147
+
148
+ - `.icp/cache/mappings/local.ids.json`
149
+
150
+ If present, it sets an `ic_env` cookie with:
151
+
152
+ - `ic_root_key=<local-root-key>`
153
+ - `PUBLIC_CANISTER_ID:<name>=<canister-id>`
154
+
155
+ This means `withCanisterEnv: true` works out of the box after `icp deploy`, without custom cookie code in `vite.config.ts`.
264
156
 
265
157
  ```typescript
266
158
  // vite.config.ts
159
+ import { defineConfig } from "vite"
160
+ import react from "@vitejs/plugin-react"
267
161
  import { icReactorPlugin } from "@ic-reactor/vite-plugin"
268
- import fs from "fs"
269
- import path from "path"
270
-
271
- function loadCanisterIds(): Record<string, string> {
272
- const idsPath = path.resolve(__dirname, ".icp/cache/mappings/local.ids.json")
273
- try {
274
- return JSON.parse(fs.readFileSync(idsPath, "utf-8"))
275
- } catch {
276
- return {}
277
- }
278
- }
279
-
280
- const canisterIds = loadCanisterIds()
281
162
 
282
163
  export default defineConfig({
283
164
  plugins: [
165
+ react(),
284
166
  icReactorPlugin({
285
167
  canisters: [
286
168
  {
@@ -290,15 +172,15 @@ export default defineConfig({
290
172
  ],
291
173
  }),
292
174
  ],
293
- server: {
294
- headers: {
295
- "Set-Cookie": `ic_env=${encodeURIComponent(
296
- Object.entries(canisterIds)
297
- .map(([name, id]) => `PUBLIC_CANISTER_ID:${name}=${id}`)
298
- .join("&")
299
- )}; SameSite=Lax;`,
300
- },
301
- },
175
+ })
176
+ ```
177
+
178
+ If you need to disable this behavior:
179
+
180
+ ```typescript
181
+ icReactorPlugin({
182
+ canisters: [...],
183
+ injectEnvironment: false,
302
184
  })
303
185
  ```
304
186