vite-plugin-fastly 0.0.4 → 0.1.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/dist/plugin.d.ts +47 -45
- package/dist/plugin.js +292 -395
- package/dist/plugin.js.map +1 -1
- package/dist/runner.js +48 -88
- package/dist/runner.js.map +1 -1
- package/package.json +35 -35
- package/readme.md +1 -1
package/dist/plugin.d.ts
CHANGED
|
@@ -1,49 +1,51 @@
|
|
|
1
|
-
import { Plugin } from
|
|
2
|
-
import { ServerOptions } from
|
|
1
|
+
import { Plugin } from "vite";
|
|
2
|
+
import { ServerOptions } from "http-proxy-3";
|
|
3
3
|
|
|
4
|
+
//#region src/plugin/plugin.d.ts
|
|
4
5
|
interface FastlyPluginOptions {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
6
|
+
/**
|
|
7
|
+
* A unique key to identify the plugin instance. This is required if you
|
|
8
|
+
* have multiple Fastly plugin instances in the same Vite configuration.
|
|
9
|
+
*
|
|
10
|
+
* @default "vite-plugin-fastly"
|
|
11
|
+
*/
|
|
12
|
+
uniqueName?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Vite environment name that the Fastly plugin should configure.
|
|
15
|
+
*
|
|
16
|
+
* @default "ssr"
|
|
17
|
+
*/
|
|
18
|
+
viteEnvironmentName?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Function that returns the command to build the Fastly Module Runner.
|
|
21
|
+
* The callback receives the input and output file paths.
|
|
22
|
+
*
|
|
23
|
+
* @default (input, output) => `js-compute-runtime ${input} ${output}`
|
|
24
|
+
*/
|
|
25
|
+
getRunnerBuildCommand?: (input: string, output: string) => string;
|
|
26
|
+
/**
|
|
27
|
+
* IPv4 address of the Fastly Dev Server to proxy requests to during development.
|
|
28
|
+
* If you have multiple Fastly plugin instances, make sure each instance uses
|
|
29
|
+
* a unique address.
|
|
30
|
+
*
|
|
31
|
+
* @default "127.0.0.1:7676"
|
|
32
|
+
*/
|
|
33
|
+
fastlyDevServerAddress?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Function that returns the command to launch the Fastly Dev Server.
|
|
36
|
+
* The callback receives the compiled wasm file path and the address to bind to.
|
|
37
|
+
*
|
|
38
|
+
* @default (wasmFile, address) => `fastly compute serve --file=${wasmFile} --addr=${address}`
|
|
39
|
+
*/
|
|
40
|
+
getLaunchDevServerCommand?: (wasmFile: string, address: string) => string;
|
|
41
|
+
/**
|
|
42
|
+
* Options to pass to the HTTP proxy server.
|
|
43
|
+
*
|
|
44
|
+
* @default {}
|
|
45
|
+
*/
|
|
46
|
+
proxyOptions?: ServerOptions;
|
|
46
47
|
}
|
|
47
48
|
declare function fastly(options?: FastlyPluginOptions): Plugin[];
|
|
48
|
-
|
|
49
|
-
export {
|
|
49
|
+
//#endregion
|
|
50
|
+
export { FastlyPluginOptions, fastly };
|
|
51
|
+
//# sourceMappingURL=plugin.d.ts.map
|
package/dist/plugin.js
CHANGED
|
@@ -1,423 +1,320 @@
|
|
|
1
|
-
|
|
1
|
+
import { createFetchableDevEnvironment } from "vite";
|
|
2
2
|
import { createProxy } from "http-proxy-3";
|
|
3
|
-
import fs from "fs";
|
|
4
|
-
import { execSync, spawn } from "child_process";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import { execSync, spawn } from "node:child_process";
|
|
5
5
|
import { launchAndTest } from "kill-em-all";
|
|
6
|
-
|
|
7
|
-
// src/plugin/expose-environment.ts
|
|
6
|
+
//#region src/plugin/expose-environment.ts
|
|
8
7
|
function exposeEnvironment() {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
command = config.command;
|
|
41
|
-
},
|
|
42
|
-
configureServer(server) {
|
|
43
|
-
server.httpServer?.once("listening", () => {
|
|
44
|
-
devServerUrl = server.resolvedUrls?.local[0];
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
};
|
|
8
|
+
let devServerUrl;
|
|
9
|
+
let command;
|
|
10
|
+
function getModuleContents(environmentName) {
|
|
11
|
+
const url = devServerUrl ? JSON.stringify(devServerUrl) : "undefined";
|
|
12
|
+
return `export const name = ${JSON.stringify(environmentName)}\nexport const command = ${JSON.stringify(command)}\nexport const devServerUrl = ${url}`;
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
name: "vite-plugin-fastly/expose-environment",
|
|
16
|
+
enforce: "pre",
|
|
17
|
+
resolveId: {
|
|
18
|
+
filter: { id: /^vite-plugin-fastly:environment$/ },
|
|
19
|
+
handler(source) {
|
|
20
|
+
if (source === "vite-plugin-fastly:environment") return "\0virtual:vite-plugin-fastly:environment";
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
load: {
|
|
24
|
+
filter: { id: /^\0virtual:vite-plugin-fastly:environment$/ },
|
|
25
|
+
handler(id) {
|
|
26
|
+
if (id !== "\0virtual:vite-plugin-fastly:environment") return;
|
|
27
|
+
return getModuleContents(this.environment.name);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
configResolved(config) {
|
|
31
|
+
command = config.command;
|
|
32
|
+
},
|
|
33
|
+
configureServer(server) {
|
|
34
|
+
server.httpServer?.once("listening", () => {
|
|
35
|
+
devServerUrl = server.resolvedUrls?.local[0];
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
};
|
|
48
39
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
40
|
+
//#endregion
|
|
41
|
+
//#region src/plugin/plugin.ts
|
|
42
|
+
const fastlyProcesses = /* @__PURE__ */ new Map();
|
|
52
43
|
function fastly(options = {}) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
this.info(buildCommand);
|
|
229
|
-
execSync(buildCommand, { stdio: "inherit" });
|
|
230
|
-
},
|
|
231
|
-
async buildEnd() {
|
|
232
|
-
if (command === "build" || fastlyProcessKilled) return;
|
|
233
|
-
fastlyProcessKilled = true;
|
|
234
|
-
await doKillProcesses(this, uniqueName);
|
|
235
|
-
},
|
|
236
|
-
configureServer(server) {
|
|
237
|
-
const environment = server.environments[viteEnvironmentName];
|
|
238
|
-
let address = null;
|
|
239
|
-
server.httpServer?.on("listening", () => {
|
|
240
|
-
address = getServerAddress(server.httpServer);
|
|
241
|
-
});
|
|
242
|
-
server.httpServer?.on("close", () => {
|
|
243
|
-
address = null;
|
|
244
|
-
});
|
|
245
|
-
server.middlewares.use((req, res, next) => {
|
|
246
|
-
if (req.method !== "POST" || req.url !== "/@vite-plugin-fastly/transport") {
|
|
247
|
-
return next();
|
|
248
|
-
}
|
|
249
|
-
void (async () => {
|
|
250
|
-
try {
|
|
251
|
-
const body = await readyBody(req);
|
|
252
|
-
const data = JSON.parse(body);
|
|
253
|
-
const result = await environment.hot.handleInvoke(data);
|
|
254
|
-
res.setHeader("Content-Type", "application/json");
|
|
255
|
-
res.end(JSON.stringify(result));
|
|
256
|
-
} catch (error) {
|
|
257
|
-
return next(error);
|
|
258
|
-
}
|
|
259
|
-
})();
|
|
260
|
-
});
|
|
261
|
-
const proxy = createProxy(proxyOptions);
|
|
262
|
-
const proxyMiddleware = (req, res, next) => {
|
|
263
|
-
if (!address) {
|
|
264
|
-
return next(
|
|
265
|
-
new Error(
|
|
266
|
-
`[${uniqueName}] Vite server address is not available for proxying`
|
|
267
|
-
)
|
|
268
|
-
);
|
|
269
|
-
}
|
|
270
|
-
try {
|
|
271
|
-
proxy.web(
|
|
272
|
-
req,
|
|
273
|
-
res,
|
|
274
|
-
{
|
|
275
|
-
target: `http://${fastlyDevServerAddress}`,
|
|
276
|
-
headers: {
|
|
277
|
-
"Vite-Plugin-Fastly-Vite-Server-Address": address,
|
|
278
|
-
"Vite-Plugin-Fastly-Handler-Entry": handlerEntry
|
|
279
|
-
}
|
|
280
|
-
},
|
|
281
|
-
(error) => {
|
|
282
|
-
next(error);
|
|
283
|
-
}
|
|
284
|
-
);
|
|
285
|
-
} catch (error) {
|
|
286
|
-
next(error);
|
|
287
|
-
}
|
|
288
|
-
};
|
|
289
|
-
if (clientConfigured) {
|
|
290
|
-
return () => {
|
|
291
|
-
server.middlewares.use(proxyMiddleware);
|
|
292
|
-
};
|
|
293
|
-
} else {
|
|
294
|
-
server.middlewares.use(proxyMiddleware);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
];
|
|
44
|
+
const { uniqueName = "vite-plugin-fastly", viteEnvironmentName = "ssr", fastlyDevServerAddress = "127.0.0.1:7676", getRunnerBuildCommand = (input, output) => `js-compute-runtime ${input} ${output}`, getLaunchDevServerCommand = (wasmFile, address) => `fastly compute serve --file=${wasmFile} --addr=${address}`, proxyOptions = {} } = options;
|
|
45
|
+
let command;
|
|
46
|
+
let handlerEntry;
|
|
47
|
+
let fastlyProcessKilled = false;
|
|
48
|
+
let clientConfigured = false;
|
|
49
|
+
let buildCommand;
|
|
50
|
+
return [exposeEnvironment(), {
|
|
51
|
+
name: uniqueName,
|
|
52
|
+
config(_, env) {
|
|
53
|
+
const hasRoldown = this.meta.rolldownVersion !== void 0;
|
|
54
|
+
return { environments: { [viteEnvironmentName]: {
|
|
55
|
+
define: { "process.env.NODE_ENV": JSON.stringify(env.mode) },
|
|
56
|
+
optimizeDeps: {
|
|
57
|
+
noDiscovery: false,
|
|
58
|
+
exclude: [
|
|
59
|
+
"fastly:acl",
|
|
60
|
+
"fastly:backend",
|
|
61
|
+
"fastly:cache",
|
|
62
|
+
"fastly:cache-override",
|
|
63
|
+
"fastly:compute",
|
|
64
|
+
"fastly:config-store",
|
|
65
|
+
"fastly:device",
|
|
66
|
+
"fastly:dictionary",
|
|
67
|
+
"fastly:edge-rate-limiter",
|
|
68
|
+
"fastly:env",
|
|
69
|
+
"fastly:experimental",
|
|
70
|
+
"fastly:fanout",
|
|
71
|
+
"fastly:geolocation",
|
|
72
|
+
"fastly:html-rewriter",
|
|
73
|
+
"fastly:image-optimizer",
|
|
74
|
+
"fastly:kv-store",
|
|
75
|
+
"fastly:logger",
|
|
76
|
+
"fastly:secret-store",
|
|
77
|
+
"fastly:websocket"
|
|
78
|
+
],
|
|
79
|
+
rolldownOptions: {
|
|
80
|
+
platform: "neutral",
|
|
81
|
+
treeshake: true
|
|
82
|
+
},
|
|
83
|
+
esbuildOptions: hasRoldown ? void 0 : {
|
|
84
|
+
platform: "neutral",
|
|
85
|
+
minify: true,
|
|
86
|
+
define: { "process.env.NODE_ENV": JSON.stringify(env.mode) }
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
resolve: {
|
|
90
|
+
builtins: [/^fastly:/],
|
|
91
|
+
noExternal: true,
|
|
92
|
+
conditions: ["fastly", "workerd"]
|
|
93
|
+
},
|
|
94
|
+
build: {
|
|
95
|
+
rolldownOptions: hasRoldown ? {
|
|
96
|
+
platform: "neutral",
|
|
97
|
+
output: { codeSplitting: false }
|
|
98
|
+
} : void 0,
|
|
99
|
+
rollupOptions: hasRoldown ? void 0 : {
|
|
100
|
+
platform: "neutral",
|
|
101
|
+
output: { inlineDynamicImports: true }
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
dev: { createEnvironment(name, config) {
|
|
105
|
+
return createFetchableDevEnvironment(name, config, {
|
|
106
|
+
hot: false,
|
|
107
|
+
handleRequest(request) {
|
|
108
|
+
throw new Error("Not implemented");
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
} }
|
|
112
|
+
} } };
|
|
113
|
+
},
|
|
114
|
+
api: { fastly: { address: fastlyDevServerAddress } },
|
|
115
|
+
configResolved(config) {
|
|
116
|
+
command = config.command;
|
|
117
|
+
if (command !== "serve") return;
|
|
118
|
+
let sameNameInstanceCount = 0;
|
|
119
|
+
let sameAddressInstanceCount = 0;
|
|
120
|
+
for (const plugin of config.plugins) {
|
|
121
|
+
if (plugin.name === uniqueName) sameNameInstanceCount++;
|
|
122
|
+
if (plugin.api?.fastly?.address === fastlyDevServerAddress) sameAddressInstanceCount++;
|
|
123
|
+
}
|
|
124
|
+
if (sameNameInstanceCount > 1) {
|
|
125
|
+
console.error(`[vite-plugin-fastly] Multiple Fastly plugin instances with the same uniqueName "${uniqueName}" detected.`);
|
|
126
|
+
console.error(`[vite-plugin-fastly] If you really need multiple instances, give each instance a unique "uniqueName".`);
|
|
127
|
+
}
|
|
128
|
+
if (sameAddressInstanceCount > 1) {
|
|
129
|
+
console.error(`[vite-plugin-fastly] Multiple Fastly plugin instances configured to use the same Fastly Dev Server address "${fastlyDevServerAddress}".`);
|
|
130
|
+
console.error(`[vite-plugin-fastly] If you really need multiple instances, give each instance a unique "fastlyDevServerAddress"`);
|
|
131
|
+
}
|
|
132
|
+
if (sameNameInstanceCount > 1 || sameAddressInstanceCount > 1) process.exit(1);
|
|
133
|
+
const optionsKey = this.meta.rolldownVersion !== void 0 ? "rolldownOptions" : "rollupOptions";
|
|
134
|
+
const clientInput = config.environments.client?.build?.[optionsKey]?.input;
|
|
135
|
+
if (typeof clientInput === "string") clientConfigured = true;
|
|
136
|
+
else if (Array.isArray(clientInput) && clientInput.length > 0) clientConfigured = true;
|
|
137
|
+
else if (typeof clientInput === "object" && clientInput !== null && Object.keys(clientInput).length > 0) clientConfigured = true;
|
|
138
|
+
},
|
|
139
|
+
async configEnvironment(name, config, env) {
|
|
140
|
+
if (name !== viteEnvironmentName || env.command !== "serve") return;
|
|
141
|
+
const optionsKey = this.meta.rolldownVersion !== void 0 ? "rolldownOptions" : "rollupOptions";
|
|
142
|
+
const input = config.build?.[optionsKey]?.input;
|
|
143
|
+
if (typeof input === "string") handlerEntry = input;
|
|
144
|
+
else if (Array.isArray(input)) handlerEntry = input[0];
|
|
145
|
+
else if (typeof input === "object" && input !== null) handlerEntry = Object.values(input)[0];
|
|
146
|
+
if (!handlerEntry) return this.error(`[${uniqueName}] No entry point found in ${optionsKey}. Please specify an input in environments.${viteEnvironmentName}.build.${optionsKey}.input.`);
|
|
147
|
+
fastlyProcessKilled = true;
|
|
148
|
+
await doKillProcesses(this, uniqueName);
|
|
149
|
+
const launchCommand = getLaunchDevServerCommand(buildDevRunnerIfNecessary(this, uniqueName, getRunnerBuildCommand), fastlyDevServerAddress);
|
|
150
|
+
this.info(`[${uniqueName}] Launching Fastly Dev Server with command:`);
|
|
151
|
+
this.info(`[${uniqueName}] ${launchCommand}`);
|
|
152
|
+
const kill = await launchAndTest(await spawnCommand(launchCommand), `http://${fastlyDevServerAddress}/@vite-plugin-fastly/ready`);
|
|
153
|
+
fastlyProcesses.set(uniqueName, kill);
|
|
154
|
+
this.info(`[${uniqueName}] Fastly Dev Server is running at http://${fastlyDevServerAddress}`);
|
|
155
|
+
},
|
|
156
|
+
async writeBundle(outputOptions, bundle) {
|
|
157
|
+
if (command !== "build" || this.environment.name !== viteEnvironmentName) return;
|
|
158
|
+
const jsFile = Object.values(bundle).find((file) => file.type === "chunk" && file.isEntry);
|
|
159
|
+
if (!jsFile) throw new Error(`[${uniqueName}] No JS entry chunk found in bundle.`);
|
|
160
|
+
buildCommand = `js-compute-runtime ${outputOptions.dir + "/" + jsFile.fileName} ${outputOptions.dir + "/app.wasm"}`;
|
|
161
|
+
},
|
|
162
|
+
async closeBundle(error) {
|
|
163
|
+
if (error || command !== "build" || this.environment.name !== viteEnvironmentName) return;
|
|
164
|
+
this.info(`Building Fastly WASM module with command:`);
|
|
165
|
+
this.info(buildCommand);
|
|
166
|
+
execSync(buildCommand, { stdio: "inherit" });
|
|
167
|
+
},
|
|
168
|
+
async buildEnd() {
|
|
169
|
+
if (command === "build" || fastlyProcessKilled) return;
|
|
170
|
+
fastlyProcessKilled = true;
|
|
171
|
+
await doKillProcesses(this, uniqueName);
|
|
172
|
+
},
|
|
173
|
+
configureServer(server) {
|
|
174
|
+
const environment = server.environments[viteEnvironmentName];
|
|
175
|
+
let address = null;
|
|
176
|
+
server.httpServer?.on("listening", () => {
|
|
177
|
+
address = getServerAddress(server.httpServer);
|
|
178
|
+
});
|
|
179
|
+
server.httpServer?.on("close", () => {
|
|
180
|
+
address = null;
|
|
181
|
+
});
|
|
182
|
+
server.middlewares.use((req, res, next) => {
|
|
183
|
+
if (req.method !== "POST" || req.url !== "/@vite-plugin-fastly/transport") return next();
|
|
184
|
+
(async () => {
|
|
185
|
+
try {
|
|
186
|
+
const body = await readyBody(req);
|
|
187
|
+
const data = JSON.parse(body);
|
|
188
|
+
const result = await environment.hot.handleInvoke(data);
|
|
189
|
+
res.setHeader("Content-Type", "application/json");
|
|
190
|
+
res.end(JSON.stringify(result));
|
|
191
|
+
} catch (error) {
|
|
192
|
+
return next(error);
|
|
193
|
+
}
|
|
194
|
+
})();
|
|
195
|
+
});
|
|
196
|
+
const proxy = createProxy(proxyOptions);
|
|
197
|
+
const proxyMiddleware = (req, res, next) => {
|
|
198
|
+
if (!address) return next(/* @__PURE__ */ new Error(`[${uniqueName}] Vite server address is not available for proxying`));
|
|
199
|
+
try {
|
|
200
|
+
proxy.web(req, res, {
|
|
201
|
+
target: `http://${fastlyDevServerAddress}`,
|
|
202
|
+
headers: {
|
|
203
|
+
"Vite-Plugin-Fastly-Vite-Server-Address": address,
|
|
204
|
+
"Vite-Plugin-Fastly-Handler-Entry": handlerEntry
|
|
205
|
+
}
|
|
206
|
+
}, (error) => {
|
|
207
|
+
next(error);
|
|
208
|
+
});
|
|
209
|
+
} catch (error) {
|
|
210
|
+
next(error);
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
if (clientConfigured) return () => {
|
|
214
|
+
server.middlewares.use(proxyMiddleware);
|
|
215
|
+
};
|
|
216
|
+
else server.middlewares.use(proxyMiddleware);
|
|
217
|
+
}
|
|
218
|
+
}];
|
|
299
219
|
}
|
|
300
220
|
async function readyBody(req) {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
221
|
+
return new Promise((resolve, reject) => {
|
|
222
|
+
let body = "";
|
|
223
|
+
req.on("data", (chunk) => {
|
|
224
|
+
body += chunk;
|
|
225
|
+
});
|
|
226
|
+
req.on("end", () => {
|
|
227
|
+
resolve(body);
|
|
228
|
+
});
|
|
229
|
+
req.on("error", (err) => {
|
|
230
|
+
reject(err);
|
|
231
|
+
});
|
|
232
|
+
});
|
|
313
233
|
}
|
|
314
234
|
function getServerAddress(server) {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
}
|
|
333
|
-
host = `http://${host}:${address.port}`;
|
|
334
|
-
}
|
|
335
|
-
return host;
|
|
235
|
+
const address = server?.address();
|
|
236
|
+
if (!address) return null;
|
|
237
|
+
let host;
|
|
238
|
+
if (typeof address === "string") host = address;
|
|
239
|
+
else {
|
|
240
|
+
switch (address.address) {
|
|
241
|
+
case "127.0.0.1":
|
|
242
|
+
case "::":
|
|
243
|
+
case "::1":
|
|
244
|
+
case "0000:0000:0000:0000:0000:0000:0000:0001":
|
|
245
|
+
host = "localhost";
|
|
246
|
+
break;
|
|
247
|
+
default: host = address.address;
|
|
248
|
+
}
|
|
249
|
+
host = `http://${host}:${address.port}`;
|
|
250
|
+
}
|
|
251
|
+
return host;
|
|
336
252
|
}
|
|
337
253
|
function buildDevRunnerIfNecessary(ctx, uniqueName, getCommand) {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
execSync(getCommand(input, output), { stdio: "inherit" });
|
|
348
|
-
return output;
|
|
254
|
+
const jsComputeRuntimeVersion = getJsComputeRuntimeVersion(uniqueName);
|
|
255
|
+
const input = "node_modules/vite-plugin-fastly/dist/runner.js";
|
|
256
|
+
const output = `node_modules/.vite-plugin-fastly/runner.${jsComputeRuntimeVersion}.wasm`;
|
|
257
|
+
const inputStat = fs.statSync(input);
|
|
258
|
+
const outputStat = statOrNull(output);
|
|
259
|
+
if (outputStat && outputStat.isFile() && outputStat.mtimeMs >= inputStat.mtimeMs) return output;
|
|
260
|
+
ctx.info(`[${uniqueName}] Building Fastly Module Runner for dev server...`);
|
|
261
|
+
execSync(getCommand(input, output), { stdio: "inherit" });
|
|
262
|
+
return output;
|
|
349
263
|
}
|
|
350
264
|
function getJsComputeRuntimeVersion(uniqueName) {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
`[${uniqueName}] Unexpected js-compute-runtime version output: ${output}`
|
|
356
|
-
);
|
|
357
|
-
}
|
|
358
|
-
return output.slice(lastSpaceIndex + 1).trim();
|
|
265
|
+
const output = execSync("js-compute-runtime --version").toString();
|
|
266
|
+
const lastSpaceIndex = output.lastIndexOf(" ");
|
|
267
|
+
if (lastSpaceIndex === -1) throw new Error(`[${uniqueName}] Unexpected js-compute-runtime version output: ${output}`);
|
|
268
|
+
return output.slice(lastSpaceIndex + 1).trim();
|
|
359
269
|
}
|
|
360
270
|
function statOrNull(path) {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
271
|
+
try {
|
|
272
|
+
return fs.statSync(path);
|
|
273
|
+
} catch {
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
366
276
|
}
|
|
367
277
|
async function doKillProcesses(ctx, name) {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
278
|
+
const kill = fastlyProcesses.get(name);
|
|
279
|
+
if (!kill) return;
|
|
280
|
+
fastlyProcesses.delete(name);
|
|
281
|
+
ctx.info(`[${name}] Shutting down Fastly dev server`);
|
|
282
|
+
await kill();
|
|
283
|
+
ctx.info(`[${name}] Fastly dev server shut down`);
|
|
374
284
|
}
|
|
375
285
|
async function spawnCommand(command) {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
});
|
|
390
|
-
});
|
|
286
|
+
const child = spawn(command, {
|
|
287
|
+
shell: true,
|
|
288
|
+
stdio: "inherit"
|
|
289
|
+
});
|
|
290
|
+
return await new Promise((resolve, reject) => {
|
|
291
|
+
child.on("spawn", () => {
|
|
292
|
+
if (!child.pid) return reject(/* @__PURE__ */ new Error("Failed to spawn process"));
|
|
293
|
+
resolve(child);
|
|
294
|
+
});
|
|
295
|
+
child.on("error", (err) => {
|
|
296
|
+
reject(err);
|
|
297
|
+
});
|
|
298
|
+
});
|
|
391
299
|
}
|
|
392
|
-
|
|
300
|
+
let killAllInProgress = false;
|
|
393
301
|
async function killAll() {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
info: (msg) => {
|
|
401
|
-
process.stdout.write(msg + "\n");
|
|
402
|
-
}
|
|
403
|
-
},
|
|
404
|
-
name
|
|
405
|
-
)
|
|
406
|
-
);
|
|
407
|
-
}
|
|
408
|
-
await Promise.all(promises);
|
|
302
|
+
killAllInProgress = true;
|
|
303
|
+
const promises = [];
|
|
304
|
+
for (const name of fastlyProcesses.keys()) promises.push(doKillProcesses({ info: (msg) => {
|
|
305
|
+
process.stdout.write(msg + "\n");
|
|
306
|
+
} }, name));
|
|
307
|
+
await Promise.all(promises);
|
|
409
308
|
}
|
|
410
309
|
function cleanupOnExit() {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
});
|
|
415
|
-
}
|
|
310
|
+
if (!killAllInProgress) killAll().finally(() => {
|
|
311
|
+
process.exit(0);
|
|
312
|
+
});
|
|
416
313
|
}
|
|
417
314
|
process.on("SIGINT", cleanupOnExit);
|
|
418
315
|
process.on("SIGTERM", cleanupOnExit);
|
|
419
316
|
process.on("exit", cleanupOnExit);
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
317
|
+
//#endregion
|
|
318
|
+
export { fastly };
|
|
319
|
+
|
|
423
320
|
//# sourceMappingURL=plugin.js.map
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/plugin/plugin.ts","../src/plugin/expose-environment.ts"],"sourcesContent":["import type { ConfigPluginContext, Connect, HttpServer, Plugin } from \"vite\";\nimport { createProxy, type ServerOptions } from \"http-proxy-3\";\nimport type { IncomingMessage } from \"node:http\";\nimport fs from \"node:fs\";\nimport { ChildProcess, execSync, spawn } from \"node:child_process\";\nimport { launchAndTest, type LaunchAndTestCleanupFunction } from \"kill-em-all\";\nimport exposeEnvironment from \"./expose-environment\";\n\nexport interface FastlyPluginOptions {\n\t/**\n\t * A unique key to identify the plugin instance. This is required if you\n\t * have multiple Fastly plugin instances in the same Vite configuration.\n\t *\n\t * @default \"vite-plugin-fastly\"\n\t */\n\tuniqueName?: string;\n\n\t/**\n\t * Vite environment name that the Fastly plugin should configure.\n\t *\n\t * @default \"ssr\"\n\t */\n\tviteEnvironmentName?: string;\n\n\t/**\n\t * Function that returns the command to build the Fastly Module Runner.\n\t * The callback receives the input and output file paths.\n\t *\n\t * @default (input, output) => `js-compute-runtime ${input} ${output}`\n\t */\n\tgetRunnerBuildCommand?: (input: string, output: string) => string;\n\n\t/**\n\t * IPv4 address of the Fastly Dev Server to proxy requests to during development.\n\t * If you have multiple Fastly plugin instances, make sure each instance uses\n\t * a unique address.\n\t *\n\t * @default \"127.0.0.1:7676\"\n\t */\n\tfastlyDevServerAddress?: string;\n\n\t/**\n\t * Function that returns the command to launch the Fastly Dev Server.\n\t * The callback receives the compiled wasm file path and the address to bind to.\n\t *\n\t * @default (wasmFile, address) => `fastly compute serve --file=${wasmFile} --addr=${address}`\n\t */\n\tgetLaunchDevServerCommand?: (wasmFile: string, address: string) => string;\n\n\t/**\n\t * Options to pass to the HTTP proxy server.\n\t *\n\t * @default {}\n\t */\n\tproxyOptions?: ServerOptions;\n}\n\n// Map of uniqueName to Fastly Dev Server child processes\nconst fastlyProcesses = new Map<string, LaunchAndTestCleanupFunction>();\n\nexport function fastly(options: FastlyPluginOptions = {}): Plugin[] {\n\tconst {\n\t\tuniqueName = \"vite-plugin-fastly\",\n\t\tviteEnvironmentName = \"ssr\",\n\t\tfastlyDevServerAddress = \"127.0.0.1:7676\",\n\t\tgetRunnerBuildCommand = (input: string, output: string) =>\n\t\t\t`js-compute-runtime ${input} ${output}`,\n\t\tgetLaunchDevServerCommand = (wasmFile, address) =>\n\t\t\t`fastly compute serve --file=${wasmFile} --addr=${address}`,\n\t\tproxyOptions = {},\n\t} = options;\n\n\tlet command: \"serve\" | \"build\";\n\tlet handlerEntry: string | undefined;\n\tlet fastlyProcessKilled = false;\n\tlet clientConfigured = false;\n\tlet buildCommand: string | undefined;\n\n\treturn [\n\t\texposeEnvironment(),\n\t\t{\n\t\t\tname: uniqueName,\n\n\t\t\tconfig(_, env) {\n\t\t\t\treturn {\n\t\t\t\t\tenvironments: {\n\t\t\t\t\t\t[viteEnvironmentName]: {\n\t\t\t\t\t\t\toptimizeDeps: {\n\t\t\t\t\t\t\t\tnoDiscovery: false,\n\t\t\t\t\t\t\t\texclude: [\n\t\t\t\t\t\t\t\t\t\"fastly:acl\",\n\t\t\t\t\t\t\t\t\t\"fastly:backend\",\n\t\t\t\t\t\t\t\t\t\"fastly:cache\",\n\t\t\t\t\t\t\t\t\t\"fastly:cache-override\",\n\t\t\t\t\t\t\t\t\t\"fastly:compute\",\n\t\t\t\t\t\t\t\t\t\"fastly:config-store\",\n\t\t\t\t\t\t\t\t\t\"fastly:device\",\n\t\t\t\t\t\t\t\t\t\"fastly:dictionary\",\n\t\t\t\t\t\t\t\t\t\"fastly:edge-rate-limiter\",\n\t\t\t\t\t\t\t\t\t\"fastly:env\",\n\t\t\t\t\t\t\t\t\t\"fastly:experimental\",\n\t\t\t\t\t\t\t\t\t\"fastly:fanout\",\n\t\t\t\t\t\t\t\t\t\"fastly:geolocation\",\n\t\t\t\t\t\t\t\t\t\"fastly:html-rewriter\",\n\t\t\t\t\t\t\t\t\t\"fastly:image-optimizer\",\n\t\t\t\t\t\t\t\t\t\"fastly:kv-store\",\n\t\t\t\t\t\t\t\t\t\"fastly:logger\",\n\t\t\t\t\t\t\t\t\t\"fastly:secret-store\",\n\t\t\t\t\t\t\t\t\t\"fastly:websocket\",\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\tesbuildOptions: {\n\t\t\t\t\t\t\t\t\tplatform: \"neutral\",\n\t\t\t\t\t\t\t\t\tminify: true,\n\t\t\t\t\t\t\t\t\tdefine: {\n\t\t\t\t\t\t\t\t\t\t\"process.env.NODE_ENV\": JSON.stringify(env.mode),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tresolve: {\n\t\t\t\t\t\t\t\tbuiltins: [/^fastly:/],\n\t\t\t\t\t\t\t\tnoExternal: true,\n\t\t\t\t\t\t\t\tconditions: [\"fastly\", \"workerd\"],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuild: {\n\t\t\t\t\t\t\t\trollupOptions: {\n\t\t\t\t\t\t\t\t\toutput: {\n\t\t\t\t\t\t\t\t\t\tinlineDynamicImports: true,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tdev: {},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t},\n\n\t\t\tapi: {\n\t\t\t\tfastly: {\n\t\t\t\t\taddress: fastlyDevServerAddress,\n\t\t\t\t},\n\t\t\t},\n\n\t\t\tconfigResolved(config) {\n\t\t\t\tcommand = config.command;\n\t\t\t\tif (command !== \"serve\") return;\n\n\t\t\t\t// Scan plugins for multiple instances with the same uniqueName\n\t\t\t\tlet sameNameInstanceCount = 0;\n\t\t\t\tlet sameAddressInstanceCount = 0;\n\t\t\t\tfor (const plugin of config.plugins) {\n\t\t\t\t\tif (plugin.name === uniqueName) {\n\t\t\t\t\t\tsameNameInstanceCount++;\n\t\t\t\t\t}\n\t\t\t\t\tif (plugin.api?.fastly?.address === fastlyDevServerAddress) {\n\t\t\t\t\t\tsameAddressInstanceCount++;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (sameNameInstanceCount > 1) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`[vite-plugin-fastly] Multiple Fastly plugin instances with the same uniqueName \"${uniqueName}\" detected.`,\n\t\t\t\t\t);\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`[vite-plugin-fastly] If you really need multiple instances, give each instance a unique \"uniqueName\".`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (sameAddressInstanceCount > 1) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`[vite-plugin-fastly] Multiple Fastly plugin instances configured to use the same Fastly Dev Server address \"${fastlyDevServerAddress}\".`,\n\t\t\t\t\t);\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`[vite-plugin-fastly] If you really need multiple instances, give each instance a unique \"fastlyDevServerAddress\"`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (sameNameInstanceCount > 1 || sameAddressInstanceCount > 1) {\n\t\t\t\t\t// This is a fatal error, we cannot continue\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\n\t\t\t\tconst clientInput =\n\t\t\t\t\tconfig.environments.client?.build.rollupOptions.input;\n\t\t\t\tif (typeof clientInput === \"string\") {\n\t\t\t\t\tclientConfigured = true;\n\t\t\t\t} else if (Array.isArray(clientInput) && clientInput.length > 0) {\n\t\t\t\t\tclientConfigured = true;\n\t\t\t\t} else if (\n\t\t\t\t\ttypeof clientInput === \"object\" &&\n\t\t\t\t\tclientInput !== null &&\n\t\t\t\t\tObject.keys(clientInput).length > 0\n\t\t\t\t) {\n\t\t\t\t\tclientConfigured = true;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tasync configEnvironment(name, config, env) {\n\t\t\t\tif (name !== viteEnvironmentName || env.command !== \"serve\") {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst input = config.build?.rollupOptions?.input;\n\t\t\t\tif (typeof input === \"string\") {\n\t\t\t\t\thandlerEntry = input;\n\t\t\t\t} else if (Array.isArray(input)) {\n\t\t\t\t\thandlerEntry = input[0];\n\t\t\t\t} else if (typeof input === \"object\" && input !== null) {\n\t\t\t\t\tconst values = Object.values(input);\n\t\t\t\t\thandlerEntry = values[0];\n\t\t\t\t}\n\n\t\t\t\tif (!handlerEntry) {\n\t\t\t\t\treturn this.error(\n\t\t\t\t\t\t`[${uniqueName}] No entry point found in Rollup options. Please specify an input in environments.${viteEnvironmentName}.build.rollupOptions.input.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Kill previous Fastly Dev Server process if any\n\t\t\t\tfastlyProcessKilled = true;\n\t\t\t\tawait doKillProcesses(this, uniqueName);\n\n\t\t\t\tconst wasmFile = buildDevRunnerIfNecessary(\n\t\t\t\t\tthis,\n\t\t\t\t\tuniqueName,\n\t\t\t\t\tgetRunnerBuildCommand,\n\t\t\t\t);\n\n\t\t\t\tconst launchCommand = getLaunchDevServerCommand(\n\t\t\t\t\twasmFile,\n\t\t\t\t\tfastlyDevServerAddress,\n\t\t\t\t);\n\n\t\t\t\tthis.info(`[${uniqueName}] Launching Fastly Dev Server with command:`);\n\t\t\t\tthis.info(`[${uniqueName}] ${launchCommand}`);\n\t\t\t\tconst fastlyDevServerProcess = await spawnCommand(launchCommand);\n\n\t\t\t\tconst kill = await launchAndTest(\n\t\t\t\t\tfastlyDevServerProcess,\n\t\t\t\t\t`http://${fastlyDevServerAddress}/@vite-plugin-fastly/ready`,\n\t\t\t\t);\n\n\t\t\t\tfastlyProcesses.set(uniqueName, kill);\n\n\t\t\t\tthis.info(\n\t\t\t\t\t`[${uniqueName}] Fastly Dev Server is running at http://${fastlyDevServerAddress}`,\n\t\t\t\t);\n\t\t\t},\n\n\t\t\tasync writeBundle(outputOptions, bundle) {\n\t\t\t\tif (\n\t\t\t\t\tcommand !== \"build\" ||\n\t\t\t\t\tthis.environment.name !== viteEnvironmentName\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst jsFile = Object.values(bundle).find(\n\t\t\t\t\t(file) => file.type === \"chunk\" && file.isEntry,\n\t\t\t\t);\n\t\t\t\tif (!jsFile) {\n\t\t\t\t\tthrow new Error(`[${uniqueName}] No JS entry chunk found in bundle.`);\n\t\t\t\t}\n\n\t\t\t\tconst input = outputOptions.dir + \"/\" + jsFile.fileName;\n\t\t\t\tconst output = outputOptions.dir + \"/app.wasm\";\n\n\t\t\t\tbuildCommand = `js-compute-runtime ${input} ${output}`;\n\t\t\t},\n\n\t\t\tasync closeBundle(error) {\n\t\t\t\tif (\n\t\t\t\t\terror ||\n\t\t\t\t\tcommand !== \"build\" ||\n\t\t\t\t\tthis.environment.name !== viteEnvironmentName\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis.info(`Building Fastly WASM module with command:`);\n\t\t\t\tthis.info(buildCommand!);\n\t\t\t\texecSync(buildCommand!, { stdio: \"inherit\" });\n\t\t\t},\n\n\t\t\tasync buildEnd() {\n\t\t\t\tif (command === \"build\" || fastlyProcessKilled) return;\n\t\t\t\tfastlyProcessKilled = true;\n\t\t\t\tawait doKillProcesses(this, uniqueName);\n\t\t\t},\n\n\t\t\tconfigureServer(server) {\n\t\t\t\tconst environment = server.environments[viteEnvironmentName]!;\n\t\t\t\tlet address: string | null = null;\n\n\t\t\t\tserver.httpServer?.on(\"listening\", () => {\n\t\t\t\t\taddress = getServerAddress(server.httpServer);\n\t\t\t\t});\n\n\t\t\t\tserver.httpServer?.on(\"close\", () => {\n\t\t\t\t\taddress = null;\n\t\t\t\t});\n\n\t\t\t\t// Transport endpoint for the runner\n\t\t\t\tserver.middlewares.use((req, res, next) => {\n\t\t\t\t\tif (\n\t\t\t\t\t\treq.method !== \"POST\" ||\n\t\t\t\t\t\treq.url !== \"/@vite-plugin-fastly/transport\"\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn next();\n\t\t\t\t\t}\n\n\t\t\t\t\tvoid (async () => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Read the body\n\t\t\t\t\t\t\tconst body = await readyBody(req);\n\t\t\t\t\t\t\tconst data = JSON.parse(body);\n\n\t\t\t\t\t\t\tconst result = await environment.hot.handleInvoke(data);\n\n\t\t\t\t\t\t\tres.setHeader(\"Content-Type\", \"application/json\");\n\t\t\t\t\t\t\tres.end(JSON.stringify(result));\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\treturn next(error);\n\t\t\t\t\t\t}\n\t\t\t\t\t})();\n\t\t\t\t});\n\n\t\t\t\tconst proxy = createProxy(proxyOptions);\n\n\t\t\t\tconst proxyMiddleware: Connect.NextHandleFunction = (\n\t\t\t\t\treq,\n\t\t\t\t\tres,\n\t\t\t\t\tnext,\n\t\t\t\t) => {\n\t\t\t\t\tif (!address) {\n\t\t\t\t\t\treturn next(\n\t\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t\t`[${uniqueName}] Vite server address is not available for proxying`,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tproxy.web(\n\t\t\t\t\t\t\treq,\n\t\t\t\t\t\t\tres,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttarget: `http://${fastlyDevServerAddress}`,\n\t\t\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\t\t\"Vite-Plugin-Fastly-Vite-Server-Address\": address,\n\t\t\t\t\t\t\t\t\t\"Vite-Plugin-Fastly-Handler-Entry\": handlerEntry,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t(error) => {\n\t\t\t\t\t\t\t\tnext(error);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tnext(error);\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\t// If a client build is configured, add the proxy middleware after Vite's own middlewares.\n\t\t\t\t// Otherwise, assume a pure server-side setup and add the proxy as the first middleware.\n\t\t\t\tif (clientConfigured) {\n\t\t\t\t\treturn () => {\n\t\t\t\t\t\tserver.middlewares.use(proxyMiddleware);\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tserver.middlewares.use(proxyMiddleware);\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t];\n}\n\nasync function readyBody(req: IncomingMessage): Promise<string> {\n\treturn new Promise<string>((resolve, reject) => {\n\t\tlet body = \"\";\n\t\treq.on(\"data\", (chunk) => {\n\t\t\tbody += chunk;\n\t\t});\n\n\t\treq.on(\"end\", () => {\n\t\t\tresolve(body);\n\t\t});\n\n\t\treq.on(\"error\", (err) => {\n\t\t\treject(err);\n\t\t});\n\t});\n}\n\nfunction getServerAddress(server: HttpServer | null): string | null {\n\tconst address = server?.address();\n\tif (!address) {\n\t\treturn null;\n\t}\n\n\tlet host: string;\n\n\tif (typeof address === \"string\") {\n\t\thost = address;\n\t} else {\n\t\tswitch (address.address) {\n\t\t\tcase \"127.0.0.1\":\n\t\t\tcase \"::\":\n\t\t\tcase \"::1\":\n\t\t\tcase \"0000:0000:0000:0000:0000:0000:0000:0001\":\n\t\t\t\thost = \"localhost\";\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\thost = address.address;\n\t\t}\n\n\t\thost = `http://${host}:${address.port}`;\n\t}\n\n\treturn host;\n}\n\nfunction buildDevRunnerIfNecessary(\n\tctx: ConfigPluginContext,\n\tuniqueName: string,\n\tgetCommand: (input: string, output: string) => string,\n): string {\n\tconst jsComputeRuntimeVersion = getJsComputeRuntimeVersion(uniqueName);\n\tconst input = \"node_modules/vite-plugin-fastly/dist/runner.js\";\n\tconst output = `node_modules/.vite-plugin-fastly/runner.${jsComputeRuntimeVersion}.wasm`;\n\n\tconst inputStat = fs.statSync(input);\n\tconst outputStat = statOrNull(output);\n\n\tif (\n\t\toutputStat &&\n\t\toutputStat.isFile() &&\n\t\toutputStat.mtimeMs >= inputStat.mtimeMs\n\t) {\n\t\t// Up to date\n\t\treturn output;\n\t}\n\n\tctx.info(`[${uniqueName}] Building Fastly Module Runner for dev server...`);\n\n\texecSync(getCommand(input, output), { stdio: \"inherit\" });\n\n\treturn output;\n}\n\nfunction getJsComputeRuntimeVersion(uniqueName: string): string {\n\tconst output = execSync(\"js-compute-runtime --version\").toString();\n\n\t// Parse version from something like \"js-compute-runtime-cli.js 3.38.2\\n\"\n\tconst lastSpaceIndex = output.lastIndexOf(\" \");\n\tif (lastSpaceIndex === -1) {\n\t\tthrow new Error(\n\t\t\t`[${uniqueName}] Unexpected js-compute-runtime version output: ${output}`,\n\t\t);\n\t}\n\n\treturn output.slice(lastSpaceIndex + 1).trim();\n}\n\nfunction statOrNull(path: string): fs.Stats | null {\n\ttry {\n\t\treturn fs.statSync(path);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function doKillProcesses(\n\tctx: {\n\t\tinfo: (msg: string) => void;\n\t},\n\tname: string,\n) {\n\tconst kill = fastlyProcesses.get(name);\n\tif (!kill) return;\n\n\tfastlyProcesses.delete(name);\n\n\tctx.info(`[${name}] Shutting down Fastly dev server`);\n\tawait kill();\n\tctx.info(`[${name}] Fastly dev server shut down`);\n}\n\nasync function spawnCommand(command: string): Promise<ChildProcess> {\n\tconst child = spawn(command, {\n\t\tshell: true,\n\t\tstdio: \"inherit\",\n\t});\n\n\treturn await new Promise((resolve, reject) => {\n\t\tchild.on(\"spawn\", () => {\n\t\t\tif (!child.pid) {\n\t\t\t\treturn reject(new Error(\"Failed to spawn process\"));\n\t\t\t}\n\n\t\t\tresolve(child);\n\t\t});\n\n\t\tchild.on(\"error\", (err) => {\n\t\t\treject(err);\n\t\t});\n\t});\n}\n\nlet killAllInProgress = false;\n\nasync function killAll() {\n\tkillAllInProgress = true;\n\tconst promises: Promise<void>[] = [];\n\tfor (const name of fastlyProcesses.keys()) {\n\t\tpromises.push(\n\t\t\tdoKillProcesses(\n\t\t\t\t{\n\t\t\t\t\tinfo: (msg: string) => {\n\t\t\t\t\t\tprocess.stdout.write(msg + \"\\n\");\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tname,\n\t\t\t),\n\t\t);\n\t}\n\tawait Promise.all(promises);\n}\n\nfunction cleanupOnExit() {\n\tif (!killAllInProgress) {\n\t\tvoid killAll().finally(() => {\n\t\t\tprocess.exit(0);\n\t\t});\n\t}\n}\n\nprocess.on(\"SIGINT\", cleanupOnExit);\nprocess.on(\"SIGTERM\", cleanupOnExit);\nprocess.on(\"exit\", cleanupOnExit);\n","import type { Plugin } from \"vite\";\n\nexport default function exposeEnvironment(): Plugin {\n\tlet devServerUrl: string | undefined;\n\tlet command: \"serve\" | \"build\";\n\n\tfunction getModuleContents(environmentName: string) {\n\t\tconst url = devServerUrl ? JSON.stringify(devServerUrl) : \"undefined\";\n\n\t\treturn (\n\t\t\t`export const name = ${JSON.stringify(environmentName)}\\n` +\n\t\t\t`export const command = ${JSON.stringify(command)}\\n` +\n\t\t\t`export const devServerUrl = ${url}`\n\t\t);\n\t}\n\n\treturn {\n\t\tname: \"vite-plugin-fastly/expose-environment\",\n\n\t\tenforce: \"pre\",\n\n\t\tresolveId: {\n\t\t\tfilter: {\n\t\t\t\tid: /^vite-plugin-fastly:environment$/,\n\t\t\t},\n\t\t\thandler(source) {\n\t\t\t\tif (source === \"vite-plugin-fastly:environment\") {\n\t\t\t\t\treturn \"\\0virtual:vite-plugin-fastly:environment\";\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\n\t\tload: {\n\t\t\tfilter: {\n\t\t\t\tid: /^\\0virtual:vite-plugin-fastly:environment$/,\n\t\t\t},\n\t\t\thandler(id) {\n\t\t\t\tif (id !== \"\\0virtual:vite-plugin-fastly:environment\") return;\n\t\t\t\treturn getModuleContents(this.environment.name);\n\t\t\t},\n\t\t},\n\n\t\tconfigResolved(config) {\n\t\t\tcommand = config.command;\n\t\t},\n\n\t\tconfigureServer(server) {\n\t\t\tserver.httpServer?.once(\"listening\", () => {\n\t\t\t\tdevServerUrl = server.resolvedUrls?.local[0];\n\t\t\t});\n\t\t},\n\t} satisfies Plugin;\n}\n"],"mappings":";AACA,SAAS,mBAAuC;AAEhD,OAAO,QAAQ;AACf,SAAuB,UAAU,aAAa;AAC9C,SAAS,qBAAwD;;;ACHlD,SAAR,oBAA6C;AACnD,MAAI;AACJ,MAAI;AAEJ,WAAS,kBAAkB,iBAAyB;AACnD,UAAM,MAAM,eAAe,KAAK,UAAU,YAAY,IAAI;AAE1D,WACC,uBAAuB,KAAK,UAAU,eAAe,CAAC;AAAA,yBAC5B,KAAK,UAAU,OAAO,CAAC;AAAA,8BAClB,GAAG;AAAA,EAEpC;AAEA,SAAO;AAAA,IACN,MAAM;AAAA,IAEN,SAAS;AAAA,IAET,WAAW;AAAA,MACV,QAAQ;AAAA,QACP,IAAI;AAAA,MACL;AAAA,MACA,QAAQ,QAAQ;AACf,YAAI,WAAW,kCAAkC;AAChD,iBAAO;AAAA,QACR;AAAA,MACD;AAAA,IACD;AAAA,IAEA,MAAM;AAAA,MACL,QAAQ;AAAA,QACP,IAAI;AAAA,MACL;AAAA,MACA,QAAQ,IAAI;AACX,YAAI,OAAO,2CAA4C;AACvD,eAAO,kBAAkB,KAAK,YAAY,IAAI;AAAA,MAC/C;AAAA,IACD;AAAA,IAEA,eAAe,QAAQ;AACtB,gBAAU,OAAO;AAAA,IAClB;AAAA,IAEA,gBAAgB,QAAQ;AACvB,aAAO,YAAY,KAAK,aAAa,MAAM;AAC1C,uBAAe,OAAO,cAAc,MAAM,CAAC;AAAA,MAC5C,CAAC;AAAA,IACF;AAAA,EACD;AACD;;;ADMA,IAAM,kBAAkB,oBAAI,IAA0C;AAE/D,SAAS,OAAO,UAA+B,CAAC,GAAa;AACnE,QAAM;AAAA,IACL,aAAa;AAAA,IACb,sBAAsB;AAAA,IACtB,yBAAyB;AAAA,IACzB,wBAAwB,CAAC,OAAe,WACvC,sBAAsB,KAAK,IAAI,MAAM;AAAA,IACtC,4BAA4B,CAAC,UAAU,YACtC,+BAA+B,QAAQ,WAAW,OAAO;AAAA,IAC1D,eAAe,CAAC;AAAA,EACjB,IAAI;AAEJ,MAAI;AACJ,MAAI;AACJ,MAAI,sBAAsB;AAC1B,MAAI,mBAAmB;AACvB,MAAI;AAEJ,SAAO;AAAA,IACN,kBAAkB;AAAA,IAClB;AAAA,MACC,MAAM;AAAA,MAEN,OAAO,GAAG,KAAK;AACd,eAAO;AAAA,UACN,cAAc;AAAA,YACb,CAAC,mBAAmB,GAAG;AAAA,cACtB,cAAc;AAAA,gBACb,aAAa;AAAA,gBACb,SAAS;AAAA,kBACR;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,gBACD;AAAA,gBACA,gBAAgB;AAAA,kBACf,UAAU;AAAA,kBACV,QAAQ;AAAA,kBACR,QAAQ;AAAA,oBACP,wBAAwB,KAAK,UAAU,IAAI,IAAI;AAAA,kBAChD;AAAA,gBACD;AAAA,cACD;AAAA,cACA,SAAS;AAAA,gBACR,UAAU,CAAC,UAAU;AAAA,gBACrB,YAAY;AAAA,gBACZ,YAAY,CAAC,UAAU,SAAS;AAAA,cACjC;AAAA,cACA,OAAO;AAAA,gBACN,eAAe;AAAA,kBACd,QAAQ;AAAA,oBACP,sBAAsB;AAAA,kBACvB;AAAA,gBACD;AAAA,cACD;AAAA,cACA,KAAK,CAAC;AAAA,YACP;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,MAEA,KAAK;AAAA,QACJ,QAAQ;AAAA,UACP,SAAS;AAAA,QACV;AAAA,MACD;AAAA,MAEA,eAAe,QAAQ;AACtB,kBAAU,OAAO;AACjB,YAAI,YAAY,QAAS;AAGzB,YAAI,wBAAwB;AAC5B,YAAI,2BAA2B;AAC/B,mBAAW,UAAU,OAAO,SAAS;AACpC,cAAI,OAAO,SAAS,YAAY;AAC/B;AAAA,UACD;AACA,cAAI,OAAO,KAAK,QAAQ,YAAY,wBAAwB;AAC3D;AAAA,UACD;AAAA,QACD;AAEA,YAAI,wBAAwB,GAAG;AAC9B,kBAAQ;AAAA,YACP,mFAAmF,UAAU;AAAA,UAC9F;AACA,kBAAQ;AAAA,YACP;AAAA,UACD;AAAA,QACD;AAEA,YAAI,2BAA2B,GAAG;AACjC,kBAAQ;AAAA,YACP,+GAA+G,sBAAsB;AAAA,UACtI;AACA,kBAAQ;AAAA,YACP;AAAA,UACD;AAAA,QACD;AAEA,YAAI,wBAAwB,KAAK,2BAA2B,GAAG;AAE9D,kBAAQ,KAAK,CAAC;AAAA,QACf;AAEA,cAAM,cACL,OAAO,aAAa,QAAQ,MAAM,cAAc;AACjD,YAAI,OAAO,gBAAgB,UAAU;AACpC,6BAAmB;AAAA,QACpB,WAAW,MAAM,QAAQ,WAAW,KAAK,YAAY,SAAS,GAAG;AAChE,6BAAmB;AAAA,QACpB,WACC,OAAO,gBAAgB,YACvB,gBAAgB,QAChB,OAAO,KAAK,WAAW,EAAE,SAAS,GACjC;AACD,6BAAmB;AAAA,QACpB;AAAA,MACD;AAAA,MAEA,MAAM,kBAAkB,MAAM,QAAQ,KAAK;AAC1C,YAAI,SAAS,uBAAuB,IAAI,YAAY,SAAS;AAC5D;AAAA,QACD;AAEA,cAAM,QAAQ,OAAO,OAAO,eAAe;AAC3C,YAAI,OAAO,UAAU,UAAU;AAC9B,yBAAe;AAAA,QAChB,WAAW,MAAM,QAAQ,KAAK,GAAG;AAChC,yBAAe,MAAM,CAAC;AAAA,QACvB,WAAW,OAAO,UAAU,YAAY,UAAU,MAAM;AACvD,gBAAM,SAAS,OAAO,OAAO,KAAK;AAClC,yBAAe,OAAO,CAAC;AAAA,QACxB;AAEA,YAAI,CAAC,cAAc;AAClB,iBAAO,KAAK;AAAA,YACX,IAAI,UAAU,qFAAqF,mBAAmB;AAAA,UACvH;AAAA,QACD;AAGA,8BAAsB;AACtB,cAAM,gBAAgB,MAAM,UAAU;AAEtC,cAAM,WAAW;AAAA,UAChB;AAAA,UACA;AAAA,UACA;AAAA,QACD;AAEA,cAAM,gBAAgB;AAAA,UACrB;AAAA,UACA;AAAA,QACD;AAEA,aAAK,KAAK,IAAI,UAAU,6CAA6C;AACrE,aAAK,KAAK,IAAI,UAAU,KAAK,aAAa,EAAE;AAC5C,cAAM,yBAAyB,MAAM,aAAa,aAAa;AAE/D,cAAM,OAAO,MAAM;AAAA,UAClB;AAAA,UACA,UAAU,sBAAsB;AAAA,QACjC;AAEA,wBAAgB,IAAI,YAAY,IAAI;AAEpC,aAAK;AAAA,UACJ,IAAI,UAAU,4CAA4C,sBAAsB;AAAA,QACjF;AAAA,MACD;AAAA,MAEA,MAAM,YAAY,eAAe,QAAQ;AACxC,YACC,YAAY,WACZ,KAAK,YAAY,SAAS,qBACzB;AACD;AAAA,QACD;AAEA,cAAM,SAAS,OAAO,OAAO,MAAM,EAAE;AAAA,UACpC,CAAC,SAAS,KAAK,SAAS,WAAW,KAAK;AAAA,QACzC;AACA,YAAI,CAAC,QAAQ;AACZ,gBAAM,IAAI,MAAM,IAAI,UAAU,sCAAsC;AAAA,QACrE;AAEA,cAAM,QAAQ,cAAc,MAAM,MAAM,OAAO;AAC/C,cAAM,SAAS,cAAc,MAAM;AAEnC,uBAAe,sBAAsB,KAAK,IAAI,MAAM;AAAA,MACrD;AAAA,MAEA,MAAM,YAAY,OAAO;AACxB,YACC,SACA,YAAY,WACZ,KAAK,YAAY,SAAS,qBACzB;AACD;AAAA,QACD;AAEA,aAAK,KAAK,2CAA2C;AACrD,aAAK,KAAK,YAAa;AACvB,iBAAS,cAAe,EAAE,OAAO,UAAU,CAAC;AAAA,MAC7C;AAAA,MAEA,MAAM,WAAW;AAChB,YAAI,YAAY,WAAW,oBAAqB;AAChD,8BAAsB;AACtB,cAAM,gBAAgB,MAAM,UAAU;AAAA,MACvC;AAAA,MAEA,gBAAgB,QAAQ;AACvB,cAAM,cAAc,OAAO,aAAa,mBAAmB;AAC3D,YAAI,UAAyB;AAE7B,eAAO,YAAY,GAAG,aAAa,MAAM;AACxC,oBAAU,iBAAiB,OAAO,UAAU;AAAA,QAC7C,CAAC;AAED,eAAO,YAAY,GAAG,SAAS,MAAM;AACpC,oBAAU;AAAA,QACX,CAAC;AAGD,eAAO,YAAY,IAAI,CAAC,KAAK,KAAK,SAAS;AAC1C,cACC,IAAI,WAAW,UACf,IAAI,QAAQ,kCACX;AACD,mBAAO,KAAK;AAAA,UACb;AAEA,gBAAM,YAAY;AACjB,gBAAI;AAEH,oBAAM,OAAO,MAAM,UAAU,GAAG;AAChC,oBAAM,OAAO,KAAK,MAAM,IAAI;AAE5B,oBAAM,SAAS,MAAM,YAAY,IAAI,aAAa,IAAI;AAEtD,kBAAI,UAAU,gBAAgB,kBAAkB;AAChD,kBAAI,IAAI,KAAK,UAAU,MAAM,CAAC;AAAA,YAC/B,SAAS,OAAO;AACf,qBAAO,KAAK,KAAK;AAAA,YAClB;AAAA,UACD,GAAG;AAAA,QACJ,CAAC;AAED,cAAM,QAAQ,YAAY,YAAY;AAEtC,cAAM,kBAA8C,CACnD,KACA,KACA,SACI;AACJ,cAAI,CAAC,SAAS;AACb,mBAAO;AAAA,cACN,IAAI;AAAA,gBACH,IAAI,UAAU;AAAA,cACf;AAAA,YACD;AAAA,UACD;AAEA,cAAI;AACH,kBAAM;AAAA,cACL;AAAA,cACA;AAAA,cACA;AAAA,gBACC,QAAQ,UAAU,sBAAsB;AAAA,gBACxC,SAAS;AAAA,kBACR,0CAA0C;AAAA,kBAC1C,oCAAoC;AAAA,gBACrC;AAAA,cACD;AAAA,cACA,CAAC,UAAU;AACV,qBAAK,KAAK;AAAA,cACX;AAAA,YACD;AAAA,UACD,SAAS,OAAO;AACf,iBAAK,KAAK;AAAA,UACX;AAAA,QACD;AAIA,YAAI,kBAAkB;AACrB,iBAAO,MAAM;AACZ,mBAAO,YAAY,IAAI,eAAe;AAAA,UACvC;AAAA,QACD,OAAO;AACN,iBAAO,YAAY,IAAI,eAAe;AAAA,QACvC;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD;AAEA,eAAe,UAAU,KAAuC;AAC/D,SAAO,IAAI,QAAgB,CAAC,SAAS,WAAW;AAC/C,QAAI,OAAO;AACX,QAAI,GAAG,QAAQ,CAAC,UAAU;AACzB,cAAQ;AAAA,IACT,CAAC;AAED,QAAI,GAAG,OAAO,MAAM;AACnB,cAAQ,IAAI;AAAA,IACb,CAAC;AAED,QAAI,GAAG,SAAS,CAAC,QAAQ;AACxB,aAAO,GAAG;AAAA,IACX,CAAC;AAAA,EACF,CAAC;AACF;AAEA,SAAS,iBAAiB,QAA0C;AACnE,QAAM,UAAU,QAAQ,QAAQ;AAChC,MAAI,CAAC,SAAS;AACb,WAAO;AAAA,EACR;AAEA,MAAI;AAEJ,MAAI,OAAO,YAAY,UAAU;AAChC,WAAO;AAAA,EACR,OAAO;AACN,YAAQ,QAAQ,SAAS;AAAA,MACxB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACJ,eAAO;AACP;AAAA,MACD;AACC,eAAO,QAAQ;AAAA,IACjB;AAEA,WAAO,UAAU,IAAI,IAAI,QAAQ,IAAI;AAAA,EACtC;AAEA,SAAO;AACR;AAEA,SAAS,0BACR,KACA,YACA,YACS;AACT,QAAM,0BAA0B,2BAA2B,UAAU;AACrE,QAAM,QAAQ;AACd,QAAM,SAAS,2CAA2C,uBAAuB;AAEjF,QAAM,YAAY,GAAG,SAAS,KAAK;AACnC,QAAM,aAAa,WAAW,MAAM;AAEpC,MACC,cACA,WAAW,OAAO,KAClB,WAAW,WAAW,UAAU,SAC/B;AAED,WAAO;AAAA,EACR;AAEA,MAAI,KAAK,IAAI,UAAU,mDAAmD;AAE1E,WAAS,WAAW,OAAO,MAAM,GAAG,EAAE,OAAO,UAAU,CAAC;AAExD,SAAO;AACR;AAEA,SAAS,2BAA2B,YAA4B;AAC/D,QAAM,SAAS,SAAS,8BAA8B,EAAE,SAAS;AAGjE,QAAM,iBAAiB,OAAO,YAAY,GAAG;AAC7C,MAAI,mBAAmB,IAAI;AAC1B,UAAM,IAAI;AAAA,MACT,IAAI,UAAU,mDAAmD,MAAM;AAAA,IACxE;AAAA,EACD;AAEA,SAAO,OAAO,MAAM,iBAAiB,CAAC,EAAE,KAAK;AAC9C;AAEA,SAAS,WAAW,MAA+B;AAClD,MAAI;AACH,WAAO,GAAG,SAAS,IAAI;AAAA,EACxB,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAEA,eAAe,gBACd,KAGA,MACC;AACD,QAAM,OAAO,gBAAgB,IAAI,IAAI;AACrC,MAAI,CAAC,KAAM;AAEX,kBAAgB,OAAO,IAAI;AAE3B,MAAI,KAAK,IAAI,IAAI,mCAAmC;AACpD,QAAM,KAAK;AACX,MAAI,KAAK,IAAI,IAAI,+BAA+B;AACjD;AAEA,eAAe,aAAa,SAAwC;AACnE,QAAM,QAAQ,MAAM,SAAS;AAAA,IAC5B,OAAO;AAAA,IACP,OAAO;AAAA,EACR,CAAC;AAED,SAAO,MAAM,IAAI,QAAQ,CAAC,SAAS,WAAW;AAC7C,UAAM,GAAG,SAAS,MAAM;AACvB,UAAI,CAAC,MAAM,KAAK;AACf,eAAO,OAAO,IAAI,MAAM,yBAAyB,CAAC;AAAA,MACnD;AAEA,cAAQ,KAAK;AAAA,IACd,CAAC;AAED,UAAM,GAAG,SAAS,CAAC,QAAQ;AAC1B,aAAO,GAAG;AAAA,IACX,CAAC;AAAA,EACF,CAAC;AACF;AAEA,IAAI,oBAAoB;AAExB,eAAe,UAAU;AACxB,sBAAoB;AACpB,QAAM,WAA4B,CAAC;AACnC,aAAW,QAAQ,gBAAgB,KAAK,GAAG;AAC1C,aAAS;AAAA,MACR;AAAA,QACC;AAAA,UACC,MAAM,CAAC,QAAgB;AACtB,oBAAQ,OAAO,MAAM,MAAM,IAAI;AAAA,UAChC;AAAA,QACD;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACA,QAAM,QAAQ,IAAI,QAAQ;AAC3B;AAEA,SAAS,gBAAgB;AACxB,MAAI,CAAC,mBAAmB;AACvB,SAAK,QAAQ,EAAE,QAAQ,MAAM;AAC5B,cAAQ,KAAK,CAAC;AAAA,IACf,CAAC;AAAA,EACF;AACD;AAEA,QAAQ,GAAG,UAAU,aAAa;AAClC,QAAQ,GAAG,WAAW,aAAa;AACnC,QAAQ,GAAG,QAAQ,aAAa;","names":[]}
|
|
1
|
+
{"version":3,"file":"plugin.js","names":[],"sources":["../src/plugin/expose-environment.ts","../src/plugin/plugin.ts"],"sourcesContent":["import type { Plugin } from \"vite\";\n\nexport default function exposeEnvironment(): Plugin {\n\tlet devServerUrl: string | undefined;\n\tlet command: \"serve\" | \"build\";\n\n\tfunction getModuleContents(environmentName: string) {\n\t\tconst url = devServerUrl ? JSON.stringify(devServerUrl) : \"undefined\";\n\n\t\treturn (\n\t\t\t`export const name = ${JSON.stringify(environmentName)}\\n` +\n\t\t\t`export const command = ${JSON.stringify(command)}\\n` +\n\t\t\t`export const devServerUrl = ${url}`\n\t\t);\n\t}\n\n\treturn {\n\t\tname: \"vite-plugin-fastly/expose-environment\",\n\n\t\tenforce: \"pre\",\n\n\t\tresolveId: {\n\t\t\tfilter: {\n\t\t\t\tid: /^vite-plugin-fastly:environment$/,\n\t\t\t},\n\t\t\thandler(source) {\n\t\t\t\tif (source === \"vite-plugin-fastly:environment\") {\n\t\t\t\t\treturn \"\\0virtual:vite-plugin-fastly:environment\";\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\n\t\tload: {\n\t\t\tfilter: {\n\t\t\t\tid: /^\\0virtual:vite-plugin-fastly:environment$/,\n\t\t\t},\n\t\t\thandler(id) {\n\t\t\t\tif (id !== \"\\0virtual:vite-plugin-fastly:environment\") return;\n\t\t\t\treturn getModuleContents(this.environment.name);\n\t\t\t},\n\t\t},\n\n\t\tconfigResolved(config) {\n\t\t\tcommand = config.command;\n\t\t},\n\n\t\tconfigureServer(server) {\n\t\t\tserver.httpServer?.once(\"listening\", () => {\n\t\t\t\tdevServerUrl = server.resolvedUrls?.local[0];\n\t\t\t});\n\t\t},\n\t} satisfies Plugin;\n}\n","import {\n\tcreateFetchableDevEnvironment,\n\ttype ConfigPluginContext,\n\ttype Connect,\n\ttype HttpServer,\n\ttype Plugin,\n} from \"vite\";\nimport { createProxy, type ServerOptions } from \"http-proxy-3\";\nimport type { IncomingMessage } from \"node:http\";\nimport fs from \"node:fs\";\nimport { ChildProcess, execSync, spawn } from \"node:child_process\";\nimport { launchAndTest, type LaunchAndTestCleanupFunction } from \"kill-em-all\";\nimport exposeEnvironment from \"./expose-environment\";\n\nexport interface FastlyPluginOptions {\n\t/**\n\t * A unique key to identify the plugin instance. This is required if you\n\t * have multiple Fastly plugin instances in the same Vite configuration.\n\t *\n\t * @default \"vite-plugin-fastly\"\n\t */\n\tuniqueName?: string;\n\n\t/**\n\t * Vite environment name that the Fastly plugin should configure.\n\t *\n\t * @default \"ssr\"\n\t */\n\tviteEnvironmentName?: string;\n\n\t/**\n\t * Function that returns the command to build the Fastly Module Runner.\n\t * The callback receives the input and output file paths.\n\t *\n\t * @default (input, output) => `js-compute-runtime ${input} ${output}`\n\t */\n\tgetRunnerBuildCommand?: (input: string, output: string) => string;\n\n\t/**\n\t * IPv4 address of the Fastly Dev Server to proxy requests to during development.\n\t * If you have multiple Fastly plugin instances, make sure each instance uses\n\t * a unique address.\n\t *\n\t * @default \"127.0.0.1:7676\"\n\t */\n\tfastlyDevServerAddress?: string;\n\n\t/**\n\t * Function that returns the command to launch the Fastly Dev Server.\n\t * The callback receives the compiled wasm file path and the address to bind to.\n\t *\n\t * @default (wasmFile, address) => `fastly compute serve --file=${wasmFile} --addr=${address}`\n\t */\n\tgetLaunchDevServerCommand?: (wasmFile: string, address: string) => string;\n\n\t/**\n\t * Options to pass to the HTTP proxy server.\n\t *\n\t * @default {}\n\t */\n\tproxyOptions?: ServerOptions;\n}\n\n// Map of uniqueName to Fastly Dev Server child processes\nconst fastlyProcesses = new Map<string, LaunchAndTestCleanupFunction>();\n\nexport function fastly(options: FastlyPluginOptions = {}): Plugin[] {\n\tconst {\n\t\tuniqueName = \"vite-plugin-fastly\",\n\t\tviteEnvironmentName = \"ssr\",\n\t\tfastlyDevServerAddress = \"127.0.0.1:7676\",\n\t\tgetRunnerBuildCommand = (input: string, output: string) =>\n\t\t\t`js-compute-runtime ${input} ${output}`,\n\t\tgetLaunchDevServerCommand = (wasmFile, address) =>\n\t\t\t`fastly compute serve --file=${wasmFile} --addr=${address}`,\n\t\tproxyOptions = {},\n\t} = options;\n\n\tlet command: \"serve\" | \"build\";\n\tlet handlerEntry: string | undefined;\n\tlet fastlyProcessKilled = false;\n\tlet clientConfigured = false;\n\tlet buildCommand: string | undefined;\n\n\treturn [\n\t\texposeEnvironment(),\n\t\t{\n\t\t\tname: uniqueName,\n\n\t\t\tconfig(_, env) {\n\t\t\t\tconst hasRoldown = this.meta.rolldownVersion !== undefined;\n\n\t\t\t\treturn {\n\t\t\t\t\tenvironments: {\n\t\t\t\t\t\t[viteEnvironmentName]: {\n\t\t\t\t\t\t\tdefine: {\n\t\t\t\t\t\t\t\t\"process.env.NODE_ENV\": JSON.stringify(env.mode),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\toptimizeDeps: {\n\t\t\t\t\t\t\t\tnoDiscovery: false,\n\t\t\t\t\t\t\t\texclude: [\n\t\t\t\t\t\t\t\t\t\"fastly:acl\",\n\t\t\t\t\t\t\t\t\t\"fastly:backend\",\n\t\t\t\t\t\t\t\t\t\"fastly:cache\",\n\t\t\t\t\t\t\t\t\t\"fastly:cache-override\",\n\t\t\t\t\t\t\t\t\t\"fastly:compute\",\n\t\t\t\t\t\t\t\t\t\"fastly:config-store\",\n\t\t\t\t\t\t\t\t\t\"fastly:device\",\n\t\t\t\t\t\t\t\t\t\"fastly:dictionary\",\n\t\t\t\t\t\t\t\t\t\"fastly:edge-rate-limiter\",\n\t\t\t\t\t\t\t\t\t\"fastly:env\",\n\t\t\t\t\t\t\t\t\t\"fastly:experimental\",\n\t\t\t\t\t\t\t\t\t\"fastly:fanout\",\n\t\t\t\t\t\t\t\t\t\"fastly:geolocation\",\n\t\t\t\t\t\t\t\t\t\"fastly:html-rewriter\",\n\t\t\t\t\t\t\t\t\t\"fastly:image-optimizer\",\n\t\t\t\t\t\t\t\t\t\"fastly:kv-store\",\n\t\t\t\t\t\t\t\t\t\"fastly:logger\",\n\t\t\t\t\t\t\t\t\t\"fastly:secret-store\",\n\t\t\t\t\t\t\t\t\t\"fastly:websocket\",\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\trolldownOptions: {\n\t\t\t\t\t\t\t\t\tplatform: \"neutral\",\n\t\t\t\t\t\t\t\t\ttreeshake: true,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tesbuildOptions: hasRoldown\n\t\t\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\t\t\tplatform: \"neutral\",\n\t\t\t\t\t\t\t\t\t\t\tminify: true,\n\t\t\t\t\t\t\t\t\t\t\tdefine: {\n\t\t\t\t\t\t\t\t\t\t\t\t\"process.env.NODE_ENV\": JSON.stringify(env.mode),\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tresolve: {\n\t\t\t\t\t\t\t\tbuiltins: [/^fastly:/],\n\t\t\t\t\t\t\t\tnoExternal: true,\n\t\t\t\t\t\t\t\tconditions: [\"fastly\", \"workerd\"],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuild: {\n\t\t\t\t\t\t\t\trolldownOptions: hasRoldown\n\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\tplatform: \"neutral\",\n\t\t\t\t\t\t\t\t\t\t\toutput: {\n\t\t\t\t\t\t\t\t\t\t\t\tcodeSplitting: false,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\t\trollupOptions: hasRoldown\n\t\t\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\t\t\tplatform: \"neutral\",\n\t\t\t\t\t\t\t\t\t\t\toutput: {\n\t\t\t\t\t\t\t\t\t\t\t\tinlineDynamicImports: true,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tdev: {\n\t\t\t\t\t\t\t\tcreateEnvironment(name, config) {\n\t\t\t\t\t\t\t\t\treturn createFetchableDevEnvironment(name, config, {\n\t\t\t\t\t\t\t\t\t\thot: false,\n\t\t\t\t\t\t\t\t\t\thandleRequest(request) {\n\t\t\t\t\t\t\t\t\t\t\t// TODO: Create a full fetchable environment\n\t\t\t\t\t\t\t\t\t\t\tvoid request;\n\t\t\t\t\t\t\t\t\t\t\tthrow new Error(\"Not implemented\");\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t},\n\n\t\t\tapi: {\n\t\t\t\tfastly: {\n\t\t\t\t\taddress: fastlyDevServerAddress,\n\t\t\t\t},\n\t\t\t},\n\n\t\t\tconfigResolved(config) {\n\t\t\t\tcommand = config.command;\n\t\t\t\tif (command !== \"serve\") return;\n\n\t\t\t\t// Scan plugins for multiple instances with the same uniqueName\n\t\t\t\tlet sameNameInstanceCount = 0;\n\t\t\t\tlet sameAddressInstanceCount = 0;\n\t\t\t\tfor (const plugin of config.plugins) {\n\t\t\t\t\tif (plugin.name === uniqueName) {\n\t\t\t\t\t\tsameNameInstanceCount++;\n\t\t\t\t\t}\n\t\t\t\t\tif (plugin.api?.fastly?.address === fastlyDevServerAddress) {\n\t\t\t\t\t\tsameAddressInstanceCount++;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (sameNameInstanceCount > 1) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`[vite-plugin-fastly] Multiple Fastly plugin instances with the same uniqueName \"${uniqueName}\" detected.`,\n\t\t\t\t\t);\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`[vite-plugin-fastly] If you really need multiple instances, give each instance a unique \"uniqueName\".`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (sameAddressInstanceCount > 1) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`[vite-plugin-fastly] Multiple Fastly plugin instances configured to use the same Fastly Dev Server address \"${fastlyDevServerAddress}\".`,\n\t\t\t\t\t);\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`[vite-plugin-fastly] If you really need multiple instances, give each instance a unique \"fastlyDevServerAddress\"`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (sameNameInstanceCount > 1 || sameAddressInstanceCount > 1) {\n\t\t\t\t\t// This is a fatal error, we cannot continue\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\n\t\t\t\tconst hasRoldown = this.meta.rolldownVersion !== undefined;\n\t\t\t\tconst optionsKey = hasRoldown\n\t\t\t\t\t? (\"rolldownOptions\" as const)\n\t\t\t\t\t: (\"rollupOptions\" as const);\n\n\t\t\t\tconst clientInput =\n\t\t\t\t\tconfig.environments.client?.build?.[optionsKey]?.input;\n\t\t\t\tif (typeof clientInput === \"string\") {\n\t\t\t\t\tclientConfigured = true;\n\t\t\t\t} else if (Array.isArray(clientInput) && clientInput.length > 0) {\n\t\t\t\t\tclientConfigured = true;\n\t\t\t\t} else if (\n\t\t\t\t\ttypeof clientInput === \"object\" &&\n\t\t\t\t\tclientInput !== null &&\n\t\t\t\t\tObject.keys(clientInput).length > 0\n\t\t\t\t) {\n\t\t\t\t\tclientConfigured = true;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tasync configEnvironment(name, config, env) {\n\t\t\t\tif (name !== viteEnvironmentName || env.command !== \"serve\") {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst hasRoldown = this.meta.rolldownVersion !== undefined;\n\t\t\t\tconst optionsKey = hasRoldown\n\t\t\t\t\t? (\"rolldownOptions\" as const)\n\t\t\t\t\t: (\"rollupOptions\" as const);\n\n\t\t\t\tconst input = config.build?.[optionsKey]?.input;\n\t\t\t\tif (typeof input === \"string\") {\n\t\t\t\t\thandlerEntry = input;\n\t\t\t\t} else if (Array.isArray(input)) {\n\t\t\t\t\thandlerEntry = input[0];\n\t\t\t\t} else if (typeof input === \"object\" && input !== null) {\n\t\t\t\t\tconst values = Object.values(input);\n\t\t\t\t\thandlerEntry = values[0];\n\t\t\t\t}\n\n\t\t\t\tif (!handlerEntry) {\n\t\t\t\t\treturn this.error(\n\t\t\t\t\t\t`[${uniqueName}] No entry point found in ${optionsKey}. Please specify an input in environments.${viteEnvironmentName}.build.${optionsKey}.input.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Kill previous Fastly Dev Server process if any\n\t\t\t\tfastlyProcessKilled = true;\n\t\t\t\tawait doKillProcesses(this, uniqueName);\n\n\t\t\t\tconst wasmFile = buildDevRunnerIfNecessary(\n\t\t\t\t\tthis,\n\t\t\t\t\tuniqueName,\n\t\t\t\t\tgetRunnerBuildCommand,\n\t\t\t\t);\n\n\t\t\t\tconst launchCommand = getLaunchDevServerCommand(\n\t\t\t\t\twasmFile,\n\t\t\t\t\tfastlyDevServerAddress,\n\t\t\t\t);\n\n\t\t\t\tthis.info(`[${uniqueName}] Launching Fastly Dev Server with command:`);\n\t\t\t\tthis.info(`[${uniqueName}] ${launchCommand}`);\n\t\t\t\tconst fastlyDevServerProcess = await spawnCommand(launchCommand);\n\n\t\t\t\tconst kill = await launchAndTest(\n\t\t\t\t\tfastlyDevServerProcess,\n\t\t\t\t\t`http://${fastlyDevServerAddress}/@vite-plugin-fastly/ready`,\n\t\t\t\t);\n\n\t\t\t\tfastlyProcesses.set(uniqueName, kill);\n\n\t\t\t\tthis.info(\n\t\t\t\t\t`[${uniqueName}] Fastly Dev Server is running at http://${fastlyDevServerAddress}`,\n\t\t\t\t);\n\t\t\t},\n\n\t\t\tasync writeBundle(outputOptions, bundle) {\n\t\t\t\tif (\n\t\t\t\t\tcommand !== \"build\" ||\n\t\t\t\t\tthis.environment.name !== viteEnvironmentName\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst jsFile = Object.values(bundle).find(\n\t\t\t\t\t(file) => file.type === \"chunk\" && file.isEntry,\n\t\t\t\t);\n\t\t\t\tif (!jsFile) {\n\t\t\t\t\tthrow new Error(`[${uniqueName}] No JS entry chunk found in bundle.`);\n\t\t\t\t}\n\n\t\t\t\tconst input = outputOptions.dir + \"/\" + jsFile.fileName;\n\t\t\t\tconst output = outputOptions.dir + \"/app.wasm\";\n\n\t\t\t\tbuildCommand = `js-compute-runtime ${input} ${output}`;\n\t\t\t},\n\n\t\t\tasync closeBundle(error) {\n\t\t\t\tif (\n\t\t\t\t\terror ||\n\t\t\t\t\tcommand !== \"build\" ||\n\t\t\t\t\tthis.environment.name !== viteEnvironmentName\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis.info(`Building Fastly WASM module with command:`);\n\t\t\t\tthis.info(buildCommand!);\n\t\t\t\texecSync(buildCommand!, { stdio: \"inherit\" });\n\t\t\t},\n\n\t\t\tasync buildEnd() {\n\t\t\t\tif (command === \"build\" || fastlyProcessKilled) return;\n\t\t\t\tfastlyProcessKilled = true;\n\t\t\t\tawait doKillProcesses(this, uniqueName);\n\t\t\t},\n\n\t\t\tconfigureServer(server) {\n\t\t\t\tconst environment = server.environments[viteEnvironmentName]!;\n\t\t\t\tlet address: string | null = null;\n\n\t\t\t\tserver.httpServer?.on(\"listening\", () => {\n\t\t\t\t\taddress = getServerAddress(server.httpServer);\n\t\t\t\t});\n\n\t\t\t\tserver.httpServer?.on(\"close\", () => {\n\t\t\t\t\taddress = null;\n\t\t\t\t});\n\n\t\t\t\t// Transport endpoint for the runner\n\t\t\t\tserver.middlewares.use((req, res, next) => {\n\t\t\t\t\tif (\n\t\t\t\t\t\treq.method !== \"POST\" ||\n\t\t\t\t\t\treq.url !== \"/@vite-plugin-fastly/transport\"\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn next();\n\t\t\t\t\t}\n\n\t\t\t\t\tvoid (async () => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Read the body\n\t\t\t\t\t\t\tconst body = await readyBody(req);\n\t\t\t\t\t\t\tconst data = JSON.parse(body);\n\n\t\t\t\t\t\t\tconst result = await environment.hot.handleInvoke(data);\n\n\t\t\t\t\t\t\tres.setHeader(\"Content-Type\", \"application/json\");\n\t\t\t\t\t\t\tres.end(JSON.stringify(result));\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\treturn next(error);\n\t\t\t\t\t\t}\n\t\t\t\t\t})();\n\t\t\t\t});\n\n\t\t\t\tconst proxy = createProxy(proxyOptions);\n\n\t\t\t\tconst proxyMiddleware: Connect.NextHandleFunction = (\n\t\t\t\t\treq,\n\t\t\t\t\tres,\n\t\t\t\t\tnext,\n\t\t\t\t) => {\n\t\t\t\t\tif (!address) {\n\t\t\t\t\t\treturn next(\n\t\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t\t`[${uniqueName}] Vite server address is not available for proxying`,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tproxy.web(\n\t\t\t\t\t\t\treq,\n\t\t\t\t\t\t\tres,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttarget: `http://${fastlyDevServerAddress}`,\n\t\t\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\t\t\"Vite-Plugin-Fastly-Vite-Server-Address\": address,\n\t\t\t\t\t\t\t\t\t\"Vite-Plugin-Fastly-Handler-Entry\": handlerEntry,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t(error) => {\n\t\t\t\t\t\t\t\tnext(error);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tnext(error);\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\t// If a client build is configured, add the proxy middleware after Vite's own middlewares.\n\t\t\t\t// Otherwise, assume a pure server-side setup and add the proxy as the first middleware.\n\t\t\t\tif (clientConfigured) {\n\t\t\t\t\treturn () => {\n\t\t\t\t\t\tserver.middlewares.use(proxyMiddleware);\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tserver.middlewares.use(proxyMiddleware);\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t];\n}\n\nasync function readyBody(req: IncomingMessage): Promise<string> {\n\treturn new Promise<string>((resolve, reject) => {\n\t\tlet body = \"\";\n\t\treq.on(\"data\", (chunk) => {\n\t\t\tbody += chunk;\n\t\t});\n\n\t\treq.on(\"end\", () => {\n\t\t\tresolve(body);\n\t\t});\n\n\t\treq.on(\"error\", (err) => {\n\t\t\treject(err);\n\t\t});\n\t});\n}\n\nfunction getServerAddress(server: HttpServer | null): string | null {\n\tconst address = server?.address();\n\tif (!address) {\n\t\treturn null;\n\t}\n\n\tlet host: string;\n\n\tif (typeof address === \"string\") {\n\t\thost = address;\n\t} else {\n\t\tswitch (address.address) {\n\t\t\tcase \"127.0.0.1\":\n\t\t\tcase \"::\":\n\t\t\tcase \"::1\":\n\t\t\tcase \"0000:0000:0000:0000:0000:0000:0000:0001\":\n\t\t\t\thost = \"localhost\";\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\thost = address.address;\n\t\t}\n\n\t\thost = `http://${host}:${address.port}`;\n\t}\n\n\treturn host;\n}\n\nfunction buildDevRunnerIfNecessary(\n\tctx: ConfigPluginContext,\n\tuniqueName: string,\n\tgetCommand: (input: string, output: string) => string,\n): string {\n\tconst jsComputeRuntimeVersion = getJsComputeRuntimeVersion(uniqueName);\n\tconst input = \"node_modules/vite-plugin-fastly/dist/runner.js\";\n\tconst output = `node_modules/.vite-plugin-fastly/runner.${jsComputeRuntimeVersion}.wasm`;\n\n\tconst inputStat = fs.statSync(input);\n\tconst outputStat = statOrNull(output);\n\n\tif (\n\t\toutputStat &&\n\t\toutputStat.isFile() &&\n\t\toutputStat.mtimeMs >= inputStat.mtimeMs\n\t) {\n\t\t// Up to date\n\t\treturn output;\n\t}\n\n\tctx.info(`[${uniqueName}] Building Fastly Module Runner for dev server...`);\n\n\texecSync(getCommand(input, output), { stdio: \"inherit\" });\n\n\treturn output;\n}\n\nfunction getJsComputeRuntimeVersion(uniqueName: string): string {\n\tconst output = execSync(\"js-compute-runtime --version\").toString();\n\n\t// Parse version from something like \"js-compute-runtime-cli.js 3.38.2\\n\"\n\tconst lastSpaceIndex = output.lastIndexOf(\" \");\n\tif (lastSpaceIndex === -1) {\n\t\tthrow new Error(\n\t\t\t`[${uniqueName}] Unexpected js-compute-runtime version output: ${output}`,\n\t\t);\n\t}\n\n\treturn output.slice(lastSpaceIndex + 1).trim();\n}\n\nfunction statOrNull(path: string): fs.Stats | null {\n\ttry {\n\t\treturn fs.statSync(path);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function doKillProcesses(\n\tctx: {\n\t\tinfo: (msg: string) => void;\n\t},\n\tname: string,\n) {\n\tconst kill = fastlyProcesses.get(name);\n\tif (!kill) return;\n\n\tfastlyProcesses.delete(name);\n\n\tctx.info(`[${name}] Shutting down Fastly dev server`);\n\tawait kill();\n\tctx.info(`[${name}] Fastly dev server shut down`);\n}\n\nasync function spawnCommand(command: string): Promise<ChildProcess> {\n\tconst child = spawn(command, {\n\t\tshell: true,\n\t\tstdio: \"inherit\",\n\t});\n\n\treturn await new Promise((resolve, reject) => {\n\t\tchild.on(\"spawn\", () => {\n\t\t\tif (!child.pid) {\n\t\t\t\treturn reject(new Error(\"Failed to spawn process\"));\n\t\t\t}\n\n\t\t\tresolve(child);\n\t\t});\n\n\t\tchild.on(\"error\", (err) => {\n\t\t\treject(err);\n\t\t});\n\t});\n}\n\nlet killAllInProgress = false;\n\nasync function killAll() {\n\tkillAllInProgress = true;\n\tconst promises: Promise<void>[] = [];\n\tfor (const name of fastlyProcesses.keys()) {\n\t\tpromises.push(\n\t\t\tdoKillProcesses(\n\t\t\t\t{\n\t\t\t\t\tinfo: (msg: string) => {\n\t\t\t\t\t\tprocess.stdout.write(msg + \"\\n\");\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tname,\n\t\t\t),\n\t\t);\n\t}\n\tawait Promise.all(promises);\n}\n\nfunction cleanupOnExit() {\n\tif (!killAllInProgress) {\n\t\tvoid killAll().finally(() => {\n\t\t\tprocess.exit(0);\n\t\t});\n\t}\n}\n\nprocess.on(\"SIGINT\", cleanupOnExit);\nprocess.on(\"SIGTERM\", cleanupOnExit);\nprocess.on(\"exit\", cleanupOnExit);\n"],"mappings":"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"}
|
package/dist/runner.js
CHANGED
|
@@ -1,95 +1,55 @@
|
|
|
1
|
-
// src/runner/runner.ts
|
|
2
1
|
import { ESModulesEvaluator, ModuleRunner } from "vite/module-runner";
|
|
3
|
-
|
|
2
|
+
//#region src/runner/runner.ts
|
|
3
|
+
const evaluator = new ESModulesEvaluator();
|
|
4
4
|
evaluator.runExternalModule = async (filepath) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return await import("fastly:experimental");
|
|
28
|
-
case "fastly:fanout":
|
|
29
|
-
return await import("fastly:fanout");
|
|
30
|
-
case "fastly:geolocation":
|
|
31
|
-
return await import("fastly:geolocation");
|
|
32
|
-
case "fastly:html-rewriter":
|
|
33
|
-
return await import("fastly:html-rewriter");
|
|
34
|
-
case "fastly:image-optimizer":
|
|
35
|
-
return await import("fastly:image-optimizer");
|
|
36
|
-
case "fastly:kv-store":
|
|
37
|
-
return await import("fastly:kv-store");
|
|
38
|
-
case "fastly:logger":
|
|
39
|
-
return await import("fastly:logger");
|
|
40
|
-
case "fastly:secret-store":
|
|
41
|
-
return await import("fastly:secret-store");
|
|
42
|
-
case "fastly:websocket":
|
|
43
|
-
return await import("fastly:websocket");
|
|
44
|
-
default:
|
|
45
|
-
throw new Error("Unknown external module: " + filepath);
|
|
46
|
-
}
|
|
5
|
+
switch (filepath) {
|
|
6
|
+
case "fastly:acl": return await import("fastly:acl");
|
|
7
|
+
case "fastly:backend": return await import("fastly:backend");
|
|
8
|
+
case "fastly:cache": return await import("fastly:cache");
|
|
9
|
+
case "fastly:cache-override": return await import("fastly:cache-override");
|
|
10
|
+
case "fastly:compute": return await import("fastly:compute");
|
|
11
|
+
case "fastly:config-store": return await import("fastly:config-store");
|
|
12
|
+
case "fastly:device": return await import("fastly:device");
|
|
13
|
+
case "fastly:dictionary": return await import("fastly:dictionary");
|
|
14
|
+
case "fastly:edge-rate-limiter": return await import("fastly:edge-rate-limiter");
|
|
15
|
+
case "fastly:env": return await import("fastly:env");
|
|
16
|
+
case "fastly:experimental": return await import("fastly:experimental");
|
|
17
|
+
case "fastly:fanout": return await import("fastly:fanout");
|
|
18
|
+
case "fastly:geolocation": return await import("fastly:geolocation");
|
|
19
|
+
case "fastly:html-rewriter": return await import("fastly:html-rewriter");
|
|
20
|
+
case "fastly:image-optimizer": return await import("fastly:image-optimizer");
|
|
21
|
+
case "fastly:kv-store": return await import("fastly:kv-store");
|
|
22
|
+
case "fastly:logger": return await import("fastly:logger");
|
|
23
|
+
case "fastly:secret-store": return await import("fastly:secret-store");
|
|
24
|
+
case "fastly:websocket": return await import("fastly:websocket");
|
|
25
|
+
default: throw new Error("Unknown external module: " + filepath);
|
|
26
|
+
}
|
|
47
27
|
};
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return r.json();
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
evaluator
|
|
66
|
-
);
|
|
28
|
+
const runner = new ModuleRunner({
|
|
29
|
+
hmr: false,
|
|
30
|
+
transport: { async invoke(data) {
|
|
31
|
+
return fetch(`${viteServerAddress}/@vite-plugin-fastly/transport`, {
|
|
32
|
+
method: "POST",
|
|
33
|
+
body: JSON.stringify(data)
|
|
34
|
+
}).then((r) => {
|
|
35
|
+
if (!r.ok) return { error: /* @__PURE__ */ new Error(`Transport error ${r.status}`) };
|
|
36
|
+
return r.json();
|
|
37
|
+
});
|
|
38
|
+
} }
|
|
39
|
+
}, evaluator);
|
|
67
40
|
addEventListener("fetch", (event) => event.respondWith(handleRequest(event)));
|
|
68
|
-
|
|
41
|
+
let viteServerAddress;
|
|
69
42
|
async function handleRequest(event) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
"Vite-Plugin-Fastly-Vite-Server-Address"
|
|
80
|
-
);
|
|
81
|
-
const handlerEntry = request.headers.get("Vite-Plugin-Fastly-Handler-Entry");
|
|
82
|
-
if (!viteServerAddress) {
|
|
83
|
-
return new Response("Vite server address header is missing", {
|
|
84
|
-
status: 500
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
if (!handlerEntry) {
|
|
88
|
-
return new Response("Handler entry header is missing", {
|
|
89
|
-
status: 500
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
const module = await runner.import(handlerEntry);
|
|
93
|
-
return await module.default(event);
|
|
43
|
+
const request = event.request;
|
|
44
|
+
if (request.method === "GET") {
|
|
45
|
+
if (new URL(request.url).pathname === "/@vite-plugin-fastly/ready") return new Response("OK", { status: 200 });
|
|
46
|
+
}
|
|
47
|
+
viteServerAddress ||= request.headers.get("Vite-Plugin-Fastly-Vite-Server-Address");
|
|
48
|
+
const handlerEntry = request.headers.get("Vite-Plugin-Fastly-Handler-Entry");
|
|
49
|
+
if (!viteServerAddress) return new Response("Vite server address header is missing", { status: 500 });
|
|
50
|
+
if (!handlerEntry) return new Response("Handler entry header is missing", { status: 500 });
|
|
51
|
+
return await (await runner.import(handlerEntry)).default(event);
|
|
94
52
|
}
|
|
53
|
+
//#endregion
|
|
54
|
+
|
|
95
55
|
//# sourceMappingURL=runner.js.map
|
package/dist/runner.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runner/runner.ts"],"sourcesContent":["import { ESModulesEvaluator, ModuleRunner } from \"vite/module-runner\";\n\nconst evaluator = new ESModulesEvaluator();\n\nevaluator.runExternalModule = async (filepath) => {\n\tswitch (filepath) {\n\t\tcase \"fastly:acl\":\n\t\t\treturn await import(\"fastly:acl\");\n\t\tcase \"fastly:backend\":\n\t\t\treturn await import(\"fastly:backend\");\n\t\tcase \"fastly:cache\":\n\t\t\treturn await import(\"fastly:cache\");\n\t\tcase \"fastly:cache-override\":\n\t\t\treturn await import(\"fastly:cache-override\");\n\t\tcase \"fastly:compute\":\n\t\t\treturn await import(\"fastly:compute\");\n\t\tcase \"fastly:config-store\":\n\t\t\treturn await import(\"fastly:config-store\");\n\t\tcase \"fastly:device\":\n\t\t\treturn await import(\"fastly:device\");\n\t\tcase \"fastly:dictionary\":\n\t\t\treturn await import(\"fastly:dictionary\");\n\t\tcase \"fastly:edge-rate-limiter\":\n\t\t\treturn await import(\"fastly:edge-rate-limiter\");\n\t\tcase \"fastly:env\":\n\t\t\treturn await import(\"fastly:env\");\n\t\tcase \"fastly:experimental\":\n\t\t\treturn await import(\"fastly:experimental\");\n\t\tcase \"fastly:fanout\":\n\t\t\treturn await import(\"fastly:fanout\");\n\t\tcase \"fastly:geolocation\":\n\t\t\treturn await import(\"fastly:geolocation\");\n\t\tcase \"fastly:html-rewriter\":\n\t\t\treturn await import(\"fastly:html-rewriter\");\n\t\tcase \"fastly:image-optimizer\":\n\t\t\treturn await import(\"fastly:image-optimizer\");\n\t\tcase \"fastly:kv-store\":\n\t\t\treturn await import(\"fastly:kv-store\");\n\t\tcase \"fastly:logger\":\n\t\t\treturn await import(\"fastly:logger\");\n\t\tcase \"fastly:secret-store\":\n\t\t\treturn await import(\"fastly:secret-store\");\n\t\tcase \"fastly:websocket\":\n\t\t\treturn await import(\"fastly:websocket\");\n\n\t\tdefault:\n\t\t\tthrow new Error(\"Unknown external module: \" + filepath);\n\t}\n};\n\nconst runner = new ModuleRunner(\n\t{\n\t\thmr: false,\n\n\t\ttransport: {\n\t\t\tasync invoke(data: any) {\n\t\t\t\treturn fetch(`${viteServerAddress}/@vite-plugin-fastly/transport`, {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: JSON.stringify(data),\n\t\t\t\t}).then((r) => {\n\t\t\t\t\tif (!r.ok) {\n\t\t\t\t\t\treturn { error: new Error(`Transport error ${r.status}`) };\n\t\t\t\t\t}\n\n\t\t\t\t\treturn r.json() as Promise<any>;\n\t\t\t\t});\n\t\t\t},\n\t\t},\n\t},\n\tevaluator,\n);\n\naddEventListener(\"fetch\", (event) => event.respondWith(handleRequest(event)));\n\nlet viteServerAddress: string;\n\nasync function handleRequest(event: FetchEvent) {\n\tconst request = event.request;\n\n\tif (request.method === \"GET\") {\n\t\tconst url = new URL(request.url);\n\t\tconst path = url.pathname;\n\t\tif (path === \"/@vite-plugin-fastly/ready\") {\n\t\t\treturn new Response(\"OK\", { status: 200 });\n\t\t}\n\t}\n\n\tviteServerAddress ||= request.headers.get(\n\t\t\"Vite-Plugin-Fastly-Vite-Server-Address\",\n\t)!;\n\n\tconst handlerEntry = request.headers.get(\"Vite-Plugin-Fastly-Handler-Entry\")!;\n\n\tif (!viteServerAddress) {\n\t\treturn new Response(\"Vite server address header is missing\", {\n\t\t\tstatus: 500,\n\t\t});\n\t}\n\n\tif (!handlerEntry) {\n\t\treturn new Response(\"Handler entry header is missing\", {\n\t\t\tstatus: 500,\n\t\t});\n\t}\n\n\tconst module = await runner.import(handlerEntry);\n\treturn await module.default(event);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"runner.js","names":[],"sources":["../src/runner/runner.ts"],"sourcesContent":["import { ESModulesEvaluator, ModuleRunner } from \"vite/module-runner\";\n\nconst evaluator = new ESModulesEvaluator();\n\nevaluator.runExternalModule = async (filepath) => {\n\tswitch (filepath) {\n\t\tcase \"fastly:acl\":\n\t\t\treturn await import(\"fastly:acl\");\n\t\tcase \"fastly:backend\":\n\t\t\treturn await import(\"fastly:backend\");\n\t\tcase \"fastly:cache\":\n\t\t\treturn await import(\"fastly:cache\");\n\t\tcase \"fastly:cache-override\":\n\t\t\treturn await import(\"fastly:cache-override\");\n\t\tcase \"fastly:compute\":\n\t\t\treturn await import(\"fastly:compute\");\n\t\tcase \"fastly:config-store\":\n\t\t\treturn await import(\"fastly:config-store\");\n\t\tcase \"fastly:device\":\n\t\t\treturn await import(\"fastly:device\");\n\t\tcase \"fastly:dictionary\":\n\t\t\treturn await import(\"fastly:dictionary\");\n\t\tcase \"fastly:edge-rate-limiter\":\n\t\t\treturn await import(\"fastly:edge-rate-limiter\");\n\t\tcase \"fastly:env\":\n\t\t\treturn await import(\"fastly:env\");\n\t\tcase \"fastly:experimental\":\n\t\t\treturn await import(\"fastly:experimental\");\n\t\tcase \"fastly:fanout\":\n\t\t\treturn await import(\"fastly:fanout\");\n\t\tcase \"fastly:geolocation\":\n\t\t\treturn await import(\"fastly:geolocation\");\n\t\tcase \"fastly:html-rewriter\":\n\t\t\treturn await import(\"fastly:html-rewriter\");\n\t\tcase \"fastly:image-optimizer\":\n\t\t\treturn await import(\"fastly:image-optimizer\");\n\t\tcase \"fastly:kv-store\":\n\t\t\treturn await import(\"fastly:kv-store\");\n\t\tcase \"fastly:logger\":\n\t\t\treturn await import(\"fastly:logger\");\n\t\tcase \"fastly:secret-store\":\n\t\t\treturn await import(\"fastly:secret-store\");\n\t\tcase \"fastly:websocket\":\n\t\t\treturn await import(\"fastly:websocket\");\n\n\t\tdefault:\n\t\t\tthrow new Error(\"Unknown external module: \" + filepath);\n\t}\n};\n\nconst runner = new ModuleRunner(\n\t{\n\t\thmr: false,\n\n\t\ttransport: {\n\t\t\tasync invoke(data: any) {\n\t\t\t\treturn fetch(`${viteServerAddress}/@vite-plugin-fastly/transport`, {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: JSON.stringify(data),\n\t\t\t\t}).then((r) => {\n\t\t\t\t\tif (!r.ok) {\n\t\t\t\t\t\treturn { error: new Error(`Transport error ${r.status}`) };\n\t\t\t\t\t}\n\n\t\t\t\t\treturn r.json() as Promise<any>;\n\t\t\t\t});\n\t\t\t},\n\t\t},\n\t},\n\tevaluator,\n);\n\naddEventListener(\"fetch\", (event) => event.respondWith(handleRequest(event)));\n\nlet viteServerAddress: string;\n\nasync function handleRequest(event: FetchEvent) {\n\tconst request = event.request;\n\n\tif (request.method === \"GET\") {\n\t\tconst url = new URL(request.url);\n\t\tconst path = url.pathname;\n\t\tif (path === \"/@vite-plugin-fastly/ready\") {\n\t\t\treturn new Response(\"OK\", { status: 200 });\n\t\t}\n\t}\n\n\tviteServerAddress ||= request.headers.get(\n\t\t\"Vite-Plugin-Fastly-Vite-Server-Address\",\n\t)!;\n\n\tconst handlerEntry = request.headers.get(\"Vite-Plugin-Fastly-Handler-Entry\")!;\n\n\tif (!viteServerAddress) {\n\t\treturn new Response(\"Vite server address header is missing\", {\n\t\t\tstatus: 500,\n\t\t});\n\t}\n\n\tif (!handlerEntry) {\n\t\treturn new Response(\"Handler entry header is missing\", {\n\t\t\tstatus: 500,\n\t\t});\n\t}\n\n\tconst module = await runner.import(handlerEntry);\n\treturn await module.default(event);\n}\n"],"mappings":";;AAEA,MAAM,YAAY,IAAI,oBAAoB;AAE1C,UAAU,oBAAoB,OAAO,aAAa;AACjD,SAAQ,UAAR;EACC,KAAK,aACJ,QAAO,MAAM,OAAO;EACrB,KAAK,iBACJ,QAAO,MAAM,OAAO;EACrB,KAAK,eACJ,QAAO,MAAM,OAAO;EACrB,KAAK,wBACJ,QAAO,MAAM,OAAO;EACrB,KAAK,iBACJ,QAAO,MAAM,OAAO;EACrB,KAAK,sBACJ,QAAO,MAAM,OAAO;EACrB,KAAK,gBACJ,QAAO,MAAM,OAAO;EACrB,KAAK,oBACJ,QAAO,MAAM,OAAO;EACrB,KAAK,2BACJ,QAAO,MAAM,OAAO;EACrB,KAAK,aACJ,QAAO,MAAM,OAAO;EACrB,KAAK,sBACJ,QAAO,MAAM,OAAO;EACrB,KAAK,gBACJ,QAAO,MAAM,OAAO;EACrB,KAAK,qBACJ,QAAO,MAAM,OAAO;EACrB,KAAK,uBACJ,QAAO,MAAM,OAAO;EACrB,KAAK,yBACJ,QAAO,MAAM,OAAO;EACrB,KAAK,kBACJ,QAAO,MAAM,OAAO;EACrB,KAAK,gBACJ,QAAO,MAAM,OAAO;EACrB,KAAK,sBACJ,QAAO,MAAM,OAAO;EACrB,KAAK,mBACJ,QAAO,MAAM,OAAO;EAErB,QACC,OAAM,IAAI,MAAM,8BAA8B,SAAS;;;AAI1D,MAAM,SAAS,IAAI,aAClB;CACC,KAAK;CAEL,WAAW,EACV,MAAM,OAAO,MAAW;AACvB,SAAO,MAAM,GAAG,kBAAkB,iCAAiC;GAClE,QAAQ;GACR,MAAM,KAAK,UAAU,KAAK;GAC1B,CAAC,CAAC,MAAM,MAAM;AACd,OAAI,CAAC,EAAE,GACN,QAAO,EAAE,uBAAO,IAAI,MAAM,mBAAmB,EAAE,SAAS,EAAE;AAG3D,UAAO,EAAE,MAAM;IACd;IAEH;CACD,EACD,UACA;AAED,iBAAiB,UAAU,UAAU,MAAM,YAAY,cAAc,MAAM,CAAC,CAAC;AAE7E,IAAI;AAEJ,eAAe,cAAc,OAAmB;CAC/C,MAAM,UAAU,MAAM;AAEtB,KAAI,QAAQ,WAAW;MACV,IAAI,IAAI,QAAQ,IAAI,CACf,aACJ,6BACZ,QAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,KAAK,CAAC;;AAI5C,uBAAsB,QAAQ,QAAQ,IACrC,yCACA;CAED,MAAM,eAAe,QAAQ,QAAQ,IAAI,mCAAmC;AAE5E,KAAI,CAAC,kBACJ,QAAO,IAAI,SAAS,yCAAyC,EAC5D,QAAQ,KACR,CAAC;AAGH,KAAI,CAAC,aACJ,QAAO,IAAI,SAAS,mCAAmC,EACtD,QAAQ,KACR,CAAC;AAIH,QAAO,OADQ,MAAM,OAAO,OAAO,aAAa,EAC5B,QAAQ,MAAM"}
|
package/package.json
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-fastly",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "vite-plugin-fastly",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"compute-at-edge",
|
|
7
|
+
"edge-computing",
|
|
8
|
+
"fastly",
|
|
9
|
+
"fastly-compute",
|
|
10
|
+
"serverless",
|
|
11
|
+
"viceroy",
|
|
12
|
+
"vite",
|
|
13
|
+
"vite-plugin"
|
|
14
|
+
],
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"repository": "github:cyco130/vite-plugin-fastly",
|
|
5
17
|
"files": [
|
|
6
18
|
"dist",
|
|
7
19
|
"*.d.ts"
|
|
8
20
|
],
|
|
9
|
-
"
|
|
10
|
-
".": "./dist/plugin.js",
|
|
11
|
-
"./runner": "./dist/runner.js",
|
|
12
|
-
"./types": "./types.d.ts"
|
|
13
|
-
},
|
|
21
|
+
"type": "module",
|
|
14
22
|
"typesVersions": {
|
|
15
23
|
"*": {
|
|
16
24
|
"*": [
|
|
@@ -18,41 +26,33 @@
|
|
|
18
26
|
]
|
|
19
27
|
}
|
|
20
28
|
},
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"compute-at-edge",
|
|
30
|
-
"viceroy",
|
|
31
|
-
"edge-computing",
|
|
32
|
-
"serverless"
|
|
33
|
-
],
|
|
34
|
-
"peerDependencies": {
|
|
35
|
-
"@fastly/js-compute": "3",
|
|
36
|
-
"vite": "7"
|
|
29
|
+
"exports": {
|
|
30
|
+
".": "./dist/plugin.js",
|
|
31
|
+
"./runner": "./dist/runner.js",
|
|
32
|
+
"./types": "./types.d.ts"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"http-proxy-3": "^1.23.2",
|
|
36
|
+
"kill-em-all": "0.0.5"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@cyco130/eslint-config": "^6.2.
|
|
40
|
-
"@fastly/cli": "^
|
|
41
|
-
"@fastly/js-compute": "^3.40.
|
|
39
|
+
"@cyco130/eslint-config": "^6.2.4",
|
|
40
|
+
"@fastly/cli": "^14.1.1",
|
|
41
|
+
"@fastly/js-compute": "^3.40.1",
|
|
42
42
|
"@types/node": "^25.0.7",
|
|
43
|
-
"eslint": "^10.
|
|
44
|
-
"publint": "^0.3.
|
|
45
|
-
"
|
|
43
|
+
"eslint": "^10.1.0",
|
|
44
|
+
"publint": "^0.3.18",
|
|
45
|
+
"tsdown": "0.21.4",
|
|
46
46
|
"typescript": "^5.9.3",
|
|
47
|
-
"vite": "
|
|
47
|
+
"vite": "8.0.1"
|
|
48
48
|
},
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"@fastly/js-compute": "3",
|
|
51
|
+
"vite": "~7.3 || 8"
|
|
52
52
|
},
|
|
53
53
|
"scripts": {
|
|
54
|
-
"build": "
|
|
55
|
-
"dev": "
|
|
54
|
+
"build": "tsdown",
|
|
55
|
+
"dev": "tsdown --watch",
|
|
56
56
|
"test": "pnpm run /^test:/",
|
|
57
57
|
"test:typecheck": "tsc -p tsconfig.json --noEmit",
|
|
58
58
|
"test:lint": "eslint . --max-warnings 0 --ignore-pattern dist --no-warn-ignored",
|
package/readme.md
CHANGED
|
@@ -20,7 +20,7 @@ Check the starter examples:
|
|
|
20
20
|
|
|
21
21
|
During development, `vite-plugin-fastly` works by launching a remote module runner via `fastly compute serve` that communicates with the Vite development server to transform source files on-the-fly and run them via a Vite [`ModuleRunner`](https://vite.dev/guide/api-environment-runtimes#modulerunner). This runner, in turn, loads your entry module and passes incoming requests to it.
|
|
22
22
|
|
|
23
|
-
The plugin also adds a middleware to the Vite development server that proxies requests to the remote module runner. This proxy is placed _before_ Vite's own middlewares if you don't configure a client entry point via `environments.client.build.
|
|
23
|
+
The plugin also adds a middleware to the Vite development server that proxies requests to the remote module runner. This proxy is placed _before_ Vite's own middlewares if you don't configure a client entry point via `environments.client.build.rolldownOptions.input`, or _after_ if you do. When placed before, the setup essentially disables Vite's client-side features.
|
|
24
24
|
|
|
25
25
|
## Limitations
|
|
26
26
|
|