@ic-reactor/vite-plugin 0.14.0 → 0.15.1

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
@@ -1,5 +1,10 @@
1
1
  # @ic-reactor/vite-plugin
2
2
 
3
+ > **AI coding agents:** read [`llms.txt`](./llms.txt) in this package
4
+ > (`node_modules/@ic-reactor/vite-plugin/llms.txt`) before writing code with it. It
5
+ > is written for the installed version and lists the patterns to use and the
6
+ > mistakes to avoid.
7
+
3
8
  Vite plugin for IC Reactor code generation. It runs the shared
4
9
  `@ic-reactor/codegen` pipeline, watches `.did` files, and can inject the
5
10
  `ic_env` cookie used by `ClientManager` during local development.
@@ -43,8 +48,9 @@ export const clientManager = new ClientManager({
43
48
  No opt-in flag is needed to pick up the plugin's environment in development:
44
49
  the plugin sets the `ic_env` cookie and `ClientManager` reads it automatically
45
50
  in the browser. That trust stops at the local replica — cookies are not
46
- origin-isolated, so on a custom domain or mainnet the cookie is ignored and a
47
- reactor with no `canisterId` throws. Set the per-canister `canisterId` in the
51
+ origin-isolated, so on a custom domain, on mainnet, and on Codespaces or Gitpod
52
+ (whose workspaces share a parent domain with every other user's) the cookie is
53
+ ignored and a reactor with no `canisterId` throws. Set the per-canister `canisterId` in the
48
54
  plugin config to bake it into the generated output for those builds, or pass
49
55
  `allowEnvConfig: true` to `ClientManager` if you trust every subdomain of the
50
56
  domain you serve from.
@@ -57,11 +63,43 @@ exports the reactor and six hooks named after the canister
57
63
  `use<Canister>InfiniteQuery`, `use<Canister>SuspenseInfiniteQuery`,
58
64
  `use<Canister>Mutation`, `use<Canister>Method`).
59
65
 
66
+ Set `factories: true` on a canister to also generate
67
+ `index.factories.generated.ts`, a query or mutation object per method bound to
68
+ the generated reactor: `createQuery` for a query method without arguments,
69
+ `createQueryFactory` for one with arguments, and `createMutation` for an
70
+ update or oneway method, named `<method>Query` or `<method>Mutation` with the
71
+ method name in camelCase. The default `index.ts` wrapper re-exports it; an
72
+ `index.ts` you have edited is left alone, and the plugin warns in the terminal
73
+ until it re-exports the factories. It needs `target: "react"`. See
74
+ https://ic-reactor.b3pay.net/v3/packages/codegen#query-and-mutation-factories
75
+ for the naming rule for any method name.
76
+
77
+ ```ts
78
+ import { icReactor } from "@ic-reactor/vite-plugin"
79
+
80
+ icReactor({
81
+ canisters: [
82
+ { name: "backend", didFile: "./backend/backend.did", factories: true },
83
+ ],
84
+ })
85
+ ```
86
+
87
+ ```tsx
88
+ import { getMessageQuery, setMessageMutation } from "./declarations/backend"
89
+
90
+ // In a component
91
+ const { data } = getMessageQuery.useQuery()
92
+
93
+ // Anywhere, outside React included
94
+ await setMessageMutation.execute(["hello"])
95
+ ```
96
+
60
97
  If Prettier resolves from Vite's `config.root`, the plugin formats the
61
- generated `.js` and `.d.ts` with it and your Prettier config, so a rebuild
62
- leaves formatted, committed declarations unchanged. Without Prettier they hold
63
- the Candid parser's output followed by a newline, and a formatting error never
64
- fails the build.
98
+ generated `.js`, `.d.ts`, `index.generated.ts`, `index.factories.generated.ts`
99
+ and the `index.ts` wrapper it writes with it and your Prettier config, so a rebuild leaves formatted,
100
+ committed output unchanged. Without Prettier the declarations hold the Candid
101
+ parser's output followed by a newline, and a formatting error never fails the
102
+ build.
65
103
 
66
104
  If you want non-React output, set `target: "core"` and install the matching
67
105
  runtime package instead of `@ic-reactor/react`.
@@ -69,6 +107,8 @@ runtime package instead of `@ic-reactor/react`.
69
107
  ## Options
70
108
 
71
109
  ```ts
110
+ import { icReactor } from "@ic-reactor/vite-plugin"
111
+
72
112
  icReactor({
73
113
  canisters: [
74
114
  {
@@ -110,6 +150,14 @@ of a `.did` file being edited.
110
150
  - `target`
111
151
  - `mode`
112
152
  - `canisterId`
153
+ - `factories`: also generate `index.factories.generated.ts` (default `false`)
154
+
155
+ Each entry needs an output directory of its own. Two entries with the same
156
+ `name` and no `outDir`, or with `outDir` values that reach one directory, would
157
+ overwrite each other's output, so the plugin generates the first of them and
158
+ fails the later one with the error the CLI reports. To generate one canister
159
+ twice, say as a `DisplayReactor` and as a `Reactor`, give each entry its own
160
+ `outDir`.
113
161
 
114
162
  Supported `mode` values:
115
163
 
@@ -126,12 +174,13 @@ Supported `target` values:
126
174
 
127
175
  ## Local Development Behavior
128
176
 
129
- When `injectEnvironment` is enabled during `vite dev`, the plugin:
177
+ When `injectEnvironment` is enabled during `vite dev` or `vite preview`, the
178
+ plugin:
130
179
 
131
180
  1. asks `icp` for the local network status
132
181
  2. resolves canister IDs — `internet_identity` is added automatically if not
133
182
  already in your canister list
134
- 3. sets the `ic_env` cookie
183
+ 3. sets the `ic_env` cookie on each response
135
184
  4. proxies `/api` to the local replica
136
185
 
137
186
  If a canister has a `canisterId` set in the plugin config, that value overrides
@@ -140,28 +189,54 @@ the auto-detected ID for that canister.
140
189
  Set the `ICP_ENVIRONMENT` environment variable to target a non-default network
141
190
  (defaults to `"local"`).
142
191
 
143
- If environment detection fails, the plugin still falls back to proxying `/api`
144
- to `http://127.0.0.1:4943`, but it will not inject canister metadata. It warns
145
- when that happens with canisters configured, because the failure is otherwise
146
- indistinguishable from success until the app breaks on an undefined canister
147
- id. Run with `DEBUG=ic-reactor` to see the `icp` output behind the warning.
148
-
149
- If your Vite config already sets `server.proxy["/api"]`, the plugin leaves that
150
- entry alone, whether detection succeeds or not.
192
+ If environment detection fails, the plugin falls back to proxying `/api` to
193
+ `http://127.0.0.1:4943`, and sets no cookie, or with no canisters configured one
194
+ that names only icp-cli's built-in Internet Identity. It warns when that happens
195
+ with canisters configured, and when a configured canister has no ID, because
196
+ the failure is otherwise indistinguishable from success until the app breaks on
197
+ an undefined canister id. Run with `DEBUG=ic-reactor` to see the `icp` output
198
+ behind the warning.
199
+
200
+ Detection is complete once `icp` reports the network and every configured
201
+ canister has an ID. Until then the plugin asks `icp` again on each page load,
202
+ and that page gets the answer: start `vite dev` first, then run
203
+ `icp network start` and `icp deploy`, and reload the page. The `/api` proxy
204
+ moves to the network `icp` reports, the fallback included. Once detection is
205
+ complete, page loads run no further `icp` commands, so redeploying into a
206
+ fresh network, with new canister IDs and a new root key, needs a dev server
207
+ restart. A configured canister you never deploy locally keeps detection
208
+ incomplete, so every page load runs `icp` for it; set its `canisterId` and it
209
+ counts as resolved. If you never run a local network, set
210
+ `injectEnvironment: false` and page loads run no `icp`.
211
+
212
+ If your Vite config or another plugin sets `server.proxy["/api"]`, the plugin
213
+ leaves that entry alone, whether detection succeeds or not, and that proxy does
214
+ not follow detection.
151
215
 
152
216
  ## File Regeneration
153
217
 
154
218
  On startup and on `.did` file changes, the plugin regenerates declarations and
155
- the managed `index.generated.ts` implementation. The user-facing `index.ts`
219
+ the managed `index.generated.ts` implementation, and `index.factories.generated.ts`
220
+ for a canister that sets `factories: true`. The user-facing `index.ts`
156
221
  entry is created once, then preserved unless it still matches the default
157
222
  wrapper or a legacy generated scaffold that can be migrated automatically.
158
223
  When a watched `.did` file changes, the plugin sends a full browser reload so
159
- the new declarations are picked up. Regeneration is serialized per canister —
160
- saves that land while a run is in flight collapse into a single rerun — so two
161
- rapid saves cannot interleave inside the pipeline's delete-then-write sequence.
224
+ the new declarations are picked up.
225
+
226
+ The plugin follows the dev server's file watcher itself, so a `.did` file that
227
+ appears after the server started, or that a build tool deletes and writes
228
+ again, is generated too, and saves regenerate even with `server.hmr: false`.
229
+
230
+ Regeneration is serialized per canister — saves that land while a run is in
231
+ flight collapse into a single rerun — so two rapid saves cannot interleave
232
+ inside the pipeline's delete-then-write sequence.
162
233
  A regeneration that fails is reported to the terminal and to the browser error
163
234
  overlay rather than leaving the page on stale bindings.
164
235
 
236
+ `vite build --watch` watches the configured `.did` files as well. Saving one
237
+ starts a rebuild that regenerates that canister's bindings. A rebuild that any
238
+ other file starts leaves the generated files alone.
239
+
165
240
  ## When To Use It
166
241
 
167
242
  - Vite apps with active `.did` iteration