wrangler 0.0.0-e22f9d7 → 0.0.0-e2a26a0
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/bin/wrangler.js +2 -2
- package/package.json +15 -10
- package/pages/functions/buildWorker.ts +1 -1
- package/pages/functions/filepath-routing.test.ts +21 -13
- package/pages/functions/filepath-routing.ts +38 -28
- package/pages/functions/routes.ts +8 -6
- package/pages/functions/template-worker.ts +16 -24
- package/src/__tests__/dev.test.tsx +7 -3
- package/src/__tests__/{clipboardy-mock.js → helpers/clipboardy-mock.js} +0 -0
- package/src/__tests__/helpers/cmd-shim.d.ts +11 -0
- package/src/__tests__/helpers/mock-account-id.ts +30 -0
- package/src/__tests__/helpers/mock-bin.ts +33 -0
- package/src/__tests__/{mock-cfetch.ts → helpers/mock-cfetch.ts} +49 -13
- package/src/__tests__/helpers/mock-console.ts +56 -0
- package/src/__tests__/{mock-dialogs.ts → helpers/mock-dialogs.ts} +1 -1
- package/src/__tests__/helpers/mock-kv.ts +40 -0
- package/src/__tests__/helpers/mock-user.ts +27 -0
- package/src/__tests__/helpers/run-in-tmp.ts +29 -0
- package/src/__tests__/helpers/run-wrangler.ts +14 -0
- package/src/__tests__/index.test.ts +312 -56
- package/src/__tests__/jest.setup.ts +17 -2
- package/src/__tests__/kv.test.ts +344 -316
- package/src/__tests__/logout.test.ts +50 -0
- package/src/__tests__/package-manager.test.ts +206 -0
- package/src/__tests__/publish.test.ts +1222 -0
- package/src/__tests__/secret.test.ts +210 -0
- package/src/__tests__/whoami.test.tsx +86 -0
- package/src/api/form_data.ts +10 -7
- package/src/api/preview.ts +2 -2
- package/src/api/worker.ts +3 -3
- package/src/cfetch/index.ts +14 -14
- package/src/cfetch/internal.ts +40 -8
- package/src/config.ts +162 -8
- package/src/dev.tsx +103 -53
- package/src/dialogs.tsx +2 -2
- package/src/index.tsx +438 -311
- package/src/inspect.ts +80 -23
- package/src/kv.tsx +9 -1
- package/src/module-collection.ts +5 -6
- package/src/package-manager.ts +120 -0
- package/src/pages.tsx +41 -26
- package/src/paths.ts +26 -0
- package/src/proxy.ts +78 -10
- package/src/publish.ts +98 -52
- package/src/sites.tsx +175 -53
- package/src/user.tsx +51 -59
- package/src/whoami.tsx +69 -0
- package/templates/new-worker.js +15 -0
- package/templates/new-worker.ts +15 -0
- package/{static-asset-facade.js → templates/static-asset-facade.js} +0 -0
- package/wrangler-dist/cli.js +111479 -110187
- package/wrangler-dist/cli.js.map +3 -3
- package/src/__tests__/run-in-tmp.ts +0 -19
- package/src/__tests__/run-wrangler.ts +0 -32
package/src/config.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* This is the static type definition for the configuration object.
|
|
3
5
|
* It reflects the configuration that you can write in wrangler.toml,
|
|
@@ -79,7 +81,6 @@ export type Config = {
|
|
|
79
81
|
*
|
|
80
82
|
* @optional
|
|
81
83
|
* @inherited
|
|
82
|
-
* @todo This could be an enum!
|
|
83
84
|
*/
|
|
84
85
|
compatibility_flags?: string[];
|
|
85
86
|
|
|
@@ -268,10 +269,9 @@ export type Config = {
|
|
|
268
269
|
* The location of your Worker script.
|
|
269
270
|
*
|
|
270
271
|
* @deprecated DO NOT use this (it's a holdover from wrangler 1.x). Either use the top level `entry` field, or pass the path to your entry file as a command line argument.
|
|
271
|
-
* @todo we should use a top level "entry" property instead
|
|
272
272
|
* @breaking
|
|
273
273
|
*/
|
|
274
|
-
"entry-point"
|
|
274
|
+
"entry-point"?: string;
|
|
275
275
|
|
|
276
276
|
/**
|
|
277
277
|
* An exclusive list of .gitignore-style patterns that match file
|
|
@@ -280,7 +280,6 @@ export type Config = {
|
|
|
280
280
|
*
|
|
281
281
|
* @optional
|
|
282
282
|
* @default `[]`
|
|
283
|
-
* @todo this needs to be implemented!
|
|
284
283
|
*/
|
|
285
284
|
include?: string[];
|
|
286
285
|
|
|
@@ -291,7 +290,6 @@ export type Config = {
|
|
|
291
290
|
*
|
|
292
291
|
* @optional
|
|
293
292
|
* @default `[]`
|
|
294
|
-
* @todo this needs to be implemented!
|
|
295
293
|
*/
|
|
296
294
|
exclude?: string[];
|
|
297
295
|
};
|
|
@@ -304,7 +302,6 @@ export type Config = {
|
|
|
304
302
|
* @inherited
|
|
305
303
|
* @default `{ crons: [] }`
|
|
306
304
|
* @optional
|
|
307
|
-
* @todo can we use typescript for cron patterns?
|
|
308
305
|
*/
|
|
309
306
|
triggers?: { crons: string[] };
|
|
310
307
|
|
|
@@ -389,7 +386,7 @@ export type Config = {
|
|
|
389
386
|
*
|
|
390
387
|
* @deprecated We infer the format automatically now.
|
|
391
388
|
*/
|
|
392
|
-
format
|
|
389
|
+
format?: "service-worker";
|
|
393
390
|
|
|
394
391
|
/**
|
|
395
392
|
* The path to the Worker script. This should be replaced
|
|
@@ -412,7 +409,7 @@ export type Config = {
|
|
|
412
409
|
*
|
|
413
410
|
* @deprecated We infer the format automatically now.
|
|
414
411
|
*/
|
|
415
|
-
format
|
|
412
|
+
format?: "modules";
|
|
416
413
|
|
|
417
414
|
/**
|
|
418
415
|
* The directory you wish to upload your modules from,
|
|
@@ -485,3 +482,160 @@ export async function validateConfig(
|
|
|
485
482
|
|
|
486
483
|
return results;
|
|
487
484
|
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Process the environments (`env`) specified in the `config`.
|
|
488
|
+
*
|
|
489
|
+
* The environments configuration is complicated since each environment is a customized version of the main config.
|
|
490
|
+
* Some of the configuration can be inherited from the main config, while other configuration must replace what is in the main config.
|
|
491
|
+
*
|
|
492
|
+
* This function ensures that each environment is set up correctly with inherited configuration, as necessary.
|
|
493
|
+
* It will log a warning if an environment is missing required configuration.
|
|
494
|
+
*/
|
|
495
|
+
export function normaliseAndValidateEnvironmentsConfig(config: Config) {
|
|
496
|
+
if (config.env == undefined) {
|
|
497
|
+
// There are no environments specified so there is nothing to do here.
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
const environments = config.env;
|
|
502
|
+
|
|
503
|
+
for (const envKey of Object.keys(environments)) {
|
|
504
|
+
const environment = environments[envKey];
|
|
505
|
+
|
|
506
|
+
// Given how TOML works, there should never be an environment containing nothing.
|
|
507
|
+
// I.e. if there is a section in a TOML file, then the parser will create an object for it.
|
|
508
|
+
// But it may be possible in the future if we change how the configuration is stored.
|
|
509
|
+
assert(
|
|
510
|
+
environment,
|
|
511
|
+
`Environment ${envKey} is specified in the config but not defined.`
|
|
512
|
+
);
|
|
513
|
+
|
|
514
|
+
// Fall back on "inherited fields" from the config, if not specified in the environment.
|
|
515
|
+
const inheritedFields = [
|
|
516
|
+
"name",
|
|
517
|
+
"account_id",
|
|
518
|
+
"workers_dev",
|
|
519
|
+
"compatibility_date",
|
|
520
|
+
"compatibility_flags",
|
|
521
|
+
"zone_id",
|
|
522
|
+
"routes",
|
|
523
|
+
"route",
|
|
524
|
+
"jsx_factory",
|
|
525
|
+
"jsx_fragment",
|
|
526
|
+
"site",
|
|
527
|
+
"triggers",
|
|
528
|
+
"usage_model",
|
|
529
|
+
];
|
|
530
|
+
for (const inheritedField of inheritedFields) {
|
|
531
|
+
if (config[inheritedField] !== undefined) {
|
|
532
|
+
if (environment[inheritedField] === undefined) {
|
|
533
|
+
environment[inheritedField] = config[inheritedField]; // TODO: - shallow or deep copy?
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// Warn if there is a "required" field in the top level config that has not been specified specified in the environment.
|
|
539
|
+
// These required fields are `vars`, `durable_objects`, `kv_namespaces` and `experimental_services`.
|
|
540
|
+
// Each of them has different characteristics that need to be checked.
|
|
541
|
+
|
|
542
|
+
// `vars` is just an object
|
|
543
|
+
if (config.vars !== undefined) {
|
|
544
|
+
if (environment.vars === undefined) {
|
|
545
|
+
console.warn(
|
|
546
|
+
`In your configuration, "vars" exists at the top level, but not on "env.${envKey}".\n` +
|
|
547
|
+
`This is not what you probably want, since "vars" is not inherited by environments.\n` +
|
|
548
|
+
`Please add "vars" to "env.${envKey}".`
|
|
549
|
+
);
|
|
550
|
+
} else {
|
|
551
|
+
for (const varField of Object.keys(config.vars)) {
|
|
552
|
+
if (!(varField in environment.vars)) {
|
|
553
|
+
console.warn(
|
|
554
|
+
`In your configuration, "vars.${varField}" exists at the top level, but not on "env.${envKey}".\n` +
|
|
555
|
+
`This is not what you probably want, since "vars" is not inherited by environments.\n` +
|
|
556
|
+
`Please add "vars.${varField}" to "env.${envKey}".`
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// `durable_objects` is an object containing a `bindings` array
|
|
564
|
+
if (config.durable_objects !== undefined) {
|
|
565
|
+
if (environment.durable_objects === undefined) {
|
|
566
|
+
console.warn(
|
|
567
|
+
`In your configuration, "durable_objects.bindings" exists at the top level, but not on "env.${envKey}".\n` +
|
|
568
|
+
`This is not what you probably want, since "durable_objects" is not inherited by environments.\n` +
|
|
569
|
+
`Please add "durable_objects.bindings" to "env.${envKey}".`
|
|
570
|
+
);
|
|
571
|
+
} else {
|
|
572
|
+
const envBindingNames = new Set(
|
|
573
|
+
environment.durable_objects.bindings.map((b) => b.name)
|
|
574
|
+
);
|
|
575
|
+
for (const bindingName of config.durable_objects.bindings.map(
|
|
576
|
+
(b) => b.name
|
|
577
|
+
)) {
|
|
578
|
+
if (!envBindingNames.has(bindingName)) {
|
|
579
|
+
console.warn(
|
|
580
|
+
`In your configuration, there is a durable_objects binding with name "${bindingName}" at the top level, but not on "env.${envKey}".\n` +
|
|
581
|
+
`This is not what you probably want, since "durable_objects" is not inherited by environments.\n` +
|
|
582
|
+
`Please add a binding for "${bindingName}" to "env.${envKey}.durable_objects.bindings".`
|
|
583
|
+
);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// `kv_namespaces` contains an array of namespace bindings
|
|
590
|
+
if (config.kv_namespaces !== undefined) {
|
|
591
|
+
if (environment.kv_namespaces === undefined) {
|
|
592
|
+
console.warn(
|
|
593
|
+
`In your configuration, "kv_namespaces" exists at the top level, but not on "env.${envKey}".\n` +
|
|
594
|
+
`This is not what you probably want, since "kv_namespaces" is not inherited by environments.\n` +
|
|
595
|
+
`Please add "kv_namespaces" to "env.${envKey}".`
|
|
596
|
+
);
|
|
597
|
+
} else {
|
|
598
|
+
const envBindings = new Set(
|
|
599
|
+
environment.kv_namespaces.map((kvNamespace) => kvNamespace.binding)
|
|
600
|
+
);
|
|
601
|
+
for (const bindingName of config.kv_namespaces.map(
|
|
602
|
+
(kvNamespace) => kvNamespace.binding
|
|
603
|
+
)) {
|
|
604
|
+
if (!envBindings.has(bindingName)) {
|
|
605
|
+
console.warn(
|
|
606
|
+
`In your configuration, there is a kv_namespaces with binding "${bindingName}" at the top level, but not on "env.${envKey}".\n` +
|
|
607
|
+
`This is not what you probably want, since "kv_namespaces" is not inherited by environments.\n` +
|
|
608
|
+
`Please add a binding for "${bindingName}" to "env.${envKey}.kv_namespaces".`
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// `experimental_services` contains an array of namespace bindings
|
|
616
|
+
if (config.experimental_services !== undefined) {
|
|
617
|
+
if (environment.experimental_services === undefined) {
|
|
618
|
+
console.warn(
|
|
619
|
+
`In your configuration, "experimental_services" exists at the top level, but not on "env.${envKey}".\n` +
|
|
620
|
+
`This is not what you probably want, since "experimental_services" is not inherited by environments.\n` +
|
|
621
|
+
`Please add "experimental_services" to "env.${envKey}".`
|
|
622
|
+
);
|
|
623
|
+
} else {
|
|
624
|
+
const envBindingNames = new Set(
|
|
625
|
+
environment.experimental_services.map((service) => service.name)
|
|
626
|
+
);
|
|
627
|
+
for (const bindingName of config.experimental_services.map(
|
|
628
|
+
(service) => service.name
|
|
629
|
+
)) {
|
|
630
|
+
if (!envBindingNames.has(bindingName)) {
|
|
631
|
+
console.warn(
|
|
632
|
+
`In your configuration, there is a experimental_services with binding name "${bindingName}" at the top level, but not on "env.${envKey}".\n` +
|
|
633
|
+
`This is not what you probably want, since "experimental_services" is not inherited by environments.\n` +
|
|
634
|
+
`Please add a service for "${bindingName}" to "env.${envKey}.experimental_services".`
|
|
635
|
+
);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
package/src/dev.tsx
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
import esbuild from "esbuild";
|
|
2
1
|
import assert from "node:assert";
|
|
3
2
|
import { spawn } from "node:child_process";
|
|
4
|
-
import { readFile } from "node:fs/promises";
|
|
5
3
|
import { existsSync } from "node:fs";
|
|
4
|
+
import { readFile } from "node:fs/promises";
|
|
6
5
|
import path from "node:path";
|
|
7
|
-
import { Box, Text, useApp, useInput } from "ink";
|
|
8
6
|
import { watch } from "chokidar";
|
|
9
7
|
import clipboardy from "clipboardy";
|
|
10
8
|
import commandExists from "command-exists";
|
|
11
|
-
import
|
|
12
|
-
import
|
|
9
|
+
import * as esbuild from "esbuild";
|
|
10
|
+
import { execaCommand } from "execa";
|
|
11
|
+
import { Box, Text, useApp, useInput } from "ink";
|
|
13
12
|
import open from "open";
|
|
14
13
|
import React, { useState, useEffect, useRef } from "react";
|
|
15
14
|
import { withErrorBoundary, useErrorHandler } from "react-error-boundary";
|
|
16
15
|
import onExit from "signal-exit";
|
|
17
16
|
import tmp from "tmp-promise";
|
|
18
|
-
import
|
|
17
|
+
import { fetch } from "undici";
|
|
19
18
|
|
|
20
|
-
import type { CfPreviewToken } from "./api/preview";
|
|
21
|
-
import type { CfModule } from "./api/worker";
|
|
22
19
|
import { createWorker } from "./api/worker";
|
|
23
|
-
import type { CfWorkerInit } from "./api/worker";
|
|
24
20
|
|
|
25
21
|
import useInspector from "./inspect";
|
|
26
22
|
import makeModuleCollector from "./module-collection";
|
|
27
|
-
import { usePreviewServer } from "./proxy";
|
|
23
|
+
import { usePreviewServer, waitForPortToBeAvailable } from "./proxy";
|
|
28
24
|
import { syncAssets } from "./sites";
|
|
29
25
|
import { getAPIToken } from "./user";
|
|
26
|
+
import type { CfPreviewToken } from "./api/preview";
|
|
27
|
+
import type { CfModule, CfWorkerInit } from "./api/worker";
|
|
28
|
+
import type { AssetPaths } from "./sites";
|
|
29
|
+
import type { DirectoryResult } from "tmp-promise";
|
|
30
30
|
|
|
31
31
|
type CfScriptFormat = undefined | "modules" | "service-worker";
|
|
32
32
|
|
|
@@ -39,9 +39,10 @@ export type DevProps = {
|
|
|
39
39
|
initialMode: "local" | "remote";
|
|
40
40
|
jsxFactory: undefined | string;
|
|
41
41
|
jsxFragment: undefined | string;
|
|
42
|
+
enableLocalPersistence: boolean;
|
|
42
43
|
bindings: CfWorkerInit["bindings"];
|
|
43
44
|
public: undefined | string;
|
|
44
|
-
|
|
45
|
+
assetPaths: undefined | AssetPaths;
|
|
45
46
|
compatibilityDate: undefined | string;
|
|
46
47
|
compatibilityFlags: undefined | string[];
|
|
47
48
|
usageModel: undefined | "bundled" | "unbound";
|
|
@@ -50,6 +51,7 @@ export type DevProps = {
|
|
|
50
51
|
cwd?: undefined | string;
|
|
51
52
|
watch_dir?: undefined | string;
|
|
52
53
|
};
|
|
54
|
+
env: string | undefined;
|
|
53
55
|
};
|
|
54
56
|
|
|
55
57
|
function Dev(props: DevProps): JSX.Element {
|
|
@@ -98,9 +100,10 @@ function Dev(props: DevProps): JSX.Element {
|
|
|
98
100
|
bundle={bundle}
|
|
99
101
|
format={props.format}
|
|
100
102
|
bindings={props.bindings}
|
|
101
|
-
|
|
103
|
+
assetPaths={props.assetPaths}
|
|
102
104
|
public={props.public}
|
|
103
105
|
port={port}
|
|
106
|
+
enableLocalPersistence={props.enableLocalPersistence}
|
|
104
107
|
/>
|
|
105
108
|
) : (
|
|
106
109
|
<Remote
|
|
@@ -110,12 +113,13 @@ function Dev(props: DevProps): JSX.Element {
|
|
|
110
113
|
accountId={props.accountId}
|
|
111
114
|
apiToken={apiToken}
|
|
112
115
|
bindings={props.bindings}
|
|
113
|
-
|
|
116
|
+
assetPaths={props.assetPaths}
|
|
114
117
|
public={props.public}
|
|
115
118
|
port={port}
|
|
116
119
|
compatibilityDate={props.compatibilityDate}
|
|
117
120
|
compatibilityFlags={props.compatibilityFlags}
|
|
118
121
|
usageModel={props.usageModel}
|
|
122
|
+
env={props.env}
|
|
119
123
|
/>
|
|
120
124
|
)}
|
|
121
125
|
<Box borderStyle="round" paddingLeft={1} paddingRight={1}>
|
|
@@ -136,7 +140,7 @@ function Remote(props: {
|
|
|
136
140
|
bundle: EsbuildBundle | undefined;
|
|
137
141
|
format: CfScriptFormat;
|
|
138
142
|
public: undefined | string;
|
|
139
|
-
|
|
143
|
+
assetPaths: undefined | AssetPaths;
|
|
140
144
|
port: number;
|
|
141
145
|
accountId: undefined | string;
|
|
142
146
|
apiToken: undefined | string;
|
|
@@ -144,6 +148,7 @@ function Remote(props: {
|
|
|
144
148
|
compatibilityDate: string | undefined;
|
|
145
149
|
compatibilityFlags: undefined | string[];
|
|
146
150
|
usageModel: undefined | "bundled" | "unbound";
|
|
151
|
+
env: string | undefined;
|
|
147
152
|
}) {
|
|
148
153
|
assert(props.accountId, "accountId is required");
|
|
149
154
|
assert(props.apiToken, "apiToken is required");
|
|
@@ -155,11 +160,12 @@ function Remote(props: {
|
|
|
155
160
|
accountId: props.accountId,
|
|
156
161
|
apiToken: props.apiToken,
|
|
157
162
|
bindings: props.bindings,
|
|
158
|
-
|
|
163
|
+
assetPaths: props.assetPaths,
|
|
159
164
|
port: props.port,
|
|
160
165
|
compatibilityDate: props.compatibilityDate,
|
|
161
166
|
compatibilityFlags: props.compatibilityFlags,
|
|
162
167
|
usageModel: props.usageModel,
|
|
168
|
+
env: props.env,
|
|
163
169
|
});
|
|
164
170
|
|
|
165
171
|
usePreviewServer({
|
|
@@ -180,16 +186,20 @@ function Local(props: {
|
|
|
180
186
|
bundle: EsbuildBundle | undefined;
|
|
181
187
|
format: CfScriptFormat;
|
|
182
188
|
bindings: CfWorkerInit["bindings"];
|
|
189
|
+
assetPaths: undefined | AssetPaths;
|
|
183
190
|
public: undefined | string;
|
|
184
|
-
site: undefined | string;
|
|
185
191
|
port: number;
|
|
192
|
+
enableLocalPersistence: boolean;
|
|
186
193
|
}) {
|
|
187
194
|
const { inspectorUrl } = useLocalWorker({
|
|
188
195
|
name: props.name,
|
|
189
196
|
bundle: props.bundle,
|
|
190
197
|
format: props.format,
|
|
191
198
|
bindings: props.bindings,
|
|
199
|
+
assetPaths: props.assetPaths,
|
|
200
|
+
public: props.public,
|
|
192
201
|
port: props.port,
|
|
202
|
+
enableLocalPersistence: props.enableLocalPersistence,
|
|
193
203
|
});
|
|
194
204
|
useInspector({ inspectorUrl, port: 9229, logToTerminal: false });
|
|
195
205
|
return null;
|
|
@@ -200,10 +210,13 @@ function useLocalWorker(props: {
|
|
|
200
210
|
bundle: EsbuildBundle | undefined;
|
|
201
211
|
format: CfScriptFormat;
|
|
202
212
|
bindings: CfWorkerInit["bindings"];
|
|
213
|
+
assetPaths: undefined | AssetPaths;
|
|
214
|
+
public: undefined | string;
|
|
203
215
|
port: number;
|
|
216
|
+
enableLocalPersistence: boolean;
|
|
204
217
|
}) {
|
|
205
218
|
// TODO: pass vars via command line
|
|
206
|
-
const { bundle, format, bindings, port } = props;
|
|
219
|
+
const { bundle, format, bindings, port, assetPaths } = props;
|
|
207
220
|
const local = useRef<ReturnType<typeof spawn>>();
|
|
208
221
|
const removeSignalExitListener = useRef<() => void>();
|
|
209
222
|
const [inspectorUrl, setInspectorUrl] = useState<string | undefined>();
|
|
@@ -221,6 +234,13 @@ function useLocalWorker(props: {
|
|
|
221
234
|
return;
|
|
222
235
|
}
|
|
223
236
|
|
|
237
|
+
await waitForPortToBeAvailable(port, { retryPeriod: 200, timeout: 2000 });
|
|
238
|
+
if (props.public) {
|
|
239
|
+
throw new Error(
|
|
240
|
+
'⎔ A "public" folder is not yet supported in local mode.'
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
224
244
|
console.log("⎔ Starting a local server...");
|
|
225
245
|
// TODO: just use execa for this
|
|
226
246
|
local.current = spawn("node", [
|
|
@@ -237,9 +257,23 @@ function useLocalWorker(props: {
|
|
|
237
257
|
path.join(__dirname, "../miniflare-config-stubs/package.empty.json"),
|
|
238
258
|
"--port",
|
|
239
259
|
port.toString(),
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
260
|
+
...(assetPaths
|
|
261
|
+
? [
|
|
262
|
+
"--site",
|
|
263
|
+
assetPaths.baseDirectory,
|
|
264
|
+
...assetPaths.includePatterns.map((pattern) => [
|
|
265
|
+
"--site-include",
|
|
266
|
+
pattern,
|
|
267
|
+
]),
|
|
268
|
+
...assetPaths.excludePatterns.map((pattern) => [
|
|
269
|
+
"--site-exclude",
|
|
270
|
+
pattern,
|
|
271
|
+
]),
|
|
272
|
+
].flatMap((x) => x)
|
|
273
|
+
: []),
|
|
274
|
+
...(props.enableLocalPersistence
|
|
275
|
+
? ["--kv-persist", "--cache-persist", "--do-persist"]
|
|
276
|
+
: []),
|
|
243
277
|
...Object.entries(bindings.vars || {}).flatMap(([key, value]) => {
|
|
244
278
|
return ["--binding", `${key}=${value}`];
|
|
245
279
|
}),
|
|
@@ -318,6 +352,9 @@ function useLocalWorker(props: {
|
|
|
318
352
|
bindings.durable_objects?.bindings,
|
|
319
353
|
bindings.kv_namespaces,
|
|
320
354
|
bindings.vars,
|
|
355
|
+
props.enableLocalPersistence,
|
|
356
|
+
assetPaths,
|
|
357
|
+
props.public,
|
|
321
358
|
]);
|
|
322
359
|
return { inspectorUrl };
|
|
323
360
|
}
|
|
@@ -345,7 +382,7 @@ function useTmpDir(): string | undefined {
|
|
|
345
382
|
return () => {
|
|
346
383
|
dir.cleanup().catch(() => {
|
|
347
384
|
// extremely unlikely,
|
|
348
|
-
// but it's
|
|
385
|
+
// but it's 2022 after all
|
|
349
386
|
console.error("failed to cleanup tmp dir");
|
|
350
387
|
});
|
|
351
388
|
};
|
|
@@ -370,20 +407,21 @@ function useCustomBuild(
|
|
|
370
407
|
if (!command) return;
|
|
371
408
|
let cmd, interval;
|
|
372
409
|
console.log("running:", command);
|
|
373
|
-
|
|
374
|
-
cmd = execa(commandPieces[0], commandPieces.slice(1), {
|
|
410
|
+
cmd = execaCommand(command, {
|
|
375
411
|
...(cwd && { cwd }),
|
|
412
|
+
shell: true,
|
|
376
413
|
stderr: "inherit",
|
|
377
414
|
stdout: "inherit",
|
|
378
415
|
});
|
|
379
416
|
if (watch_dir) {
|
|
380
417
|
watch(watch_dir, { persistent: true, ignoreInitial: true }).on(
|
|
381
418
|
"all",
|
|
382
|
-
(_event,
|
|
383
|
-
console.log(`The file ${
|
|
419
|
+
(_event, filePath) => {
|
|
420
|
+
console.log(`The file ${filePath} changed, restarting build...`);
|
|
384
421
|
cmd.kill();
|
|
385
|
-
cmd =
|
|
422
|
+
cmd = execaCommand(command, {
|
|
386
423
|
...(cwd && { cwd }),
|
|
424
|
+
shell: true,
|
|
387
425
|
stderr: "inherit",
|
|
388
426
|
stdout: "inherit",
|
|
389
427
|
});
|
|
@@ -454,6 +492,9 @@ function useEsbuild(props: {
|
|
|
454
492
|
sourcemap: true,
|
|
455
493
|
loader: {
|
|
456
494
|
".js": "jsx",
|
|
495
|
+
".html": "text",
|
|
496
|
+
".pem": "text",
|
|
497
|
+
".txt": "text",
|
|
457
498
|
},
|
|
458
499
|
...(jsxFactory && { jsxFactory }),
|
|
459
500
|
...(jsxFragment && { jsxFragment }),
|
|
@@ -522,11 +563,12 @@ function useWorker(props: {
|
|
|
522
563
|
accountId: string;
|
|
523
564
|
apiToken: string;
|
|
524
565
|
bindings: CfWorkerInit["bindings"];
|
|
525
|
-
|
|
566
|
+
assetPaths: undefined | AssetPaths;
|
|
526
567
|
port: number;
|
|
527
568
|
compatibilityDate: string | undefined;
|
|
528
569
|
compatibilityFlags: string[] | undefined;
|
|
529
570
|
usageModel: undefined | "bundled" | "unbound";
|
|
571
|
+
env: string | undefined;
|
|
530
572
|
}): CfPreviewToken | undefined {
|
|
531
573
|
const {
|
|
532
574
|
name,
|
|
@@ -536,7 +578,7 @@ function useWorker(props: {
|
|
|
536
578
|
accountId,
|
|
537
579
|
apiToken,
|
|
538
580
|
bindings,
|
|
539
|
-
|
|
581
|
+
assetPaths,
|
|
540
582
|
compatibilityDate,
|
|
541
583
|
compatibilityFlags,
|
|
542
584
|
usageModel,
|
|
@@ -568,32 +610,34 @@ function useWorker(props: {
|
|
|
568
610
|
if (!startedRef.current) {
|
|
569
611
|
startedRef.current = true;
|
|
570
612
|
} else {
|
|
571
|
-
console.log("⎔ Detected changes,
|
|
613
|
+
console.log("⎔ Detected changes, restarted server.");
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
const assets = await syncAssets(
|
|
617
|
+
accountId,
|
|
618
|
+
name || path.basename(bundle.path),
|
|
619
|
+
assetPaths,
|
|
620
|
+
true,
|
|
621
|
+
props.env
|
|
622
|
+
); // TODO: cancellable?
|
|
623
|
+
|
|
624
|
+
const workerType = format || bundle.type === "esm" ? "esm" : "commonjs";
|
|
625
|
+
let content = await readFile(bundle.path, "utf-8");
|
|
626
|
+
if (workerType !== "esm" && assets.manifest) {
|
|
627
|
+
content = `const __STATIC_CONTENT_MANIFEST = ${JSON.stringify(
|
|
628
|
+
assets.manifest
|
|
629
|
+
)};\n${content}`;
|
|
572
630
|
}
|
|
573
631
|
|
|
574
|
-
const assets = sitesFolder
|
|
575
|
-
? await syncAssets(
|
|
576
|
-
accountId,
|
|
577
|
-
path.basename(bundle.path),
|
|
578
|
-
sitesFolder,
|
|
579
|
-
true,
|
|
580
|
-
undefined // TODO: env
|
|
581
|
-
)
|
|
582
|
-
: {
|
|
583
|
-
manifest: undefined,
|
|
584
|
-
namespace: undefined,
|
|
585
|
-
}; // TODO: cancellable?
|
|
586
|
-
|
|
587
|
-
const content = await readFile(bundle.path, "utf-8");
|
|
588
632
|
const init: CfWorkerInit = {
|
|
589
633
|
name,
|
|
590
634
|
main: {
|
|
591
635
|
name: path.basename(bundle.path),
|
|
592
|
-
type:
|
|
636
|
+
type: workerType,
|
|
593
637
|
content,
|
|
594
638
|
},
|
|
595
639
|
modules: modules.concat(
|
|
596
|
-
assets.manifest
|
|
640
|
+
assets.manifest && workerType === "esm"
|
|
597
641
|
? {
|
|
598
642
|
name: "__STATIC_CONTENT_MANIFEST",
|
|
599
643
|
content: JSON.stringify(assets.manifest),
|
|
@@ -633,12 +677,13 @@ function useWorker(props: {
|
|
|
633
677
|
accountId,
|
|
634
678
|
apiToken,
|
|
635
679
|
port,
|
|
636
|
-
|
|
680
|
+
assetPaths,
|
|
637
681
|
compatibilityDate,
|
|
638
682
|
compatibilityFlags,
|
|
639
683
|
usageModel,
|
|
640
684
|
bindings,
|
|
641
685
|
modules,
|
|
686
|
+
props.env,
|
|
642
687
|
]);
|
|
643
688
|
return token;
|
|
644
689
|
}
|
|
@@ -736,29 +781,34 @@ function useHotkeys(initial: useHotkeysInitialState, port: number) {
|
|
|
736
781
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
737
782
|
key
|
|
738
783
|
) => {
|
|
739
|
-
switch (input) {
|
|
740
|
-
|
|
784
|
+
switch (input.toLowerCase()) {
|
|
785
|
+
// open browser
|
|
786
|
+
case "b":
|
|
741
787
|
await open(`http://localhost:${port}/`);
|
|
742
788
|
break;
|
|
743
|
-
|
|
789
|
+
// toggle inspector
|
|
790
|
+
case "d":
|
|
744
791
|
await open(
|
|
745
792
|
`https://built-devtools.pages.dev/js_app?experiments=true&v8only=true&ws=localhost:9229/ws`
|
|
746
793
|
);
|
|
747
794
|
break;
|
|
748
|
-
|
|
795
|
+
// toggle tunnel
|
|
796
|
+
case "s":
|
|
749
797
|
setToggles((previousToggles) => ({
|
|
750
798
|
...previousToggles,
|
|
751
799
|
tunnel: !previousToggles.tunnel,
|
|
752
800
|
}));
|
|
753
801
|
break;
|
|
754
|
-
|
|
802
|
+
// toggle local
|
|
803
|
+
case "l":
|
|
755
804
|
setToggles((previousToggles) => ({
|
|
756
805
|
...previousToggles,
|
|
757
806
|
local: !previousToggles.local,
|
|
758
807
|
}));
|
|
759
808
|
break;
|
|
760
|
-
|
|
761
|
-
case "
|
|
809
|
+
// shut down
|
|
810
|
+
case "q":
|
|
811
|
+
case "x":
|
|
762
812
|
process.exit(0);
|
|
763
813
|
break;
|
|
764
814
|
default:
|
package/src/dialogs.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { useState } from "react";
|
|
3
1
|
import { Box, Text, useInput, render } from "ink";
|
|
4
2
|
import TextInput from "ink-text-input";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { useState } from "react";
|
|
5
5
|
type ConfirmProps = {
|
|
6
6
|
text: string;
|
|
7
7
|
onConfirm: (answer: boolean) => void;
|