@ic-reactor/vite-plugin 0.11.1 → 0.12.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 +11 -3
- package/dist/index.cjs +40 -5
- package/dist/index.js +40 -5
- package/llms.txt +41 -0
- package/package.json +25 -13
- package/src/env.ts +47 -5
- package/src/index.test.ts +52 -2
- package/src/index.ts +18 -2
package/README.md
CHANGED
|
@@ -31,17 +31,25 @@ export default defineConfig({
|
|
|
31
31
|
|
|
32
32
|
```ts
|
|
33
33
|
// src/clients.ts
|
|
34
|
-
import { ClientManager } from "@ic-reactor/
|
|
34
|
+
import { ClientManager } from "@ic-reactor/react"
|
|
35
35
|
import { QueryClient } from "@tanstack/react-query"
|
|
36
36
|
|
|
37
37
|
export const queryClient = new QueryClient()
|
|
38
38
|
export const clientManager = new ClientManager({
|
|
39
39
|
queryClient,
|
|
40
|
-
withCanisterEnv: true,
|
|
41
40
|
})
|
|
42
41
|
```
|
|
43
42
|
|
|
44
|
-
|
|
43
|
+
No opt-in flag is needed to pick up the plugin's environment: the plugin sets
|
|
44
|
+
the `ic_env` cookie and `ClientManager` reads it automatically in the browser.
|
|
45
|
+
|
|
46
|
+
The plugin generates files under `src/declarations/<canister>/` by default —
|
|
47
|
+
`declarations/<did-basename>.{js,d.ts,did}` plus a managed `index.generated.ts`
|
|
48
|
+
and a stable `index.ts` wrapper. With `target: "react"`, `index.generated.ts`
|
|
49
|
+
exports the reactor and six hooks named after the canister
|
|
50
|
+
(`use<Canister>Query`, `use<Canister>SuspenseQuery`,
|
|
51
|
+
`use<Canister>InfiniteQuery`, `use<Canister>SuspenseInfiniteQuery`,
|
|
52
|
+
`use<Canister>Mutation`, `use<Canister>Method`).
|
|
45
53
|
|
|
46
54
|
If you want non-React output, set `target: "core"` and install the matching
|
|
47
55
|
runtime package instead of `@ic-reactor/react`.
|
package/dist/index.cjs
CHANGED
|
@@ -49,7 +49,10 @@ function getIcEnvironmentInfo(canisterNames) {
|
|
|
49
49
|
})
|
|
50
50
|
);
|
|
51
51
|
const rootKey = networkStatus.root_key;
|
|
52
|
-
const proxyTarget = `http://127.0.0.1:${networkStatus.port}
|
|
52
|
+
const proxyTarget = networkStatus.api_url || networkStatus.gateway_url || (networkStatus.port ? `http://127.0.0.1:${networkStatus.port}` : void 0);
|
|
53
|
+
if (!proxyTarget) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
53
56
|
const canisterIds = {};
|
|
54
57
|
for (const name of canisterNames) {
|
|
55
58
|
try {
|
|
@@ -64,18 +67,41 @@ function getIcEnvironmentInfo(canisterNames) {
|
|
|
64
67
|
} catch {
|
|
65
68
|
}
|
|
66
69
|
}
|
|
67
|
-
|
|
70
|
+
const internetIdentityProvider = !canisterIds.internet_identity && isLocalhostGateway(proxyTarget) && environment !== "ic" ? localInternetIdentityProvider(proxyTarget) : void 0;
|
|
71
|
+
return {
|
|
72
|
+
environment,
|
|
73
|
+
rootKey,
|
|
74
|
+
proxyTarget,
|
|
75
|
+
canisterIds,
|
|
76
|
+
internetIdentityProvider
|
|
77
|
+
};
|
|
68
78
|
} catch (error) {
|
|
69
79
|
return null;
|
|
70
80
|
}
|
|
71
81
|
}
|
|
72
|
-
function buildIcEnvCookie(canisterIds, rootKey) {
|
|
73
|
-
const parts = [`ic_root_key=${rootKey}`];
|
|
82
|
+
function buildIcEnvCookie(canisterIds, rootKey, internetIdentityProvider) {
|
|
83
|
+
const parts = rootKey ? [`ic_root_key=${rootKey}`] : [];
|
|
74
84
|
for (const [name, id] of Object.entries(canisterIds)) {
|
|
75
85
|
parts.push(`PUBLIC_CANISTER_ID:${name}=${id}`);
|
|
76
86
|
}
|
|
87
|
+
if (internetIdentityProvider) {
|
|
88
|
+
parts.push(`INTERNET_IDENTITY_PROVIDER=${internetIdentityProvider}`);
|
|
89
|
+
}
|
|
77
90
|
return encodeURIComponent(parts.join("&"));
|
|
78
91
|
}
|
|
92
|
+
function isLocalhostGateway(proxyTarget) {
|
|
93
|
+
try {
|
|
94
|
+
const { hostname } = new URL(proxyTarget);
|
|
95
|
+
return hostname === "localhost" || hostname === "127.0.0.1";
|
|
96
|
+
} catch {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function localInternetIdentityProvider(proxyTarget) {
|
|
101
|
+
const { protocol, port } = new URL(proxyTarget);
|
|
102
|
+
const portSuffix = port ? `:${port}` : "";
|
|
103
|
+
return `${protocol}//id.ai.localhost${portSuffix}/authorize`;
|
|
104
|
+
}
|
|
79
105
|
|
|
80
106
|
// src/index.ts
|
|
81
107
|
function icReactor(options) {
|
|
@@ -112,8 +138,16 @@ function icReactor(options) {
|
|
|
112
138
|
}
|
|
113
139
|
const icEnv = getIcEnvironmentInfo(canisterNames);
|
|
114
140
|
if (!icEnv) {
|
|
141
|
+
const envOnlyCookie = canisters.length === 0 ? buildIcEnvCookie(
|
|
142
|
+
{},
|
|
143
|
+
void 0,
|
|
144
|
+
"http://id.ai.localhost:8000/authorize"
|
|
145
|
+
) : void 0;
|
|
115
146
|
return {
|
|
116
147
|
server: {
|
|
148
|
+
headers: envOnlyCookie ? {
|
|
149
|
+
"Set-Cookie": `ic_env=${envOnlyCookie}; Path=/; SameSite=Lax;`
|
|
150
|
+
} : void 0,
|
|
117
151
|
proxy: {
|
|
118
152
|
"/api": {
|
|
119
153
|
target: "http://127.0.0.1:4943",
|
|
@@ -128,7 +162,8 @@ function icReactor(options) {
|
|
|
128
162
|
...icEnv.canisterIds,
|
|
129
163
|
...configuredCanisterIds
|
|
130
164
|
},
|
|
131
|
-
icEnv.rootKey
|
|
165
|
+
icEnv.rootKey,
|
|
166
|
+
icEnv.internetIdentityProvider
|
|
132
167
|
);
|
|
133
168
|
return {
|
|
134
169
|
server: {
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,10 @@ function getIcEnvironmentInfo(canisterNames) {
|
|
|
17
17
|
})
|
|
18
18
|
);
|
|
19
19
|
const rootKey = networkStatus.root_key;
|
|
20
|
-
const proxyTarget = `http://127.0.0.1:${networkStatus.port}
|
|
20
|
+
const proxyTarget = networkStatus.api_url || networkStatus.gateway_url || (networkStatus.port ? `http://127.0.0.1:${networkStatus.port}` : void 0);
|
|
21
|
+
if (!proxyTarget) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
21
24
|
const canisterIds = {};
|
|
22
25
|
for (const name of canisterNames) {
|
|
23
26
|
try {
|
|
@@ -32,18 +35,41 @@ function getIcEnvironmentInfo(canisterNames) {
|
|
|
32
35
|
} catch {
|
|
33
36
|
}
|
|
34
37
|
}
|
|
35
|
-
|
|
38
|
+
const internetIdentityProvider = !canisterIds.internet_identity && isLocalhostGateway(proxyTarget) && environment !== "ic" ? localInternetIdentityProvider(proxyTarget) : void 0;
|
|
39
|
+
return {
|
|
40
|
+
environment,
|
|
41
|
+
rootKey,
|
|
42
|
+
proxyTarget,
|
|
43
|
+
canisterIds,
|
|
44
|
+
internetIdentityProvider
|
|
45
|
+
};
|
|
36
46
|
} catch (error) {
|
|
37
47
|
return null;
|
|
38
48
|
}
|
|
39
49
|
}
|
|
40
|
-
function buildIcEnvCookie(canisterIds, rootKey) {
|
|
41
|
-
const parts = [`ic_root_key=${rootKey}`];
|
|
50
|
+
function buildIcEnvCookie(canisterIds, rootKey, internetIdentityProvider) {
|
|
51
|
+
const parts = rootKey ? [`ic_root_key=${rootKey}`] : [];
|
|
42
52
|
for (const [name, id] of Object.entries(canisterIds)) {
|
|
43
53
|
parts.push(`PUBLIC_CANISTER_ID:${name}=${id}`);
|
|
44
54
|
}
|
|
55
|
+
if (internetIdentityProvider) {
|
|
56
|
+
parts.push(`INTERNET_IDENTITY_PROVIDER=${internetIdentityProvider}`);
|
|
57
|
+
}
|
|
45
58
|
return encodeURIComponent(parts.join("&"));
|
|
46
59
|
}
|
|
60
|
+
function isLocalhostGateway(proxyTarget) {
|
|
61
|
+
try {
|
|
62
|
+
const { hostname } = new URL(proxyTarget);
|
|
63
|
+
return hostname === "localhost" || hostname === "127.0.0.1";
|
|
64
|
+
} catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function localInternetIdentityProvider(proxyTarget) {
|
|
69
|
+
const { protocol, port } = new URL(proxyTarget);
|
|
70
|
+
const portSuffix = port ? `:${port}` : "";
|
|
71
|
+
return `${protocol}//id.ai.localhost${portSuffix}/authorize`;
|
|
72
|
+
}
|
|
47
73
|
|
|
48
74
|
// src/index.ts
|
|
49
75
|
function icReactor(options) {
|
|
@@ -80,8 +106,16 @@ function icReactor(options) {
|
|
|
80
106
|
}
|
|
81
107
|
const icEnv = getIcEnvironmentInfo(canisterNames);
|
|
82
108
|
if (!icEnv) {
|
|
109
|
+
const envOnlyCookie = canisters.length === 0 ? buildIcEnvCookie(
|
|
110
|
+
{},
|
|
111
|
+
void 0,
|
|
112
|
+
"http://id.ai.localhost:8000/authorize"
|
|
113
|
+
) : void 0;
|
|
83
114
|
return {
|
|
84
115
|
server: {
|
|
116
|
+
headers: envOnlyCookie ? {
|
|
117
|
+
"Set-Cookie": `ic_env=${envOnlyCookie}; Path=/; SameSite=Lax;`
|
|
118
|
+
} : void 0,
|
|
85
119
|
proxy: {
|
|
86
120
|
"/api": {
|
|
87
121
|
target: "http://127.0.0.1:4943",
|
|
@@ -96,7 +130,8 @@ function icReactor(options) {
|
|
|
96
130
|
...icEnv.canisterIds,
|
|
97
131
|
...configuredCanisterIds
|
|
98
132
|
},
|
|
99
|
-
icEnv.rootKey
|
|
133
|
+
icEnv.rootKey,
|
|
134
|
+
icEnv.internetIdentityProvider
|
|
100
135
|
);
|
|
101
136
|
return {
|
|
102
137
|
server: {
|
package/llms.txt
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# @ic-reactor/vite-plugin — AI Quick Guide
|
|
2
|
+
|
|
3
|
+
Vite integration for automatic IC Reactor generation from `.did` files.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add -D @ic-reactor/vite-plugin
|
|
9
|
+
pnpm add @ic-reactor/react @tanstack/react-query @icp-sdk/core
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Minimal Setup
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { icReactor } from "@ic-reactor/vite-plugin"
|
|
16
|
+
|
|
17
|
+
icReactor({
|
|
18
|
+
canisters: [{ name: "backend", didFile: "./backend/backend.did" }],
|
|
19
|
+
})
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Behavior
|
|
23
|
+
|
|
24
|
+
- Runs codegen on startup and `.did` changes
|
|
25
|
+
- Regenerates declarations + `index.generated.ts`
|
|
26
|
+
- Preserves user-facing `index.ts` wrapper after initial creation
|
|
27
|
+
|
|
28
|
+
## Key Options
|
|
29
|
+
|
|
30
|
+
- `canisters`, `outDir`, `clientManagerPath`, `target`, `mode`, `canisterId`
|
|
31
|
+
- `injectEnvironment` for local `ic_env` cookie + `/api` proxy behavior
|
|
32
|
+
|
|
33
|
+
## Best Practices
|
|
34
|
+
|
|
35
|
+
- Keep custom code in stable wrapper/factory modules
|
|
36
|
+
- Do not hand-edit generated `index.generated.ts`
|
|
37
|
+
|
|
38
|
+
## Full References
|
|
39
|
+
|
|
40
|
+
- Full AI guide: https://ic-reactor.b3pay.net/llms-full.txt
|
|
41
|
+
- Vite plugin docs: https://ic-reactor.b3pay.net/v3/packages/vite-plugin
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ic-reactor/vite-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.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",
|
|
@@ -8,14 +8,22 @@
|
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
9
|
"exports": {
|
|
10
10
|
".": {
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"./package.json": "./package.json"
|
|
15
21
|
},
|
|
16
22
|
"files": [
|
|
17
23
|
"dist",
|
|
18
|
-
"src"
|
|
24
|
+
"src",
|
|
25
|
+
"README.md",
|
|
26
|
+
"llms.txt"
|
|
19
27
|
],
|
|
20
28
|
"keywords": [
|
|
21
29
|
"vite",
|
|
@@ -24,7 +32,9 @@
|
|
|
24
32
|
"candid",
|
|
25
33
|
"ic-reactor",
|
|
26
34
|
"dfinity",
|
|
27
|
-
"icp"
|
|
35
|
+
"icp",
|
|
36
|
+
"llms",
|
|
37
|
+
"ai-friendly"
|
|
28
38
|
],
|
|
29
39
|
"author": "Behrad Deylami",
|
|
30
40
|
"license": "MIT",
|
|
@@ -36,22 +46,24 @@
|
|
|
36
46
|
"bugs": {
|
|
37
47
|
"url": "https://github.com/B3Pay/ic-reactor/issues"
|
|
38
48
|
},
|
|
49
|
+
"homepage": "https://ic-reactor.b3pay.net/v3/packages/vite-plugin",
|
|
39
50
|
"dependencies": {
|
|
40
|
-
"@ic-reactor/codegen": "0.
|
|
51
|
+
"@ic-reactor/codegen": "0.12.0"
|
|
41
52
|
},
|
|
42
53
|
"peerDependencies": {
|
|
43
54
|
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
|
|
44
55
|
},
|
|
45
56
|
"devDependencies": {
|
|
46
|
-
"@icp-sdk/bindgen": "^0.
|
|
47
|
-
"@types/node": "^
|
|
57
|
+
"@icp-sdk/bindgen": "^0.4.0",
|
|
58
|
+
"@types/node": "^26.1.1",
|
|
48
59
|
"tsup": "^8.5.1",
|
|
49
|
-
"typescript": "^
|
|
50
|
-
"vitest": "^4.1.
|
|
60
|
+
"typescript": "^6.0.3",
|
|
61
|
+
"vitest": "^4.1.10"
|
|
51
62
|
},
|
|
52
63
|
"scripts": {
|
|
53
64
|
"build": "tsup src/index.ts --format esm,cjs --dts --tsconfig tsconfig.json",
|
|
54
65
|
"dev": "tsup src/index.ts --format esm,cjs --dts --watch --tsconfig tsconfig.json",
|
|
55
|
-
"test": "vitest run"
|
|
66
|
+
"test": "vitest run",
|
|
67
|
+
"typecheck": "tsc --noEmit -p tsconfig.typecheck.json"
|
|
56
68
|
}
|
|
57
69
|
}
|
package/src/env.ts
CHANGED
|
@@ -12,6 +12,7 @@ export interface IcEnvironment {
|
|
|
12
12
|
rootKey: string
|
|
13
13
|
proxyTarget: string
|
|
14
14
|
canisterIds: Record<string, string>
|
|
15
|
+
internetIdentityProvider?: string
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
/**
|
|
@@ -31,8 +32,16 @@ export function getIcEnvironmentInfo(
|
|
|
31
32
|
)
|
|
32
33
|
|
|
33
34
|
const rootKey = networkStatus.root_key
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
const proxyTarget =
|
|
36
|
+
networkStatus.api_url ||
|
|
37
|
+
networkStatus.gateway_url ||
|
|
38
|
+
(networkStatus.port
|
|
39
|
+
? `http://127.0.0.1:${networkStatus.port}`
|
|
40
|
+
: undefined)
|
|
41
|
+
|
|
42
|
+
if (!proxyTarget) {
|
|
43
|
+
return null
|
|
44
|
+
}
|
|
36
45
|
|
|
37
46
|
const canisterIds: Record<string, string> = {}
|
|
38
47
|
|
|
@@ -52,7 +61,20 @@ export function getIcEnvironmentInfo(
|
|
|
52
61
|
}
|
|
53
62
|
}
|
|
54
63
|
|
|
55
|
-
|
|
64
|
+
const internetIdentityProvider =
|
|
65
|
+
!canisterIds.internet_identity &&
|
|
66
|
+
isLocalhostGateway(proxyTarget) &&
|
|
67
|
+
environment !== "ic"
|
|
68
|
+
? localInternetIdentityProvider(proxyTarget)
|
|
69
|
+
: undefined
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
environment,
|
|
73
|
+
rootKey,
|
|
74
|
+
proxyTarget,
|
|
75
|
+
canisterIds,
|
|
76
|
+
internetIdentityProvider,
|
|
77
|
+
}
|
|
56
78
|
} catch (error) {
|
|
57
79
|
// CLI not found or failed
|
|
58
80
|
return null
|
|
@@ -65,13 +87,33 @@ export function getIcEnvironmentInfo(
|
|
|
65
87
|
*/
|
|
66
88
|
export function buildIcEnvCookie(
|
|
67
89
|
canisterIds: Record<string, string>,
|
|
68
|
-
rootKey
|
|
90
|
+
rootKey?: string,
|
|
91
|
+
internetIdentityProvider?: string
|
|
69
92
|
): string {
|
|
70
|
-
const parts = [`ic_root_key=${rootKey}`]
|
|
93
|
+
const parts = rootKey ? [`ic_root_key=${rootKey}`] : []
|
|
71
94
|
|
|
72
95
|
for (const [name, id] of Object.entries(canisterIds)) {
|
|
73
96
|
parts.push(`PUBLIC_CANISTER_ID:${name}=${id}`)
|
|
74
97
|
}
|
|
75
98
|
|
|
99
|
+
if (internetIdentityProvider) {
|
|
100
|
+
parts.push(`INTERNET_IDENTITY_PROVIDER=${internetIdentityProvider}`)
|
|
101
|
+
}
|
|
102
|
+
|
|
76
103
|
return encodeURIComponent(parts.join("&"))
|
|
77
104
|
}
|
|
105
|
+
|
|
106
|
+
function isLocalhostGateway(proxyTarget: string): boolean {
|
|
107
|
+
try {
|
|
108
|
+
const { hostname } = new URL(proxyTarget)
|
|
109
|
+
return hostname === "localhost" || hostname === "127.0.0.1"
|
|
110
|
+
} catch {
|
|
111
|
+
return false
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function localInternetIdentityProvider(proxyTarget: string): string {
|
|
116
|
+
const { protocol, port } = new URL(proxyTarget)
|
|
117
|
+
const portSuffix = port ? `:${port}` : ""
|
|
118
|
+
return `${protocol}//id.ai.localhost${portSuffix}/authorize`
|
|
119
|
+
}
|
package/src/index.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from "vitest"
|
|
2
|
-
import * as vitePluginModule from "./index"
|
|
3
|
-
import type { IcReactorPluginOptions } from "./index"
|
|
2
|
+
import * as vitePluginModule from "./index.js"
|
|
3
|
+
import type { IcReactorPluginOptions } from "./index.js"
|
|
4
4
|
import path from "path"
|
|
5
5
|
import { execFileSync } from "child_process"
|
|
6
6
|
import { runCanisterPipeline } from "@ic-reactor/codegen"
|
|
@@ -150,6 +150,42 @@ describe("icReactor", () => {
|
|
|
150
150
|
)
|
|
151
151
|
})
|
|
152
152
|
|
|
153
|
+
it("should inject built-in local Internet Identity provider when no project II canister is found", () => {
|
|
154
|
+
;(execFileSync as any).mockImplementation(
|
|
155
|
+
(command: string, args: string[], _options: any) => {
|
|
156
|
+
if (
|
|
157
|
+
command === "icp" &&
|
|
158
|
+
args.includes("network") &&
|
|
159
|
+
args.includes("status")
|
|
160
|
+
) {
|
|
161
|
+
return JSON.stringify({
|
|
162
|
+
root_key: "mock-root-key",
|
|
163
|
+
api_url: "http://localhost:8000/",
|
|
164
|
+
})
|
|
165
|
+
}
|
|
166
|
+
if (
|
|
167
|
+
command === "icp" &&
|
|
168
|
+
args.includes("canister") &&
|
|
169
|
+
args.includes("status")
|
|
170
|
+
) {
|
|
171
|
+
if (args.includes("internet_identity")) {
|
|
172
|
+
throw new Error("system canister is not a project canister")
|
|
173
|
+
}
|
|
174
|
+
return "mock-canister-id"
|
|
175
|
+
}
|
|
176
|
+
return ""
|
|
177
|
+
}
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
const plugin = createVitePlugin(mockOptions)
|
|
181
|
+
const config = (plugin as any).config({}, { command: "serve" })
|
|
182
|
+
|
|
183
|
+
expect(config.server.headers["Set-Cookie"]).toContain(
|
|
184
|
+
"INTERNET_IDENTITY_PROVIDER%3Dhttp%3A%2F%2Fid.ai.localhost%3A8000%2Fauthorize"
|
|
185
|
+
)
|
|
186
|
+
expect(config.server.proxy["/api"].target).toBe("http://localhost:8000/")
|
|
187
|
+
})
|
|
188
|
+
|
|
153
189
|
it("should fallback to default proxy when icp-cli fails", () => {
|
|
154
190
|
;(execFileSync as any).mockImplementation(() => {
|
|
155
191
|
throw new Error("Command not found")
|
|
@@ -162,6 +198,20 @@ describe("icReactor", () => {
|
|
|
162
198
|
expect(config.server.proxy["/api"].target).toBe("http://127.0.0.1:4943")
|
|
163
199
|
})
|
|
164
200
|
|
|
201
|
+
it("should inject default local II provider in env-only mode when icp-cli project detection fails", () => {
|
|
202
|
+
;(execFileSync as any).mockImplementation(() => {
|
|
203
|
+
throw new Error("project manifest not found")
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
const plugin = createVitePlugin({ canisters: [] })
|
|
207
|
+
const config = (plugin as any).config({}, { command: "serve" })
|
|
208
|
+
|
|
209
|
+
expect(config.server.headers["Set-Cookie"]).toContain(
|
|
210
|
+
"INTERNET_IDENTITY_PROVIDER%3Dhttp%3A%2F%2Fid.ai.localhost%3A8000%2Fauthorize"
|
|
211
|
+
)
|
|
212
|
+
expect(config.server.proxy["/api"].target).toBe("http://127.0.0.1:4943")
|
|
213
|
+
})
|
|
214
|
+
|
|
165
215
|
it("should return empty config for build command", () => {
|
|
166
216
|
const plugin = createVitePlugin(mockOptions)
|
|
167
217
|
const config = (plugin as any).config({}, { command: "build" })
|
package/src/index.ts
CHANGED
|
@@ -96,9 +96,24 @@ export function icReactor(options: IcReactorPluginOptions): any {
|
|
|
96
96
|
const icEnv = getIcEnvironmentInfo(canisterNames)
|
|
97
97
|
|
|
98
98
|
if (!icEnv) {
|
|
99
|
-
|
|
99
|
+
const envOnlyCookie =
|
|
100
|
+
canisters.length === 0
|
|
101
|
+
? buildIcEnvCookie(
|
|
102
|
+
{},
|
|
103
|
+
undefined,
|
|
104
|
+
"http://id.ai.localhost:8000/authorize"
|
|
105
|
+
)
|
|
106
|
+
: undefined
|
|
107
|
+
|
|
108
|
+
// Fallback: proxy /api to default local replica. In env-only mode,
|
|
109
|
+
// still provide the standard ICP CLI built-in local II URL.
|
|
100
110
|
return {
|
|
101
111
|
server: {
|
|
112
|
+
headers: envOnlyCookie
|
|
113
|
+
? {
|
|
114
|
+
"Set-Cookie": `ic_env=${envOnlyCookie}; Path=/; SameSite=Lax;`,
|
|
115
|
+
}
|
|
116
|
+
: undefined,
|
|
102
117
|
proxy: {
|
|
103
118
|
"/api": {
|
|
104
119
|
target: "http://127.0.0.1:4943",
|
|
@@ -114,7 +129,8 @@ export function icReactor(options: IcReactorPluginOptions): any {
|
|
|
114
129
|
...icEnv.canisterIds,
|
|
115
130
|
...configuredCanisterIds,
|
|
116
131
|
},
|
|
117
|
-
icEnv.rootKey
|
|
132
|
+
icEnv.rootKey,
|
|
133
|
+
icEnv.internetIdentityProvider
|
|
118
134
|
)
|
|
119
135
|
|
|
120
136
|
return {
|