@ic-reactor/vite-plugin 0.13.1 → 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,12 +63,52 @@ 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
+
97
+ If Prettier resolves from Vite's `config.root`, the plugin formats the
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.
103
+
60
104
  If you want non-React output, set `target: "core"` and install the matching
61
105
  runtime package instead of `@ic-reactor/react`.
62
106
 
63
107
  ## Options
64
108
 
65
109
  ```ts
110
+ import { icReactor } from "@ic-reactor/vite-plugin"
111
+
66
112
  icReactor({
67
113
  canisters: [
68
114
  {
@@ -104,6 +150,14 @@ of a `.did` file being edited.
104
150
  - `target`
105
151
  - `mode`
106
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`.
107
161
 
108
162
  Supported `mode` values:
109
163
 
@@ -120,12 +174,13 @@ Supported `target` values:
120
174
 
121
175
  ## Local Development Behavior
122
176
 
123
- When `injectEnvironment` is enabled during `vite dev`, the plugin:
177
+ When `injectEnvironment` is enabled during `vite dev` or `vite preview`, the
178
+ plugin:
124
179
 
125
180
  1. asks `icp` for the local network status
126
181
  2. resolves canister IDs — `internet_identity` is added automatically if not
127
182
  already in your canister list
128
- 3. sets the `ic_env` cookie
183
+ 3. sets the `ic_env` cookie on each response
129
184
  4. proxies `/api` to the local replica
130
185
 
131
186
  If a canister has a `canisterId` set in the plugin config, that value overrides
@@ -134,25 +189,54 @@ the auto-detected ID for that canister.
134
189
  Set the `ICP_ENVIRONMENT` environment variable to target a non-default network
135
190
  (defaults to `"local"`).
136
191
 
137
- If environment detection fails, the plugin still falls back to proxying `/api`
138
- to `http://127.0.0.1:4943`, but it will not inject canister metadata. It warns
139
- when that happens with canisters configured, because the failure is otherwise
140
- indistinguishable from success until the app breaks on an undefined canister
141
- id. Run with `DEBUG=ic-reactor` to see the `icp` output behind the warning.
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.
142
215
 
143
216
  ## File Regeneration
144
217
 
145
218
  On startup and on `.did` file changes, the plugin regenerates declarations and
146
- 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`
147
221
  entry is created once, then preserved unless it still matches the default
148
222
  wrapper or a legacy generated scaffold that can be migrated automatically.
149
223
  When a watched `.did` file changes, the plugin sends a full browser reload so
150
- the new declarations are picked up. Regeneration is serialized per canister —
151
- saves that land while a run is in flight collapse into a single rerun — so two
152
- 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.
153
233
  A regeneration that fails is reported to the terminal and to the browser error
154
234
  overlay rather than leaving the page on stale bindings.
155
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
+
156
240
  ## When To Use It
157
241
 
158
242
  - Vite apps with active `.did` iteration