wrangler 2.0.7 → 2.0.8
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 +1 -1
- package/bin/wrangler.js +16 -4
- package/package.json +2 -2
- package/src/__tests__/configuration.test.ts +131 -70
- package/src/__tests__/dev.test.tsx +97 -8
- package/src/__tests__/helpers/mock-dialogs.ts +41 -1
- package/src/__tests__/init.test.ts +188 -111
- package/src/__tests__/kv.test.ts +8 -8
- package/src/__tests__/package-manager.test.ts +154 -7
- package/src/__tests__/pages.test.ts +17 -17
- package/src/__tests__/publish.test.ts +71 -13
- package/src/__tests__/secret.test.ts +4 -4
- package/src/cfetch/index.ts +17 -2
- package/src/cfetch/internal.ts +6 -0
- package/src/config/validation.ts +59 -33
- package/src/dev/dev.tsx +0 -3
- package/src/dialogs.tsx +48 -0
- package/src/index.tsx +159 -84
- package/src/package-manager.ts +50 -3
- package/src/pages.tsx +4 -0
- package/src/sites.tsx +6 -1
- package/templates/new-worker-scheduled.js +17 -0
- package/templates/new-worker-scheduled.ts +32 -0
- package/wrangler-dist/cli.js +307 -175
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"] ??
|
|
@@ -400,29 +384,38 @@ function normalizeAndValidateMigrations(
|
|
|
400
384
|
return [];
|
|
401
385
|
} else {
|
|
402
386
|
for (let i = 0; i < rawMigrations.length; i++) {
|
|
403
|
-
const
|
|
387
|
+
const { tag, new_classes, renamed_classes, deleted_classes, ...rest } =
|
|
388
|
+
rawMigrations[i];
|
|
389
|
+
|
|
390
|
+
validateAdditionalProperties(
|
|
391
|
+
diagnostics,
|
|
392
|
+
"migrations",
|
|
393
|
+
Object.keys(rest),
|
|
394
|
+
[]
|
|
395
|
+
);
|
|
396
|
+
|
|
404
397
|
validateRequiredProperty(
|
|
405
398
|
diagnostics,
|
|
406
399
|
`migrations[${i}]`,
|
|
407
400
|
`tag`,
|
|
408
|
-
|
|
401
|
+
tag,
|
|
409
402
|
"string"
|
|
410
403
|
);
|
|
411
404
|
validateOptionalTypedArray(
|
|
412
405
|
diagnostics,
|
|
413
406
|
`migrations[${i}].new_classes`,
|
|
414
|
-
|
|
407
|
+
new_classes,
|
|
415
408
|
"string"
|
|
416
409
|
);
|
|
417
|
-
if (
|
|
418
|
-
if (!Array.isArray(
|
|
410
|
+
if (renamed_classes !== undefined) {
|
|
411
|
+
if (!Array.isArray(renamed_classes)) {
|
|
419
412
|
diagnostics.errors.push(
|
|
420
413
|
`Expected "migrations[${i}].renamed_classes" to be an array of "{from: string, to: string}" objects but got ${JSON.stringify(
|
|
421
|
-
|
|
414
|
+
renamed_classes
|
|
422
415
|
)}.`
|
|
423
416
|
);
|
|
424
417
|
} else if (
|
|
425
|
-
|
|
418
|
+
renamed_classes.some(
|
|
426
419
|
(c) =>
|
|
427
420
|
typeof c !== "object" ||
|
|
428
421
|
!isRequiredProperty(c, "from", "string") ||
|
|
@@ -431,7 +424,7 @@ function normalizeAndValidateMigrations(
|
|
|
431
424
|
) {
|
|
432
425
|
diagnostics.errors.push(
|
|
433
426
|
`Expected "migrations[${i}].renamed_classes" to be an array of "{from: string, to: string}" objects but got ${JSON.stringify(
|
|
434
|
-
|
|
427
|
+
renamed_classes
|
|
435
428
|
)}.`
|
|
436
429
|
);
|
|
437
430
|
}
|
|
@@ -439,7 +432,7 @@ function normalizeAndValidateMigrations(
|
|
|
439
432
|
validateOptionalTypedArray(
|
|
440
433
|
diagnostics,
|
|
441
434
|
`migrations[${i}].deleted_classes`,
|
|
442
|
-
|
|
435
|
+
deleted_classes,
|
|
443
436
|
"string"
|
|
444
437
|
);
|
|
445
438
|
}
|
|
@@ -453,13 +446,32 @@ function normalizeAndValidateMigrations(
|
|
|
453
446
|
(binding) => !binding.script_name
|
|
454
447
|
);
|
|
455
448
|
if (exportedDurableObjects.length > 0 && rawMigrations.length === 0) {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
449
|
+
if (
|
|
450
|
+
!exportedDurableObjects.some(
|
|
451
|
+
(exportedDurableObject) =>
|
|
452
|
+
typeof exportedDurableObject.class_name !== "string"
|
|
453
|
+
)
|
|
454
|
+
) {
|
|
455
|
+
const durableObjectClassnames = exportedDurableObjects.map(
|
|
456
|
+
(durable) => durable.class_name
|
|
457
|
+
);
|
|
458
|
+
|
|
459
|
+
diagnostics.warnings.push(
|
|
460
|
+
`In wrangler.toml, you have configured [durable_objects] exported by this Worker (${durableObjectClassnames.join(
|
|
460
461
|
", "
|
|
461
|
-
)}), but no [migrations] for them. This may not work as expected until you add a [migrations] section to your wrangler.toml.
|
|
462
|
-
|
|
462
|
+
)}), 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:
|
|
463
|
+
|
|
464
|
+
\`\`\`
|
|
465
|
+
[[migrations]]
|
|
466
|
+
tag = "v1" # Should be unique for each entry
|
|
467
|
+
new_classes = [${durableObjectClassnames
|
|
468
|
+
.map((name) => `"${name}"`)
|
|
469
|
+
.join(", ")}]
|
|
470
|
+
\`\`\`
|
|
471
|
+
|
|
472
|
+
Refer to https://developers.cloudflare.com/workers/learning/using-durable-objects/#durable-object-migrations-in-wranglertoml for more details.`
|
|
473
|
+
);
|
|
474
|
+
}
|
|
463
475
|
}
|
|
464
476
|
}
|
|
465
477
|
|
|
@@ -928,8 +940,22 @@ function normalizeAndValidateEnvironment(
|
|
|
928
940
|
}
|
|
929
941
|
),
|
|
930
942
|
zone_id: rawEnv.zone_id,
|
|
931
|
-
minify:
|
|
932
|
-
|
|
943
|
+
minify: inheritable(
|
|
944
|
+
diagnostics,
|
|
945
|
+
topLevelEnv,
|
|
946
|
+
rawEnv,
|
|
947
|
+
"minify",
|
|
948
|
+
isBoolean,
|
|
949
|
+
undefined
|
|
950
|
+
),
|
|
951
|
+
node_compat: inheritable(
|
|
952
|
+
diagnostics,
|
|
953
|
+
topLevelEnv,
|
|
954
|
+
rawEnv,
|
|
955
|
+
"node_compat",
|
|
956
|
+
isBoolean,
|
|
957
|
+
undefined
|
|
958
|
+
),
|
|
933
959
|
};
|
|
934
960
|
|
|
935
961
|
return environment;
|
package/src/dev/dev.tsx
CHANGED
|
@@ -9,7 +9,6 @@ import { withErrorBoundary, useErrorHandler } from "react-error-boundary";
|
|
|
9
9
|
import onExit from "signal-exit";
|
|
10
10
|
import tmp from "tmp-promise";
|
|
11
11
|
import { fetch } from "undici";
|
|
12
|
-
import { printBindings } from "../config";
|
|
13
12
|
import { runCustomBuild } from "../entry";
|
|
14
13
|
import { openInspector } from "../inspect";
|
|
15
14
|
import { logger } from "../logger";
|
|
@@ -106,8 +105,6 @@ export function DevImplementation(props: DevProps): JSX.Element {
|
|
|
106
105
|
nodeCompat: props.nodeCompat,
|
|
107
106
|
});
|
|
108
107
|
|
|
109
|
-
printBindings(props.bindings);
|
|
110
|
-
|
|
111
108
|
// only load the UI if we're running in a supported environment
|
|
112
109
|
const { isRawModeSupported } = useStdin();
|
|
113
110
|
return isRawModeSupported ? (
|
package/src/dialogs.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import { Box, Text, useInput, render } from "ink";
|
|
3
|
+
import SelectInput from "ink-select-input";
|
|
3
4
|
import TextInput from "ink-text-input";
|
|
4
5
|
import * as React from "react";
|
|
5
6
|
import { useState } from "react";
|
|
@@ -85,3 +86,50 @@ export async function prompt(
|
|
|
85
86
|
);
|
|
86
87
|
});
|
|
87
88
|
}
|
|
89
|
+
|
|
90
|
+
type SelectOption = {
|
|
91
|
+
value: string;
|
|
92
|
+
label: string;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
type SelectProps = {
|
|
96
|
+
text: string;
|
|
97
|
+
options: SelectOption[];
|
|
98
|
+
initialIndex: number;
|
|
99
|
+
onSelect: (value: string) => void;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
function Select(props: SelectProps) {
|
|
103
|
+
return (
|
|
104
|
+
<Box flexDirection="column">
|
|
105
|
+
<Text>{props.text}</Text>
|
|
106
|
+
<SelectInput
|
|
107
|
+
initialIndex={props.initialIndex}
|
|
108
|
+
items={props.options}
|
|
109
|
+
onSelect={async (selected) => {
|
|
110
|
+
props.onSelect(selected.value);
|
|
111
|
+
}}
|
|
112
|
+
/>
|
|
113
|
+
</Box>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function select(
|
|
118
|
+
text: string,
|
|
119
|
+
options: SelectOption[],
|
|
120
|
+
initialIndex: number
|
|
121
|
+
): Promise<string> {
|
|
122
|
+
return new Promise((resolve) => {
|
|
123
|
+
const { unmount } = render(
|
|
124
|
+
<Select
|
|
125
|
+
text={text}
|
|
126
|
+
options={options}
|
|
127
|
+
initialIndex={initialIndex}
|
|
128
|
+
onSelect={(option: string) => {
|
|
129
|
+
unmount();
|
|
130
|
+
resolve(option);
|
|
131
|
+
}}
|
|
132
|
+
/>
|
|
133
|
+
);
|
|
134
|
+
});
|
|
135
|
+
}
|
package/src/index.tsx
CHANGED
|
@@ -15,11 +15,11 @@ import { setGlobalDispatcher, ProxyAgent } from "undici";
|
|
|
15
15
|
import makeCLI from "yargs";
|
|
16
16
|
import { version as wranglerVersion } from "../package.json";
|
|
17
17
|
import { fetchResult } from "./cfetch";
|
|
18
|
-
import { findWranglerToml, readConfig } from "./config";
|
|
18
|
+
import { findWranglerToml, printBindings, readConfig } from "./config";
|
|
19
19
|
import { createWorkerUploadForm } from "./create-worker-upload-form";
|
|
20
20
|
import Dev from "./dev/dev";
|
|
21
21
|
import { getVarsForDev } from "./dev/dev-vars";
|
|
22
|
-
import { confirm, prompt } from "./dialogs";
|
|
22
|
+
import { confirm, prompt, select } from "./dialogs";
|
|
23
23
|
import { getEntry } from "./entry";
|
|
24
24
|
import { DeprecationError } from "./errors";
|
|
25
25
|
import {
|
|
@@ -628,21 +628,21 @@ function createCLIParser(argv: string[]) {
|
|
|
628
628
|
isWritingScripts: boolean,
|
|
629
629
|
isCreatingWranglerToml: boolean,
|
|
630
630
|
packagePath: string,
|
|
631
|
-
scriptPath: string
|
|
631
|
+
scriptPath: string,
|
|
632
|
+
extraToml: TOML.JsonMap
|
|
632
633
|
) {
|
|
633
634
|
if (isCreatingWranglerToml) {
|
|
634
|
-
// rewrite wrangler.toml with main = "path/to/script"
|
|
635
|
+
// rewrite wrangler.toml with main = "path/to/script" and any additional config specified in `extraToml`
|
|
635
636
|
const parsedWranglerToml = parseTOML(
|
|
636
637
|
readFileSync(wranglerTomlDestination)
|
|
637
638
|
);
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
);
|
|
639
|
+
const newToml = {
|
|
640
|
+
name: parsedWranglerToml.name,
|
|
641
|
+
main: scriptPath,
|
|
642
|
+
compatibility_date: parsedWranglerToml.compatibility_date,
|
|
643
|
+
...extraToml,
|
|
644
|
+
};
|
|
645
|
+
fs.writeFileSync(wranglerTomlDestination, TOML.stringify(newToml));
|
|
646
646
|
}
|
|
647
647
|
const isNamedWorker =
|
|
648
648
|
isCreatingWranglerToml && path.dirname(packagePath) !== process.cwd();
|
|
@@ -658,7 +658,7 @@ function createCLIParser(argv: string[]) {
|
|
|
658
658
|
start: isCreatingWranglerToml
|
|
659
659
|
? `wrangler dev`
|
|
660
660
|
: `wrangler dev ${scriptPath}`,
|
|
661
|
-
|
|
661
|
+
deploy: isCreatingWranglerToml
|
|
662
662
|
? `wrangler publish`
|
|
663
663
|
: `wrangler publish ${scriptPath}`,
|
|
664
664
|
},
|
|
@@ -673,7 +673,7 @@ function createCLIParser(argv: string[]) {
|
|
|
673
673
|
}npm start\``
|
|
674
674
|
);
|
|
675
675
|
instructions.push(
|
|
676
|
-
`To publish your Worker to the Internet, run \`npm run
|
|
676
|
+
`To publish your Worker to the Internet, run \`npm run deploy\``
|
|
677
677
|
);
|
|
678
678
|
} else {
|
|
679
679
|
instructions.push(
|
|
@@ -689,24 +689,75 @@ function createCLIParser(argv: string[]) {
|
|
|
689
689
|
}
|
|
690
690
|
}
|
|
691
691
|
|
|
692
|
+
async function getNewWorkerType(newWorkerFilename: string) {
|
|
693
|
+
return select(
|
|
694
|
+
`Would you like to create a Worker at ${newWorkerFilename}?`,
|
|
695
|
+
[
|
|
696
|
+
{
|
|
697
|
+
value: "none",
|
|
698
|
+
label: "None",
|
|
699
|
+
},
|
|
700
|
+
{
|
|
701
|
+
value: "fetch",
|
|
702
|
+
label: "Fetch handler",
|
|
703
|
+
},
|
|
704
|
+
{
|
|
705
|
+
value: "scheduled",
|
|
706
|
+
label: "Scheduled handler",
|
|
707
|
+
},
|
|
708
|
+
],
|
|
709
|
+
1
|
|
710
|
+
) as Promise<"none" | "fetch" | "scheduled">;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
function getNewWorkerTemplate(
|
|
714
|
+
lang: "js" | "ts",
|
|
715
|
+
workerType: "fetch" | "scheduled"
|
|
716
|
+
) {
|
|
717
|
+
const templates = {
|
|
718
|
+
"js-fetch": "new-worker.js",
|
|
719
|
+
"js-scheduled": "new-worker-scheduled.js",
|
|
720
|
+
"ts-fetch": "new-worker.ts",
|
|
721
|
+
"ts-scheduled": "new-worker-scheduled.ts",
|
|
722
|
+
};
|
|
723
|
+
|
|
724
|
+
return templates[`${lang}-${workerType}`];
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
function getNewWorkerToml(
|
|
728
|
+
workerType: "fetch" | "scheduled"
|
|
729
|
+
): TOML.JsonMap {
|
|
730
|
+
if (workerType === "scheduled") {
|
|
731
|
+
return {
|
|
732
|
+
triggers: {
|
|
733
|
+
crons: ["1 * * * *"],
|
|
734
|
+
},
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
return {};
|
|
739
|
+
}
|
|
740
|
+
|
|
692
741
|
if (isTypescriptProject) {
|
|
693
742
|
if (!fs.existsSync(path.join(creationDirectory, "./src/index.ts"))) {
|
|
694
|
-
const
|
|
695
|
-
|
|
696
|
-
(
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
)
|
|
743
|
+
const newWorkerFilename = path.relative(
|
|
744
|
+
process.cwd(),
|
|
745
|
+
path.join(creationDirectory, "./src/index.ts")
|
|
746
|
+
);
|
|
747
|
+
|
|
748
|
+
const newWorkerType = yesFlag
|
|
749
|
+
? "fetch"
|
|
750
|
+
: await getNewWorkerType(newWorkerFilename);
|
|
751
|
+
|
|
752
|
+
if (newWorkerType !== "none") {
|
|
753
|
+
const template = getNewWorkerTemplate("ts", newWorkerType);
|
|
702
754
|
|
|
703
|
-
if (shouldCreateSource) {
|
|
704
755
|
await mkdir(path.join(creationDirectory, "./src"), {
|
|
705
756
|
recursive: true,
|
|
706
757
|
});
|
|
707
758
|
await writeFile(
|
|
708
759
|
path.join(creationDirectory, "./src/index.ts"),
|
|
709
|
-
readFileSync(path.join(__dirname,
|
|
760
|
+
readFileSync(path.join(__dirname, `../templates/${template}`))
|
|
710
761
|
);
|
|
711
762
|
|
|
712
763
|
logger.log(
|
|
@@ -720,28 +771,31 @@ function createCLIParser(argv: string[]) {
|
|
|
720
771
|
shouldWritePackageJsonScripts,
|
|
721
772
|
justCreatedWranglerToml,
|
|
722
773
|
pathToPackageJson,
|
|
723
|
-
"src/index.ts"
|
|
774
|
+
"src/index.ts",
|
|
775
|
+
getNewWorkerToml(newWorkerType)
|
|
724
776
|
);
|
|
725
777
|
}
|
|
726
778
|
}
|
|
727
779
|
} else {
|
|
728
780
|
if (!fs.existsSync(path.join(creationDirectory, "./src/index.js"))) {
|
|
729
|
-
const
|
|
730
|
-
|
|
731
|
-
(
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
)
|
|
781
|
+
const newWorkerFilename = path.relative(
|
|
782
|
+
process.cwd(),
|
|
783
|
+
path.join(creationDirectory, "./src/index.js")
|
|
784
|
+
);
|
|
785
|
+
|
|
786
|
+
const newWorkerType = yesFlag
|
|
787
|
+
? "fetch"
|
|
788
|
+
: await getNewWorkerType(newWorkerFilename);
|
|
789
|
+
|
|
790
|
+
if (newWorkerType !== "none") {
|
|
791
|
+
const template = getNewWorkerTemplate("js", newWorkerType);
|
|
737
792
|
|
|
738
|
-
if (shouldCreateSource) {
|
|
739
793
|
await mkdir(path.join(creationDirectory, "./src"), {
|
|
740
794
|
recursive: true,
|
|
741
795
|
});
|
|
742
796
|
await writeFile(
|
|
743
797
|
path.join(creationDirectory, "./src/index.js"),
|
|
744
|
-
readFileSync(path.join(__dirname,
|
|
798
|
+
readFileSync(path.join(__dirname, `../templates/${template}`))
|
|
745
799
|
);
|
|
746
800
|
|
|
747
801
|
logger.log(
|
|
@@ -755,7 +809,8 @@ function createCLIParser(argv: string[]) {
|
|
|
755
809
|
shouldWritePackageJsonScripts,
|
|
756
810
|
justCreatedWranglerToml,
|
|
757
811
|
pathToPackageJson,
|
|
758
|
-
"src/index.js"
|
|
812
|
+
"src/index.js",
|
|
813
|
+
getNewWorkerToml(newWorkerType)
|
|
759
814
|
);
|
|
760
815
|
}
|
|
761
816
|
}
|
|
@@ -1119,6 +1174,70 @@ function createCLIParser(argv: string[]) {
|
|
|
1119
1174
|
);
|
|
1120
1175
|
}
|
|
1121
1176
|
|
|
1177
|
+
const bindings = {
|
|
1178
|
+
kv_namespaces: config.kv_namespaces?.map(
|
|
1179
|
+
({ binding, preview_id, id: _id }) => {
|
|
1180
|
+
// In `dev`, we make folks use a separate kv namespace called
|
|
1181
|
+
// `preview_id` instead of `id` so that they don't
|
|
1182
|
+
// break production data. So here we check that a `preview_id`
|
|
1183
|
+
// has actually been configured.
|
|
1184
|
+
// This whole block of code will be obsoleted in the future
|
|
1185
|
+
// when we have copy-on-write for previews on edge workers.
|
|
1186
|
+
if (!preview_id) {
|
|
1187
|
+
// TODO: This error has to be a _lot_ better, ideally just asking
|
|
1188
|
+
// to create a preview namespace for the user automatically
|
|
1189
|
+
throw new Error(
|
|
1190
|
+
`In development, you should use a separate kv namespace than the one you'd use in production. Please create a new kv namespace with "wrangler kv:namespace create <name> --preview" and add its id as preview_id to the kv_namespace "${binding}" in your wrangler.toml`
|
|
1191
|
+
); // Ugh, I really don't like this message very much
|
|
1192
|
+
}
|
|
1193
|
+
return {
|
|
1194
|
+
binding,
|
|
1195
|
+
id: preview_id,
|
|
1196
|
+
};
|
|
1197
|
+
}
|
|
1198
|
+
),
|
|
1199
|
+
// Use a copy of combinedVars since we're modifying it later
|
|
1200
|
+
vars: getVarsForDev(config),
|
|
1201
|
+
wasm_modules: config.wasm_modules,
|
|
1202
|
+
text_blobs: config.text_blobs,
|
|
1203
|
+
data_blobs: config.data_blobs,
|
|
1204
|
+
durable_objects: config.durable_objects,
|
|
1205
|
+
r2_buckets: config.r2_buckets?.map(
|
|
1206
|
+
({ binding, preview_bucket_name, bucket_name: _bucket_name }) => {
|
|
1207
|
+
// same idea as kv namespace preview id,
|
|
1208
|
+
// same copy-on-write TODO
|
|
1209
|
+
if (!preview_bucket_name) {
|
|
1210
|
+
throw new Error(
|
|
1211
|
+
`In development, you should use a separate r2 bucket than the one you'd use in production. Please create a new r2 bucket with "wrangler r2 bucket create <name>" and add its name as preview_bucket_name to the r2_buckets "${binding}" in your wrangler.toml`
|
|
1212
|
+
);
|
|
1213
|
+
}
|
|
1214
|
+
return {
|
|
1215
|
+
binding,
|
|
1216
|
+
bucket_name: preview_bucket_name,
|
|
1217
|
+
};
|
|
1218
|
+
}
|
|
1219
|
+
),
|
|
1220
|
+
services: config.services,
|
|
1221
|
+
unsafe: config.unsafe?.bindings,
|
|
1222
|
+
};
|
|
1223
|
+
|
|
1224
|
+
// mask anything that was overridden in .dev.vars
|
|
1225
|
+
// so that we don't log potential secrets into the terminal
|
|
1226
|
+
const maskedVars = { ...bindings.vars };
|
|
1227
|
+
for (const key of Object.keys(maskedVars)) {
|
|
1228
|
+
if (maskedVars[key] !== config.vars[key]) {
|
|
1229
|
+
// This means it was overridden in .dev.vars
|
|
1230
|
+
// so let's mask it
|
|
1231
|
+
maskedVars[key] = "(hidden)";
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
// now log all available bindings into the terminal
|
|
1236
|
+
printBindings({
|
|
1237
|
+
...bindings,
|
|
1238
|
+
vars: maskedVars,
|
|
1239
|
+
});
|
|
1240
|
+
|
|
1122
1241
|
const { waitUntilExit } = render(
|
|
1123
1242
|
<Dev
|
|
1124
1243
|
name={getScriptName(args, config)}
|
|
@@ -1164,51 +1283,7 @@ function createCLIParser(argv: string[]) {
|
|
|
1164
1283
|
args["compatibility-flags"] || config.compatibility_flags
|
|
1165
1284
|
}
|
|
1166
1285
|
usageModel={config.usage_model}
|
|
1167
|
-
bindings={
|
|
1168
|
-
kv_namespaces: config.kv_namespaces?.map(
|
|
1169
|
-
({ binding, preview_id, id: _id }) => {
|
|
1170
|
-
// In `dev`, we make folks use a separate kv namespace called
|
|
1171
|
-
// `preview_id` instead of `id` so that they don't
|
|
1172
|
-
// break production data. So here we check that a `preview_id`
|
|
1173
|
-
// has actually been configured.
|
|
1174
|
-
// This whole block of code will be obsoleted in the future
|
|
1175
|
-
// when we have copy-on-write for previews on edge workers.
|
|
1176
|
-
if (!preview_id) {
|
|
1177
|
-
// TODO: This error has to be a _lot_ better, ideally just asking
|
|
1178
|
-
// to create a preview namespace for the user automatically
|
|
1179
|
-
throw new Error(
|
|
1180
|
-
`In development, you should use a separate kv namespace than the one you'd use in production. Please create a new kv namespace with "wrangler kv:namespace create <name> --preview" and add its id as preview_id to the kv_namespace "${binding}" in your wrangler.toml`
|
|
1181
|
-
); // Ugh, I really don't like this message very much
|
|
1182
|
-
}
|
|
1183
|
-
return {
|
|
1184
|
-
binding,
|
|
1185
|
-
id: preview_id,
|
|
1186
|
-
};
|
|
1187
|
-
}
|
|
1188
|
-
),
|
|
1189
|
-
vars: getVarsForDev(config),
|
|
1190
|
-
wasm_modules: config.wasm_modules,
|
|
1191
|
-
text_blobs: config.text_blobs,
|
|
1192
|
-
data_blobs: config.data_blobs,
|
|
1193
|
-
durable_objects: config.durable_objects,
|
|
1194
|
-
r2_buckets: config.r2_buckets?.map(
|
|
1195
|
-
({ binding, preview_bucket_name, bucket_name: _bucket_name }) => {
|
|
1196
|
-
// same idea as kv namespace preview id,
|
|
1197
|
-
// same copy-on-write TODO
|
|
1198
|
-
if (!preview_bucket_name) {
|
|
1199
|
-
throw new Error(
|
|
1200
|
-
`In development, you should use a separate r2 bucket than the one you'd use in production. Please create a new r2 bucket with "wrangler r2 bucket create <name>" and add its name as preview_bucket_name to the r2_buckets "${binding}" in your wrangler.toml`
|
|
1201
|
-
);
|
|
1202
|
-
}
|
|
1203
|
-
return {
|
|
1204
|
-
binding,
|
|
1205
|
-
bucket_name: preview_bucket_name,
|
|
1206
|
-
};
|
|
1207
|
-
}
|
|
1208
|
-
),
|
|
1209
|
-
services: config.services,
|
|
1210
|
-
unsafe: config.unsafe?.bindings,
|
|
1211
|
-
}}
|
|
1286
|
+
bindings={bindings}
|
|
1212
1287
|
crons={config.triggers.crons}
|
|
1213
1288
|
/>
|
|
1214
1289
|
);
|
|
@@ -2752,14 +2827,14 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2752
2827
|
await createCLIParser([...argv, "--help"]).parse();
|
|
2753
2828
|
} else if (e instanceof ParseError) {
|
|
2754
2829
|
e.notes.push({
|
|
2755
|
-
text: "\nIf you think this is a bug, please open an issue at: https://github.com/cloudflare/wrangler2/issues/new",
|
|
2830
|
+
text: "\nIf you think this is a bug, please open an issue at: https://github.com/cloudflare/wrangler2/issues/new/choose",
|
|
2756
2831
|
});
|
|
2757
|
-
logger.
|
|
2832
|
+
logger.log(formatMessage(e));
|
|
2758
2833
|
} else {
|
|
2759
2834
|
logger.error(e instanceof Error ? e.message : e);
|
|
2760
2835
|
logger.log(
|
|
2761
2836
|
`${fgGreenColor}%s${resetColor}`,
|
|
2762
|
-
"If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new
|
|
2837
|
+
"If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
|
|
2763
2838
|
);
|
|
2764
2839
|
}
|
|
2765
2840
|
throw e;
|
package/src/package-manager.ts
CHANGED
|
@@ -5,15 +5,20 @@ import { logger } from "./logger";
|
|
|
5
5
|
|
|
6
6
|
export interface PackageManager {
|
|
7
7
|
cwd: string;
|
|
8
|
-
type: "npm" | "yarn";
|
|
8
|
+
type: "npm" | "yarn" | "pnpm";
|
|
9
9
|
addDevDeps(...packages: string[]): Promise<void>;
|
|
10
10
|
install(): Promise<void>;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export async function getPackageManager(cwd: string): Promise<PackageManager> {
|
|
14
|
-
const [hasYarn, hasNpm] = await Promise.all([
|
|
14
|
+
const [hasYarn, hasNpm, hasPnpm] = await Promise.all([
|
|
15
|
+
supportsYarn(),
|
|
16
|
+
supportsNpm(),
|
|
17
|
+
supportsPnpm(),
|
|
18
|
+
]);
|
|
15
19
|
const hasYarnLock = existsSync(join(cwd, "yarn.lock"));
|
|
16
20
|
const hasNpmLock = existsSync(join(cwd, "package-lock.json"));
|
|
21
|
+
const hasPnpmLock = existsSync(join(cwd, "pnpm-lock.yaml"));
|
|
17
22
|
|
|
18
23
|
if (hasNpmLock) {
|
|
19
24
|
if (hasNpm) {
|
|
@@ -28,6 +33,18 @@ export async function getPackageManager(cwd: string): Promise<PackageManager> {
|
|
|
28
33
|
);
|
|
29
34
|
return { ...YarnPackageManager, cwd };
|
|
30
35
|
}
|
|
36
|
+
} else if (hasPnpmLock) {
|
|
37
|
+
if (hasPnpm) {
|
|
38
|
+
logger.log(
|
|
39
|
+
"Using pnpm as package manager, as there is already a pnpm-lock.yaml file."
|
|
40
|
+
);
|
|
41
|
+
return { ...PnpmPackageManager, cwd };
|
|
42
|
+
} else {
|
|
43
|
+
logger.warn(
|
|
44
|
+
"There is already a pnpm-lock.yaml file but could not find pnpm on the PATH."
|
|
45
|
+
);
|
|
46
|
+
// will simply fallback to the first found of [npm, yaml, pnpm] in the next if round.
|
|
47
|
+
}
|
|
31
48
|
} else if (hasYarnLock) {
|
|
32
49
|
if (hasYarn) {
|
|
33
50
|
logger.log(
|
|
@@ -49,9 +66,12 @@ export async function getPackageManager(cwd: string): Promise<PackageManager> {
|
|
|
49
66
|
} else if (hasYarn) {
|
|
50
67
|
logger.log("Using yarn as package manager.");
|
|
51
68
|
return { ...YarnPackageManager, cwd };
|
|
69
|
+
} else if (hasPnpm) {
|
|
70
|
+
logger.log("Using pnpm as package manager.");
|
|
71
|
+
return { ...PnpmPackageManager, cwd };
|
|
52
72
|
} else {
|
|
53
73
|
throw new Error(
|
|
54
|
-
"Unable to find a package manager. Supported managers are: npm and
|
|
74
|
+
"Unable to find a package manager. Supported managers are: npm, yarn, and pnpm."
|
|
55
75
|
);
|
|
56
76
|
}
|
|
57
77
|
}
|
|
@@ -86,6 +106,29 @@ const NpmPackageManager: PackageManager = {
|
|
|
86
106
|
},
|
|
87
107
|
};
|
|
88
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Manage packages using pnpm
|
|
111
|
+
*/
|
|
112
|
+
const PnpmPackageManager: PackageManager = {
|
|
113
|
+
cwd: process.cwd(),
|
|
114
|
+
type: "pnpm",
|
|
115
|
+
/** Add and install a new devDependency into the local package.json. */
|
|
116
|
+
async addDevDeps(...packages: string[]): Promise<void> {
|
|
117
|
+
await execa("pnpm", ["install", ...packages, "--save-dev"], {
|
|
118
|
+
stdio: "inherit",
|
|
119
|
+
cwd: this.cwd,
|
|
120
|
+
});
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
/** Install all the dependencies in the local package.json. */
|
|
124
|
+
async install(): Promise<void> {
|
|
125
|
+
await execa("pnpm", ["install"], {
|
|
126
|
+
stdio: "inherit",
|
|
127
|
+
cwd: this.cwd,
|
|
128
|
+
});
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
|
|
89
132
|
/**
|
|
90
133
|
* Manage packages using yarn
|
|
91
134
|
*/
|
|
@@ -125,3 +168,7 @@ function supportsYarn(): Promise<boolean> {
|
|
|
125
168
|
function supportsNpm(): Promise<boolean> {
|
|
126
169
|
return supports("npm");
|
|
127
170
|
}
|
|
171
|
+
|
|
172
|
+
function supportsPnpm(): Promise<boolean> {
|
|
173
|
+
return supports("pnpm");
|
|
174
|
+
}
|
package/src/pages.tsx
CHANGED
|
@@ -1066,6 +1066,7 @@ const createDeployment: CommandModule<
|
|
|
1066
1066
|
"_headers",
|
|
1067
1067
|
".DS_Store",
|
|
1068
1068
|
"node_modules",
|
|
1069
|
+
".git",
|
|
1069
1070
|
];
|
|
1070
1071
|
|
|
1071
1072
|
const walk = async (
|
|
@@ -1522,6 +1523,9 @@ export const pages: BuilderCallback<unknown, unknown> = (yargs) => {
|
|
|
1522
1523
|
} else {
|
|
1523
1524
|
logger.log("No functions. Shimming...");
|
|
1524
1525
|
miniflareArgs = {
|
|
1526
|
+
// cfFetch sets the `cf` object that a function could expect
|
|
1527
|
+
// If there are no functions, there's no reason to set this up (and not make that network call)
|
|
1528
|
+
cfFetch: false,
|
|
1525
1529
|
// TODO: The fact that these request/response hacks are necessary is ridiculous.
|
|
1526
1530
|
// We need to eliminate them from env.ASSETS.fetch (not sure if just local or prod as well)
|
|
1527
1531
|
script: `
|