@ic-reactor/vite-plugin 0.5.1 → 0.6.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
@@ -38,12 +38,12 @@ pnpm add @ic-reactor/react @tanstack/react-query @icp-sdk/core
38
38
  // vite.config.ts
39
39
  import { defineConfig } from "vite"
40
40
  import react from "@vitejs/plugin-react"
41
- import { icReactorPlugin } from "@ic-reactor/vite-plugin"
41
+ import { icReactor } from "@ic-reactor/vite-plugin"
42
42
 
43
43
  export default defineConfig({
44
44
  plugins: [
45
45
  react(),
46
- icReactorPlugin({
46
+ icReactor({
47
47
  canisters: [
48
48
  {
49
49
  name: "backend",
@@ -87,6 +87,56 @@ function MyComponent() {
87
87
  }
88
88
  ```
89
89
 
90
+ ### Reactor Mode (raw vs display)
91
+
92
+ By default, generated hooks use `DisplayReactor` (backward compatible). You can switch the default globally, and override specific canisters that need raw Candid shapes.
93
+
94
+ ```ts
95
+ icReactor({
96
+ canisters: [
97
+ { name: "backend", didFile: "./backend/backend.did" },
98
+ { name: "workflow_engine", didFile: "./workflow/workflow_engine.did" },
99
+ ],
100
+ reactor: {
101
+ defaultMode: "display",
102
+ canisters: {
103
+ workflow_engine: "raw",
104
+ },
105
+ },
106
+ })
107
+ ```
108
+
109
+ Generated canister folders now contain:
110
+
111
+ - `index.generated.ts` (overwritten on regenerate)
112
+ - `index.ts` (created once if missing, never overwritten)
113
+
114
+ The generated implementation exports both factories so apps can opt in explicitly without editing generated files:
115
+
116
+ ```ts
117
+ // display-default canister (generated)
118
+ export function createBackendRawReactor() {
119
+ /* ... */
120
+ }
121
+ export function createBackendDisplayReactor() {
122
+ /* ... */
123
+ }
124
+ export const backendReactor = createBackendDisplayReactor()
125
+ export const BackendReactorMode = "display" as const
126
+ ```
127
+
128
+ ```ts
129
+ // raw-default canister (generated)
130
+ export function createWorkflowEngineRawReactor() {
131
+ /* ... */
132
+ }
133
+ export function createWorkflowEngineDisplayReactor() {
134
+ /* ... */
135
+ }
136
+ export const workflowEngineReactor = createWorkflowEngineRawReactor()
137
+ export const WorkflowEngineReactorMode = "raw" as const
138
+ ```
139
+
90
140
  ## Configuration
91
141
 
92
142
  ### Plugin Options
@@ -97,6 +147,7 @@ function MyComponent() {
97
147
  | `outDir` | `string` | Base output directory for generated files. | `"src/declarations"` |
98
148
  | `clientManagerPath` | `string` | Path to client manager import. | `"../../clients"` |
99
149
  | `injectEnvironment` | `boolean` | Inject `ic_env` cookie for local development. | `true` |
150
+ | `reactor` | `ReactorConfig` | Default/per-canister raw vs display reactor mode. | display default |
100
151
 
101
152
  ### Canister Config
102
153
 
@@ -108,6 +159,13 @@ function MyComponent() {
108
159
  | `clientManagerPath` | `string` | Override client manager path. | No |
109
160
  | `canisterId` | `string` | Optional fixed canister ID. | No |
110
161
 
162
+ ### ReactorConfig
163
+
164
+ | Option | Type | Description | Required |
165
+ | :------------ | :----------------------------------- | :--------------------------------------- | :------- |
166
+ | `defaultMode` | `"raw" \| "display"` | Global default mode for generated hooks. | No |
167
+ | `canisters` | `Record<string, "raw" \| "display">` | Per-canister overrides keyed by name. | No |
168
+
111
169
  ## Local Development (Environment Injection)
112
170
 
113
171
  When running `vite dev`, the plugin automatically handles local canister environment connection:
package/dist/index.cjs CHANGED
@@ -30,7 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
- icReactorPlugin: () => icReactorPlugin
33
+ icReactor: () => icReactor
34
34
  });
35
35
  module.exports = __toCommonJS(index_exports);
36
36
  var import_node_path = __toESM(require("path"), 1);
@@ -78,17 +78,21 @@ function buildIcEnvCookie(canisterIds, rootKey) {
78
78
  }
79
79
 
80
80
  // src/index.ts
81
- function icReactorPlugin(options) {
81
+ function icReactor(options) {
82
82
  const {
83
83
  canisters,
84
84
  outDir = "src/declarations",
85
85
  clientManagerPath = "../../clients",
86
- injectEnvironment = true
86
+ injectEnvironment = true,
87
+ reactor
87
88
  } = options;
88
89
  const globalConfig = {
89
90
  outDir,
90
91
  clientManagerPath
91
92
  };
93
+ if (reactor != null) {
94
+ globalConfig.reactor = reactor;
95
+ }
92
96
  const plugin = {
93
97
  name: "ic-reactor-plugin",
94
98
  enforce: "pre",
@@ -185,5 +189,5 @@ function icReactorPlugin(options) {
185
189
  }
186
190
  // Annotate the CommonJS export names for ESM import in node:
187
191
  0 && (module.exports = {
188
- icReactorPlugin
192
+ icReactor
189
193
  });
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { CanisterConfig } from '@ic-reactor/codegen';
1
+ import { CanisterConfig, ReactorGenerationConfig } from '@ic-reactor/codegen';
2
2
 
3
3
  /**
4
4
  * @ic-reactor/vite-plugin
@@ -30,7 +30,12 @@ interface IcReactorPluginOptions {
30
30
  * Default: true
31
31
  */
32
32
  injectEnvironment?: boolean;
33
+ /**
34
+ * Reactor generation behavior.
35
+ * Controls whether generated default hooks use raw (Reactor) or display (DisplayReactor).
36
+ */
37
+ reactor?: ReactorGenerationConfig;
33
38
  }
34
- declare function icReactorPlugin(options: IcReactorPluginOptions): any;
39
+ declare function icReactor(options: IcReactorPluginOptions): any;
35
40
 
36
- export { type IcReactorPluginOptions, icReactorPlugin };
41
+ export { type IcReactorPluginOptions, icReactor };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { CanisterConfig } from '@ic-reactor/codegen';
1
+ import { CanisterConfig, ReactorGenerationConfig } from '@ic-reactor/codegen';
2
2
 
3
3
  /**
4
4
  * @ic-reactor/vite-plugin
@@ -30,7 +30,12 @@ interface IcReactorPluginOptions {
30
30
  * Default: true
31
31
  */
32
32
  injectEnvironment?: boolean;
33
+ /**
34
+ * Reactor generation behavior.
35
+ * Controls whether generated default hooks use raw (Reactor) or display (DisplayReactor).
36
+ */
37
+ reactor?: ReactorGenerationConfig;
33
38
  }
34
- declare function icReactorPlugin(options: IcReactorPluginOptions): any;
39
+ declare function icReactor(options: IcReactorPluginOptions): any;
35
40
 
36
- export { type IcReactorPluginOptions, icReactorPlugin };
41
+ export { type IcReactorPluginOptions, icReactor };
package/dist/index.js CHANGED
@@ -46,17 +46,21 @@ function buildIcEnvCookie(canisterIds, rootKey) {
46
46
  }
47
47
 
48
48
  // src/index.ts
49
- function icReactorPlugin(options) {
49
+ function icReactor(options) {
50
50
  const {
51
51
  canisters,
52
52
  outDir = "src/declarations",
53
53
  clientManagerPath = "../../clients",
54
- injectEnvironment = true
54
+ injectEnvironment = true,
55
+ reactor
55
56
  } = options;
56
57
  const globalConfig = {
57
58
  outDir,
58
59
  clientManagerPath
59
60
  };
61
+ if (reactor != null) {
62
+ globalConfig.reactor = reactor;
63
+ }
60
64
  const plugin = {
61
65
  name: "ic-reactor-plugin",
62
66
  enforce: "pre",
@@ -152,5 +156,5 @@ function icReactorPlugin(options) {
152
156
  return plugin;
153
157
  }
154
158
  export {
155
- icReactorPlugin
159
+ icReactor
156
160
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ic-reactor/vite-plugin",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
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,7 +37,7 @@
37
37
  "url": "https://github.com/B3Pay/ic-reactor/issues"
38
38
  },
39
39
  "dependencies": {
40
- "@ic-reactor/codegen": "0.5.1"
40
+ "@ic-reactor/codegen": "0.6.0"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
package/src/index.test.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect, vi, beforeEach } from "vitest"
2
- import { icReactorPlugin, type IcReactorPluginOptions } from "./index"
2
+ import { icReactor, type IcReactorPluginOptions } from "./index"
3
3
  import path from "path"
4
4
  import { execFileSync } from "child_process"
5
5
  import { runCanisterPipeline } from "@ic-reactor/codegen"
@@ -24,7 +24,7 @@ vi.mock("fs", () => ({
24
24
  },
25
25
  }))
26
26
 
27
- describe("icReactorPlugin", () => {
27
+ describe("icReactor", () => {
28
28
  const mockOptions: IcReactorPluginOptions = {
29
29
  canisters: [
30
30
  {
@@ -60,7 +60,7 @@ describe("icReactorPlugin", () => {
60
60
  })
61
61
 
62
62
  it("should return correct plugin structure", () => {
63
- const plugin = icReactorPlugin(mockOptions)
63
+ const plugin = icReactor(mockOptions)
64
64
  expect(plugin.name).toBe("ic-reactor-plugin")
65
65
  expect(plugin.buildStart).toBeDefined()
66
66
  expect(plugin.handleHotUpdate).toBeDefined()
@@ -89,7 +89,7 @@ describe("icReactorPlugin", () => {
89
89
  }
90
90
  )
91
91
 
92
- const plugin = icReactorPlugin(mockOptions)
92
+ const plugin = icReactor(mockOptions)
93
93
  const config = (plugin as any).config({}, { command: "serve" })
94
94
 
95
95
  expect(config.server.headers["Set-Cookie"]).toContain("ic_env=")
@@ -107,7 +107,7 @@ describe("icReactorPlugin", () => {
107
107
  throw new Error("Command not found")
108
108
  })
109
109
 
110
- const plugin = icReactorPlugin(mockOptions)
110
+ const plugin = icReactor(mockOptions)
111
111
  const config = (plugin as any).config({}, { command: "serve" })
112
112
 
113
113
  expect(config.server.headers).toBeUndefined()
@@ -115,7 +115,7 @@ describe("icReactorPlugin", () => {
115
115
  })
116
116
 
117
117
  it("should return empty config for build command", () => {
118
- const plugin = icReactorPlugin(mockOptions)
118
+ const plugin = icReactor(mockOptions)
119
119
  const config = (plugin as any).config({}, { command: "build" })
120
120
 
121
121
  expect(config).toEqual({})
@@ -124,7 +124,7 @@ describe("icReactorPlugin", () => {
124
124
 
125
125
  describe("buildStart", () => {
126
126
  it("should generate declarations and reactor file", async () => {
127
- const plugin = icReactorPlugin(mockOptions)
127
+ const plugin = icReactor(mockOptions)
128
128
  await (plugin.buildStart as any)()
129
129
 
130
130
  expect(runCanisterPipeline).toHaveBeenCalledWith({
@@ -147,7 +147,7 @@ describe("icReactorPlugin", () => {
147
147
  error: "Failed to generate",
148
148
  })
149
149
 
150
- const plugin = icReactorPlugin(mockOptions)
150
+ const plugin = icReactor(mockOptions)
151
151
  await (plugin.buildStart as any)()
152
152
 
153
153
  expect(consoleErrorSpy).toHaveBeenCalledWith(
@@ -156,11 +156,40 @@ describe("icReactorPlugin", () => {
156
156
 
157
157
  consoleErrorSpy.mockRestore()
158
158
  })
159
+
160
+ it("should pass reactor mode config to codegen", async () => {
161
+ const plugin = icReactor({
162
+ ...mockOptions,
163
+ reactor: {
164
+ defaultMode: "display",
165
+ canisters: {
166
+ test_canister: "raw",
167
+ },
168
+ },
169
+ })
170
+
171
+ await (plugin.buildStart as any)()
172
+
173
+ expect(runCanisterPipeline).toHaveBeenCalledWith({
174
+ canisterConfig: mockOptions.canisters[0],
175
+ projectRoot: expect.any(String),
176
+ globalConfig: {
177
+ outDir: "src/declarations",
178
+ clientManagerPath: "../../clients",
179
+ reactor: {
180
+ defaultMode: "display",
181
+ canisters: {
182
+ test_canister: "raw",
183
+ },
184
+ },
185
+ },
186
+ })
187
+ })
159
188
  })
160
189
 
161
190
  describe("handleHotUpdate", () => {
162
191
  it("should restart server when .did file changes", async () => {
163
- const plugin = icReactorPlugin(mockOptions)
192
+ const plugin = icReactor(mockOptions)
164
193
  const ctx = {
165
194
  file: "/absolute/path/to/src/declarations/test.did",
166
195
  server: mockServer,
@@ -181,7 +210,7 @@ describe("icReactorPlugin", () => {
181
210
  })
182
211
 
183
212
  it("should ignore other files", () => {
184
- const plugin = icReactorPlugin(mockOptions)
213
+ const plugin = icReactor(mockOptions)
185
214
  const ctx = {
186
215
  file: "/some/other/file.ts",
187
216
  server: mockServer,
package/src/index.ts CHANGED
@@ -13,6 +13,7 @@ import {
13
13
  runCanisterPipeline,
14
14
  type CanisterConfig,
15
15
  type CodegenConfig,
16
+ type ReactorGenerationConfig,
16
17
  } from "@ic-reactor/codegen"
17
18
  import { getIcEnvironmentInfo, buildIcEnvCookie } from "./env.js"
18
19
 
@@ -37,21 +38,33 @@ export interface IcReactorPluginOptions {
37
38
  * Default: true
38
39
  */
39
40
  injectEnvironment?: boolean
41
+ /**
42
+ * Reactor generation behavior.
43
+ * Controls whether generated default hooks use raw (Reactor) or display (DisplayReactor).
44
+ */
45
+ reactor?: ReactorGenerationConfig
40
46
  }
41
47
 
42
- export function icReactorPlugin(options: IcReactorPluginOptions): any {
48
+ export function icReactor(options: IcReactorPluginOptions): any {
43
49
  const {
44
50
  canisters,
45
51
  outDir = "src/declarations",
46
52
  clientManagerPath = "../../clients",
47
53
  injectEnvironment = true,
54
+ reactor,
48
55
  } = options
49
56
 
50
57
  // Construct a partial CodegenConfig to pass to the pipeline
51
- const globalConfig: Pick<CodegenConfig, "outDir" | "clientManagerPath"> = {
58
+ const globalConfig: Pick<
59
+ CodegenConfig,
60
+ "outDir" | "clientManagerPath" | "reactor"
61
+ > = {
52
62
  outDir,
53
63
  clientManagerPath,
54
64
  }
65
+ if (reactor != null) {
66
+ globalConfig.reactor = reactor
67
+ }
55
68
 
56
69
  const plugin: Plugin = {
57
70
  name: "ic-reactor-plugin",