wrangler 0.0.0-e2f9bb2 → 0.0.0-e322475
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/Cloudflare_CA.pem +18 -0
- package/README.md +3 -1
- package/bin/wrangler.js +36 -4
- package/kv-asset-handler.js +1 -0
- package/package.json +15 -7
- package/pages/functions/buildPlugin.ts +13 -0
- package/pages/functions/buildWorker.ts +14 -1
- package/pages/functions/template-plugin.ts +3 -2
- package/src/__tests__/configuration.test.ts +652 -229
- package/src/__tests__/dev.test.tsx +372 -79
- package/src/__tests__/helpers/mock-cfetch.ts +2 -2
- package/src/__tests__/helpers/mock-console.ts +11 -1
- package/src/__tests__/helpers/mock-dialogs.ts +75 -11
- package/src/__tests__/helpers/mock-process.ts +24 -0
- package/src/__tests__/index.test.ts +81 -72
- package/src/__tests__/init.test.ts +1360 -410
- package/src/__tests__/jest.setup.ts +38 -0
- package/src/__tests__/kv.test.ts +218 -152
- package/src/__tests__/logger.test.ts +26 -0
- package/src/__tests__/package-manager.test.ts +154 -7
- package/src/__tests__/pages.test.ts +478 -53
- package/src/__tests__/parse.test.ts +8 -0
- package/src/__tests__/publish.test.ts +1614 -333
- package/src/__tests__/r2.test.ts +55 -36
- package/src/__tests__/secret.test.ts +39 -4
- package/src/__tests__/user.test.ts +1 -0
- package/src/__tests__/whoami.test.tsx +34 -0
- package/src/abort.d.ts +3 -0
- package/src/bundle-reporter.tsx +29 -0
- package/src/bundle.ts +42 -7
- package/src/cfetch/index.ts +21 -4
- package/src/cfetch/internal.ts +25 -20
- package/src/config/config.ts +11 -2
- package/src/config/environment.ts +41 -15
- package/src/config/index.ts +162 -0
- package/src/config/validation-helpers.ts +10 -1
- package/src/config/validation.ts +234 -78
- package/src/create-worker-preview.ts +32 -22
- package/src/create-worker-upload-form.ts +22 -8
- package/src/dev/dev.tsx +48 -67
- package/src/dev/local.tsx +16 -7
- package/src/dev/remote.tsx +57 -21
- package/src/dev/use-esbuild.ts +1 -7
- package/src/dialogs.tsx +48 -0
- package/src/durable.ts +102 -0
- package/src/entry.ts +71 -10
- package/src/generate-auth-url.ts +33 -0
- package/src/generate-random-state.ts +16 -0
- package/src/git-client.ts +42 -0
- package/src/index.tsx +619 -338
- package/src/inspect.ts +39 -0
- package/src/kv.ts +116 -27
- package/src/logger.ts +8 -1
- package/src/open-in-browser.ts +3 -12
- package/src/package-manager.ts +50 -3
- package/src/pages.tsx +434 -207
- package/src/parse.ts +44 -5
- package/src/proxy.ts +66 -44
- package/src/publish.ts +407 -137
- package/src/sites.tsx +103 -28
- package/src/user.tsx +35 -26
- package/src/whoami.tsx +3 -2
- package/src/worker.ts +10 -1
- package/src/zones.ts +73 -0
- package/templates/new-worker-scheduled.js +17 -0
- package/templates/new-worker-scheduled.ts +32 -0
- package/templates/new-worker.ts +16 -1
- package/templates/no-op-worker.js +10 -0
- package/templates/static-asset-facade.js +2 -6
- package/wrangler-dist/cli.js +46122 -32396
- 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/src/config/validation.ts
CHANGED
|
@@ -94,22 +94,6 @@ export function normalizeAndValidateConfig(
|
|
|
94
94
|
"boolean"
|
|
95
95
|
);
|
|
96
96
|
|
|
97
|
-
validateOptionalProperty(
|
|
98
|
-
diagnostics,
|
|
99
|
-
"",
|
|
100
|
-
"minify",
|
|
101
|
-
rawConfig.minify,
|
|
102
|
-
"boolean"
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
validateOptionalProperty(
|
|
106
|
-
diagnostics,
|
|
107
|
-
"",
|
|
108
|
-
"node_compat",
|
|
109
|
-
rawConfig.node_compat,
|
|
110
|
-
"boolean"
|
|
111
|
-
);
|
|
112
|
-
|
|
113
97
|
// TODO: set the default to false to turn on service environments as the default
|
|
114
98
|
const isLegacyEnv =
|
|
115
99
|
(args as { "legacy-env": boolean | undefined })["legacy-env"] ??
|
|
@@ -193,7 +177,8 @@ export function normalizeAndValidateConfig(
|
|
|
193
177
|
dev: normalizeAndValidateDev(diagnostics, rawConfig.dev ?? {}),
|
|
194
178
|
migrations: normalizeAndValidateMigrations(
|
|
195
179
|
diagnostics,
|
|
196
|
-
rawConfig.migrations ?? []
|
|
180
|
+
rawConfig.migrations ?? [],
|
|
181
|
+
activeEnv.durable_objects
|
|
197
182
|
),
|
|
198
183
|
site: normalizeAndValidateSite(
|
|
199
184
|
diagnostics,
|
|
@@ -201,6 +186,7 @@ export function normalizeAndValidateConfig(
|
|
|
201
186
|
rawConfig,
|
|
202
187
|
activeEnv.main
|
|
203
188
|
),
|
|
189
|
+
assets: normalizeAndValidateAssets(diagnostics, configPath, rawConfig),
|
|
204
190
|
wasm_modules: normalizeAndValidateModulePaths(
|
|
205
191
|
diagnostics,
|
|
206
192
|
configPath,
|
|
@@ -230,6 +216,8 @@ export function normalizeAndValidateConfig(
|
|
|
230
216
|
[...Object.keys(config), "env"]
|
|
231
217
|
);
|
|
232
218
|
|
|
219
|
+
experimental(diagnostics, rawConfig, "assets");
|
|
220
|
+
|
|
233
221
|
return { config, diagnostics };
|
|
234
222
|
}
|
|
235
223
|
|
|
@@ -242,19 +230,23 @@ function normalizeAndValidateBuild(
|
|
|
242
230
|
rawBuild: Config["build"],
|
|
243
231
|
configPath: string | undefined
|
|
244
232
|
): Config["build"] & { deprecatedUpload: DeprecatedUpload } {
|
|
245
|
-
const { command, cwd, watch_dir, upload, ...rest } = rawBuild;
|
|
233
|
+
const { command, cwd, watch_dir = "./src", upload, ...rest } = rawBuild;
|
|
246
234
|
const deprecatedUpload: DeprecatedUpload = { ...upload };
|
|
247
235
|
validateAdditionalProperties(diagnostics, "build", Object.keys(rest), []);
|
|
248
236
|
|
|
249
237
|
validateOptionalProperty(diagnostics, "build", "command", command, "string");
|
|
250
238
|
validateOptionalProperty(diagnostics, "build", "cwd", cwd, "string");
|
|
251
|
-
|
|
252
|
-
diagnostics,
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
239
|
+
if (Array.isArray(watch_dir)) {
|
|
240
|
+
validateTypedArray(diagnostics, "build.watch_dir", watch_dir, "string");
|
|
241
|
+
} else {
|
|
242
|
+
validateOptionalProperty(
|
|
243
|
+
diagnostics,
|
|
244
|
+
"build",
|
|
245
|
+
"watch_dir",
|
|
246
|
+
watch_dir,
|
|
247
|
+
"string"
|
|
248
|
+
);
|
|
249
|
+
}
|
|
258
250
|
|
|
259
251
|
deprecated(
|
|
260
252
|
diagnostics,
|
|
@@ -303,13 +295,18 @@ function normalizeAndValidateBuild(
|
|
|
303
295
|
// - `configPath` will always be defined since `build` can only
|
|
304
296
|
// be configured in `wrangler.toml`, but who knows, that may
|
|
305
297
|
// change in the future, so we do a check anyway
|
|
306
|
-
command
|
|
307
|
-
?
|
|
308
|
-
?
|
|
298
|
+
command && configPath
|
|
299
|
+
? Array.isArray(watch_dir)
|
|
300
|
+
? watch_dir.map((dir) =>
|
|
301
|
+
path.relative(
|
|
302
|
+
process.cwd(),
|
|
303
|
+
path.join(path.dirname(configPath), `${dir}`)
|
|
304
|
+
)
|
|
305
|
+
)
|
|
306
|
+
: path.relative(
|
|
309
307
|
process.cwd(),
|
|
310
|
-
path.join(path.dirname(configPath), watch_dir
|
|
308
|
+
path.join(path.dirname(configPath), `${watch_dir}`)
|
|
311
309
|
)
|
|
312
|
-
: watch_dir || "./src"
|
|
313
310
|
: watch_dir,
|
|
314
311
|
cwd,
|
|
315
312
|
deprecatedUpload,
|
|
@@ -352,7 +349,7 @@ function normalizeAndValidateDev(
|
|
|
352
349
|
): DevConfig {
|
|
353
350
|
const {
|
|
354
351
|
ip = "localhost",
|
|
355
|
-
port
|
|
352
|
+
port,
|
|
356
353
|
local_protocol = "http",
|
|
357
354
|
upstream_protocol = "https",
|
|
358
355
|
host,
|
|
@@ -387,7 +384,8 @@ function normalizeAndValidateDev(
|
|
|
387
384
|
*/
|
|
388
385
|
function normalizeAndValidateMigrations(
|
|
389
386
|
diagnostics: Diagnostics,
|
|
390
|
-
rawMigrations: Config["migrations"]
|
|
387
|
+
rawMigrations: Config["migrations"],
|
|
388
|
+
durableObjects: Config["durable_objects"]
|
|
391
389
|
): Config["migrations"] {
|
|
392
390
|
if (!Array.isArray(rawMigrations)) {
|
|
393
391
|
diagnostics.errors.push(
|
|
@@ -398,29 +396,38 @@ function normalizeAndValidateMigrations(
|
|
|
398
396
|
return [];
|
|
399
397
|
} else {
|
|
400
398
|
for (let i = 0; i < rawMigrations.length; i++) {
|
|
401
|
-
const
|
|
399
|
+
const { tag, new_classes, renamed_classes, deleted_classes, ...rest } =
|
|
400
|
+
rawMigrations[i];
|
|
401
|
+
|
|
402
|
+
validateAdditionalProperties(
|
|
403
|
+
diagnostics,
|
|
404
|
+
"migrations",
|
|
405
|
+
Object.keys(rest),
|
|
406
|
+
[]
|
|
407
|
+
);
|
|
408
|
+
|
|
402
409
|
validateRequiredProperty(
|
|
403
410
|
diagnostics,
|
|
404
411
|
`migrations[${i}]`,
|
|
405
412
|
`tag`,
|
|
406
|
-
|
|
413
|
+
tag,
|
|
407
414
|
"string"
|
|
408
415
|
);
|
|
409
416
|
validateOptionalTypedArray(
|
|
410
417
|
diagnostics,
|
|
411
418
|
`migrations[${i}].new_classes`,
|
|
412
|
-
|
|
419
|
+
new_classes,
|
|
413
420
|
"string"
|
|
414
421
|
);
|
|
415
|
-
if (
|
|
416
|
-
if (!Array.isArray(
|
|
422
|
+
if (renamed_classes !== undefined) {
|
|
423
|
+
if (!Array.isArray(renamed_classes)) {
|
|
417
424
|
diagnostics.errors.push(
|
|
418
425
|
`Expected "migrations[${i}].renamed_classes" to be an array of "{from: string, to: string}" objects but got ${JSON.stringify(
|
|
419
|
-
|
|
426
|
+
renamed_classes
|
|
420
427
|
)}.`
|
|
421
428
|
);
|
|
422
429
|
} else if (
|
|
423
|
-
|
|
430
|
+
renamed_classes.some(
|
|
424
431
|
(c) =>
|
|
425
432
|
typeof c !== "object" ||
|
|
426
433
|
!isRequiredProperty(c, "from", "string") ||
|
|
@@ -429,7 +436,7 @@ function normalizeAndValidateMigrations(
|
|
|
429
436
|
) {
|
|
430
437
|
diagnostics.errors.push(
|
|
431
438
|
`Expected "migrations[${i}].renamed_classes" to be an array of "{from: string, to: string}" objects but got ${JSON.stringify(
|
|
432
|
-
|
|
439
|
+
renamed_classes
|
|
433
440
|
)}.`
|
|
434
441
|
);
|
|
435
442
|
}
|
|
@@ -437,10 +444,49 @@ function normalizeAndValidateMigrations(
|
|
|
437
444
|
validateOptionalTypedArray(
|
|
438
445
|
diagnostics,
|
|
439
446
|
`migrations[${i}].deleted_classes`,
|
|
440
|
-
|
|
447
|
+
deleted_classes,
|
|
441
448
|
"string"
|
|
442
449
|
);
|
|
443
450
|
}
|
|
451
|
+
|
|
452
|
+
if (
|
|
453
|
+
Array.isArray(durableObjects?.bindings) &&
|
|
454
|
+
durableObjects.bindings.length > 0
|
|
455
|
+
) {
|
|
456
|
+
// intrinsic [durable_objects] implies [migrations]
|
|
457
|
+
const exportedDurableObjects = (durableObjects.bindings || []).filter(
|
|
458
|
+
(binding) => !binding.script_name
|
|
459
|
+
);
|
|
460
|
+
if (exportedDurableObjects.length > 0 && rawMigrations.length === 0) {
|
|
461
|
+
if (
|
|
462
|
+
!exportedDurableObjects.some(
|
|
463
|
+
(exportedDurableObject) =>
|
|
464
|
+
typeof exportedDurableObject.class_name !== "string"
|
|
465
|
+
)
|
|
466
|
+
) {
|
|
467
|
+
const durableObjectClassnames = exportedDurableObjects.map(
|
|
468
|
+
(durable) => durable.class_name
|
|
469
|
+
);
|
|
470
|
+
|
|
471
|
+
diagnostics.warnings.push(
|
|
472
|
+
`In wrangler.toml, you have configured [durable_objects] exported by this Worker (${durableObjectClassnames.join(
|
|
473
|
+
", "
|
|
474
|
+
)}), but no [migrations] for them. This may not work as expected until you add a [migrations] section to your wrangler.toml. Add this configuration to your wrangler.toml:
|
|
475
|
+
|
|
476
|
+
\`\`\`
|
|
477
|
+
[[migrations]]
|
|
478
|
+
tag = "v1" # Should be unique for each entry
|
|
479
|
+
new_classes = [${durableObjectClassnames
|
|
480
|
+
.map((name) => `"${name}"`)
|
|
481
|
+
.join(", ")}]
|
|
482
|
+
\`\`\`
|
|
483
|
+
|
|
484
|
+
Refer to https://developers.cloudflare.com/workers/learning/using-durable-objects/#durable-object-migrations-in-wranglertoml for more details.`
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
444
490
|
return rawMigrations;
|
|
445
491
|
}
|
|
446
492
|
}
|
|
@@ -528,6 +574,35 @@ function normalizeAndValidateSite(
|
|
|
528
574
|
return undefined;
|
|
529
575
|
}
|
|
530
576
|
|
|
577
|
+
/**
|
|
578
|
+
* Validate the `assets` configuration and return normalized values.
|
|
579
|
+
*/
|
|
580
|
+
function normalizeAndValidateAssets(
|
|
581
|
+
diagnostics: Diagnostics,
|
|
582
|
+
configPath: string | undefined,
|
|
583
|
+
rawConfig: RawConfig
|
|
584
|
+
) {
|
|
585
|
+
if (
|
|
586
|
+
typeof rawConfig?.assets === "string" ||
|
|
587
|
+
rawConfig?.assets === undefined
|
|
588
|
+
) {
|
|
589
|
+
return rawConfig?.assets;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
const { bucket, include = [], exclude = [], ...rest } = rawConfig.assets;
|
|
593
|
+
|
|
594
|
+
validateAdditionalProperties(diagnostics, "assets", Object.keys(rest), []);
|
|
595
|
+
validateRequiredProperty(diagnostics, "assets", "bucket", bucket, "string");
|
|
596
|
+
validateTypedArray(diagnostics, "assets.include", include, "string");
|
|
597
|
+
validateTypedArray(diagnostics, "assets.exclude", exclude, "string");
|
|
598
|
+
|
|
599
|
+
return {
|
|
600
|
+
bucket,
|
|
601
|
+
include,
|
|
602
|
+
exclude,
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
|
|
531
606
|
/**
|
|
532
607
|
* Map the paths of the `wasm_modules`, `text_blobs` or `data_blobs` configuration to be relative to the current working directory.
|
|
533
608
|
*/
|
|
@@ -562,19 +637,37 @@ function normalizeAndValidateModulePaths(
|
|
|
562
637
|
* or an object that looks like {pattern: string, zone_id: string }
|
|
563
638
|
*/
|
|
564
639
|
function isValidRouteValue(item: unknown): boolean {
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
640
|
+
if (!item) {
|
|
641
|
+
return false;
|
|
642
|
+
}
|
|
643
|
+
if (typeof item === "string") {
|
|
644
|
+
return true;
|
|
645
|
+
}
|
|
646
|
+
if (typeof item === "object") {
|
|
647
|
+
if (!hasProperty(item, "pattern") || typeof item.pattern !== "string") {
|
|
648
|
+
return false;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
const otherKeys = Object.keys(item).length - 1; // minus one to subtract "pattern"
|
|
652
|
+
|
|
653
|
+
const hasZoneId =
|
|
654
|
+
hasProperty(item, "zone_id") && typeof item.zone_id === "string";
|
|
655
|
+
const hasZoneName =
|
|
656
|
+
hasProperty(item, "zone_name") && typeof item.zone_name === "string";
|
|
657
|
+
const hasCustomDomainFlag =
|
|
658
|
+
hasProperty(item, "custom_domain") &&
|
|
659
|
+
typeof item.custom_domain === "boolean";
|
|
660
|
+
|
|
661
|
+
if (otherKeys === 2 && hasCustomDomainFlag && (hasZoneId || hasZoneName)) {
|
|
662
|
+
return true;
|
|
663
|
+
} else if (
|
|
664
|
+
otherKeys === 1 &&
|
|
665
|
+
(hasZoneId || hasZoneName || hasCustomDomainFlag)
|
|
666
|
+
) {
|
|
667
|
+
return true;
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
return false;
|
|
578
671
|
}
|
|
579
672
|
|
|
580
673
|
/**
|
|
@@ -583,7 +676,7 @@ function isValidRouteValue(item: unknown): boolean {
|
|
|
583
676
|
const isRoute: ValidatorFn = (diagnostics, field, value) => {
|
|
584
677
|
if (value !== undefined && !isValidRouteValue(value)) {
|
|
585
678
|
diagnostics.errors.push(
|
|
586
|
-
`Expected "${field}" to be either a string, or an object with shape { pattern, zone_id | zone_name }, but got ${JSON.stringify(
|
|
679
|
+
`Expected "${field}" to be either a string, or an object with shape { pattern, custom_domain, zone_id | zone_name }, but got ${JSON.stringify(
|
|
587
680
|
value
|
|
588
681
|
)}.`
|
|
589
682
|
);
|
|
@@ -613,7 +706,7 @@ const isRouteArray: ValidatorFn = (diagnostics, field, value) => {
|
|
|
613
706
|
}
|
|
614
707
|
if (invalidRoutes.length > 0) {
|
|
615
708
|
diagnostics.errors.push(
|
|
616
|
-
`Expected "${field}" to be an array of either strings or objects with the shape { pattern, zone_id | zone_name }, but these weren't valid: ${JSON.stringify(
|
|
709
|
+
`Expected "${field}" to be an array of either strings or objects with the shape { pattern, custom_domain, zone_id | zone_name }, but these weren't valid: ${JSON.stringify(
|
|
617
710
|
invalidRoutes,
|
|
618
711
|
null,
|
|
619
712
|
2
|
|
@@ -696,27 +789,12 @@ function normalizeAndValidateEnvironment(
|
|
|
696
789
|
diagnostics,
|
|
697
790
|
rawEnv,
|
|
698
791
|
"experimental_services",
|
|
699
|
-
`The "experimental_services" field is no longer supported.
|
|
700
|
-
"```\n" +
|
|
701
|
-
TOML.stringify({
|
|
702
|
-
unsafe: {
|
|
703
|
-
bindings: (rawEnv?.experimental_services || []).map(
|
|
704
|
-
(serviceDefinition) => {
|
|
705
|
-
return {
|
|
706
|
-
name: serviceDefinition.name,
|
|
707
|
-
type: "service",
|
|
708
|
-
service: serviceDefinition.service,
|
|
709
|
-
environment: serviceDefinition.environment,
|
|
710
|
-
};
|
|
711
|
-
}
|
|
712
|
-
),
|
|
713
|
-
},
|
|
714
|
-
}) +
|
|
715
|
-
"```",
|
|
792
|
+
`The "experimental_services" field is no longer supported. Simply rename the [experimental_services] field to [services].`,
|
|
716
793
|
true
|
|
717
794
|
);
|
|
718
795
|
|
|
719
796
|
experimental(diagnostics, rawEnv, "unsafe");
|
|
797
|
+
experimental(diagnostics, rawEnv, "services");
|
|
720
798
|
|
|
721
799
|
const route = validateRoute(diagnostics, topLevelEnv, rawEnv);
|
|
722
800
|
|
|
@@ -880,6 +958,16 @@ function normalizeAndValidateEnvironment(
|
|
|
880
958
|
validateBindingArray(envName, validateR2Binding),
|
|
881
959
|
[]
|
|
882
960
|
),
|
|
961
|
+
services: notInheritable(
|
|
962
|
+
diagnostics,
|
|
963
|
+
topLevelEnv,
|
|
964
|
+
rawConfig,
|
|
965
|
+
rawEnv,
|
|
966
|
+
envName,
|
|
967
|
+
"services",
|
|
968
|
+
validateBindingArray(envName, validateServiceBinding),
|
|
969
|
+
[]
|
|
970
|
+
),
|
|
883
971
|
unsafe: notInheritable(
|
|
884
972
|
diagnostics,
|
|
885
973
|
topLevelEnv,
|
|
@@ -893,8 +981,22 @@ function normalizeAndValidateEnvironment(
|
|
|
893
981
|
}
|
|
894
982
|
),
|
|
895
983
|
zone_id: rawEnv.zone_id,
|
|
896
|
-
minify:
|
|
897
|
-
|
|
984
|
+
minify: inheritable(
|
|
985
|
+
diagnostics,
|
|
986
|
+
topLevelEnv,
|
|
987
|
+
rawEnv,
|
|
988
|
+
"minify",
|
|
989
|
+
isBoolean,
|
|
990
|
+
undefined
|
|
991
|
+
),
|
|
992
|
+
node_compat: inheritable(
|
|
993
|
+
diagnostics,
|
|
994
|
+
topLevelEnv,
|
|
995
|
+
rawEnv,
|
|
996
|
+
"node_compat",
|
|
997
|
+
isBoolean,
|
|
998
|
+
undefined
|
|
999
|
+
),
|
|
898
1000
|
};
|
|
899
1001
|
|
|
900
1002
|
return environment;
|
|
@@ -1014,7 +1116,7 @@ const validateRule: ValidatorFn = (diagnostics, field, value) => {
|
|
|
1014
1116
|
|
|
1015
1117
|
if (!isOptionalProperty(rule, "fallthrough", "boolean")) {
|
|
1016
1118
|
diagnostics.errors.push(
|
|
1017
|
-
`
|
|
1119
|
+
`the field "fallthrough", when present, should be a boolean.`
|
|
1018
1120
|
);
|
|
1019
1121
|
isValid = false;
|
|
1020
1122
|
}
|
|
@@ -1135,7 +1237,7 @@ const validateDurableObjectBinding: ValidatorFn = (
|
|
|
1135
1237
|
return false;
|
|
1136
1238
|
}
|
|
1137
1239
|
|
|
1138
|
-
// Durable Object bindings must have a name and class_name, and optionally a script_name.
|
|
1240
|
+
// Durable Object bindings must have a name and class_name, and optionally a script_name and an environment.
|
|
1139
1241
|
let isValid = true;
|
|
1140
1242
|
if (!isRequiredProperty(value, "name", "string")) {
|
|
1141
1243
|
diagnostics.errors.push(`binding should have a string "name" field.`);
|
|
@@ -1147,7 +1249,21 @@ const validateDurableObjectBinding: ValidatorFn = (
|
|
|
1147
1249
|
}
|
|
1148
1250
|
if (!isOptionalProperty(value, "script_name", "string")) {
|
|
1149
1251
|
diagnostics.errors.push(
|
|
1150
|
-
`
|
|
1252
|
+
`the field "script_name", when present, should be a string.`
|
|
1253
|
+
);
|
|
1254
|
+
isValid = false;
|
|
1255
|
+
}
|
|
1256
|
+
// environment requires a script_name
|
|
1257
|
+
if (!isOptionalProperty(value, "environment", "string")) {
|
|
1258
|
+
diagnostics.errors.push(
|
|
1259
|
+
`the field "environment", when present, should be a string.`
|
|
1260
|
+
);
|
|
1261
|
+
isValid = false;
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
if ("environment" in value && !("script_name" in value)) {
|
|
1265
|
+
diagnostics.errors.push(
|
|
1266
|
+
`binding should have a "script_name" field if "environment" is present.`
|
|
1151
1267
|
);
|
|
1152
1268
|
isValid = false;
|
|
1153
1269
|
}
|
|
@@ -1178,8 +1294,13 @@ const validateUnsafeBinding: ValidatorFn = (diagnostics, field, value) => {
|
|
|
1178
1294
|
const safeBindings = [
|
|
1179
1295
|
"plain_text",
|
|
1180
1296
|
"json",
|
|
1297
|
+
"wasm_module",
|
|
1298
|
+
"data_blob",
|
|
1299
|
+
"text_blob",
|
|
1181
1300
|
"kv_namespace",
|
|
1182
1301
|
"durable_object_namespace",
|
|
1302
|
+
"r2_bucket",
|
|
1303
|
+
"service",
|
|
1183
1304
|
];
|
|
1184
1305
|
|
|
1185
1306
|
if (safeBindings.includes(value.type)) {
|
|
@@ -1422,3 +1543,38 @@ const validateBindingsHaveUniqueNames = (
|
|
|
1422
1543
|
|
|
1423
1544
|
return !hasDuplicates;
|
|
1424
1545
|
};
|
|
1546
|
+
const validateServiceBinding: ValidatorFn = (diagnostics, field, value) => {
|
|
1547
|
+
if (typeof value !== "object" || value === null) {
|
|
1548
|
+
diagnostics.errors.push(
|
|
1549
|
+
`"services" bindings should be objects, but got ${JSON.stringify(value)}`
|
|
1550
|
+
);
|
|
1551
|
+
return false;
|
|
1552
|
+
}
|
|
1553
|
+
let isValid = true;
|
|
1554
|
+
// Service bindings must have a binding, service, and environment.
|
|
1555
|
+
if (!isRequiredProperty(value, "binding", "string")) {
|
|
1556
|
+
diagnostics.errors.push(
|
|
1557
|
+
`"${field}" bindings should have a string "binding" field but got ${JSON.stringify(
|
|
1558
|
+
value
|
|
1559
|
+
)}.`
|
|
1560
|
+
);
|
|
1561
|
+
isValid = false;
|
|
1562
|
+
}
|
|
1563
|
+
if (!isRequiredProperty(value, "service", "string")) {
|
|
1564
|
+
diagnostics.errors.push(
|
|
1565
|
+
`"${field}" bindings should have a string "service" field but got ${JSON.stringify(
|
|
1566
|
+
value
|
|
1567
|
+
)}.`
|
|
1568
|
+
);
|
|
1569
|
+
isValid = false;
|
|
1570
|
+
}
|
|
1571
|
+
if (!isOptionalProperty(value, "environment", "string")) {
|
|
1572
|
+
diagnostics.errors.push(
|
|
1573
|
+
`"${field}" bindings should have a string "environment" field but got ${JSON.stringify(
|
|
1574
|
+
value
|
|
1575
|
+
)}.`
|
|
1576
|
+
);
|
|
1577
|
+
isValid = false;
|
|
1578
|
+
}
|
|
1579
|
+
return isValid;
|
|
1580
|
+
};
|
|
@@ -63,10 +63,15 @@ async function sessionToken(
|
|
|
63
63
|
): Promise<CfPreviewToken> {
|
|
64
64
|
const { accountId } = account;
|
|
65
65
|
const initUrl = ctx.zone
|
|
66
|
-
? `/zones/${ctx.zone
|
|
66
|
+
? `/zones/${ctx.zone}/workers/edge-preview`
|
|
67
67
|
: `/accounts/${accountId}/workers/subdomain/edge-preview`;
|
|
68
68
|
|
|
69
|
-
const { exchange_url } = await fetchResult<{ exchange_url: string }>(
|
|
69
|
+
const { exchange_url } = await fetchResult<{ exchange_url: string }>(
|
|
70
|
+
initUrl,
|
|
71
|
+
undefined,
|
|
72
|
+
undefined,
|
|
73
|
+
abortSignal
|
|
74
|
+
);
|
|
70
75
|
const { inspector_websocket, prewarm, token } = (await (
|
|
71
76
|
await fetch(exchange_url, { signal: abortSignal })
|
|
72
77
|
).json()) as { inspector_websocket: string; token: string; prewarm: string };
|
|
@@ -106,7 +111,7 @@ async function createPreviewToken(
|
|
|
106
111
|
);
|
|
107
112
|
|
|
108
113
|
const { accountId } = account;
|
|
109
|
-
const scriptId = ctx.zone ? randomId() :
|
|
114
|
+
const scriptId = worker.name || (ctx.zone ? randomId() : host.split(".")[0]);
|
|
110
115
|
const url =
|
|
111
116
|
ctx.env && !ctx.legacyEnv
|
|
112
117
|
? `/accounts/${accountId}/workers/services/${scriptId}/environments/${ctx.env}/edge-preview`
|
|
@@ -119,29 +124,34 @@ async function createPreviewToken(
|
|
|
119
124
|
const formData = createWorkerUploadForm(worker);
|
|
120
125
|
formData.set("wrangler-session-config", JSON.stringify(mode));
|
|
121
126
|
|
|
122
|
-
const { preview_token } = await fetchResult<{ preview_token: string }>(
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
+
const { preview_token } = await fetchResult<{ preview_token: string }>(
|
|
128
|
+
url,
|
|
129
|
+
{
|
|
130
|
+
method: "POST",
|
|
131
|
+
body: formData,
|
|
132
|
+
headers: {
|
|
133
|
+
"cf-preview-upload-config-token": value,
|
|
134
|
+
},
|
|
127
135
|
},
|
|
128
|
-
|
|
136
|
+
undefined,
|
|
137
|
+
abortSignal
|
|
138
|
+
);
|
|
129
139
|
|
|
130
140
|
return {
|
|
131
141
|
value: preview_token,
|
|
132
|
-
host:
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
142
|
+
host:
|
|
143
|
+
ctx.host ??
|
|
144
|
+
(worker.name
|
|
145
|
+
? `${
|
|
146
|
+
worker.name
|
|
147
|
+
// TODO: this should also probably have the env prefix
|
|
148
|
+
// but it doesn't appear to work yet, instead giving us the
|
|
149
|
+
// "There is nothing here yet" screen
|
|
150
|
+
// ctx.env && !ctx.legacyEnv
|
|
151
|
+
// ? `${ctx.env}.${worker.name}`
|
|
152
|
+
// : worker.name
|
|
153
|
+
}.${host.split(".").slice(1).join(".")}`
|
|
154
|
+
: host),
|
|
145
155
|
|
|
146
156
|
inspectorUrl,
|
|
147
157
|
prewarmUrl,
|
|
@@ -32,20 +32,24 @@ export interface WorkerMetadata {
|
|
|
32
32
|
compatibility_flags?: string[];
|
|
33
33
|
usage_model?: "bundled" | "unbound";
|
|
34
34
|
migrations?: CfDurableObjectMigrations;
|
|
35
|
+
// If you add any new binding types here, also add it to safeBindings
|
|
36
|
+
// under validateUnsafeBinding in config/validation.ts
|
|
35
37
|
bindings: (
|
|
36
|
-
| { type: "kv_namespace"; name: string; namespace_id: string }
|
|
37
38
|
| { type: "plain_text"; name: string; text: string }
|
|
38
39
|
| { type: "json"; name: string; json: unknown }
|
|
39
40
|
| { type: "wasm_module"; name: string; part: string }
|
|
40
41
|
| { type: "text_blob"; name: string; part: string }
|
|
41
42
|
| { type: "data_blob"; name: string; part: string }
|
|
43
|
+
| { type: "kv_namespace"; name: string; namespace_id: string }
|
|
42
44
|
| {
|
|
43
45
|
type: "durable_object_namespace";
|
|
44
46
|
name: string;
|
|
45
47
|
class_name: string;
|
|
46
48
|
script_name?: string;
|
|
49
|
+
environment?: string;
|
|
47
50
|
}
|
|
48
51
|
| { type: "r2_bucket"; name: string; bucket_name: string }
|
|
52
|
+
| { type: "service"; name: string; service: string; environment?: string }
|
|
49
53
|
)[];
|
|
50
54
|
}
|
|
51
55
|
|
|
@@ -67,6 +71,14 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
|
|
|
67
71
|
|
|
68
72
|
const metadataBindings: WorkerMetadata["bindings"] = [];
|
|
69
73
|
|
|
74
|
+
Object.entries(bindings.vars || {})?.forEach(([key, value]) => {
|
|
75
|
+
if (typeof value === "string") {
|
|
76
|
+
metadataBindings.push({ name: key, type: "plain_text", text: value });
|
|
77
|
+
} else {
|
|
78
|
+
metadataBindings.push({ name: key, type: "json", json: value });
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
70
82
|
bindings.kv_namespaces?.forEach(({ id, binding }) => {
|
|
71
83
|
metadataBindings.push({
|
|
72
84
|
name: binding,
|
|
@@ -76,12 +88,13 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
|
|
|
76
88
|
});
|
|
77
89
|
|
|
78
90
|
bindings.durable_objects?.bindings.forEach(
|
|
79
|
-
({ name, class_name, script_name }) => {
|
|
91
|
+
({ name, class_name, script_name, environment }) => {
|
|
80
92
|
metadataBindings.push({
|
|
81
93
|
name,
|
|
82
94
|
type: "durable_object_namespace",
|
|
83
95
|
class_name: class_name,
|
|
84
96
|
...(script_name && { script_name }),
|
|
97
|
+
...(environment && { environment }),
|
|
85
98
|
});
|
|
86
99
|
}
|
|
87
100
|
);
|
|
@@ -94,12 +107,13 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
|
|
|
94
107
|
});
|
|
95
108
|
});
|
|
96
109
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
110
|
+
bindings.services?.forEach(({ binding, service, environment }) => {
|
|
111
|
+
metadataBindings.push({
|
|
112
|
+
name: binding,
|
|
113
|
+
type: "service",
|
|
114
|
+
service,
|
|
115
|
+
...(environment && { environment }),
|
|
116
|
+
});
|
|
103
117
|
});
|
|
104
118
|
|
|
105
119
|
for (const [name, filePath] of Object.entries(bindings.wasm_modules || {})) {
|