wrangler 0.0.0-e9a1820 → 0.0.0-e9ab55a
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/package.json +12 -5
- package/pages/functions/buildWorker.ts +62 -0
- package/pages/functions/filepath-routing.test.ts +39 -0
- package/pages/functions/filepath-routing.ts +228 -0
- package/pages/functions/identifiers.ts +78 -0
- package/pages/functions/routes.ts +158 -0
- package/pages/functions/template-worker.ts +136 -0
- package/src/__tests__/dev.test.tsx +67 -0
- package/src/__tests__/jest.setup.ts +5 -1
- package/src/__tests__/kv.test.ts +849 -45
- package/src/__tests__/mock-cfetch.ts +137 -29
- package/src/__tests__/publish.test.ts +102 -0
- package/src/api/form_data.ts +1 -1
- package/src/api/preview.ts +4 -4
- package/src/api/worker.ts +6 -6
- package/src/cfetch/index.ts +102 -0
- package/src/cfetch/internal.ts +69 -0
- package/src/config.ts +633 -118
- package/src/dev.tsx +114 -209
- package/src/index.tsx +265 -239
- package/src/inspect.ts +543 -0
- package/src/kv.tsx +49 -30
- package/src/pages.tsx +431 -242
- package/src/proxy.ts +275 -76
- package/src/publish.ts +79 -47
- package/src/sites.tsx +10 -7
- package/src/tail.tsx +5 -3
- package/src/user.tsx +22 -17
- package/wrangler-dist/cli.js +42319 -36190
- package/wrangler-dist/cli.js.map +3 -3
- package/src/api/inspect.ts +0 -430
- package/src/cfetch.ts +0 -72
package/src/dev.tsx
CHANGED
|
@@ -1,49 +1,50 @@
|
|
|
1
1
|
import esbuild from "esbuild";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
2
|
+
import assert from "node:assert";
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
4
|
+
import { readFile } from "node:fs/promises";
|
|
5
|
+
import { existsSync } from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { Box, Text, useApp, useInput } from "ink";
|
|
8
|
+
import { watch } from "chokidar";
|
|
9
|
+
import clipboardy from "clipboardy";
|
|
10
|
+
import commandExists from "command-exists";
|
|
11
|
+
import { execa } from "execa";
|
|
12
|
+
import fetch from "node-fetch";
|
|
13
|
+
import open from "open";
|
|
14
|
+
import React, { useState, useEffect, useRef } from "react";
|
|
15
|
+
import { withErrorBoundary, useErrorHandler } from "react-error-boundary";
|
|
16
|
+
import onExit from "signal-exit";
|
|
5
17
|
import tmp from "tmp-promise";
|
|
18
|
+
import type { DirectoryResult } from "tmp-promise";
|
|
19
|
+
|
|
6
20
|
import type { CfPreviewToken } from "./api/preview";
|
|
7
|
-
import { Box, Text, useInput } from "ink";
|
|
8
|
-
import React, { useState, useEffect, useRef } from "react";
|
|
9
|
-
import path from "path";
|
|
10
|
-
import open from "open";
|
|
11
|
-
import { DtInspector } from "./api/inspect";
|
|
12
21
|
import type { CfModule } from "./api/worker";
|
|
13
22
|
import { createWorker } from "./api/worker";
|
|
14
23
|
import type { CfWorkerInit } from "./api/worker";
|
|
15
|
-
|
|
16
|
-
import
|
|
24
|
+
|
|
25
|
+
import useInspector from "./inspect";
|
|
26
|
+
import makeModuleCollector from "./module-collection";
|
|
27
|
+
import { usePreviewServer } from "./proxy";
|
|
17
28
|
import { syncAssets } from "./sites";
|
|
18
|
-
import clipboardy from "clipboardy";
|
|
19
|
-
import http from "node:http";
|
|
20
|
-
import commandExists from "command-exists";
|
|
21
|
-
import assert from "assert";
|
|
22
29
|
import { getAPIToken } from "./user";
|
|
23
|
-
import fetch from "node-fetch";
|
|
24
|
-
import makeModuleCollector from "./module-collection";
|
|
25
|
-
import { withErrorBoundary, useErrorHandler } from "react-error-boundary";
|
|
26
|
-
import { createHttpProxy } from "./proxy";
|
|
27
|
-
import { execa } from "execa";
|
|
28
|
-
import { watch } from "chokidar";
|
|
29
30
|
|
|
30
|
-
type CfScriptFormat =
|
|
31
|
+
type CfScriptFormat = undefined | "modules" | "service-worker";
|
|
31
32
|
|
|
32
|
-
type
|
|
33
|
+
export type DevProps = {
|
|
33
34
|
name?: string;
|
|
34
35
|
entry: string;
|
|
35
36
|
port?: number;
|
|
36
37
|
format: CfScriptFormat;
|
|
37
|
-
accountId:
|
|
38
|
+
accountId: undefined | string;
|
|
38
39
|
initialMode: "local" | "remote";
|
|
39
|
-
jsxFactory:
|
|
40
|
-
jsxFragment:
|
|
40
|
+
jsxFactory: undefined | string;
|
|
41
|
+
jsxFragment: undefined | string;
|
|
41
42
|
bindings: CfWorkerInit["bindings"];
|
|
42
|
-
public:
|
|
43
|
-
site:
|
|
44
|
-
compatibilityDate:
|
|
45
|
-
compatibilityFlags:
|
|
46
|
-
usageModel:
|
|
43
|
+
public: undefined | string;
|
|
44
|
+
site: undefined | string;
|
|
45
|
+
compatibilityDate: undefined | string;
|
|
46
|
+
compatibilityFlags: undefined | string[];
|
|
47
|
+
usageModel: undefined | "bundled" | "unbound";
|
|
47
48
|
buildCommand: {
|
|
48
49
|
command?: undefined | string;
|
|
49
50
|
cwd?: undefined | string;
|
|
@@ -51,13 +52,13 @@ type Props = {
|
|
|
51
52
|
};
|
|
52
53
|
};
|
|
53
54
|
|
|
54
|
-
function Dev(props:
|
|
55
|
+
function Dev(props: DevProps): JSX.Element {
|
|
55
56
|
if (props.public && props.format === "service-worker") {
|
|
56
57
|
throw new Error(
|
|
57
58
|
"You cannot use the service worker format with a `public` directory."
|
|
58
59
|
);
|
|
59
60
|
}
|
|
60
|
-
const port = props.port
|
|
61
|
+
const port = props.port ?? 8787;
|
|
61
62
|
const apiToken = getAPIToken();
|
|
62
63
|
const directory = useTmpDir();
|
|
63
64
|
|
|
@@ -79,9 +80,6 @@ function Dev(props: Props): JSX.Element {
|
|
|
79
80
|
);
|
|
80
81
|
}
|
|
81
82
|
|
|
82
|
-
// @ts-expect-error whack
|
|
83
|
-
useDevtoolsRefresh(bundle?.id ?? 0);
|
|
84
|
-
|
|
85
83
|
const toggles = useHotkeys(
|
|
86
84
|
{
|
|
87
85
|
local: props.initialMode === "local",
|
|
@@ -102,7 +100,7 @@ function Dev(props: Props): JSX.Element {
|
|
|
102
100
|
bindings={props.bindings}
|
|
103
101
|
site={props.site}
|
|
104
102
|
public={props.public}
|
|
105
|
-
port={
|
|
103
|
+
port={port}
|
|
106
104
|
/>
|
|
107
105
|
) : (
|
|
108
106
|
<Remote
|
|
@@ -114,7 +112,7 @@ function Dev(props: Props): JSX.Element {
|
|
|
114
112
|
bindings={props.bindings}
|
|
115
113
|
site={props.site}
|
|
116
114
|
public={props.public}
|
|
117
|
-
port={
|
|
115
|
+
port={port}
|
|
118
116
|
compatibilityDate={props.compatibilityDate}
|
|
119
117
|
compatibilityFlags={props.compatibilityFlags}
|
|
120
118
|
usageModel={props.usageModel}
|
|
@@ -133,53 +131,23 @@ function Dev(props: Props): JSX.Element {
|
|
|
133
131
|
);
|
|
134
132
|
}
|
|
135
133
|
|
|
136
|
-
function useDevtoolsRefresh(bundleId: number) {
|
|
137
|
-
// TODO: this is a hack while we figure out
|
|
138
|
-
// a better cleaner solution to get devtools to reconnect
|
|
139
|
-
// without having to do a full refresh
|
|
140
|
-
const ref = useRef();
|
|
141
|
-
// @ts-expect-error whack
|
|
142
|
-
ref.current = bundleId;
|
|
143
|
-
|
|
144
|
-
useEffect(() => {
|
|
145
|
-
const server = http.createServer((req, res) => {
|
|
146
|
-
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
147
|
-
res.setHeader("Access-Control-Request-Method", "*");
|
|
148
|
-
res.setHeader("Access-Control-Allow-Methods", "OPTIONS, GET");
|
|
149
|
-
res.setHeader("Access-Control-Allow-Headers", "*");
|
|
150
|
-
if (req.method === "OPTIONS") {
|
|
151
|
-
res.writeHead(200);
|
|
152
|
-
res.end();
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
res.writeHead(200, { "Content-Type": "application/json" });
|
|
156
|
-
res.end(JSON.stringify({ value: ref.current }));
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
server.listen(3142);
|
|
160
|
-
return () => {
|
|
161
|
-
server.close();
|
|
162
|
-
};
|
|
163
|
-
}, []);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
134
|
function Remote(props: {
|
|
167
|
-
name:
|
|
168
|
-
bundle: EsbuildBundle |
|
|
135
|
+
name: undefined | string;
|
|
136
|
+
bundle: EsbuildBundle | undefined;
|
|
169
137
|
format: CfScriptFormat;
|
|
170
|
-
public:
|
|
171
|
-
site:
|
|
138
|
+
public: undefined | string;
|
|
139
|
+
site: undefined | string;
|
|
172
140
|
port: number;
|
|
173
|
-
accountId:
|
|
174
|
-
apiToken:
|
|
141
|
+
accountId: undefined | string;
|
|
142
|
+
apiToken: undefined | string;
|
|
175
143
|
bindings: CfWorkerInit["bindings"];
|
|
176
|
-
compatibilityDate: string |
|
|
177
|
-
compatibilityFlags:
|
|
178
|
-
usageModel:
|
|
144
|
+
compatibilityDate: string | undefined;
|
|
145
|
+
compatibilityFlags: undefined | string[];
|
|
146
|
+
usageModel: undefined | "bundled" | "unbound";
|
|
179
147
|
}) {
|
|
180
148
|
assert(props.accountId, "accountId is required");
|
|
181
149
|
assert(props.apiToken, "apiToken is required");
|
|
182
|
-
const
|
|
150
|
+
const previewToken = useWorker({
|
|
183
151
|
name: props.name,
|
|
184
152
|
bundle: props.bundle,
|
|
185
153
|
format: props.format,
|
|
@@ -194,18 +162,26 @@ function Remote(props: {
|
|
|
194
162
|
usageModel: props.usageModel,
|
|
195
163
|
});
|
|
196
164
|
|
|
197
|
-
|
|
165
|
+
usePreviewServer({
|
|
166
|
+
previewToken,
|
|
167
|
+
publicRoot: props.public,
|
|
168
|
+
port: props.port,
|
|
169
|
+
});
|
|
198
170
|
|
|
199
|
-
useInspector(
|
|
171
|
+
useInspector({
|
|
172
|
+
inspectorUrl: previewToken ? previewToken.inspectorUrl.href : undefined,
|
|
173
|
+
port: 9229,
|
|
174
|
+
logToTerminal: true,
|
|
175
|
+
});
|
|
200
176
|
return null;
|
|
201
177
|
}
|
|
202
178
|
function Local(props: {
|
|
203
|
-
name:
|
|
204
|
-
bundle: EsbuildBundle |
|
|
179
|
+
name: undefined | string;
|
|
180
|
+
bundle: EsbuildBundle | undefined;
|
|
205
181
|
format: CfScriptFormat;
|
|
206
182
|
bindings: CfWorkerInit["bindings"];
|
|
207
|
-
public:
|
|
208
|
-
site:
|
|
183
|
+
public: undefined | string;
|
|
184
|
+
site: undefined | string;
|
|
209
185
|
port: number;
|
|
210
186
|
}) {
|
|
211
187
|
const { inspectorUrl } = useLocalWorker({
|
|
@@ -215,13 +191,13 @@ function Local(props: {
|
|
|
215
191
|
bindings: props.bindings,
|
|
216
192
|
port: props.port,
|
|
217
193
|
});
|
|
218
|
-
useInspector(inspectorUrl);
|
|
194
|
+
useInspector({ inspectorUrl, port: 9229, logToTerminal: false });
|
|
219
195
|
return null;
|
|
220
196
|
}
|
|
221
197
|
|
|
222
198
|
function useLocalWorker(props: {
|
|
223
|
-
name:
|
|
224
|
-
bundle: EsbuildBundle |
|
|
199
|
+
name: undefined | string;
|
|
200
|
+
bundle: EsbuildBundle | undefined;
|
|
225
201
|
format: CfScriptFormat;
|
|
226
202
|
bindings: CfWorkerInit["bindings"];
|
|
227
203
|
port: number;
|
|
@@ -230,7 +206,7 @@ function useLocalWorker(props: {
|
|
|
230
206
|
const { bundle, format, bindings, port } = props;
|
|
231
207
|
const local = useRef<ReturnType<typeof spawn>>();
|
|
232
208
|
const removeSignalExitListener = useRef<() => void>();
|
|
233
|
-
const [inspectorUrl, setInspectorUrl] = useState<string |
|
|
209
|
+
const [inspectorUrl, setInspectorUrl] = useState<string | undefined>();
|
|
234
210
|
useEffect(() => {
|
|
235
211
|
async function startLocalWorker() {
|
|
236
212
|
if (!bundle) return;
|
|
@@ -289,11 +265,11 @@ function useLocalWorker(props: {
|
|
|
289
265
|
}
|
|
290
266
|
});
|
|
291
267
|
|
|
292
|
-
local.current.stdout
|
|
268
|
+
local.current.stdout?.on("data", (data: Buffer) => {
|
|
293
269
|
console.log(`${data.toString()}`);
|
|
294
270
|
});
|
|
295
271
|
|
|
296
|
-
local.current.stderr
|
|
272
|
+
local.current.stderr?.on("data", (data: Buffer) => {
|
|
297
273
|
console.error(`${data.toString()}`);
|
|
298
274
|
const matches =
|
|
299
275
|
/Debugger listening on (ws:\/\/127\.0\.0\.1:9229\/[A-Za-z0-9-]+)/.exec(
|
|
@@ -346,7 +322,7 @@ function useLocalWorker(props: {
|
|
|
346
322
|
return { inspectorUrl };
|
|
347
323
|
}
|
|
348
324
|
|
|
349
|
-
function useTmpDir(): string |
|
|
325
|
+
function useTmpDir(): string | undefined {
|
|
350
326
|
const [directory, setDirectory] = useState<DirectoryResult>();
|
|
351
327
|
const handleError = useErrorHandler();
|
|
352
328
|
useEffect(() => {
|
|
@@ -384,10 +360,10 @@ function useCustomBuild(
|
|
|
384
360
|
cwd?: undefined | string;
|
|
385
361
|
watch_dir?: undefined | string;
|
|
386
362
|
}
|
|
387
|
-
):
|
|
388
|
-
const [entry, setEntry] = useState<string |
|
|
363
|
+
): undefined | string {
|
|
364
|
+
const [entry, setEntry] = useState<string | undefined>(
|
|
389
365
|
// if there's no build command, just return the expected entry
|
|
390
|
-
props.command
|
|
366
|
+
props.command || expectedEntry
|
|
391
367
|
);
|
|
392
368
|
const { command, cwd, watch_dir } = props;
|
|
393
369
|
useEffect(() => {
|
|
@@ -456,16 +432,16 @@ type EsbuildBundle = {
|
|
|
456
432
|
};
|
|
457
433
|
|
|
458
434
|
function useEsbuild(props: {
|
|
459
|
-
entry:
|
|
460
|
-
destination: string |
|
|
461
|
-
staticRoot:
|
|
462
|
-
jsxFactory: string |
|
|
463
|
-
jsxFragment: string |
|
|
464
|
-
}): EsbuildBundle |
|
|
435
|
+
entry: undefined | string;
|
|
436
|
+
destination: string | undefined;
|
|
437
|
+
staticRoot: undefined | string;
|
|
438
|
+
jsxFactory: string | undefined;
|
|
439
|
+
jsxFragment: string | undefined;
|
|
440
|
+
}): EsbuildBundle | undefined {
|
|
465
441
|
const { entry, destination, staticRoot, jsxFactory, jsxFragment } = props;
|
|
466
442
|
const [bundle, setBundle] = useState<EsbuildBundle>();
|
|
467
443
|
useEffect(() => {
|
|
468
|
-
let result: esbuild.BuildResult;
|
|
444
|
+
let result: esbuild.BuildResult | undefined;
|
|
469
445
|
async function build() {
|
|
470
446
|
if (!destination || !entry) return;
|
|
471
447
|
const moduleCollector = makeModuleCollector();
|
|
@@ -491,25 +467,37 @@ function useEsbuild(props: {
|
|
|
491
467
|
else {
|
|
492
468
|
// nothing really changes here, so let's increment the id
|
|
493
469
|
// to change the return object's identity
|
|
494
|
-
setBundle((previousBundle) =>
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
470
|
+
setBundle((previousBundle) => {
|
|
471
|
+
if (previousBundle === undefined) {
|
|
472
|
+
assert.fail(
|
|
473
|
+
"Rebuild triggered with no previous build available"
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
return { ...previousBundle, id: previousBundle.id + 1 };
|
|
477
|
+
});
|
|
498
478
|
}
|
|
499
479
|
},
|
|
500
480
|
},
|
|
501
481
|
});
|
|
502
482
|
|
|
503
|
-
|
|
483
|
+
// result.metafile is defined because of the `metafile: true` option above.
|
|
484
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
485
|
+
const metafile = result.metafile!;
|
|
486
|
+
const outputEntry = Object.entries(metafile.outputs).find(
|
|
504
487
|
([_path, { entryPoint }]) => entryPoint === entry
|
|
505
488
|
); // assumedly only one entry point
|
|
506
489
|
|
|
490
|
+
if (outputEntry === undefined) {
|
|
491
|
+
throw new Error(
|
|
492
|
+
`Cannot find entry-point "${entry}" in generated bundle.`
|
|
493
|
+
);
|
|
494
|
+
}
|
|
507
495
|
setBundle({
|
|
508
496
|
id: 0,
|
|
509
497
|
entry,
|
|
510
|
-
path:
|
|
511
|
-
type:
|
|
512
|
-
exports:
|
|
498
|
+
path: outputEntry[0],
|
|
499
|
+
type: outputEntry[1].exports.length > 0 ? "esm" : "commonjs",
|
|
500
|
+
exports: outputEntry[1].exports,
|
|
513
501
|
modules: moduleCollector.modules,
|
|
514
502
|
});
|
|
515
503
|
}
|
|
@@ -520,26 +508,26 @@ function useEsbuild(props: {
|
|
|
520
508
|
// so this is a no-op error handler
|
|
521
509
|
});
|
|
522
510
|
return () => {
|
|
523
|
-
result?.stop();
|
|
511
|
+
result?.stop?.();
|
|
524
512
|
};
|
|
525
513
|
}, [entry, destination, staticRoot, jsxFactory, jsxFragment]);
|
|
526
514
|
return bundle;
|
|
527
515
|
}
|
|
528
516
|
|
|
529
517
|
function useWorker(props: {
|
|
530
|
-
name:
|
|
531
|
-
bundle: EsbuildBundle |
|
|
518
|
+
name: undefined | string;
|
|
519
|
+
bundle: EsbuildBundle | undefined;
|
|
532
520
|
format: CfScriptFormat;
|
|
533
521
|
modules: CfModule[];
|
|
534
522
|
accountId: string;
|
|
535
523
|
apiToken: string;
|
|
536
524
|
bindings: CfWorkerInit["bindings"];
|
|
537
|
-
sitesFolder:
|
|
525
|
+
sitesFolder: undefined | string;
|
|
538
526
|
port: number;
|
|
539
|
-
compatibilityDate: string |
|
|
540
|
-
compatibilityFlags: string[] |
|
|
541
|
-
usageModel:
|
|
542
|
-
}): CfPreviewToken |
|
|
527
|
+
compatibilityDate: string | undefined;
|
|
528
|
+
compatibilityFlags: string[] | undefined;
|
|
529
|
+
usageModel: undefined | "bundled" | "unbound";
|
|
530
|
+
}): CfPreviewToken | undefined {
|
|
543
531
|
const {
|
|
544
532
|
name,
|
|
545
533
|
bundle,
|
|
@@ -554,7 +542,7 @@ function useWorker(props: {
|
|
|
554
542
|
usageModel,
|
|
555
543
|
port,
|
|
556
544
|
} = props;
|
|
557
|
-
const [token, setToken] = useState<CfPreviewToken>();
|
|
545
|
+
const [token, setToken] = useState<CfPreviewToken | undefined>();
|
|
558
546
|
|
|
559
547
|
// This is the most reliable way to detect whether
|
|
560
548
|
// something's "happened" in our system; We make a ref and
|
|
@@ -563,6 +551,8 @@ function useWorker(props: {
|
|
|
563
551
|
|
|
564
552
|
useEffect(() => {
|
|
565
553
|
async function start() {
|
|
554
|
+
setToken(undefined); // reset token in case we're re-running
|
|
555
|
+
|
|
566
556
|
if (!bundle) return;
|
|
567
557
|
if (format === "modules" && bundle.type === "commonjs") {
|
|
568
558
|
console.error("⎔ Cannot use modules with a commonjs bundle.");
|
|
@@ -576,7 +566,6 @@ function useWorker(props: {
|
|
|
576
566
|
}
|
|
577
567
|
|
|
578
568
|
if (!startedRef.current) {
|
|
579
|
-
console.log("⎔ Starting server...");
|
|
580
569
|
startedRef.current = true;
|
|
581
570
|
} else {
|
|
582
571
|
console.log("⎔ Detected changes, restarting server...");
|
|
@@ -654,85 +643,6 @@ function useWorker(props: {
|
|
|
654
643
|
return token;
|
|
655
644
|
}
|
|
656
645
|
|
|
657
|
-
function useProxy({
|
|
658
|
-
token,
|
|
659
|
-
publicRoot,
|
|
660
|
-
port,
|
|
661
|
-
}: {
|
|
662
|
-
token: CfPreviewToken | void;
|
|
663
|
-
publicRoot: void | string;
|
|
664
|
-
port: number;
|
|
665
|
-
}) {
|
|
666
|
-
useEffect(() => {
|
|
667
|
-
if (!token) return;
|
|
668
|
-
// TODO(soon): since headers are added in callbacks, the server
|
|
669
|
-
// does not need to restart when changes are made.
|
|
670
|
-
const host = token.host;
|
|
671
|
-
const proxy = createHttpProxy({
|
|
672
|
-
host,
|
|
673
|
-
assetPath: typeof publicRoot === "string" ? publicRoot : null,
|
|
674
|
-
onRequest: (headers) => {
|
|
675
|
-
headers["cf-workers-preview-token"] = token.value;
|
|
676
|
-
},
|
|
677
|
-
onResponse: (headers) => {
|
|
678
|
-
for (const [name, value] of Object.entries(headers)) {
|
|
679
|
-
// Rewrite the remote host to the local host.
|
|
680
|
-
if (typeof value === "string" && value.includes(host)) {
|
|
681
|
-
headers[name] = value
|
|
682
|
-
.replaceAll(`https://${host}`, `http://localhost:${port}`)
|
|
683
|
-
.replaceAll(host, `localhost:${port}`);
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
},
|
|
687
|
-
});
|
|
688
|
-
|
|
689
|
-
console.log(`⬣ Listening at http://localhost:${port}`);
|
|
690
|
-
|
|
691
|
-
const server = proxy.listen(port);
|
|
692
|
-
|
|
693
|
-
// TODO(soon): refactor logging format into its own function
|
|
694
|
-
proxy.on("request", function (req, res) {
|
|
695
|
-
// log all requests
|
|
696
|
-
console.log(
|
|
697
|
-
new Date().toLocaleTimeString(),
|
|
698
|
-
req.method,
|
|
699
|
-
req.url,
|
|
700
|
-
res.statusCode
|
|
701
|
-
);
|
|
702
|
-
});
|
|
703
|
-
proxy.on("upgrade", (req) => {
|
|
704
|
-
console.log(
|
|
705
|
-
new Date().toLocaleTimeString(),
|
|
706
|
-
req.method,
|
|
707
|
-
req.url,
|
|
708
|
-
101,
|
|
709
|
-
"(WebSocket)"
|
|
710
|
-
);
|
|
711
|
-
});
|
|
712
|
-
proxy.on("error", (err) => {
|
|
713
|
-
console.error(new Date().toLocaleTimeString(), err);
|
|
714
|
-
});
|
|
715
|
-
|
|
716
|
-
return () => {
|
|
717
|
-
proxy.close();
|
|
718
|
-
server.close();
|
|
719
|
-
};
|
|
720
|
-
}, [token, publicRoot, port]);
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
function useInspector(inspectorUrl: string | void) {
|
|
724
|
-
useEffect(() => {
|
|
725
|
-
if (!inspectorUrl) return;
|
|
726
|
-
|
|
727
|
-
const inspector = new DtInspector(inspectorUrl);
|
|
728
|
-
const abortController = inspector.proxyTo(9229);
|
|
729
|
-
return () => {
|
|
730
|
-
inspector.close();
|
|
731
|
-
abortController.abort();
|
|
732
|
-
};
|
|
733
|
-
}, [inspectorUrl]);
|
|
734
|
-
}
|
|
735
|
-
|
|
736
646
|
function sleep(period: number) {
|
|
737
647
|
return new Promise((resolve) => setTimeout(resolve, period));
|
|
738
648
|
}
|
|
@@ -740,7 +650,7 @@ const SLEEP_DURATION = 2000;
|
|
|
740
650
|
// really need a first class api for this
|
|
741
651
|
const hostNameRegex = /userHostname="(.*)"/g;
|
|
742
652
|
async function findTunnelHostname() {
|
|
743
|
-
let hostName: string;
|
|
653
|
+
let hostName: string | undefined;
|
|
744
654
|
while (!hostName) {
|
|
745
655
|
try {
|
|
746
656
|
const resp = await fetch("http://localhost:8789/metrics");
|
|
@@ -860,19 +770,14 @@ function useHotkeys(initial: useHotkeysInitialState, port: number) {
|
|
|
860
770
|
return toggles;
|
|
861
771
|
}
|
|
862
772
|
|
|
863
|
-
function ErrorFallback(props: {
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
}) {
|
|
867
|
-
useEffect(() => {
|
|
868
|
-
console.error(props.error);
|
|
869
|
-
process.exit(1);
|
|
870
|
-
});
|
|
773
|
+
function ErrorFallback(props: { error: Error }) {
|
|
774
|
+
const { exit } = useApp();
|
|
775
|
+
useEffect(() => exit(new Error()));
|
|
871
776
|
return (
|
|
872
|
-
|
|
777
|
+
<>
|
|
873
778
|
<Text>Something went wrong:</Text>
|
|
874
|
-
<Text>{props.error.
|
|
875
|
-
|
|
779
|
+
<Text>{props.error.stack}</Text>
|
|
780
|
+
</>
|
|
876
781
|
);
|
|
877
782
|
}
|
|
878
783
|
|