@ic-reactor/vite-plugin 0.7.0 → 0.7.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/dist/index.cjs CHANGED
@@ -89,6 +89,10 @@ function icReactor(options) {
89
89
  outDir,
90
90
  clientManagerPath
91
91
  };
92
+ const projectRoot = process.cwd();
93
+ const resolveDidPath = (didFile) => import_node_path.default.normalize(
94
+ import_node_path.default.isAbsolute(didFile) ? didFile : import_node_path.default.resolve(projectRoot, didFile)
95
+ );
92
96
  const plugin = {
93
97
  name: "ic-reactor-plugin",
94
98
  enforce: "pre",
@@ -129,8 +133,11 @@ function icReactor(options) {
129
133
  }
130
134
  };
131
135
  },
136
+ configureServer(server) {
137
+ const didFiles = canisters.map((c) => resolveDidPath(c.didFile));
138
+ server.watcher.add(didFiles);
139
+ },
132
140
  async buildStart() {
133
- const projectRoot = process.cwd();
134
141
  console.log(
135
142
  `[ic-reactor] Generating hooks for ${canisters.length} canisters...`
136
143
  );
@@ -158,14 +165,13 @@ function icReactor(options) {
158
165
  handleHotUpdate({ file, server }) {
159
166
  if (file.endsWith(".did")) {
160
167
  const affectedCanister = canisters.find((c) => {
161
- const configPath = import_node_path.default.resolve(process.cwd(), c.didFile);
162
- return configPath === file;
168
+ const configPath = resolveDidPath(c.didFile);
169
+ return configPath === import_node_path.default.normalize(file);
163
170
  });
164
171
  if (affectedCanister) {
165
172
  console.log(
166
173
  `[ic-reactor] .did file changed: ${affectedCanister.name}. Regenerating...`
167
174
  );
168
- const projectRoot = process.cwd();
169
175
  (0, import_codegen.runCanisterPipeline)({
170
176
  canisterConfig: affectedCanister,
171
177
  projectRoot,
package/dist/index.js CHANGED
@@ -57,6 +57,10 @@ function icReactor(options) {
57
57
  outDir,
58
58
  clientManagerPath
59
59
  };
60
+ const projectRoot = process.cwd();
61
+ const resolveDidPath = (didFile) => path.normalize(
62
+ path.isAbsolute(didFile) ? didFile : path.resolve(projectRoot, didFile)
63
+ );
60
64
  const plugin = {
61
65
  name: "ic-reactor-plugin",
62
66
  enforce: "pre",
@@ -97,8 +101,11 @@ function icReactor(options) {
97
101
  }
98
102
  };
99
103
  },
104
+ configureServer(server) {
105
+ const didFiles = canisters.map((c) => resolveDidPath(c.didFile));
106
+ server.watcher.add(didFiles);
107
+ },
100
108
  async buildStart() {
101
- const projectRoot = process.cwd();
102
109
  console.log(
103
110
  `[ic-reactor] Generating hooks for ${canisters.length} canisters...`
104
111
  );
@@ -126,14 +133,13 @@ function icReactor(options) {
126
133
  handleHotUpdate({ file, server }) {
127
134
  if (file.endsWith(".did")) {
128
135
  const affectedCanister = canisters.find((c) => {
129
- const configPath = path.resolve(process.cwd(), c.didFile);
130
- return configPath === file;
136
+ const configPath = resolveDidPath(c.didFile);
137
+ return configPath === path.normalize(file);
131
138
  });
132
139
  if (affectedCanister) {
133
140
  console.log(
134
141
  `[ic-reactor] .did file changed: ${affectedCanister.name}. Regenerating...`
135
142
  );
136
- const projectRoot = process.cwd();
137
143
  runCanisterPipeline({
138
144
  canisterConfig: affectedCanister,
139
145
  projectRoot,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ic-reactor/vite-plugin",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "description": "Vite plugin for zero-config IC reactor generation from Candid files",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -37,14 +37,14 @@
37
37
  "url": "https://github.com/B3Pay/ic-reactor/issues"
38
38
  },
39
39
  "dependencies": {
40
- "@ic-reactor/codegen": "0.7.0"
40
+ "@ic-reactor/codegen": "0.7.2"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
44
44
  },
45
45
  "devDependencies": {
46
- "@icp-sdk/bindgen": "^0.2.1",
47
- "@types/node": "^25.2.3",
46
+ "@icp-sdk/bindgen": "^0.2.2",
47
+ "@types/node": "^25.3.0",
48
48
  "tsup": "^8.5.1",
49
49
  "typescript": "^5.9.3",
50
50
  "vitest": "^4.0.18"
package/src/index.test.ts CHANGED
@@ -1,9 +1,14 @@
1
1
  import { describe, it, expect, vi, beforeEach } from "vitest"
2
- import { icReactor, type IcReactorPluginOptions } from "./index"
2
+ import * as vitePluginModule from "./index"
3
+ import type { IcReactorPluginOptions } from "./index"
3
4
  import path from "path"
4
5
  import { execFileSync } from "child_process"
5
6
  import { runCanisterPipeline } from "@ic-reactor/codegen"
6
7
 
8
+ const createVitePlugin =
9
+ (vitePluginModule as any).icReactor ??
10
+ (vitePluginModule as any).icReactorPlugin
11
+
7
12
  // Mock internal dependencies
8
13
  vi.mock("@ic-reactor/codegen", () => ({
9
14
  runCanisterPipeline: vi.fn(),
@@ -50,6 +55,9 @@ describe("icReactor", () => {
50
55
  ws: {
51
56
  send: vi.fn(),
52
57
  },
58
+ watcher: {
59
+ add: vi.fn(),
60
+ },
53
61
  }
54
62
 
55
63
  beforeEach(() => {
@@ -60,7 +68,7 @@ describe("icReactor", () => {
60
68
  })
61
69
 
62
70
  it("should return correct plugin structure", () => {
63
- const plugin = icReactor(mockOptions)
71
+ const plugin = createVitePlugin(mockOptions)
64
72
  expect(plugin.name).toBe("ic-reactor-plugin")
65
73
  expect(plugin.buildStart).toBeDefined()
66
74
  expect(plugin.handleHotUpdate).toBeDefined()
@@ -89,7 +97,7 @@ describe("icReactor", () => {
89
97
  }
90
98
  )
91
99
 
92
- const plugin = icReactor(mockOptions)
100
+ const plugin = createVitePlugin(mockOptions)
93
101
  const config = (plugin as any).config({}, { command: "serve" })
94
102
 
95
103
  expect(config.server.headers["Set-Cookie"]).toContain("ic_env=")
@@ -107,7 +115,7 @@ describe("icReactor", () => {
107
115
  throw new Error("Command not found")
108
116
  })
109
117
 
110
- const plugin = icReactor(mockOptions)
118
+ const plugin = createVitePlugin(mockOptions)
111
119
  const config = (plugin as any).config({}, { command: "serve" })
112
120
 
113
121
  expect(config.server.headers).toBeUndefined()
@@ -115,7 +123,7 @@ describe("icReactor", () => {
115
123
  })
116
124
 
117
125
  it("should return empty config for build command", () => {
118
- const plugin = icReactor(mockOptions)
126
+ const plugin = createVitePlugin(mockOptions)
119
127
  const config = (plugin as any).config({}, { command: "build" })
120
128
 
121
129
  expect(config).toEqual({})
@@ -124,7 +132,7 @@ describe("icReactor", () => {
124
132
 
125
133
  describe("buildStart", () => {
126
134
  it("should generate declarations and reactor file", async () => {
127
- const plugin = icReactor(mockOptions)
135
+ const plugin = createVitePlugin(mockOptions)
128
136
  await (plugin.buildStart as any)()
129
137
 
130
138
  expect(runCanisterPipeline).toHaveBeenCalledWith({
@@ -147,7 +155,7 @@ describe("icReactor", () => {
147
155
  error: "Failed to generate",
148
156
  })
149
157
 
150
- const plugin = icReactor(mockOptions)
158
+ const plugin = createVitePlugin(mockOptions)
151
159
  await (plugin.buildStart as any)()
152
160
 
153
161
  expect(consoleErrorSpy).toHaveBeenCalledWith(
@@ -158,7 +166,7 @@ describe("icReactor", () => {
158
166
  })
159
167
 
160
168
  it("should pass canister mode through to codegen via canister config", async () => {
161
- const plugin = icReactor({
169
+ const plugin = createVitePlugin({
162
170
  canisters: [
163
171
  {
164
172
  ...mockOptions.canisters[0],
@@ -185,8 +193,17 @@ describe("icReactor", () => {
185
193
  })
186
194
 
187
195
  describe("handleHotUpdate", () => {
196
+ it("should register configured .did files with the watcher", () => {
197
+ const plugin = createVitePlugin(mockOptions)
198
+ ;(plugin.configureServer as any)(mockServer)
199
+
200
+ expect(mockServer.watcher.add).toHaveBeenCalledWith([
201
+ expect.stringContaining("src/declarations/test.did"),
202
+ ])
203
+ })
204
+
188
205
  it("should restart server when .did file changes", async () => {
189
- const plugin = icReactor(mockOptions)
206
+ const plugin = createVitePlugin(mockOptions)
190
207
  const ctx = {
191
208
  file: "/absolute/path/to/src/declarations/test.did",
192
209
  server: mockServer,
@@ -207,7 +224,7 @@ describe("icReactor", () => {
207
224
  })
208
225
 
209
226
  it("should ignore other files", () => {
210
- const plugin = icReactor(mockOptions)
227
+ const plugin = createVitePlugin(mockOptions)
211
228
  const ctx = {
212
229
  file: "/some/other/file.ts",
213
230
  server: mockServer,
package/src/index.ts CHANGED
@@ -52,6 +52,11 @@ export function icReactor(options: IcReactorPluginOptions): any {
52
52
  outDir,
53
53
  clientManagerPath,
54
54
  }
55
+ const projectRoot = process.cwd()
56
+ const resolveDidPath = (didFile: string) =>
57
+ path.normalize(
58
+ path.isAbsolute(didFile) ? didFile : path.resolve(projectRoot, didFile)
59
+ )
55
60
 
56
61
  const plugin: Plugin = {
57
62
  name: "ic-reactor-plugin",
@@ -105,10 +110,15 @@ export function icReactor(options: IcReactorPluginOptions): any {
105
110
  }
106
111
  },
107
112
 
113
+ configureServer(server) {
114
+ // Explicitly watch configured DID files so HMR works even when they are not in the module graph.
115
+ const didFiles = canisters.map((c) => resolveDidPath(c.didFile))
116
+ server.watcher.add(didFiles)
117
+ },
118
+
108
119
  async buildStart() {
109
120
  // ── Code Generation ──────────────────────────────────────────────────
110
121
 
111
- const projectRoot = process.cwd()
112
122
  console.log(
113
123
  `[ic-reactor] Generating hooks for ${canisters.length} canisters...`
114
124
  )
@@ -148,8 +158,8 @@ export function icReactor(options: IcReactorPluginOptions): any {
148
158
  const affectedCanister = canisters.find((c) => {
149
159
  // Check if changed file matches configured didFile
150
160
  // Cast is safe because didFile is required in CanisterConfig
151
- const configPath = path.resolve(process.cwd(), c.didFile)
152
- return configPath === file
161
+ const configPath = resolveDidPath(c.didFile)
162
+ return configPath === path.normalize(file)
153
163
  })
154
164
 
155
165
  if (affectedCanister) {
@@ -158,7 +168,6 @@ export function icReactor(options: IcReactorPluginOptions): any {
158
168
  )
159
169
 
160
170
  // Re-run pipeline for this canister
161
- const projectRoot = process.cwd()
162
171
  runCanisterPipeline({
163
172
  canisterConfig: affectedCanister,
164
173
  projectRoot,