wrangler 0.0.0-ece06ea → 0.0.0-ecef68635
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 +50 -15
- package/bin/wrangler.js +94 -31
- package/config-schema.json +3074 -0
- package/kv-asset-handler.js +1 -0
- package/package.json +155 -75
- package/templates/__tests__/pages-dev-util.test.ts +128 -0
- package/templates/__tests__/tsconfig-sanity.ts +12 -0
- package/templates/__tests__/tsconfig.json +8 -0
- package/templates/checked-fetch.js +30 -0
- package/templates/facade.d.ts +19 -0
- package/templates/gitignore +170 -0
- package/templates/init-tests/test-jest-new-worker.js +23 -0
- package/templates/init-tests/test-vitest-new-worker.js +24 -0
- package/templates/init-tests/test-vitest-new-worker.ts +25 -0
- package/templates/middleware/common.ts +67 -0
- package/templates/middleware/loader-modules.ts +134 -0
- package/templates/middleware/loader-sw.ts +229 -0
- package/templates/middleware/middleware-ensure-req-body-drained.ts +18 -0
- package/templates/middleware/middleware-miniflare3-json-error.ts +32 -0
- package/templates/middleware/middleware-mock-analytics-engine.d.ts +3 -0
- package/templates/middleware/middleware-mock-analytics-engine.ts +30 -0
- package/templates/middleware/middleware-pretty-error.ts +40 -0
- package/templates/middleware/middleware-scheduled.ts +29 -0
- package/templates/middleware/middleware-serve-static-assets.d.ts +6 -0
- package/templates/middleware/middleware-serve-static-assets.ts +56 -0
- package/templates/modules-watch-stub.js +4 -0
- package/templates/new-worker-scheduled.js +17 -0
- package/templates/new-worker-scheduled.ts +32 -0
- package/templates/new-worker.js +15 -0
- package/templates/new-worker.ts +33 -0
- package/templates/no-op-worker.js +10 -0
- package/templates/pages-dev-pipeline.ts +32 -0
- package/templates/pages-dev-util.ts +55 -0
- package/templates/pages-shim.ts +9 -0
- package/templates/pages-template-plugin.ts +190 -0
- package/templates/pages-template-worker.ts +198 -0
- package/templates/startDevWorker/InspectorProxyWorker.ts +664 -0
- package/templates/startDevWorker/ProxyWorker.ts +336 -0
- package/templates/tsconfig-sanity.ts +11 -0
- package/templates/tsconfig.init.json +22 -0
- package/templates/tsconfig.json +8 -0
- package/wrangler-dist/InspectorProxyWorker.js +464 -0
- package/wrangler-dist/InspectorProxyWorker.js.map +6 -0
- package/wrangler-dist/ProxyWorker.js +241 -0
- package/wrangler-dist/ProxyWorker.js.map +6 -0
- package/wrangler-dist/cli.d.ts +26463 -0
- package/wrangler-dist/cli.js +206335 -125492
- package/wrangler-dist/wasm-sync.wasm +0 -0
- package/import_meta_url.js +0 -3
- package/miniflare-config-stubs/.env.empty +0 -0
- package/miniflare-config-stubs/package.empty.json +0 -1
- package/miniflare-config-stubs/wrangler.empty.toml +0 -0
- package/src/__tests__/clipboardy-mock.js +0 -4
- package/src/__tests__/fixtures/init/.gitkeep +0 -0
- package/src/__tests__/index.test.ts +0 -153
- package/src/__tests__/mock-cfetch.js +0 -46
- package/src/api/form_data.ts +0 -158
- package/src/api/inspect.ts +0 -441
- package/src/api/preview.ts +0 -123
- package/src/api/worker.ts +0 -161
- package/src/cfetch.ts +0 -72
- package/src/cli.ts +0 -10
- package/src/config.ts +0 -124
- package/src/dev.tsx +0 -736
- package/src/dialogs.tsx +0 -85
- package/src/index.tsx +0 -1845
- package/src/kv.tsx +0 -211
- package/src/pages.tsx +0 -344
- package/src/publish.ts +0 -354
- package/src/sites.tsx +0 -115
- package/src/tail.tsx +0 -71
- package/src/user.tsx +0 -1029
- package/src/util/fetch.ts +0 -74
- package/static-asset-facade.js +0 -47
- package/vendor/@cloudflare/kv-asset-handler/CHANGELOG.md +0 -332
- package/vendor/@cloudflare/kv-asset-handler/LICENSE_APACHE +0 -176
- package/vendor/@cloudflare/kv-asset-handler/LICENSE_MIT +0 -25
- package/vendor/@cloudflare/kv-asset-handler/README.md +0 -245
- package/vendor/@cloudflare/kv-asset-handler/dist/index.d.ts +0 -32
- package/vendor/@cloudflare/kv-asset-handler/dist/index.js +0 -354
- package/vendor/@cloudflare/kv-asset-handler/dist/mocks.d.ts +0 -13
- package/vendor/@cloudflare/kv-asset-handler/dist/mocks.js +0 -148
- package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.d.ts +0 -1
- package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.js +0 -436
- package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.d.ts +0 -1
- package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.js +0 -40
- package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.d.ts +0 -1
- package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.js +0 -42
- package/vendor/@cloudflare/kv-asset-handler/dist/types.d.ts +0 -26
- package/vendor/@cloudflare/kv-asset-handler/dist/types.js +0 -31
- package/vendor/@cloudflare/kv-asset-handler/package.json +0 -52
- package/vendor/@cloudflare/kv-asset-handler/src/index.ts +0 -296
- package/vendor/@cloudflare/kv-asset-handler/src/mocks.ts +0 -136
- package/vendor/@cloudflare/kv-asset-handler/src/test/getAssetFromKV.ts +0 -464
- package/vendor/@cloudflare/kv-asset-handler/src/test/mapRequestToAsset.ts +0 -33
- package/vendor/@cloudflare/kv-asset-handler/src/test/serveSinglePageApp.ts +0 -42
- package/vendor/@cloudflare/kv-asset-handler/src/types.ts +0 -39
- package/vendor/wrangler-mime/CHANGELOG.md +0 -289
- package/vendor/wrangler-mime/LICENSE +0 -21
- package/vendor/wrangler-mime/Mime.js +0 -97
- package/vendor/wrangler-mime/README.md +0 -187
- package/vendor/wrangler-mime/cli.js +0 -46
- package/vendor/wrangler-mime/index.js +0 -4
- package/vendor/wrangler-mime/lite.js +0 -4
- package/vendor/wrangler-mime/package.json +0 -52
- package/vendor/wrangler-mime/types/other.js +0 -1
- package/vendor/wrangler-mime/types/standard.js +0 -1
- package/wrangler-dist/cli.js.map +0 -7
package/src/api/inspect.ts
DELETED
|
@@ -1,441 +0,0 @@
|
|
|
1
|
-
import { Response, Request, Headers } from "node-fetch";
|
|
2
|
-
import type { MessageEvent } from "ws";
|
|
3
|
-
import WebSocket, { WebSocketServer } from "ws";
|
|
4
|
-
import type { IncomingMessage, ServerResponse } from "http";
|
|
5
|
-
import { createServer } from "http";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* A call frame.
|
|
9
|
-
*
|
|
10
|
-
* @link https://chromedevtools.github.io/devtools-protocol/1-3/Runtime/#type-CallFrame
|
|
11
|
-
*/
|
|
12
|
-
export interface DtCallFrame {
|
|
13
|
-
/**
|
|
14
|
-
* The module path.
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* 'worker.js'
|
|
18
|
-
*/
|
|
19
|
-
url: string;
|
|
20
|
-
/**
|
|
21
|
-
* The function name.
|
|
22
|
-
*/
|
|
23
|
-
functionName?: string;
|
|
24
|
-
/**
|
|
25
|
-
* The line number. (0-based)
|
|
26
|
-
*/
|
|
27
|
-
lineNumber: number;
|
|
28
|
-
/**
|
|
29
|
-
* The column number. (0-based)
|
|
30
|
-
*/
|
|
31
|
-
columnNumber: number;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* A stack trace.
|
|
36
|
-
*
|
|
37
|
-
* @link https://chromedevtools.github.io/devtools-protocol/1-3/Runtime/#type-StackTrace
|
|
38
|
-
*/
|
|
39
|
-
export interface DtStackTrace {
|
|
40
|
-
/**
|
|
41
|
-
* A description of the stack, only present in certain contexts.
|
|
42
|
-
*/
|
|
43
|
-
description?: string;
|
|
44
|
-
/**
|
|
45
|
-
* The call frames.
|
|
46
|
-
*/
|
|
47
|
-
callFrames: DtCallFrame[];
|
|
48
|
-
/**
|
|
49
|
-
* The parent stack trace.
|
|
50
|
-
*/
|
|
51
|
-
parent?: DtStackTrace;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* A JavaScript object type.
|
|
56
|
-
*/
|
|
57
|
-
export type DtRemoteObjectType =
|
|
58
|
-
| "object"
|
|
59
|
-
| "function"
|
|
60
|
-
| "undefined"
|
|
61
|
-
| "string"
|
|
62
|
-
| "number"
|
|
63
|
-
| "boolean"
|
|
64
|
-
| "symbol"
|
|
65
|
-
| "bigint";
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* A view of a remote JavaScript object.
|
|
69
|
-
*
|
|
70
|
-
* @link https://chromedevtools.github.io/devtools-protocol/1-3/Runtime/#type-RemoteObject
|
|
71
|
-
*/
|
|
72
|
-
export interface DtRemoteObject<T> {
|
|
73
|
-
/**
|
|
74
|
-
* The object type.
|
|
75
|
-
*
|
|
76
|
-
* @example
|
|
77
|
-
* 'string'
|
|
78
|
-
*/
|
|
79
|
-
type: DtRemoteObjectType;
|
|
80
|
-
/**
|
|
81
|
-
* The specific object type, if the type is `object`.
|
|
82
|
-
*
|
|
83
|
-
* @example
|
|
84
|
-
* 'arraybuffer'
|
|
85
|
-
*/
|
|
86
|
-
subtype?: string;
|
|
87
|
-
/**
|
|
88
|
-
* The class name, if the type if `object`.
|
|
89
|
-
*/
|
|
90
|
-
className?: string;
|
|
91
|
-
/**
|
|
92
|
-
* The object as a string.
|
|
93
|
-
*
|
|
94
|
-
* @example
|
|
95
|
-
* 'Array(1)'
|
|
96
|
-
* 'TypeError: Oops!\n at worker.js:5:15'
|
|
97
|
-
*/
|
|
98
|
-
description?: string;
|
|
99
|
-
/**
|
|
100
|
-
* The object.
|
|
101
|
-
*/
|
|
102
|
-
value?: T;
|
|
103
|
-
// TODO(soon): add a preview field for more complex types
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* An event when `console.log()` is invoked.
|
|
108
|
-
*
|
|
109
|
-
* @link https://chromedevtools.github.io/devtools-protocol/1-3/Runtime/#event-consoleAPICalled
|
|
110
|
-
*/
|
|
111
|
-
export interface DtLogEvent {
|
|
112
|
-
timestamp: number;
|
|
113
|
-
type: string;
|
|
114
|
-
args: DtRemoteObject<unknown>[];
|
|
115
|
-
stackTrace?: DtStackTrace;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* An event when an uncaught `Error` is thrown.
|
|
120
|
-
*
|
|
121
|
-
* @link https://chromedevtools.github.io/devtools-protocol/1-3/Runtime/#event-exceptionThrown
|
|
122
|
-
*/
|
|
123
|
-
export interface DtExceptionEvent {
|
|
124
|
-
timestamp: number;
|
|
125
|
-
exceptionDetails: {
|
|
126
|
-
lineNumber: number;
|
|
127
|
-
columnNumber: number;
|
|
128
|
-
exception: DtRemoteObject<Error>;
|
|
129
|
-
stackTrace: DtStackTrace;
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* A DevTools event.
|
|
135
|
-
*/
|
|
136
|
-
export type DtEvent = DtLogEvent | DtExceptionEvent;
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* A listener that receives DevTools events.
|
|
140
|
-
*/
|
|
141
|
-
export type DtListener = (event: DtEvent) => void;
|
|
142
|
-
|
|
143
|
-
interface DtProtocolRequest<T> {
|
|
144
|
-
id: number;
|
|
145
|
-
method: string;
|
|
146
|
-
params?: T;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
interface DtProtocolResponse<T> {
|
|
150
|
-
id: number;
|
|
151
|
-
result: T;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* A DevTools inspector that listens to logs and debug events from a Worker.
|
|
156
|
-
*
|
|
157
|
-
* @example
|
|
158
|
-
* const worker: CfWorker
|
|
159
|
-
* const inspector: DtInspector = await worker.inspect()
|
|
160
|
-
*
|
|
161
|
-
* @link https://chromedevtools.github.io/devtools-protocol/
|
|
162
|
-
*/
|
|
163
|
-
export class DtInspector {
|
|
164
|
-
#webSocket: WebSocket;
|
|
165
|
-
#keepAlive?: NodeJS.Timer;
|
|
166
|
-
|
|
167
|
-
constructor(url: string) {
|
|
168
|
-
// this.#events = [];
|
|
169
|
-
// this.#listeners = [];
|
|
170
|
-
this.#webSocket = new WebSocket(url);
|
|
171
|
-
this.#webSocket.onopen = () => {
|
|
172
|
-
this.enable();
|
|
173
|
-
};
|
|
174
|
-
this.#webSocket.onclose = () => {
|
|
175
|
-
this.disable();
|
|
176
|
-
};
|
|
177
|
-
this.#webSocket.on("unexpected-response", () => {
|
|
178
|
-
console.log("504??"); // TODO: refactor this class to start again
|
|
179
|
-
});
|
|
180
|
-
this.#webSocket.onmessage = (event: MessageEvent) => {
|
|
181
|
-
// TODO: this seems unnecessary, unless we're planning
|
|
182
|
-
// on logging to console. We'll see.
|
|
183
|
-
if (typeof event.data === "string") {
|
|
184
|
-
// this.recv(JSON.parse(event.data));
|
|
185
|
-
} else {
|
|
186
|
-
// ??
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Exposes a websocket proxy on a localhost port.
|
|
193
|
-
*/
|
|
194
|
-
proxyTo(port: number): AbortController {
|
|
195
|
-
return bind(new DtInspectorBridge(this.#webSocket, port), port);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* If the inspector is closed.
|
|
200
|
-
*/
|
|
201
|
-
get closed(): boolean {
|
|
202
|
-
return this.#webSocket.readyState === WebSocket.CLOSED;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Closes the inspector.
|
|
207
|
-
*/
|
|
208
|
-
close(): void {
|
|
209
|
-
if (!this.closed) {
|
|
210
|
-
try {
|
|
211
|
-
this.#webSocket.close();
|
|
212
|
-
} catch (err) {
|
|
213
|
-
// Closing before the websocket is ready will throw an error.
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
// this.#events = [];
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
private send(event: Record<string, unknown>): void {
|
|
220
|
-
if (!this.closed) {
|
|
221
|
-
this.#webSocket.send(JSON.stringify(event));
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
private enable(): void {
|
|
226
|
-
let id = 1;
|
|
227
|
-
this.send({ method: "Runtime.enable", id });
|
|
228
|
-
this.#keepAlive = setInterval(() => {
|
|
229
|
-
this.send({ method: "Runtime.getIsolateId", id: id++ });
|
|
230
|
-
}, 10_000);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
private disable(): void {
|
|
234
|
-
if (this.#keepAlive) {
|
|
235
|
-
clearInterval(this.#keepAlive);
|
|
236
|
-
this.#keepAlive = undefined;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* A HTTP server that responds to `fetch()` requests.
|
|
243
|
-
*/
|
|
244
|
-
interface FetchServer {
|
|
245
|
-
/**
|
|
246
|
-
* Responds to a request.
|
|
247
|
-
*/
|
|
248
|
-
fetch(request: Request): Promise<Response>;
|
|
249
|
-
/**
|
|
250
|
-
* Accepts a websocket connection.
|
|
251
|
-
*/
|
|
252
|
-
upgrade?(webSocket: WebSocket): void;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* A bridge between a remote DevTools inspector and Chrome.
|
|
257
|
-
*
|
|
258
|
-
* Exposes a localhost HTTP server that responds to informational requests
|
|
259
|
-
* from Chrome about the DevTools inspector. Then, when it receives a
|
|
260
|
-
* WebSocket upgrade, forwards the connection to the remote inspector.
|
|
261
|
-
*/
|
|
262
|
-
class DtInspectorBridge implements FetchServer {
|
|
263
|
-
#webSocket: WebSocket;
|
|
264
|
-
#localPort: number;
|
|
265
|
-
#connected: boolean;
|
|
266
|
-
|
|
267
|
-
constructor(webSocket: WebSocket, localPort?: number) {
|
|
268
|
-
this.#webSocket = webSocket;
|
|
269
|
-
this.#localPort = localPort;
|
|
270
|
-
this.#connected = false;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
async fetch(request: Request): Promise<Response> {
|
|
274
|
-
const { url } = request;
|
|
275
|
-
const { pathname } = new URL(url);
|
|
276
|
-
switch (pathname) {
|
|
277
|
-
case "/json/version":
|
|
278
|
-
return this.version;
|
|
279
|
-
case "/json":
|
|
280
|
-
case "/json/list":
|
|
281
|
-
return this.location;
|
|
282
|
-
default:
|
|
283
|
-
break;
|
|
284
|
-
}
|
|
285
|
-
return new Response("Not Found", { status: 404 });
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
upgrade(webSocket: WebSocket): void {
|
|
289
|
-
if (this.#connected) {
|
|
290
|
-
webSocket.close(
|
|
291
|
-
1013,
|
|
292
|
-
"Too many clients; only one can be connected at a time"
|
|
293
|
-
);
|
|
294
|
-
} else {
|
|
295
|
-
this.#connected = true;
|
|
296
|
-
webSocket.addEventListener("close", () => (this.#connected = false));
|
|
297
|
-
proxyWebSocket(webSocket, this.#webSocket);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
private get version(): Response {
|
|
302
|
-
const headers = { "Content-Type": "application/json" };
|
|
303
|
-
const body = {
|
|
304
|
-
Browser: "workers-run/v0.0.0", // TODO: this should pick up version from package.json
|
|
305
|
-
// TODO: (someday): The DevTools protocol should match that of edgeworker.
|
|
306
|
-
// This could be exposed by the preview API.
|
|
307
|
-
"Protocol-Version": "1.3",
|
|
308
|
-
};
|
|
309
|
-
return new Response(JSON.stringify(body), { headers });
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
private get location(): Response {
|
|
313
|
-
const headers = { "Content-Type": "application/json" };
|
|
314
|
-
const localHost = `localhost:${this.#localPort}/ws`;
|
|
315
|
-
const devtoolsFrontendUrl = `devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws=${localHost}`;
|
|
316
|
-
const devtoolsFrontendUrlCompat = `devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=${localHost}`;
|
|
317
|
-
const body = [
|
|
318
|
-
{
|
|
319
|
-
id: randomId(),
|
|
320
|
-
type: "node",
|
|
321
|
-
description: "workers",
|
|
322
|
-
webSocketDebuggerUrl: `ws://${localHost}`,
|
|
323
|
-
devtoolsFrontendUrl,
|
|
324
|
-
devtoolsFrontendUrlCompat,
|
|
325
|
-
// Below are fields that are visible in the DevTools UI.
|
|
326
|
-
title: "Cloudflare Worker",
|
|
327
|
-
faviconUrl: "https://workers.cloudflare.com/favicon.ico",
|
|
328
|
-
url: "https://" + new URL(this.#webSocket.url).host,
|
|
329
|
-
},
|
|
330
|
-
];
|
|
331
|
-
return new Response(JSON.stringify(body), { headers });
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
function bind(fetcher: FetchServer, port?: number): AbortController {
|
|
336
|
-
const controller = new AbortController();
|
|
337
|
-
|
|
338
|
-
const server = createServer(
|
|
339
|
-
(input: IncomingMessage, output: ServerResponse) =>
|
|
340
|
-
toRequest(input)
|
|
341
|
-
.then((request) => fetcher.fetch(request))
|
|
342
|
-
.then((response) => toResponse(response, output))
|
|
343
|
-
.catch((error) => console.error(error))
|
|
344
|
-
);
|
|
345
|
-
|
|
346
|
-
if (fetcher.upgrade) {
|
|
347
|
-
const webSocket = new WebSocketServer({ server });
|
|
348
|
-
webSocket.on("connection", (ws: WebSocket) => fetcher.upgrade(ws));
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
const socket = server.listen({ port });
|
|
352
|
-
controller.signal.onabort = () => {
|
|
353
|
-
server.close();
|
|
354
|
-
socket.close();
|
|
355
|
-
};
|
|
356
|
-
return controller;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
/**
|
|
360
|
-
* Converts a Node.js request to a Web standard `Request`.
|
|
361
|
-
*/
|
|
362
|
-
async function toRequest(request: IncomingMessage): Promise<Request> {
|
|
363
|
-
const host = request.headers.host ?? "localhost";
|
|
364
|
-
const { href } = new URL(request.url, "http://" + host);
|
|
365
|
-
|
|
366
|
-
const { rawHeaders, method } = request;
|
|
367
|
-
const headers = new Headers();
|
|
368
|
-
for (let i = 0; i < rawHeaders.length; i += 2) {
|
|
369
|
-
headers.append(rawHeaders[i], rawHeaders[i + 1]);
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
return new Promise((resolve, reject) => {
|
|
373
|
-
const chunks = [];
|
|
374
|
-
request.on("data", (chunk) => chunks.push(chunk));
|
|
375
|
-
request.on("error", (error) => reject(error));
|
|
376
|
-
request.on("end", () => {
|
|
377
|
-
const buffer = Buffer.concat(chunks);
|
|
378
|
-
const body = buffer.length === 0 ? undefined : buffer;
|
|
379
|
-
resolve(new Request(href, { method, headers, body }));
|
|
380
|
-
});
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
/**
|
|
385
|
-
* Converts a Web standard `Response` into a Node.js response.
|
|
386
|
-
*/
|
|
387
|
-
async function toResponse(
|
|
388
|
-
input: Response,
|
|
389
|
-
response: ServerResponse
|
|
390
|
-
): Promise<void> {
|
|
391
|
-
const { status, statusText, headers, body: hasBody } = input;
|
|
392
|
-
|
|
393
|
-
for (const [name, value] of headers.entries()) {
|
|
394
|
-
response.setHeader(name, value);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
let body: Uint8Array;
|
|
398
|
-
if (hasBody) {
|
|
399
|
-
body = new Uint8Array(await input.arrayBuffer());
|
|
400
|
-
response.setHeader("Content-Length", body.byteLength);
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
response.writeHead(status, statusText);
|
|
404
|
-
response.write(body);
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
/**
|
|
408
|
-
* Creates a proxy bridge between two websockets.
|
|
409
|
-
*/
|
|
410
|
-
function proxyWebSocket(webSocket: WebSocket, otherSocket: WebSocket): void {
|
|
411
|
-
webSocket.addEventListener("message", (event: MessageEvent) => {
|
|
412
|
-
try {
|
|
413
|
-
otherSocket.send(event.data);
|
|
414
|
-
} catch (e) {
|
|
415
|
-
if (e.message !== "WebSocket is not open: readyState 0 (CONNECTING)") {
|
|
416
|
-
// this just means we haven't opened a websocket yet
|
|
417
|
-
// usually happens until there's at least one request
|
|
418
|
-
// which is weird, because we may miss something that happens on
|
|
419
|
-
// the first request
|
|
420
|
-
console.error(e);
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
});
|
|
424
|
-
otherSocket.addEventListener("message", (event: MessageEvent) =>
|
|
425
|
-
webSocket.send(event.data)
|
|
426
|
-
);
|
|
427
|
-
|
|
428
|
-
// Some close codes are marked as 'reserved' and will throw an error if used.
|
|
429
|
-
// Therefore, it's not worth the effort to passthrough the close code and reason.
|
|
430
|
-
webSocket.addEventListener("close", () => otherSocket.close());
|
|
431
|
-
otherSocket.addEventListener("close", () => webSocket.close());
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
// Credit: https://stackoverflow.com/a/2117523
|
|
435
|
-
function randomId(): string {
|
|
436
|
-
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
|
|
437
|
-
const r = (Math.random() * 16) | 0,
|
|
438
|
-
v = c == "x" ? r : (r & 0x3) | 0x8;
|
|
439
|
-
return v.toString(16);
|
|
440
|
-
});
|
|
441
|
-
}
|
package/src/api/preview.ts
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import cfetch from "../cfetch";
|
|
2
|
-
import { fetchJson } from "../util/fetch";
|
|
3
|
-
import { toFormData } from "./form_data";
|
|
4
|
-
import type { CfAccount, CfWorkerInit } from "./worker";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* A preview mode.
|
|
8
|
-
*
|
|
9
|
-
* * If true, then using a `workers.dev` subdomain.
|
|
10
|
-
* * Otherwise, a list of routes under a single zone.
|
|
11
|
-
*/
|
|
12
|
-
export type CfPreviewMode = { workers_dev: boolean } | { routes: string[] };
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* A preview token.
|
|
16
|
-
*/
|
|
17
|
-
export interface CfPreviewToken {
|
|
18
|
-
/**
|
|
19
|
-
* The header value required to trigger a preview.
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* const headers = { 'cf-workers-preview-token': value }
|
|
23
|
-
* const response = await fetch('https://' + host, { headers })
|
|
24
|
-
*/
|
|
25
|
-
value: string;
|
|
26
|
-
/**
|
|
27
|
-
* The host where the preview is available.
|
|
28
|
-
*/
|
|
29
|
-
host: string;
|
|
30
|
-
/**
|
|
31
|
-
* A websocket url to a DevTools inspector.
|
|
32
|
-
*
|
|
33
|
-
* Workers does not have a fully-featured implementation
|
|
34
|
-
* of the Chrome DevTools protocol, but supports the following:
|
|
35
|
-
* * `console.log()` output.
|
|
36
|
-
* * `Error` stack traces.
|
|
37
|
-
* * `fetch()` events.
|
|
38
|
-
*
|
|
39
|
-
* There is no support for breakpoints, but we want to implement
|
|
40
|
-
* this eventually.
|
|
41
|
-
*
|
|
42
|
-
* @link https://chromedevtools.github.io/devtools-protocol/
|
|
43
|
-
*/
|
|
44
|
-
inspectorUrl: URL;
|
|
45
|
-
/**
|
|
46
|
-
* A url to prewarm the preview session.
|
|
47
|
-
*
|
|
48
|
-
* @example
|
|
49
|
-
* fetch(prewarmUrl, { method: 'POST' })
|
|
50
|
-
*/
|
|
51
|
-
prewarmUrl: URL;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Generates a preview session token.
|
|
56
|
-
*/
|
|
57
|
-
async function sessionToken(account: CfAccount): Promise<CfPreviewToken> {
|
|
58
|
-
const { accountId, zoneId } = account;
|
|
59
|
-
const initUrl = zoneId
|
|
60
|
-
? `/zones/${zoneId}/workers/edge-preview`
|
|
61
|
-
: `/accounts/${accountId}/workers/subdomain/edge-preview`;
|
|
62
|
-
|
|
63
|
-
const { exchange_url: tokenUrl } = await cfetch<{ exchange_url: string }>(
|
|
64
|
-
initUrl
|
|
65
|
-
);
|
|
66
|
-
const { inspector_websocket: url, token } = await fetchJson()(tokenUrl);
|
|
67
|
-
const { host } = new URL(url);
|
|
68
|
-
const query = `cf_workers_preview_token=${token}`;
|
|
69
|
-
|
|
70
|
-
return {
|
|
71
|
-
value: token,
|
|
72
|
-
host,
|
|
73
|
-
inspectorUrl: new URL(`${url}?${query}`),
|
|
74
|
-
prewarmUrl: new URL(
|
|
75
|
-
`https://${host}/cdn-cgi/workers/preview/prewarm?${query}`
|
|
76
|
-
),
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Credit: https://stackoverflow.com/a/2117523
|
|
81
|
-
function randomId(): string {
|
|
82
|
-
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
|
|
83
|
-
const r = (Math.random() * 16) | 0,
|
|
84
|
-
v = c == "x" ? r : (r & 0x3) | 0x8;
|
|
85
|
-
return v.toString(16);
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Creates a preview token.
|
|
91
|
-
*/
|
|
92
|
-
export async function previewToken(
|
|
93
|
-
account: CfAccount,
|
|
94
|
-
worker: CfWorkerInit
|
|
95
|
-
): Promise<CfPreviewToken> {
|
|
96
|
-
const { value, host, inspectorUrl, prewarmUrl } = await sessionToken(account);
|
|
97
|
-
|
|
98
|
-
const { accountId, zoneId } = account;
|
|
99
|
-
const scriptId = zoneId ? randomId() : host.split(".")[0];
|
|
100
|
-
const url = `/accounts/${accountId}/workers/scripts/${scriptId}/edge-preview`;
|
|
101
|
-
|
|
102
|
-
const mode = zoneId ? { routes: ["*/*"] } : { workers_dev: true };
|
|
103
|
-
const formData = toFormData(worker);
|
|
104
|
-
formData.set("wrangler-session-config", JSON.stringify(mode));
|
|
105
|
-
|
|
106
|
-
const { preview_token: token } = await cfetch<{ preview_token: string }>(
|
|
107
|
-
url,
|
|
108
|
-
{
|
|
109
|
-
method: "POST",
|
|
110
|
-
// @ts-expect-error TODO: fix this
|
|
111
|
-
body: formData,
|
|
112
|
-
headers: {
|
|
113
|
-
"cf-preview-upload-config-token": value,
|
|
114
|
-
},
|
|
115
|
-
}
|
|
116
|
-
);
|
|
117
|
-
return {
|
|
118
|
-
value: token,
|
|
119
|
-
host,
|
|
120
|
-
inspectorUrl,
|
|
121
|
-
prewarmUrl,
|
|
122
|
-
};
|
|
123
|
-
}
|
package/src/api/worker.ts
DELETED
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
import type { CfPreviewToken } from "./preview";
|
|
2
|
-
import { previewToken } from "./preview";
|
|
3
|
-
import fetch from "node-fetch";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* A Cloudflare account.
|
|
7
|
-
*/
|
|
8
|
-
export interface CfAccount {
|
|
9
|
-
/**
|
|
10
|
-
* An API token.
|
|
11
|
-
*
|
|
12
|
-
* @link https://api.cloudflare.com/#user-api-tokens-properties
|
|
13
|
-
*/
|
|
14
|
-
apiToken: string;
|
|
15
|
-
/**
|
|
16
|
-
* An account ID.
|
|
17
|
-
*/
|
|
18
|
-
accountId: string;
|
|
19
|
-
/**
|
|
20
|
-
* A zone ID, only required if not using `workers.dev`.
|
|
21
|
-
*/
|
|
22
|
-
zoneId?: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* A module type.
|
|
27
|
-
*/
|
|
28
|
-
export type CfModuleType =
|
|
29
|
-
| "esm"
|
|
30
|
-
| "commonjs"
|
|
31
|
-
| "compiled-wasm"
|
|
32
|
-
| "text"
|
|
33
|
-
| "buffer";
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* An imported module.
|
|
37
|
-
*/
|
|
38
|
-
export interface CfModule {
|
|
39
|
-
/**
|
|
40
|
-
* The module name.
|
|
41
|
-
*
|
|
42
|
-
* @example
|
|
43
|
-
* './src/index.js'
|
|
44
|
-
*/
|
|
45
|
-
name: string;
|
|
46
|
-
/**
|
|
47
|
-
* The module content, usually JavaScript or WASM code.
|
|
48
|
-
*
|
|
49
|
-
* @example
|
|
50
|
-
* export default {
|
|
51
|
-
* async fetch(request) {
|
|
52
|
-
* return new Response('Ok')
|
|
53
|
-
* }
|
|
54
|
-
* }
|
|
55
|
-
*/
|
|
56
|
-
content: string | BufferSource;
|
|
57
|
-
/**
|
|
58
|
-
* The module type.
|
|
59
|
-
*
|
|
60
|
-
* If absent, will default to the main module's type.
|
|
61
|
-
*/
|
|
62
|
-
type?: CfModuleType;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* A KV namespace.
|
|
67
|
-
*/
|
|
68
|
-
export interface CfKvNamespace {
|
|
69
|
-
/**
|
|
70
|
-
* The namespace ID.
|
|
71
|
-
*/
|
|
72
|
-
namespaceId: string;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export interface CfDurableObject {
|
|
76
|
-
class_name: string;
|
|
77
|
-
script_name?: string;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
interface CfDOMigrations {
|
|
81
|
-
old_tag?: string;
|
|
82
|
-
new_tag: string;
|
|
83
|
-
steps: {
|
|
84
|
-
new_classes?: string[];
|
|
85
|
-
renamed_classes?: string[];
|
|
86
|
-
deleted_classes?: string[];
|
|
87
|
-
}[];
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* A `WebCrypto` key.
|
|
92
|
-
*
|
|
93
|
-
* @link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey
|
|
94
|
-
*/
|
|
95
|
-
export interface CfCryptoKey {
|
|
96
|
-
/**
|
|
97
|
-
* The format.
|
|
98
|
-
*/
|
|
99
|
-
format: string;
|
|
100
|
-
/**
|
|
101
|
-
* The algorithm.
|
|
102
|
-
*/
|
|
103
|
-
algorithm: string;
|
|
104
|
-
/**
|
|
105
|
-
* The usages.
|
|
106
|
-
*/
|
|
107
|
-
usages: string[];
|
|
108
|
-
/**
|
|
109
|
-
* The data.
|
|
110
|
-
*/
|
|
111
|
-
data: BufferSource | JsonWebKey;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* A variable (aka. environment variable).
|
|
116
|
-
*/
|
|
117
|
-
export type CfVariable = string | CfKvNamespace | CfCryptoKey | CfDurableObject;
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Options for creating a `CfWorker`.
|
|
121
|
-
*/
|
|
122
|
-
export interface CfWorkerInit {
|
|
123
|
-
/**
|
|
124
|
-
* The name of the worker.
|
|
125
|
-
*/
|
|
126
|
-
name: string;
|
|
127
|
-
/**
|
|
128
|
-
* The entrypoint module.
|
|
129
|
-
*/
|
|
130
|
-
main: CfModule;
|
|
131
|
-
/**
|
|
132
|
-
* The list of additional modules.
|
|
133
|
-
*/
|
|
134
|
-
modules: void | CfModule[];
|
|
135
|
-
/**
|
|
136
|
-
* The map of names to variables. (aka. environment variables)
|
|
137
|
-
*/
|
|
138
|
-
variables?: { [name: string]: CfVariable };
|
|
139
|
-
migrations: void | CfDOMigrations;
|
|
140
|
-
compatibility_date: string | void;
|
|
141
|
-
compatibility_flags: void | string[];
|
|
142
|
-
usage_model: void | "bundled" | "unbound";
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* A stub to create a Cloudflare Worker preview.
|
|
147
|
-
*
|
|
148
|
-
* @example
|
|
149
|
-
* const {value, host} = await createWorker(init, acct);
|
|
150
|
-
*/
|
|
151
|
-
export async function createWorker(
|
|
152
|
-
init: CfWorkerInit,
|
|
153
|
-
account: CfAccount
|
|
154
|
-
): Promise<CfPreviewToken> {
|
|
155
|
-
const token = await previewToken(account, init);
|
|
156
|
-
const response = await fetch(token.prewarmUrl.href, { method: "POST" });
|
|
157
|
-
if (!response.ok) {
|
|
158
|
-
// console.error("worker failed to prewarm: ", response.statusText);
|
|
159
|
-
}
|
|
160
|
-
return token;
|
|
161
|
-
}
|