@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 +60 -2
- package/dist/index.cjs +8 -4
- package/dist/index.d.cts +8 -3
- package/dist/index.d.ts +8 -3
- package/dist/index.js +7 -3
- package/package.json +2 -2
- package/src/index.test.ts +39 -10
- package/src/index.ts +15 -2
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 {
|
|
41
|
+
import { icReactor } from "@ic-reactor/vite-plugin"
|
|
42
42
|
|
|
43
43
|
export default defineConfig({
|
|
44
44
|
plugins: [
|
|
45
45
|
react(),
|
|
46
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
39
|
+
declare function icReactor(options: IcReactorPluginOptions): any;
|
|
35
40
|
|
|
36
|
-
export { type IcReactorPluginOptions,
|
|
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
|
|
39
|
+
declare function icReactor(options: IcReactorPluginOptions): any;
|
|
35
40
|
|
|
36
|
-
export { type IcReactorPluginOptions,
|
|
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
|
|
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
|
-
|
|
159
|
+
icReactor
|
|
156
160
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ic-reactor/vite-plugin",
|
|
3
|
-
"version": "0.
|
|
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.
|
|
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 {
|
|
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("
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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<
|
|
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",
|