wrangler 2.0.23 → 2.0.26
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 +20 -2
- package/bin/wrangler.js +1 -1
- package/miniflare-dist/index.mjs +235 -47
- package/package.json +11 -6
- package/src/__tests__/configuration.test.ts +89 -17
- package/src/__tests__/dev.test.tsx +29 -4
- package/src/__tests__/generate.test.ts +93 -0
- package/src/__tests__/helpers/mock-cfetch.ts +87 -2
- package/src/__tests__/index.test.ts +10 -27
- package/src/__tests__/init.test.ts +537 -359
- package/src/__tests__/jest.setup.ts +34 -1
- package/src/__tests__/kv.test.ts +2 -2
- package/src/__tests__/metrics.test.ts +5 -0
- package/src/__tests__/pages.test.ts +14 -0
- package/src/__tests__/publish.test.ts +497 -254
- package/src/__tests__/r2.test.ts +173 -71
- package/src/__tests__/tail.test.ts +112 -42
- package/src/__tests__/user.test.ts +1 -0
- package/src/__tests__/validate-dev-props.test.ts +56 -0
- package/src/__tests__/whoami.test.tsx +60 -1
- package/src/api/dev.ts +7 -0
- package/src/bundle.ts +279 -44
- package/src/cfetch/internal.ts +73 -2
- package/src/config/config.ts +8 -3
- package/src/config/environment.ts +40 -8
- package/src/config/index.ts +13 -0
- package/src/config/validation.ts +102 -8
- package/src/create-worker-upload-form.ts +25 -0
- package/src/dev/dev.tsx +121 -28
- package/src/dev/local.tsx +88 -14
- package/src/dev/remote.tsx +39 -8
- package/src/dev/use-esbuild.ts +28 -0
- package/src/dev/validate-dev-props.ts +31 -0
- package/src/dev-registry.tsx +160 -0
- package/src/dev.tsx +107 -80
- package/src/generate.ts +112 -14
- package/src/index.tsx +212 -4
- package/src/init.ts +111 -38
- package/src/inspect.ts +90 -5
- package/src/metrics/index.ts +1 -0
- package/src/metrics/metrics-dispatcher.ts +1 -0
- package/src/metrics/metrics-usage-headers.ts +24 -0
- package/src/metrics/send-event.ts +2 -2
- package/src/miniflare-cli/assets.ts +27 -16
- package/src/miniflare-cli/index.ts +124 -2
- package/src/module-collection.ts +3 -3
- package/src/pages/build.tsx +75 -41
- package/src/pages/constants.ts +5 -0
- package/src/pages/deployments.tsx +10 -10
- package/src/pages/dev.tsx +177 -52
- package/src/pages/errors.ts +22 -0
- package/src/pages/functions/buildPlugin.ts +4 -0
- package/src/pages/functions/buildWorker.ts +4 -0
- package/src/pages/functions/routes-consolidation.test.ts +250 -0
- package/src/pages/functions/routes-consolidation.ts +73 -0
- package/src/pages/functions/routes-transformation.test.ts +271 -0
- package/src/pages/functions/routes-transformation.ts +122 -0
- package/src/pages/functions.tsx +96 -0
- package/src/pages/index.tsx +65 -55
- package/src/pages/projects.tsx +9 -3
- package/src/pages/publish.tsx +76 -23
- package/src/pages/types.ts +9 -0
- package/src/pages/upload.tsx +38 -21
- package/src/publish.ts +126 -112
- package/src/r2.ts +81 -0
- package/src/tail/filters.ts +3 -1
- package/src/tail/index.ts +15 -2
- package/src/tail/printing.ts +43 -3
- package/src/user/user.tsx +20 -2
- package/src/whoami.tsx +79 -1
- package/src/worker.ts +12 -0
- package/templates/first-party-worker-module-facade.ts +18 -0
- package/templates/format-dev-errors.ts +32 -0
- package/templates/pages-template-plugin.ts +16 -4
- package/templates/pages-template-worker.ts +16 -5
- package/templates/{static-asset-facade.js → serve-static-assets.ts} +21 -7
- package/templates/service-bindings-module-facade.js +54 -0
- package/templates/service-bindings-sw-facade.js +42 -0
- package/wrangler-dist/cli.d.ts +7 -0
- package/wrangler-dist/cli.js +40851 -15332
|
@@ -217,6 +217,11 @@ interface EnvironmentInheritable {
|
|
|
217
217
|
namespace: string;
|
|
218
218
|
}[];
|
|
219
219
|
|
|
220
|
+
/**
|
|
221
|
+
* Designates this worker as an internal-only "first-party" worker.
|
|
222
|
+
*/
|
|
223
|
+
first_party_worker: boolean | undefined;
|
|
224
|
+
|
|
220
225
|
/**
|
|
221
226
|
* TODO: remove this as it has been deprecated.
|
|
222
227
|
*
|
|
@@ -224,6 +229,24 @@ interface EnvironmentInheritable {
|
|
|
224
229
|
* So we need to include it in this type so it is available.
|
|
225
230
|
*/
|
|
226
231
|
zone_id?: string;
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Specify a compiled capnp schema to use
|
|
235
|
+
* Then add a binding per field in the top level message that you will send to logfwdr
|
|
236
|
+
*
|
|
237
|
+
* @default `{schema:undefined,bindings:[]}`
|
|
238
|
+
* @inheritable
|
|
239
|
+
*/
|
|
240
|
+
logfwdr: {
|
|
241
|
+
/** capnp schema filename */
|
|
242
|
+
schema: string | undefined;
|
|
243
|
+
bindings: {
|
|
244
|
+
/** The binding name used to refer to logfwdr */
|
|
245
|
+
name: string;
|
|
246
|
+
/** The destination for this logged message */
|
|
247
|
+
destination: string;
|
|
248
|
+
}[];
|
|
249
|
+
};
|
|
227
250
|
}
|
|
228
251
|
|
|
229
252
|
/**
|
|
@@ -329,14 +352,16 @@ interface EnvironmentNonInheritable {
|
|
|
329
352
|
* @default `[]`
|
|
330
353
|
* @nonInheritable
|
|
331
354
|
*/
|
|
332
|
-
services:
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
355
|
+
services:
|
|
356
|
+
| {
|
|
357
|
+
/** The binding name used to refer to the bound service. */
|
|
358
|
+
binding: string;
|
|
359
|
+
/** The name of the service. */
|
|
360
|
+
service: string;
|
|
361
|
+
/** The environment of the service (e.g. production, staging, etc). */
|
|
362
|
+
environment?: string;
|
|
363
|
+
}[]
|
|
364
|
+
| undefined;
|
|
340
365
|
|
|
341
366
|
/**
|
|
342
367
|
* "Unsafe" tables for features that aren't directly supported by wrangler.
|
|
@@ -375,6 +400,13 @@ interface EnvironmentDeprecated {
|
|
|
375
400
|
*/
|
|
376
401
|
zone_id?: string;
|
|
377
402
|
|
|
403
|
+
/**
|
|
404
|
+
* Legacy way of defining KVNamespaces that is no longer supported.
|
|
405
|
+
*
|
|
406
|
+
* @deprecated DO NOT USE. This was a legacy bug from wrangler 1, that we do not want to support.
|
|
407
|
+
*/
|
|
408
|
+
"kv-namespaces"?: string;
|
|
409
|
+
|
|
378
410
|
/**
|
|
379
411
|
* A list of services that your worker should be bound to.
|
|
380
412
|
*
|
package/src/config/index.ts
CHANGED
|
@@ -85,6 +85,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {
|
|
|
85
85
|
durable_objects,
|
|
86
86
|
kv_namespaces,
|
|
87
87
|
r2_buckets,
|
|
88
|
+
logfwdr,
|
|
88
89
|
services,
|
|
89
90
|
text_blobs,
|
|
90
91
|
unsafe,
|
|
@@ -149,6 +150,18 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {
|
|
|
149
150
|
});
|
|
150
151
|
}
|
|
151
152
|
|
|
153
|
+
if (logfwdr !== undefined && logfwdr.bindings.length > 0) {
|
|
154
|
+
output.push({
|
|
155
|
+
type: "logfwdr",
|
|
156
|
+
entries: logfwdr.bindings.map((binding) => {
|
|
157
|
+
return {
|
|
158
|
+
key: binding.name,
|
|
159
|
+
value: binding.destination,
|
|
160
|
+
};
|
|
161
|
+
}),
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
152
165
|
if (services !== undefined && services.length > 0) {
|
|
153
166
|
output.push({
|
|
154
167
|
type: "Services",
|
package/src/config/validation.ts
CHANGED
|
@@ -357,7 +357,7 @@ function normalizeAndValidateDev(
|
|
|
357
357
|
rawDev: RawDevConfig
|
|
358
358
|
): DevConfig {
|
|
359
359
|
const {
|
|
360
|
-
ip = "
|
|
360
|
+
ip = "0.0.0.0",
|
|
361
361
|
port,
|
|
362
362
|
inspector_port,
|
|
363
363
|
local_protocol = "http",
|
|
@@ -598,25 +598,68 @@ function normalizeAndValidateAssets(
|
|
|
598
598
|
diagnostics: Diagnostics,
|
|
599
599
|
configPath: string | undefined,
|
|
600
600
|
rawConfig: RawConfig
|
|
601
|
-
) {
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
) {
|
|
606
|
-
return
|
|
601
|
+
): Config["assets"] {
|
|
602
|
+
// Even though the type doesn't say it,
|
|
603
|
+
// we allow for a string input in the config,
|
|
604
|
+
// so let's normalise it
|
|
605
|
+
if (typeof rawConfig?.assets === "string") {
|
|
606
|
+
return {
|
|
607
|
+
bucket: rawConfig.assets,
|
|
608
|
+
include: [],
|
|
609
|
+
exclude: [],
|
|
610
|
+
browser_TTL: undefined,
|
|
611
|
+
serve_single_page_app: false,
|
|
612
|
+
};
|
|
607
613
|
}
|
|
608
614
|
|
|
609
|
-
|
|
615
|
+
if (rawConfig?.assets === undefined) {
|
|
616
|
+
return undefined;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
if (typeof rawConfig.assets !== "object") {
|
|
620
|
+
diagnostics.errors.push(
|
|
621
|
+
`Expected the \`assets\` field to be a string or an object, but got ${typeof rawConfig.assets}.`
|
|
622
|
+
);
|
|
623
|
+
return undefined;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
const {
|
|
627
|
+
bucket,
|
|
628
|
+
include = [],
|
|
629
|
+
exclude = [],
|
|
630
|
+
browser_TTL,
|
|
631
|
+
serve_single_page_app,
|
|
632
|
+
...rest
|
|
633
|
+
} = rawConfig.assets;
|
|
610
634
|
|
|
611
635
|
validateAdditionalProperties(diagnostics, "assets", Object.keys(rest), []);
|
|
636
|
+
|
|
612
637
|
validateRequiredProperty(diagnostics, "assets", "bucket", bucket, "string");
|
|
613
638
|
validateTypedArray(diagnostics, "assets.include", include, "string");
|
|
614
639
|
validateTypedArray(diagnostics, "assets.exclude", exclude, "string");
|
|
615
640
|
|
|
641
|
+
validateOptionalProperty(
|
|
642
|
+
diagnostics,
|
|
643
|
+
"assets",
|
|
644
|
+
"browser_TTL",
|
|
645
|
+
browser_TTL,
|
|
646
|
+
"number"
|
|
647
|
+
);
|
|
648
|
+
|
|
649
|
+
validateOptionalProperty(
|
|
650
|
+
diagnostics,
|
|
651
|
+
"assets",
|
|
652
|
+
"serve_single_page_app",
|
|
653
|
+
serve_single_page_app,
|
|
654
|
+
"boolean"
|
|
655
|
+
);
|
|
656
|
+
|
|
616
657
|
return {
|
|
617
658
|
bucket,
|
|
618
659
|
include,
|
|
619
660
|
exclude,
|
|
661
|
+
browser_TTL,
|
|
662
|
+
serve_single_page_app,
|
|
620
663
|
};
|
|
621
664
|
}
|
|
622
665
|
|
|
@@ -830,6 +873,13 @@ function normalizeAndValidateEnvironment(
|
|
|
830
873
|
isLegacyEnv?: boolean,
|
|
831
874
|
rawConfig?: RawConfig | undefined
|
|
832
875
|
): Environment {
|
|
876
|
+
deprecated(
|
|
877
|
+
diagnostics,
|
|
878
|
+
rawEnv,
|
|
879
|
+
"kv-namespaces",
|
|
880
|
+
`The "kv-namespaces" field is no longer supported, please rename to "kv_namespaces"`,
|
|
881
|
+
true
|
|
882
|
+
);
|
|
833
883
|
deprecated(
|
|
834
884
|
diagnostics,
|
|
835
885
|
rawEnv,
|
|
@@ -1045,6 +1095,17 @@ function normalizeAndValidateEnvironment(
|
|
|
1045
1095
|
validateBindingArray(envName, validateWorkerNamespaceBinding),
|
|
1046
1096
|
[]
|
|
1047
1097
|
),
|
|
1098
|
+
logfwdr: inheritable(
|
|
1099
|
+
diagnostics,
|
|
1100
|
+
topLevelEnv,
|
|
1101
|
+
rawEnv,
|
|
1102
|
+
"logfwdr",
|
|
1103
|
+
validateBindingsProperty(envName, validateCflogfwdrBinding),
|
|
1104
|
+
{
|
|
1105
|
+
schema: undefined,
|
|
1106
|
+
bindings: [],
|
|
1107
|
+
}
|
|
1108
|
+
),
|
|
1048
1109
|
unsafe: notInheritable(
|
|
1049
1110
|
diagnostics,
|
|
1050
1111
|
topLevelEnv,
|
|
@@ -1082,6 +1143,14 @@ function normalizeAndValidateEnvironment(
|
|
|
1082
1143
|
isBoolean,
|
|
1083
1144
|
undefined
|
|
1084
1145
|
),
|
|
1146
|
+
first_party_worker: inheritable(
|
|
1147
|
+
diagnostics,
|
|
1148
|
+
topLevelEnv,
|
|
1149
|
+
rawEnv,
|
|
1150
|
+
"first_party_worker",
|
|
1151
|
+
isBoolean,
|
|
1152
|
+
undefined
|
|
1153
|
+
),
|
|
1085
1154
|
};
|
|
1086
1155
|
|
|
1087
1156
|
return environment;
|
|
@@ -1418,6 +1487,30 @@ const validateDurableObjectBinding: ValidatorFn = (
|
|
|
1418
1487
|
return isValid;
|
|
1419
1488
|
};
|
|
1420
1489
|
|
|
1490
|
+
const validateCflogfwdrBinding: ValidatorFn = (diagnostics, field, value) => {
|
|
1491
|
+
if (typeof value !== "object" || value === null) {
|
|
1492
|
+
diagnostics.errors.push(
|
|
1493
|
+
`Expected "${field}" to be an object but got ${JSON.stringify(value)}`
|
|
1494
|
+
);
|
|
1495
|
+
return false;
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
let isValid = true;
|
|
1499
|
+
if (!isRequiredProperty(value, "name", "string")) {
|
|
1500
|
+
diagnostics.errors.push(`binding should have a string "name" field.`);
|
|
1501
|
+
isValid = false;
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
if (!isRequiredProperty(value, "destination", "string")) {
|
|
1505
|
+
diagnostics.errors.push(
|
|
1506
|
+
`binding should have a string "destination" field.`
|
|
1507
|
+
);
|
|
1508
|
+
isValid = false;
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
return isValid;
|
|
1512
|
+
};
|
|
1513
|
+
|
|
1421
1514
|
/**
|
|
1422
1515
|
* Check that the given field is a valid "unsafe" binding object.
|
|
1423
1516
|
*
|
|
@@ -1448,6 +1541,7 @@ const validateUnsafeBinding: ValidatorFn = (diagnostics, field, value) => {
|
|
|
1448
1541
|
"durable_object_namespace",
|
|
1449
1542
|
"r2_bucket",
|
|
1450
1543
|
"service",
|
|
1544
|
+
"logfwdr",
|
|
1451
1545
|
];
|
|
1452
1546
|
|
|
1453
1547
|
if (safeBindings.includes(value.type)) {
|
|
@@ -32,6 +32,7 @@ export interface WorkerMetadata {
|
|
|
32
32
|
compatibility_flags?: string[];
|
|
33
33
|
usage_model?: "bundled" | "unbound";
|
|
34
34
|
migrations?: CfDurableObjectMigrations;
|
|
35
|
+
capnp_schema?: string;
|
|
35
36
|
// If you add any new binding types here, also add it to safeBindings
|
|
36
37
|
// under validateUnsafeBinding in config/validation.ts
|
|
37
38
|
bindings: (
|
|
@@ -51,6 +52,11 @@ export interface WorkerMetadata {
|
|
|
51
52
|
| { type: "r2_bucket"; name: string; bucket_name: string }
|
|
52
53
|
| { type: "service"; name: string; service: string; environment?: string }
|
|
53
54
|
| { type: "namespace"; name: string; namespace: string }
|
|
55
|
+
| {
|
|
56
|
+
type: "logfwdr";
|
|
57
|
+
name: string;
|
|
58
|
+
destination: string;
|
|
59
|
+
}
|
|
54
60
|
)[];
|
|
55
61
|
}
|
|
56
62
|
|
|
@@ -125,6 +131,14 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
|
|
|
125
131
|
});
|
|
126
132
|
});
|
|
127
133
|
|
|
134
|
+
bindings.logfwdr?.bindings.forEach(({ name, destination }) => {
|
|
135
|
+
metadataBindings.push({
|
|
136
|
+
name: name,
|
|
137
|
+
type: "logfwdr",
|
|
138
|
+
destination,
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
128
142
|
for (const [name, filePath] of Object.entries(bindings.wasm_modules || {})) {
|
|
129
143
|
metadataBindings.push({
|
|
130
144
|
name,
|
|
@@ -240,6 +254,7 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
|
|
|
240
254
|
...(compatibility_flags && { compatibility_flags }),
|
|
241
255
|
...(usage_model && { usage_model }),
|
|
242
256
|
...(migrations && { migrations }),
|
|
257
|
+
capnp_schema: bindings.logfwdr?.schema,
|
|
243
258
|
};
|
|
244
259
|
|
|
245
260
|
formData.set("metadata", JSON.stringify(metadata));
|
|
@@ -259,5 +274,15 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
|
|
|
259
274
|
);
|
|
260
275
|
}
|
|
261
276
|
|
|
277
|
+
if (bindings.logfwdr && bindings.logfwdr.schema) {
|
|
278
|
+
const filePath = bindings.logfwdr.schema;
|
|
279
|
+
formData.set(
|
|
280
|
+
filePath,
|
|
281
|
+
new File([readFileSync(filePath)], filePath, {
|
|
282
|
+
type: "application/octet-stream",
|
|
283
|
+
})
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
|
|
262
287
|
return formData;
|
|
263
288
|
}
|
package/src/dev/dev.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
+
import * as util from "node:util";
|
|
3
4
|
import { watch } from "chokidar";
|
|
4
5
|
import clipboardy from "clipboardy";
|
|
5
6
|
import commandExists from "command-exists";
|
|
@@ -9,6 +10,12 @@ import { withErrorBoundary, useErrorHandler } from "react-error-boundary";
|
|
|
9
10
|
import onExit from "signal-exit";
|
|
10
11
|
import tmp from "tmp-promise";
|
|
11
12
|
import { fetch } from "undici";
|
|
13
|
+
import {
|
|
14
|
+
getRegisteredWorkers,
|
|
15
|
+
startWorkerRegistry,
|
|
16
|
+
stopWorkerRegistry,
|
|
17
|
+
unregisterWorker,
|
|
18
|
+
} from "../dev-registry";
|
|
12
19
|
import { runCustomBuild } from "../entry";
|
|
13
20
|
import { openInspector } from "../inspect";
|
|
14
21
|
import { logger } from "../logger";
|
|
@@ -16,13 +23,103 @@ import openInBrowser from "../open-in-browser";
|
|
|
16
23
|
import { Local } from "./local";
|
|
17
24
|
import { Remote } from "./remote";
|
|
18
25
|
import { useEsbuild } from "./use-esbuild";
|
|
26
|
+
import { validateDevProps } from "./validate-dev-props";
|
|
19
27
|
import type { Config } from "../config";
|
|
20
28
|
import type { Route } from "../config/environment";
|
|
29
|
+
import type { WorkerRegistry } from "../dev-registry";
|
|
21
30
|
import type { Entry } from "../entry";
|
|
22
31
|
import type { EnablePagesAssetsServiceBindingOptions } from "../miniflare-cli";
|
|
23
32
|
import type { AssetPaths } from "../sites";
|
|
24
33
|
import type { CfWorkerInit } from "../worker";
|
|
25
34
|
|
|
35
|
+
/**
|
|
36
|
+
* This hooks establishes a connection with the dev registry,
|
|
37
|
+
* and periodically updates itself with details of workers currently
|
|
38
|
+
* running a dev session on this system.
|
|
39
|
+
*/
|
|
40
|
+
function useDevRegistry(
|
|
41
|
+
name: string | undefined,
|
|
42
|
+
services: Config["services"] | undefined,
|
|
43
|
+
durableObjects: Config["durable_objects"] | undefined,
|
|
44
|
+
mode: "local" | "remote"
|
|
45
|
+
): WorkerRegistry {
|
|
46
|
+
const [workers, setWorkers] = useState<WorkerRegistry>({});
|
|
47
|
+
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
// Let's try to start registry
|
|
50
|
+
// TODO: we should probably call this in a loop
|
|
51
|
+
// in case the registry dies elsewhere
|
|
52
|
+
startWorkerRegistry().catch((err) => {
|
|
53
|
+
logger.error("failed to start worker registry", err);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const serviceNames = (services || []).map(
|
|
57
|
+
(serviceBinding) => serviceBinding.service
|
|
58
|
+
);
|
|
59
|
+
const durableObjectServices = (
|
|
60
|
+
durableObjects || { bindings: [] }
|
|
61
|
+
).bindings.map((durableObjectBinding) => durableObjectBinding.script_name);
|
|
62
|
+
|
|
63
|
+
const interval =
|
|
64
|
+
// TODO: enable this for remote mode as well
|
|
65
|
+
// https://github.com/cloudflare/wrangler2/issues/1182
|
|
66
|
+
mode === "local"
|
|
67
|
+
? setInterval(() => {
|
|
68
|
+
getRegisteredWorkers().then(
|
|
69
|
+
(workerDefinitions: WorkerRegistry | undefined) => {
|
|
70
|
+
// We only want the workers that we're bound to
|
|
71
|
+
// so let's filter out the others
|
|
72
|
+
const filteredWorkers = Object.fromEntries(
|
|
73
|
+
Object.entries(workerDefinitions || {}).filter(
|
|
74
|
+
([key, _value]) =>
|
|
75
|
+
serviceNames.includes(key) ||
|
|
76
|
+
durableObjectServices.includes(key)
|
|
77
|
+
)
|
|
78
|
+
);
|
|
79
|
+
setWorkers((prevWorkers) => {
|
|
80
|
+
if (!util.isDeepStrictEqual(filteredWorkers, prevWorkers)) {
|
|
81
|
+
return filteredWorkers;
|
|
82
|
+
}
|
|
83
|
+
return prevWorkers;
|
|
84
|
+
});
|
|
85
|
+
},
|
|
86
|
+
(err) => {
|
|
87
|
+
logger.warn("Failed to get worker definitions", err);
|
|
88
|
+
}
|
|
89
|
+
);
|
|
90
|
+
}, 300)
|
|
91
|
+
: undefined;
|
|
92
|
+
|
|
93
|
+
return () => {
|
|
94
|
+
interval && clearInterval(interval);
|
|
95
|
+
Promise.allSettled([
|
|
96
|
+
name ? unregisterWorker(name) : Promise.resolve(),
|
|
97
|
+
stopWorkerRegistry(),
|
|
98
|
+
]).then(
|
|
99
|
+
([unregisterResult, stopRegistryResult]) => {
|
|
100
|
+
if (unregisterResult.status === "rejected") {
|
|
101
|
+
logger.error(
|
|
102
|
+
"Failed to unregister worker",
|
|
103
|
+
unregisterResult.reason
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
if (stopRegistryResult.status === "rejected") {
|
|
107
|
+
logger.error(
|
|
108
|
+
"Failed to stop worker registry",
|
|
109
|
+
stopRegistryResult.reason
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
(err) => {
|
|
114
|
+
logger.error("Failed to clear dev registry effect", err);
|
|
115
|
+
}
|
|
116
|
+
);
|
|
117
|
+
};
|
|
118
|
+
}, [name, services, durableObjects, mode]);
|
|
119
|
+
|
|
120
|
+
return workers;
|
|
121
|
+
}
|
|
122
|
+
|
|
26
123
|
export type DevProps = {
|
|
27
124
|
name: string | undefined;
|
|
28
125
|
noBundle: boolean;
|
|
@@ -46,6 +143,7 @@ export type DevProps = {
|
|
|
46
143
|
crons: Config["triggers"]["crons"];
|
|
47
144
|
isWorkersSite: boolean;
|
|
48
145
|
assetPaths: AssetPaths | undefined;
|
|
146
|
+
assetsConfig: Config["assets"];
|
|
49
147
|
compatibilityDate: string;
|
|
50
148
|
compatibilityFlags: string[] | undefined;
|
|
51
149
|
usageModel: "bundled" | "unbound" | undefined;
|
|
@@ -64,36 +162,12 @@ export type DevProps = {
|
|
|
64
162
|
showInteractiveDevSession: boolean | undefined;
|
|
65
163
|
forceLocal: boolean | undefined;
|
|
66
164
|
enablePagesAssetsServiceBinding?: EnablePagesAssetsServiceBindingOptions;
|
|
165
|
+
firstPartyWorker: boolean | undefined;
|
|
166
|
+
sendMetrics: boolean | undefined;
|
|
67
167
|
};
|
|
68
168
|
|
|
69
169
|
export function DevImplementation(props: DevProps): JSX.Element {
|
|
70
|
-
|
|
71
|
-
!props.isWorkersSite &&
|
|
72
|
-
props.assetPaths &&
|
|
73
|
-
props.entry.format === "service-worker"
|
|
74
|
-
) {
|
|
75
|
-
throw new Error(
|
|
76
|
-
"You cannot use the service-worker format with an `assets` directory yet. For information on how to migrate to the module-worker format, see: https://developers.cloudflare.com/workers/learning/migrating-to-module-workers/"
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (props.bindings.wasm_modules && props.entry.format === "modules") {
|
|
81
|
-
throw new Error(
|
|
82
|
-
"You cannot configure [wasm_modules] with an ES module worker. Instead, import the .wasm module directly in your code"
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (props.bindings.text_blobs && props.entry.format === "modules") {
|
|
87
|
-
throw new Error(
|
|
88
|
-
"You cannot configure [text_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure `[rules]` in your wrangler.toml"
|
|
89
|
-
);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (props.bindings.data_blobs && props.entry.format === "modules") {
|
|
93
|
-
throw new Error(
|
|
94
|
-
"You cannot configure [data_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure `[rules]` in your wrangler.toml"
|
|
95
|
-
);
|
|
96
|
-
}
|
|
170
|
+
validateDevProps(props);
|
|
97
171
|
|
|
98
172
|
// only load the UI if we're running in a supported environment
|
|
99
173
|
const { isRawModeSupported } = useStdin();
|
|
@@ -157,6 +231,13 @@ function DevSession(props: DevSessionProps) {
|
|
|
157
231
|
|
|
158
232
|
const directory = useTmpDir();
|
|
159
233
|
|
|
234
|
+
const workerDefinitions = useDevRegistry(
|
|
235
|
+
props.name,
|
|
236
|
+
props.bindings.services,
|
|
237
|
+
props.bindings.durable_objects,
|
|
238
|
+
props.local ? "local" : "remote"
|
|
239
|
+
);
|
|
240
|
+
|
|
160
241
|
const bundle = useEsbuild({
|
|
161
242
|
entry: props.entry,
|
|
162
243
|
destination: directory,
|
|
@@ -171,6 +252,11 @@ function DevSession(props: DevSessionProps) {
|
|
|
171
252
|
nodeCompat: props.nodeCompat,
|
|
172
253
|
define: props.define,
|
|
173
254
|
noBundle: props.noBundle,
|
|
255
|
+
assets: props.assetsConfig,
|
|
256
|
+
workerDefinitions,
|
|
257
|
+
services: props.bindings.services,
|
|
258
|
+
durableObjects: props.bindings.durable_objects || { bindings: [] },
|
|
259
|
+
firstPartyWorkerDevFacade: props.firstPartyWorker,
|
|
174
260
|
});
|
|
175
261
|
|
|
176
262
|
return props.local ? (
|
|
@@ -180,9 +266,10 @@ function DevSession(props: DevSessionProps) {
|
|
|
180
266
|
format={props.entry.format}
|
|
181
267
|
compatibilityDate={props.compatibilityDate}
|
|
182
268
|
compatibilityFlags={props.compatibilityFlags}
|
|
269
|
+
usageModel={props.usageModel}
|
|
183
270
|
bindings={props.bindings}
|
|
271
|
+
workerDefinitions={workerDefinitions}
|
|
184
272
|
assetPaths={props.assetPaths}
|
|
185
|
-
isWorkersSite={props.isWorkersSite}
|
|
186
273
|
port={props.port}
|
|
187
274
|
ip={props.ip}
|
|
188
275
|
rules={props.rules}
|
|
@@ -223,6 +310,8 @@ function DevSession(props: DevSessionProps) {
|
|
|
223
310
|
host={props.host}
|
|
224
311
|
routes={props.routes}
|
|
225
312
|
onReady={props.onReady}
|
|
313
|
+
sourceMapPath={bundle?.sourceMapPath}
|
|
314
|
+
sendMetrics={props.sendMetrics}
|
|
226
315
|
/>
|
|
227
316
|
);
|
|
228
317
|
}
|
|
@@ -404,6 +493,10 @@ function useHotkeys(props: {
|
|
|
404
493
|
break;
|
|
405
494
|
// open browser
|
|
406
495
|
case "b": {
|
|
496
|
+
if (ip === "0.0.0.0") {
|
|
497
|
+
await openInBrowser(`${localProtocol}://127.0.0.1:${port}`);
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
407
500
|
await openInBrowser(`${localProtocol}://${ip}:${port}`);
|
|
408
501
|
break;
|
|
409
502
|
}
|