wrangler 0.0.0-e6733a3 → 0.0.0-e88a54e
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/miniflare-dist/index.mjs +79 -0
- package/miniflare-dist/index.mjs.map +7 -0
- package/package.json +35 -16
- package/pages/functions/buildWorker.ts +1 -1
- package/pages/functions/filepath-routing.test.ts +212 -28
- package/pages/functions/filepath-routing.ts +91 -131
- package/pages/functions/routes.ts +11 -18
- package/pages/functions/template-worker.ts +19 -33
- package/src/__tests__/configuration.test.ts +2796 -0
- package/src/__tests__/dev.test.tsx +488 -58
- package/src/__tests__/dev2.test.tsx +154 -0
- package/src/__tests__/guess-worker-format.test.ts +58 -0
- 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/faye-websocket.d.ts +6 -0
- package/src/__tests__/helpers/mock-account-id.ts +48 -0
- package/src/__tests__/helpers/mock-bin.ts +36 -0
- package/src/__tests__/{mock-cfetch.ts → helpers/mock-cfetch.ts} +55 -19
- package/src/__tests__/helpers/mock-console.ts +70 -0
- package/src/__tests__/{mock-dialogs.ts → helpers/mock-dialogs.ts} +1 -1
- package/src/__tests__/helpers/mock-kv.ts +33 -0
- package/src/__tests__/helpers/mock-stdin.ts +103 -0
- package/src/__tests__/helpers/mock-web-socket.ts +29 -0
- package/src/__tests__/helpers/run-in-tmp.ts +32 -0
- package/src/__tests__/helpers/run-wrangler.ts +16 -0
- package/src/__tests__/helpers/write-wrangler-toml.ts +17 -0
- package/src/__tests__/https-options.test.ts +127 -0
- package/src/__tests__/index.test.ts +779 -75
- package/src/__tests__/jest.setup.ts +53 -6
- package/src/__tests__/kv.test.ts +738 -454
- package/src/__tests__/logout.test.ts +52 -0
- package/src/__tests__/package-manager.test.ts +206 -0
- package/src/__tests__/pages.test.ts +44 -0
- package/src/__tests__/parse.test.ts +322 -0
- package/src/__tests__/publish.test.ts +2704 -0
- package/src/__tests__/r2.test.ts +198 -0
- package/src/__tests__/route.test.ts +45 -0
- package/src/__tests__/secret.test.ts +425 -0
- package/src/__tests__/sentry.test.ts +146 -0
- package/src/__tests__/tail.test.ts +564 -0
- package/src/__tests__/whoami.test.tsx +100 -0
- package/src/bundle.ts +142 -0
- package/src/cfetch/index.ts +21 -19
- package/src/cfetch/internal.ts +94 -24
- package/src/cli.ts +10 -0
- package/src/config/README.md +107 -0
- package/src/config/config.ts +218 -0
- package/src/config/diagnostics.ts +80 -0
- package/src/config/environment.ts +366 -0
- package/src/config/index.ts +62 -0
- package/src/config/validation-helpers.ts +486 -0
- package/src/config/validation.ts +1090 -0
- package/src/{api/preview.ts → create-worker-preview.ts} +61 -23
- package/src/create-worker-upload-form.ts +217 -0
- package/src/dev/dev.tsx +364 -0
- package/src/dev/local.tsx +232 -0
- package/src/dev/remote.tsx +203 -0
- package/src/dev/use-esbuild.ts +100 -0
- package/src/dialogs.tsx +2 -2
- package/src/entry.ts +208 -0
- package/src/environment-variables.ts +33 -0
- package/src/https-options.ts +122 -0
- package/src/index.tsx +1198 -799
- package/src/inspect.ts +159 -66
- package/src/{kv.tsx → kv.ts} +117 -65
- package/src/miniflare-cli/README.md +30 -0
- package/src/miniflare-cli/enum-keys.ts +17 -0
- package/src/miniflare-cli/index.ts +37 -0
- package/src/module-collection.ts +229 -35
- package/src/open-in-browser.ts +25 -0
- package/src/package-manager.ts +126 -0
- package/src/pages.tsx +58 -42
- package/src/parse.ts +183 -0
- package/src/paths.ts +26 -0
- package/src/proxy.ts +224 -78
- package/src/publish.ts +281 -292
- package/src/r2.ts +50 -0
- package/src/reporting.ts +131 -0
- package/src/selfsigned.d.ts +29 -0
- package/src/sites.tsx +224 -58
- package/src/tail/filters.ts +279 -0
- package/src/tail/index.ts +299 -0
- package/src/tail/printing.ts +62 -0
- package/src/user.tsx +273 -180
- package/src/whoami.tsx +69 -0
- package/src/{api/worker.ts → worker.ts} +45 -37
- 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/templates/tsconfig.json +105 -0
- package/wrangler-dist/cli.js +130612 -112486
- 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/api/form_data.ts +0 -131
- package/src/config.ts +0 -487
- package/src/dev.tsx +0 -771
- package/src/tail.tsx +0 -73
package/src/index.tsx
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import { writeFile, mkdir } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { setTimeout } from "node:timers/promises";
|
|
5
|
+
import TOML from "@iarna/toml";
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import { findUp } from "find-up";
|
|
8
|
+
import getPort from "get-port";
|
|
2
9
|
import { render } from "ink";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
10
|
+
import React from "react";
|
|
11
|
+
import onExit from "signal-exit";
|
|
12
|
+
import supportsColor from "supports-color";
|
|
5
13
|
import makeCLI from "yargs";
|
|
6
|
-
import type Yargs from "yargs";
|
|
7
|
-
import { findUp } from "find-up";
|
|
8
|
-
import TOML from "@iarna/toml";
|
|
9
|
-
import type { Config } from "./config";
|
|
10
|
-
import { confirm, prompt } from "./dialogs";
|
|
11
14
|
import { version as wranglerVersion } from "../package.json";
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
getAccountId,
|
|
19
|
-
} from "./user";
|
|
15
|
+
import { fetchResult } from "./cfetch";
|
|
16
|
+
import { findWranglerToml, readConfig } from "./config";
|
|
17
|
+
import { createWorkerUploadForm } from "./create-worker-upload-form";
|
|
18
|
+
import Dev from "./dev/dev";
|
|
19
|
+
import { confirm, prompt } from "./dialogs";
|
|
20
|
+
import { getEntry } from "./entry";
|
|
20
21
|
import {
|
|
21
22
|
getNamespaceId,
|
|
22
23
|
listNamespaces,
|
|
@@ -26,92 +27,150 @@ import {
|
|
|
26
27
|
deleteBulkKeyValue,
|
|
27
28
|
createNamespace,
|
|
28
29
|
isValidNamespaceBinding,
|
|
30
|
+
getKeyValue,
|
|
31
|
+
isKeyValue,
|
|
32
|
+
unexpectedKeyValueProps,
|
|
29
33
|
} from "./kv";
|
|
30
|
-
|
|
34
|
+
import { getPackageManager } from "./package-manager";
|
|
31
35
|
import { pages } from "./pages";
|
|
36
|
+
import { formatMessage, ParseError, parseJSON, readFileSync } from "./parse";
|
|
37
|
+
import publish from "./publish";
|
|
38
|
+
import { createR2Bucket, deleteR2Bucket, listR2Buckets } from "./r2";
|
|
39
|
+
import { getAssetPaths } from "./sites";
|
|
40
|
+
import {
|
|
41
|
+
createTail,
|
|
42
|
+
jsonPrintLogs,
|
|
43
|
+
prettyPrintLogs,
|
|
44
|
+
translateCLICommandToFilterMessage,
|
|
45
|
+
} from "./tail";
|
|
46
|
+
import {
|
|
47
|
+
login,
|
|
48
|
+
logout,
|
|
49
|
+
listScopes,
|
|
50
|
+
loginOrRefreshIfRequired,
|
|
51
|
+
getAccountId,
|
|
52
|
+
validateScopeKeys,
|
|
53
|
+
} from "./user";
|
|
54
|
+
import { whoami } from "./whoami";
|
|
32
55
|
|
|
33
|
-
import {
|
|
56
|
+
import type { Config } from "./config";
|
|
57
|
+
import type { TailCLIFilters } from "./tail";
|
|
58
|
+
import type { RawData } from "ws";
|
|
59
|
+
import type { CommandModule } from "yargs";
|
|
60
|
+
import type Yargs from "yargs";
|
|
34
61
|
|
|
35
|
-
|
|
36
|
-
import path from "path/posix";
|
|
37
|
-
import { writeFile } from "node:fs/promises";
|
|
38
|
-
import { toFormData } from "./api/form_data";
|
|
62
|
+
type ConfigPath = string | undefined;
|
|
39
63
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
64
|
+
const resetColor = "\x1b[0m";
|
|
65
|
+
const fgGreenColor = "\x1b[32m";
|
|
66
|
+
|
|
67
|
+
function getRules(config: Config): Config["rules"] {
|
|
68
|
+
const rules = config.rules ?? config.build?.upload?.rules ?? [];
|
|
45
69
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
// TODO - terminate this early instead of going all the way to the root
|
|
70
|
+
if (config.rules && config.build?.upload?.rules) {
|
|
71
|
+
throw new Error(
|
|
72
|
+
`You cannot configure both [rules] and [build.upload.rules] in your wrangler.toml. Delete the \`build.upload\` section.`
|
|
73
|
+
);
|
|
51
74
|
}
|
|
52
75
|
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
76
|
+
if (config.build?.upload?.rules) {
|
|
77
|
+
console.warn(
|
|
78
|
+
`Deprecation notice: The \`build.upload.rules\` config field is no longer used, the rules should be specified via the \`rules\` config field. Delete the \`build.upload\` field from the configuration file, and add this:
|
|
79
|
+
|
|
80
|
+
${TOML.stringify({ rules: config.build.upload.rules })}`
|
|
81
|
+
);
|
|
57
82
|
}
|
|
83
|
+
return rules;
|
|
84
|
+
}
|
|
58
85
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
Object.keys(config.env || {}).forEach((env) => {
|
|
76
|
-
inheritedFields.forEach((field) => {
|
|
77
|
-
if (config[field] !== undefined && config.env[env][field] === undefined) {
|
|
78
|
-
config.env[env][field] = config[field]; // TODO: - shallow copy?
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
});
|
|
86
|
+
function printWranglerBanner() {
|
|
87
|
+
// Let's not print this in tests
|
|
88
|
+
if (typeof jest !== "undefined") {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const text = ` ⛅️ wrangler ${wranglerVersion} `;
|
|
92
|
+
|
|
93
|
+
console.log(
|
|
94
|
+
text +
|
|
95
|
+
"\n" +
|
|
96
|
+
(supportsColor.stdout
|
|
97
|
+
? chalk.hex("#FF8800")("-".repeat(text.length))
|
|
98
|
+
: "-".repeat(text.length))
|
|
99
|
+
);
|
|
100
|
+
}
|
|
82
101
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
"
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
Object.keys(config.env || {}).forEach((env) => {
|
|
90
|
-
mirroredFields.forEach((field) => {
|
|
91
|
-
// if it exists on top level, it should exist on env definitions
|
|
92
|
-
Object.keys(config[field] || {}).forEach((fieldKey) => {
|
|
93
|
-
if (!(fieldKey in config.env[env][field])) {
|
|
94
|
-
console.warn(
|
|
95
|
-
`In your configuration, "${field}.${fieldKey}" exists at a top level, but not on "env.${env}". This is not what you probably want, since the field "${field}" is not inherited by environments. Please add "${field}.${fieldKey}" to "env.${env}".`
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
});
|
|
102
|
+
function isLegacyEnv(args: unknown, config: Config): boolean {
|
|
103
|
+
return (
|
|
104
|
+
(args as { "legacy-env": boolean | undefined })["legacy-env"] ??
|
|
105
|
+
config.legacy_env
|
|
106
|
+
);
|
|
107
|
+
}
|
|
101
108
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
109
|
+
function getScriptName(
|
|
110
|
+
args: { name: string | undefined; env: string | undefined },
|
|
111
|
+
config: Config
|
|
112
|
+
): string | undefined {
|
|
113
|
+
const shortScriptName = args.name ?? config.name;
|
|
114
|
+
if (!shortScriptName) {
|
|
115
|
+
return;
|
|
106
116
|
}
|
|
107
117
|
|
|
108
|
-
|
|
109
|
-
|
|
118
|
+
return isLegacyEnv(args, config)
|
|
119
|
+
? `${shortScriptName}${args.env ? `-${args.env}` : ""}`
|
|
120
|
+
: shortScriptName;
|
|
121
|
+
}
|
|
110
122
|
|
|
111
|
-
|
|
112
|
-
|
|
123
|
+
/**
|
|
124
|
+
* Ensure that a user is logged in, and a valid account_id is available.
|
|
125
|
+
*/
|
|
126
|
+
async function requireAuth(
|
|
127
|
+
config: Config,
|
|
128
|
+
isInteractive = true
|
|
129
|
+
): Promise<string> {
|
|
130
|
+
const loggedIn = await loginOrRefreshIfRequired(isInteractive);
|
|
131
|
+
if (!loggedIn) {
|
|
132
|
+
// didn't login, let's just quit
|
|
133
|
+
throw new Error("Did not login, quitting...");
|
|
134
|
+
}
|
|
135
|
+
const accountId = config.account_id || (await getAccountId(isInteractive));
|
|
136
|
+
if (!accountId) {
|
|
137
|
+
throw new Error("No account id found, quitting...");
|
|
138
|
+
}
|
|
113
139
|
|
|
114
|
-
return
|
|
140
|
+
return accountId;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Get a promise to the streamed input from stdin.
|
|
145
|
+
*
|
|
146
|
+
* This function can be used to grab the incoming stream of data from, say,
|
|
147
|
+
* piping the output of another process into the wrangler process.
|
|
148
|
+
*/
|
|
149
|
+
function readFromStdin(): Promise<string> {
|
|
150
|
+
return new Promise((resolve, reject) => {
|
|
151
|
+
const stdin = process.stdin;
|
|
152
|
+
const chunks: string[] = [];
|
|
153
|
+
|
|
154
|
+
// When there is data ready to be read, the `readable` event will be triggered.
|
|
155
|
+
// In the handler for `readable` we call `read()` over and over until all the available data has been read.
|
|
156
|
+
stdin.on("readable", () => {
|
|
157
|
+
let chunk;
|
|
158
|
+
while (null !== (chunk = stdin.read())) {
|
|
159
|
+
chunks.push(chunk);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// When the streamed data is complete the `end` event will be triggered.
|
|
164
|
+
// In the handler for `end` we join the chunks together and resolve the promise.
|
|
165
|
+
stdin.on("end", () => {
|
|
166
|
+
resolve(chunks.join(""));
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// If there is an `error` event then the handler will reject the promise.
|
|
170
|
+
stdin.on("error", (err) => {
|
|
171
|
+
reject(err);
|
|
172
|
+
});
|
|
173
|
+
});
|
|
115
174
|
}
|
|
116
175
|
|
|
117
176
|
// a helper to demand one of a set of options
|
|
@@ -140,8 +199,11 @@ function demandOneOfOption(...options: string[]) {
|
|
|
140
199
|
}
|
|
141
200
|
|
|
142
201
|
class CommandLineArgsError extends Error {}
|
|
143
|
-
class DeprecationError extends Error {
|
|
144
|
-
|
|
202
|
+
class DeprecationError extends Error {
|
|
203
|
+
constructor(message: string) {
|
|
204
|
+
super(`DEPRECATION WARNING:\n${message}`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
145
207
|
|
|
146
208
|
export async function main(argv: string[]): Promise<void> {
|
|
147
209
|
const wrangler = makeCLI(argv)
|
|
@@ -159,7 +221,15 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
159
221
|
.scriptName("wrangler")
|
|
160
222
|
.wrap(null);
|
|
161
223
|
|
|
162
|
-
//
|
|
224
|
+
// Default help command that supports the subcommands
|
|
225
|
+
const subHelp: CommandModule = {
|
|
226
|
+
command: ["*"],
|
|
227
|
+
handler: async (args) => {
|
|
228
|
+
setImmediate(() =>
|
|
229
|
+
wrangler.parse([...args._.map((a) => `${a}`), "--help"])
|
|
230
|
+
);
|
|
231
|
+
},
|
|
232
|
+
};
|
|
163
233
|
wrangler.command(
|
|
164
234
|
["*"],
|
|
165
235
|
false,
|
|
@@ -200,7 +270,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
200
270
|
() => {
|
|
201
271
|
// "👯 [DEPRECATED]. Scaffold a Cloudflare Workers project from a public GitHub repository.",
|
|
202
272
|
throw new DeprecationError(
|
|
203
|
-
"`wrangler generate` has been deprecated, please refer to
|
|
273
|
+
"`wrangler generate` has been deprecated, please refer to https://github.com/cloudflare/wrangler2/blob/main/docs/deprecations.md#generate for alternatives"
|
|
204
274
|
);
|
|
205
275
|
}
|
|
206
276
|
);
|
|
@@ -210,12 +280,19 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
210
280
|
"init [name]",
|
|
211
281
|
"📥 Create a wrangler.toml configuration file",
|
|
212
282
|
(yargs) => {
|
|
213
|
-
return yargs
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
283
|
+
return yargs
|
|
284
|
+
.positional("name", {
|
|
285
|
+
describe: "The name of your worker",
|
|
286
|
+
type: "string",
|
|
287
|
+
})
|
|
288
|
+
.option("yes", {
|
|
289
|
+
describe: 'Answer "yes" to any prompts for new projects',
|
|
290
|
+
type: "boolean",
|
|
291
|
+
alias: "y",
|
|
292
|
+
});
|
|
217
293
|
},
|
|
218
294
|
async (args) => {
|
|
295
|
+
printWranglerBanner();
|
|
219
296
|
if ("type" in args) {
|
|
220
297
|
let message = "The --type option is no longer supported.";
|
|
221
298
|
if (args.type === "webpack") {
|
|
@@ -226,94 +303,285 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
226
303
|
throw new CommandLineArgsError(message);
|
|
227
304
|
}
|
|
228
305
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
306
|
+
// TODO: make sure args.name is a valid identifier for a worker name
|
|
307
|
+
|
|
308
|
+
const creationDirectory = path.join(process.cwd(), args.name ?? "");
|
|
309
|
+
|
|
310
|
+
const packageManager = await getPackageManager(creationDirectory);
|
|
311
|
+
|
|
312
|
+
// TODO: ask which directory to make the worker in (defaults to args.name)
|
|
313
|
+
// TODO: if args.name isn't provided, ask what to name the worker
|
|
314
|
+
|
|
315
|
+
const wranglerTomlDestination = path.join(
|
|
316
|
+
creationDirectory,
|
|
317
|
+
"./wrangler.toml"
|
|
318
|
+
);
|
|
319
|
+
let justCreatedWranglerToml = false;
|
|
320
|
+
const workerName =
|
|
321
|
+
args.name || path.basename(path.resolve(process.cwd()));
|
|
322
|
+
if (fs.existsSync(wranglerTomlDestination)) {
|
|
323
|
+
console.warn(`${wranglerTomlDestination} file already exists!`);
|
|
324
|
+
const shouldContinue = await confirm(
|
|
233
325
|
"Do you want to continue initializing this project?"
|
|
234
326
|
);
|
|
235
|
-
if (!
|
|
327
|
+
if (!shouldContinue) {
|
|
236
328
|
return;
|
|
237
329
|
}
|
|
330
|
+
} else {
|
|
331
|
+
await mkdir(creationDirectory, { recursive: true });
|
|
332
|
+
const compatibilityDate = new Date().toISOString().substring(0, 10);
|
|
333
|
+
try {
|
|
334
|
+
await writeFile(
|
|
335
|
+
wranglerTomlDestination,
|
|
336
|
+
TOML.stringify({
|
|
337
|
+
name: workerName,
|
|
338
|
+
compatibility_date: compatibilityDate,
|
|
339
|
+
}) + "\n"
|
|
340
|
+
);
|
|
341
|
+
console.log(`✨ Successfully created wrangler.toml`);
|
|
342
|
+
justCreatedWranglerToml = true;
|
|
343
|
+
} catch (err) {
|
|
344
|
+
throw new Error(
|
|
345
|
+
`Failed to create wrangler.toml.\n${(err as Error).message ?? err}`
|
|
346
|
+
);
|
|
347
|
+
}
|
|
238
348
|
}
|
|
239
349
|
|
|
240
|
-
const compatibilityDate = new Date().toISOString().substring(0, 10);
|
|
241
|
-
try {
|
|
242
|
-
await writeFile(
|
|
243
|
-
destination,
|
|
244
|
-
`compatibility_date = "${compatibilityDate}"` + "\n"
|
|
245
|
-
);
|
|
246
|
-
console.log(`✨ Successfully created wrangler.toml`);
|
|
247
|
-
// TODO: suggest next steps?
|
|
248
|
-
} catch (err) {
|
|
249
|
-
throw new Error(
|
|
250
|
-
`Failed to create wrangler.toml.\n${err.message ?? err}`
|
|
251
|
-
);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// if no package.json, ask, and if yes, create one
|
|
255
350
|
let pathToPackageJson = await findUp("package.json");
|
|
256
|
-
|
|
351
|
+
let shouldCreatePackageJson = false;
|
|
352
|
+
const yesFlag = args.yes ?? false;
|
|
257
353
|
if (!pathToPackageJson) {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
354
|
+
// If no package.json exists, ask to create one
|
|
355
|
+
shouldCreatePackageJson =
|
|
356
|
+
yesFlag ||
|
|
357
|
+
(await confirm(
|
|
358
|
+
"No package.json found. Would you like to create one?"
|
|
359
|
+
));
|
|
360
|
+
|
|
361
|
+
if (shouldCreatePackageJson) {
|
|
261
362
|
await writeFile(
|
|
262
|
-
path.join(
|
|
363
|
+
path.join(creationDirectory, "./package.json"),
|
|
263
364
|
JSON.stringify(
|
|
264
365
|
{
|
|
265
|
-
name:
|
|
266
|
-
version: "0.0.
|
|
366
|
+
name: workerName,
|
|
367
|
+
version: "0.0.0",
|
|
368
|
+
devDependencies: {
|
|
369
|
+
wrangler: wranglerVersion,
|
|
370
|
+
},
|
|
371
|
+
private: true,
|
|
267
372
|
},
|
|
268
373
|
null,
|
|
269
374
|
" "
|
|
270
375
|
) + "\n"
|
|
271
376
|
);
|
|
377
|
+
await packageManager.install();
|
|
272
378
|
console.log(`✨ Created package.json`);
|
|
273
|
-
pathToPackageJson = path.join(
|
|
379
|
+
pathToPackageJson = path.join(creationDirectory, "package.json");
|
|
274
380
|
} else {
|
|
275
381
|
return;
|
|
276
382
|
}
|
|
383
|
+
} else {
|
|
384
|
+
// If package.json exists and wrangler isn't installed,
|
|
385
|
+
// then ask to add wrangler to devDependencies
|
|
386
|
+
const packageJson = parseJSON(
|
|
387
|
+
readFileSync(pathToPackageJson),
|
|
388
|
+
pathToPackageJson
|
|
389
|
+
);
|
|
390
|
+
if (
|
|
391
|
+
!(
|
|
392
|
+
packageJson.devDependencies?.wrangler ||
|
|
393
|
+
packageJson.dependencies?.wrangler
|
|
394
|
+
)
|
|
395
|
+
) {
|
|
396
|
+
const shouldInstall =
|
|
397
|
+
yesFlag ||
|
|
398
|
+
(await confirm(
|
|
399
|
+
"Would you like to install wrangler into your package.json?"
|
|
400
|
+
));
|
|
401
|
+
if (shouldInstall) {
|
|
402
|
+
await packageManager.addDevDeps(`wrangler@${wranglerVersion}`);
|
|
403
|
+
console.log(`✨ Installed wrangler`);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
277
406
|
}
|
|
278
407
|
|
|
279
|
-
|
|
280
|
-
// offer to install it
|
|
281
|
-
// and make a tsconfig?
|
|
408
|
+
let isTypescriptProject = false;
|
|
282
409
|
let pathToTSConfig = await findUp("tsconfig.json");
|
|
283
410
|
if (!pathToTSConfig) {
|
|
284
|
-
|
|
411
|
+
// If there's no tsconfig, offer to create one
|
|
412
|
+
// and install @cloudflare/workers-types
|
|
413
|
+
if (yesFlag || (await confirm("Would you like to use TypeScript?"))) {
|
|
414
|
+
isTypescriptProject = true;
|
|
415
|
+
await writeFile(
|
|
416
|
+
path.join(creationDirectory, "./tsconfig.json"),
|
|
417
|
+
readFileSync(path.join(__dirname, "../templates/tsconfig.json"))
|
|
418
|
+
);
|
|
419
|
+
await packageManager.addDevDeps(
|
|
420
|
+
"@cloudflare/workers-types",
|
|
421
|
+
"typescript"
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
console.log(
|
|
425
|
+
`✨ Created tsconfig.json, installed @cloudflare/workers-types into devDependencies`
|
|
426
|
+
);
|
|
427
|
+
pathToTSConfig = path.join(creationDirectory, "tsconfig.json");
|
|
428
|
+
}
|
|
429
|
+
} else {
|
|
430
|
+
isTypescriptProject = true;
|
|
431
|
+
// If there's a tsconfig, check if @cloudflare/workers-types
|
|
432
|
+
// is already installed, and offer to install it if not
|
|
433
|
+
const packageJson = parseJSON(
|
|
434
|
+
readFileSync(pathToPackageJson),
|
|
435
|
+
pathToPackageJson
|
|
436
|
+
);
|
|
437
|
+
if (
|
|
438
|
+
!(
|
|
439
|
+
packageJson.devDependencies?.["@cloudflare/workers-types"] ||
|
|
440
|
+
packageJson.dependencies?.["@cloudflare/workers-types"]
|
|
441
|
+
)
|
|
442
|
+
) {
|
|
443
|
+
const shouldInstall = await confirm(
|
|
444
|
+
"Would you like to install the type definitions for Workers into your package.json?"
|
|
445
|
+
);
|
|
446
|
+
if (shouldInstall) {
|
|
447
|
+
await packageManager.addDevDeps("@cloudflare/workers-types");
|
|
448
|
+
// We don't update the tsconfig.json because
|
|
449
|
+
// it could be complicated in existing projects
|
|
450
|
+
// and we don't want to break them. Instead, we simply
|
|
451
|
+
// tell the user that they need to update their tsconfig.json
|
|
452
|
+
console.log(
|
|
453
|
+
`✨ Installed @cloudflare/workers-types.\nPlease add "@cloudflare/workers-types" to compilerOptions.types in your tsconfig.json`
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
const packageJsonContent = parseJSON(
|
|
460
|
+
readFileSync(pathToPackageJson),
|
|
461
|
+
pathToPackageJson
|
|
462
|
+
);
|
|
463
|
+
const shouldWritePackageJsonScripts =
|
|
464
|
+
!packageJsonContent.scripts?.start &&
|
|
465
|
+
!packageJsonContent.scripts?.publish &&
|
|
466
|
+
shouldCreatePackageJson;
|
|
467
|
+
|
|
468
|
+
async function writePackageJsonScriptsAndUpdateWranglerToml(
|
|
469
|
+
isWritingScripts: boolean,
|
|
470
|
+
isCreatingWranglerToml: boolean,
|
|
471
|
+
packagePath: string,
|
|
472
|
+
scriptPath: string
|
|
473
|
+
) {
|
|
474
|
+
if (isCreatingWranglerToml) {
|
|
475
|
+
// rewrite wrangler.toml with main = "path/to/script"
|
|
476
|
+
const parsedWranglerToml = TOML.parse(
|
|
477
|
+
readFileSync(wranglerTomlDestination)
|
|
478
|
+
);
|
|
479
|
+
fs.writeFileSync(
|
|
480
|
+
wranglerTomlDestination,
|
|
481
|
+
TOML.stringify({
|
|
482
|
+
name: parsedWranglerToml.name,
|
|
483
|
+
main: scriptPath,
|
|
484
|
+
compatibility_date: parsedWranglerToml.compatibility_date,
|
|
485
|
+
})
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
const isNamedWorker =
|
|
489
|
+
isCreatingWranglerToml && path.dirname(packagePath) !== process.cwd();
|
|
490
|
+
|
|
491
|
+
if (isWritingScripts) {
|
|
285
492
|
await writeFile(
|
|
286
|
-
|
|
493
|
+
packagePath,
|
|
287
494
|
JSON.stringify(
|
|
288
495
|
{
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
lib: ["esnext"],
|
|
299
|
-
jsx: "react",
|
|
300
|
-
resolveJsonModule: true,
|
|
301
|
-
types: ["@cloudflare/workers-types"],
|
|
496
|
+
...packageJsonContent,
|
|
497
|
+
scripts: {
|
|
498
|
+
...packageJsonContent.scripts,
|
|
499
|
+
start: isCreatingWranglerToml
|
|
500
|
+
? `wrangler dev`
|
|
501
|
+
: `wrangler dev ${scriptPath}`,
|
|
502
|
+
publish: isCreatingWranglerToml
|
|
503
|
+
? `wrangler publish`
|
|
504
|
+
: `wrangler publish ${scriptPath}`,
|
|
302
505
|
},
|
|
303
506
|
},
|
|
304
507
|
null,
|
|
305
|
-
|
|
508
|
+
2
|
|
306
509
|
) + "\n"
|
|
307
510
|
);
|
|
308
|
-
await execa("npm", [
|
|
309
|
-
"install",
|
|
310
|
-
"@cloudflare/workers-types",
|
|
311
|
-
"--save-dev",
|
|
312
|
-
]);
|
|
313
511
|
console.log(
|
|
314
|
-
|
|
512
|
+
`\nTo start developing your Worker, run \`${
|
|
513
|
+
isNamedWorker ? `cd ${args.name} && ` : ""
|
|
514
|
+
}npm start\``
|
|
515
|
+
);
|
|
516
|
+
console.log(
|
|
517
|
+
`To publish your Worker to the Internet, run \`npm run publish\``
|
|
518
|
+
);
|
|
519
|
+
} else {
|
|
520
|
+
console.log(
|
|
521
|
+
`\nTo start developing your Worker, run \`npx wrangler dev\`${
|
|
522
|
+
isCreatingWranglerToml ? "" : ` ${scriptPath}`
|
|
523
|
+
}`
|
|
524
|
+
);
|
|
525
|
+
console.log(
|
|
526
|
+
`To publish your Worker to the Internet, run \`npx wrangler publish\`${
|
|
527
|
+
isCreatingWranglerToml ? "" : ` ${scriptPath}`
|
|
528
|
+
}`
|
|
315
529
|
);
|
|
316
|
-
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
if (isTypescriptProject) {
|
|
534
|
+
if (!fs.existsSync(path.join(creationDirectory, "./src/index.ts"))) {
|
|
535
|
+
let shouldCreateSource = false;
|
|
536
|
+
|
|
537
|
+
shouldCreateSource =
|
|
538
|
+
yesFlag ||
|
|
539
|
+
(await confirm(
|
|
540
|
+
`Would you like to create a Worker at src/index.ts?`
|
|
541
|
+
));
|
|
542
|
+
|
|
543
|
+
if (shouldCreateSource) {
|
|
544
|
+
await mkdir(path.join(creationDirectory, "./src"), {
|
|
545
|
+
recursive: true,
|
|
546
|
+
});
|
|
547
|
+
await writeFile(
|
|
548
|
+
path.join(creationDirectory, "./src/index.ts"),
|
|
549
|
+
readFileSync(path.join(__dirname, "../templates/new-worker.ts"))
|
|
550
|
+
);
|
|
551
|
+
|
|
552
|
+
console.log(`✨ Created src/index.ts`);
|
|
553
|
+
|
|
554
|
+
await writePackageJsonScriptsAndUpdateWranglerToml(
|
|
555
|
+
shouldWritePackageJsonScripts,
|
|
556
|
+
justCreatedWranglerToml,
|
|
557
|
+
pathToPackageJson,
|
|
558
|
+
"src/index.ts"
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
} else {
|
|
563
|
+
if (!fs.existsSync("./src/index.js")) {
|
|
564
|
+
const shouldCreateSource = await confirm(
|
|
565
|
+
`Would you like to create a Worker at src/index.js?`
|
|
566
|
+
);
|
|
567
|
+
if (shouldCreateSource) {
|
|
568
|
+
await mkdir(path.join(creationDirectory, "./src"), {
|
|
569
|
+
recursive: true,
|
|
570
|
+
});
|
|
571
|
+
await writeFile(
|
|
572
|
+
path.join(path.join(creationDirectory, "./src/index.js")),
|
|
573
|
+
readFileSync(path.join(__dirname, "../templates/new-worker.js"))
|
|
574
|
+
);
|
|
575
|
+
|
|
576
|
+
console.log(`✨ Created src/index.js`);
|
|
577
|
+
|
|
578
|
+
await writePackageJsonScriptsAndUpdateWranglerToml(
|
|
579
|
+
shouldWritePackageJsonScripts,
|
|
580
|
+
justCreatedWranglerToml,
|
|
581
|
+
pathToPackageJson,
|
|
582
|
+
"src/index.js"
|
|
583
|
+
);
|
|
584
|
+
}
|
|
317
585
|
}
|
|
318
586
|
}
|
|
319
587
|
}
|
|
@@ -331,7 +599,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
331
599
|
() => {
|
|
332
600
|
// "[DEPRECATED] 🦀 Build your project (if applicable)",
|
|
333
601
|
throw new DeprecationError(
|
|
334
|
-
"`wrangler build` has been deprecated, please refer to
|
|
602
|
+
"`wrangler build` has been deprecated, please refer to https://github.com/cloudflare/wrangler2/blob/main/docs/deprecations.md#build for alternatives"
|
|
335
603
|
);
|
|
336
604
|
}
|
|
337
605
|
);
|
|
@@ -347,10 +615,10 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
347
615
|
// I mean, this entire app does, but this too.
|
|
348
616
|
return yargs
|
|
349
617
|
.option("scopes-list", {
|
|
350
|
-
describe: "
|
|
618
|
+
describe: "List all the available OAuth scopes with descriptions",
|
|
351
619
|
})
|
|
352
620
|
.option("scopes", {
|
|
353
|
-
describe: "
|
|
621
|
+
describe: "Pick the set of applicable OAuth scopes when logging in",
|
|
354
622
|
array: true,
|
|
355
623
|
type: "string",
|
|
356
624
|
});
|
|
@@ -358,6 +626,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
358
626
|
// TODO: scopes
|
|
359
627
|
},
|
|
360
628
|
async (args) => {
|
|
629
|
+
printWranglerBanner();
|
|
361
630
|
if (args["scopes-list"]) {
|
|
362
631
|
listScopes();
|
|
363
632
|
return;
|
|
@@ -368,6 +637,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
368
637
|
listScopes();
|
|
369
638
|
return;
|
|
370
639
|
}
|
|
640
|
+
if (!validateScopeKeys(args.scopes)) {
|
|
641
|
+
throw new CommandLineArgsError(
|
|
642
|
+
`One of ${args.scopes} is not a valid authentication scope. Run "wrangler login --list-scopes" to see the valid scopes.`
|
|
643
|
+
);
|
|
644
|
+
}
|
|
371
645
|
await login({ scopes: args.scopes });
|
|
372
646
|
return;
|
|
373
647
|
}
|
|
@@ -387,6 +661,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
387
661
|
// "🚪 Logout from Cloudflare",
|
|
388
662
|
() => {},
|
|
389
663
|
async () => {
|
|
664
|
+
printWranglerBanner();
|
|
390
665
|
await logout();
|
|
391
666
|
}
|
|
392
667
|
);
|
|
@@ -394,11 +669,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
394
669
|
// whoami
|
|
395
670
|
wrangler.command(
|
|
396
671
|
"whoami",
|
|
397
|
-
|
|
398
|
-
// "🕵️ Retrieve your user info and test your auth config",
|
|
672
|
+
"🕵️ Retrieve your user info and test your auth config",
|
|
399
673
|
() => {},
|
|
400
|
-
(
|
|
401
|
-
|
|
674
|
+
async () => {
|
|
675
|
+
printWranglerBanner();
|
|
676
|
+
await whoami();
|
|
402
677
|
}
|
|
403
678
|
);
|
|
404
679
|
|
|
@@ -410,20 +685,23 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
410
685
|
() => {
|
|
411
686
|
// "🕵️ Authenticate Wrangler with a Cloudflare API Token",
|
|
412
687
|
throw new DeprecationError(
|
|
413
|
-
"`wrangler config` has been deprecated, please refer to
|
|
688
|
+
"`wrangler config` has been deprecated, please refer to https://github.com/cloudflare/wrangler2/blob/main/docs/deprecations.md#config for alternatives"
|
|
414
689
|
);
|
|
415
690
|
}
|
|
416
691
|
);
|
|
417
692
|
|
|
418
693
|
// dev
|
|
419
694
|
wrangler.command(
|
|
420
|
-
"dev
|
|
695
|
+
"dev [script]",
|
|
421
696
|
"👂 Start a local server for developing your worker",
|
|
422
697
|
(yargs) => {
|
|
423
698
|
return yargs
|
|
424
|
-
.positional("
|
|
699
|
+
.positional("script", {
|
|
700
|
+
describe: "The path to an entry point for your worker",
|
|
701
|
+
type: "string",
|
|
702
|
+
})
|
|
425
703
|
.option("name", {
|
|
426
|
-
describe: "
|
|
704
|
+
describe: "Name of the worker",
|
|
427
705
|
type: "string",
|
|
428
706
|
})
|
|
429
707
|
.option("format", {
|
|
@@ -433,7 +711,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
433
711
|
.option("env", {
|
|
434
712
|
describe: "Perform on a specific environment",
|
|
435
713
|
type: "string",
|
|
436
|
-
|
|
714
|
+
alias: "e",
|
|
437
715
|
})
|
|
438
716
|
.option("compatibility-date", {
|
|
439
717
|
describe: "Date to use for compatibility checks",
|
|
@@ -450,14 +728,21 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
450
728
|
default: true,
|
|
451
729
|
})
|
|
452
730
|
.option("ip", {
|
|
453
|
-
describe: "IP address to listen on",
|
|
731
|
+
describe: "IP address to listen on, defaults to `localhost`",
|
|
454
732
|
type: "string",
|
|
455
|
-
default: "127.0.0.1",
|
|
456
733
|
})
|
|
457
734
|
.option("port", {
|
|
458
|
-
describe: "Port to listen on
|
|
735
|
+
describe: "Port to listen on",
|
|
736
|
+
type: "number",
|
|
737
|
+
})
|
|
738
|
+
.option("inspector-port", {
|
|
739
|
+
describe: "Port for devtools to connect to",
|
|
459
740
|
type: "number",
|
|
460
|
-
|
|
741
|
+
})
|
|
742
|
+
.option("routes", {
|
|
743
|
+
describe: "Routes to upload",
|
|
744
|
+
alias: "route",
|
|
745
|
+
type: "array",
|
|
461
746
|
})
|
|
462
747
|
.option("host", {
|
|
463
748
|
type: "string",
|
|
@@ -465,9 +750,8 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
465
750
|
"Host to forward requests to, defaults to the zone of project",
|
|
466
751
|
})
|
|
467
752
|
.option("local-protocol", {
|
|
468
|
-
default: "http",
|
|
469
753
|
describe: "Protocol to listen to requests on, defaults to http.",
|
|
470
|
-
choices: ["http", "https"],
|
|
754
|
+
choices: ["http", "https"] as const,
|
|
471
755
|
})
|
|
472
756
|
.option("experimental-public", {
|
|
473
757
|
describe: "Static assets to be served",
|
|
@@ -477,11 +761,22 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
477
761
|
describe: "Root folder of static assets for Workers Sites",
|
|
478
762
|
type: "string",
|
|
479
763
|
})
|
|
764
|
+
.option("site-include", {
|
|
765
|
+
describe:
|
|
766
|
+
"Array of .gitignore-style patterns that match file or directory names from the sites directory. Only matched items will be uploaded.",
|
|
767
|
+
type: "string",
|
|
768
|
+
array: true,
|
|
769
|
+
})
|
|
770
|
+
.option("site-exclude", {
|
|
771
|
+
describe:
|
|
772
|
+
"Array of .gitignore-style patterns that match file or directory names from the sites directory. Matched items will not be uploaded.",
|
|
773
|
+
type: "string",
|
|
774
|
+
array: true,
|
|
775
|
+
})
|
|
480
776
|
.option("upstream-protocol", {
|
|
481
|
-
default: "https",
|
|
482
777
|
describe:
|
|
483
778
|
"Protocol to forward requests to host on, defaults to https.",
|
|
484
|
-
choices: ["http", "https"],
|
|
779
|
+
choices: ["http", "https"] as const,
|
|
485
780
|
})
|
|
486
781
|
.option("jsx-factory", {
|
|
487
782
|
describe: "The function that is called for each JSX element",
|
|
@@ -490,11 +785,25 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
490
785
|
.option("jsx-fragment", {
|
|
491
786
|
describe: "The function that is called for each JSX fragment",
|
|
492
787
|
type: "string",
|
|
788
|
+
})
|
|
789
|
+
.option("local", {
|
|
790
|
+
alias: "l",
|
|
791
|
+
describe: "Run on my machine",
|
|
792
|
+
type: "boolean",
|
|
793
|
+
default: false, // I bet this will a point of contention. We'll revisit it.
|
|
794
|
+
})
|
|
795
|
+
.option("experimental-enable-local-persistence", {
|
|
796
|
+
describe: "Enable persistence for this session (only for local mode)",
|
|
797
|
+
type: "boolean",
|
|
493
798
|
});
|
|
494
799
|
},
|
|
495
800
|
async (args) => {
|
|
496
|
-
|
|
497
|
-
const
|
|
801
|
+
printWranglerBanner();
|
|
802
|
+
const configPath =
|
|
803
|
+
(args.config as ConfigPath) ||
|
|
804
|
+
(args.script && findWranglerToml(path.dirname(args.script)));
|
|
805
|
+
const config = readConfig(configPath, args.env);
|
|
806
|
+
const entry = await getEntry(args, config, "dev");
|
|
498
807
|
|
|
499
808
|
if (args["experimental-public"]) {
|
|
500
809
|
console.warn(
|
|
@@ -508,50 +817,122 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
508
817
|
);
|
|
509
818
|
}
|
|
510
819
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
if (!config.account_id) {
|
|
521
|
-
config.account_id = await getAccountId();
|
|
522
|
-
if (!config.account_id) {
|
|
523
|
-
throw new Error("No account id found, quitting...");
|
|
524
|
-
}
|
|
525
|
-
}
|
|
820
|
+
const upstreamProtocol =
|
|
821
|
+
(args["upstream-protocol"] as "http" | "https") ||
|
|
822
|
+
config.dev.upstream_protocol;
|
|
823
|
+
if (upstreamProtocol === "http") {
|
|
824
|
+
console.warn(
|
|
825
|
+
"Setting upstream-protocol to http is not currently implemented.\n" +
|
|
826
|
+
"If this is required in your project, please add your use case to the following issue:\n" +
|
|
827
|
+
"https://github.com/cloudflare/wrangler2/issues/583."
|
|
828
|
+
);
|
|
526
829
|
}
|
|
527
830
|
|
|
528
|
-
|
|
831
|
+
const accountId = !args.local ? await requireAuth(config) : undefined;
|
|
529
832
|
|
|
530
|
-
|
|
833
|
+
// TODO: if worker_dev = false and no routes, then error (only for dev)
|
|
531
834
|
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
)
|
|
835
|
+
/**
|
|
836
|
+
* Given something that resembles a URL,
|
|
837
|
+
* try to extract a host from it
|
|
838
|
+
*/
|
|
839
|
+
function getHost(urlLike: string): string | undefined {
|
|
840
|
+
if (
|
|
841
|
+
!(urlLike.startsWith("http://") || urlLike.startsWith("https://"))
|
|
842
|
+
) {
|
|
843
|
+
urlLike = "http://" + urlLike;
|
|
539
844
|
}
|
|
540
|
-
|
|
845
|
+
return new URL(urlLike).host;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
/**
|
|
849
|
+
* Given something that resembles a host,
|
|
850
|
+
* try to infer a zone id from it
|
|
851
|
+
*/
|
|
852
|
+
async function getZoneId(host: string): Promise<string | undefined> {
|
|
853
|
+
const zones = await fetchResult<{ id: string }[]>(
|
|
854
|
+
`/zones`,
|
|
855
|
+
{},
|
|
856
|
+
new URLSearchParams({ name: host })
|
|
857
|
+
);
|
|
858
|
+
return zones[0]?.id;
|
|
541
859
|
}
|
|
542
860
|
|
|
861
|
+
const hostLike =
|
|
862
|
+
args.host ||
|
|
863
|
+
config.dev.host ||
|
|
864
|
+
(args.routes && args.routes[0]) ||
|
|
865
|
+
config.route ||
|
|
866
|
+
(config.routes && config.routes[0]);
|
|
867
|
+
|
|
868
|
+
// When we're given a host (in one of the above ways), we do 2 things:
|
|
869
|
+
// - We try to extract a host from it
|
|
870
|
+
// - We try to get a zone id from the host
|
|
871
|
+
//
|
|
872
|
+
// So it turns out it's particularly hard to get a 'valid' domain
|
|
873
|
+
// from a string, so we don't even try to validate TLDs, etc.
|
|
874
|
+
// Once we get something that looks like w.x.y.z-ish, we then try to
|
|
875
|
+
// get a zone id for it, by lopping off subdomains until we get a hit
|
|
876
|
+
// from the API. That's it!
|
|
877
|
+
|
|
878
|
+
const host = typeof hostLike === "string" ? getHost(hostLike) : undefined;
|
|
879
|
+
|
|
880
|
+
let zoneId: string | undefined;
|
|
881
|
+
const hostPieces = typeof host === "string" ? host.split(".") : undefined;
|
|
882
|
+
|
|
883
|
+
while (hostPieces && hostPieces.length > 1) {
|
|
884
|
+
zoneId = await getZoneId(hostPieces.join("."));
|
|
885
|
+
if (zoneId) break;
|
|
886
|
+
hostPieces.shift();
|
|
887
|
+
}
|
|
888
|
+
if (host && !zoneId) {
|
|
889
|
+
throw new Error(`Could not find zone for ${hostLike}`);
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
const zone =
|
|
893
|
+
typeof zoneId === "string" && typeof host === "string"
|
|
894
|
+
? {
|
|
895
|
+
host,
|
|
896
|
+
id: zoneId,
|
|
897
|
+
}
|
|
898
|
+
: undefined;
|
|
899
|
+
|
|
543
900
|
const { waitUntilExit } = render(
|
|
544
901
|
<Dev
|
|
545
|
-
name={args
|
|
546
|
-
entry={
|
|
902
|
+
name={getScriptName(args, config)}
|
|
903
|
+
entry={entry}
|
|
904
|
+
env={args.env}
|
|
905
|
+
zone={zone}
|
|
906
|
+
rules={getRules(config)}
|
|
907
|
+
legacyEnv={isLegacyEnv(args, config)}
|
|
547
908
|
buildCommand={config.build || {}}
|
|
548
|
-
format={format}
|
|
549
909
|
initialMode={args.local ? "local" : "remote"}
|
|
550
|
-
jsxFactory={args["jsx-factory"] ||
|
|
551
|
-
jsxFragment={args["jsx-fragment"] ||
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
910
|
+
jsxFactory={args["jsx-factory"] || config.jsx_factory}
|
|
911
|
+
jsxFragment={args["jsx-fragment"] || config.jsx_fragment}
|
|
912
|
+
upstreamProtocol={upstreamProtocol}
|
|
913
|
+
localProtocol={
|
|
914
|
+
// The typings are not quite clever enough to handle element accesses, only property accesses,
|
|
915
|
+
// so we need to cast here.
|
|
916
|
+
(args["local-protocol"] as "http" | "https") ||
|
|
917
|
+
config.dev.local_protocol
|
|
918
|
+
}
|
|
919
|
+
enableLocalPersistence={
|
|
920
|
+
args["experimental-enable-local-persistence"] || false
|
|
921
|
+
}
|
|
922
|
+
accountId={accountId}
|
|
923
|
+
assetPaths={getAssetPaths(
|
|
924
|
+
config,
|
|
925
|
+
args.site,
|
|
926
|
+
args.siteInclude,
|
|
927
|
+
args.siteExclude
|
|
928
|
+
)}
|
|
929
|
+
port={
|
|
930
|
+
args.port || config.dev?.port || (await getPort({ port: 8787 }))
|
|
931
|
+
}
|
|
932
|
+
ip={args.ip || config.dev.ip}
|
|
933
|
+
inspectorPort={
|
|
934
|
+
args["inspector-port"] ?? (await getPort({ port: 9229 }))
|
|
935
|
+
}
|
|
555
936
|
public={args["experimental-public"]}
|
|
556
937
|
compatibilityDate={
|
|
557
938
|
args["compatibility-date"] ||
|
|
@@ -564,7 +945,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
564
945
|
}
|
|
565
946
|
usageModel={config.usage_model}
|
|
566
947
|
bindings={{
|
|
567
|
-
kv_namespaces:
|
|
948
|
+
kv_namespaces: config.kv_namespaces?.map(
|
|
568
949
|
({ binding, preview_id, id: _id }) => {
|
|
569
950
|
// In `dev`, we make folks use a separate kv namespace called
|
|
570
951
|
// `preview_id` instead of `id` so that they don't
|
|
@@ -585,9 +966,12 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
585
966
|
};
|
|
586
967
|
}
|
|
587
968
|
),
|
|
588
|
-
vars:
|
|
589
|
-
|
|
590
|
-
|
|
969
|
+
vars: config.vars,
|
|
970
|
+
wasm_modules: config.wasm_modules,
|
|
971
|
+
text_blobs: config.text_blobs,
|
|
972
|
+
durable_objects: config.durable_objects,
|
|
973
|
+
r2_buckets: config.r2_buckets,
|
|
974
|
+
unsafe: config.unsafe?.bindings,
|
|
591
975
|
}}
|
|
592
976
|
/>
|
|
593
977
|
);
|
|
@@ -604,15 +988,20 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
604
988
|
.option("env", {
|
|
605
989
|
type: "string",
|
|
606
990
|
describe: "Perform on a specific environment",
|
|
991
|
+
alias: "e",
|
|
607
992
|
})
|
|
608
993
|
.positional("script", {
|
|
609
|
-
describe: "
|
|
994
|
+
describe: "The path to an entry point for your worker",
|
|
610
995
|
type: "string",
|
|
611
996
|
})
|
|
612
997
|
.option("name", {
|
|
613
|
-
describe: "
|
|
998
|
+
describe: "Name of the worker",
|
|
614
999
|
type: "string",
|
|
615
1000
|
})
|
|
1001
|
+
.option("format", {
|
|
1002
|
+
choices: ["modules", "service-worker"] as const,
|
|
1003
|
+
describe: "Choose an entry type",
|
|
1004
|
+
})
|
|
616
1005
|
.option("compatibility-date", {
|
|
617
1006
|
describe: "Date to use for compatibility checks",
|
|
618
1007
|
type: "string",
|
|
@@ -635,22 +1024,28 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
635
1024
|
describe: "Root folder of static assets for Workers Sites",
|
|
636
1025
|
type: "string",
|
|
637
1026
|
})
|
|
1027
|
+
.option("site-include", {
|
|
1028
|
+
describe:
|
|
1029
|
+
"Array of .gitignore-style patterns that match file or directory names from the sites directory. Only matched items will be uploaded.",
|
|
1030
|
+
type: "string",
|
|
1031
|
+
array: true,
|
|
1032
|
+
})
|
|
1033
|
+
.option("site-exclude", {
|
|
1034
|
+
describe:
|
|
1035
|
+
"Array of .gitignore-style patterns that match file or directory names from the sites directory. Matched items will not be uploaded.",
|
|
1036
|
+
type: "string",
|
|
1037
|
+
array: true,
|
|
1038
|
+
})
|
|
638
1039
|
.option("triggers", {
|
|
639
1040
|
describe: "cron schedules to attach",
|
|
640
1041
|
alias: ["schedule", "schedules"],
|
|
641
1042
|
type: "array",
|
|
642
1043
|
})
|
|
643
1044
|
.option("routes", {
|
|
644
|
-
describe: "
|
|
1045
|
+
describe: "Routes to upload",
|
|
645
1046
|
alias: "route",
|
|
646
1047
|
type: "array",
|
|
647
1048
|
})
|
|
648
|
-
.option("services", {
|
|
649
|
-
describe: "experimental support for services",
|
|
650
|
-
type: "boolean",
|
|
651
|
-
default: "false",
|
|
652
|
-
hidden: true,
|
|
653
|
-
})
|
|
654
1049
|
.option("jsx-factory", {
|
|
655
1050
|
describe: "The function that is called for each JSX element",
|
|
656
1051
|
type: "string",
|
|
@@ -661,12 +1056,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
661
1056
|
});
|
|
662
1057
|
},
|
|
663
1058
|
async (args) => {
|
|
664
|
-
|
|
665
|
-
throw new NotImplementedError(
|
|
666
|
-
"🚫 Local publishing is not yet supported"
|
|
667
|
-
);
|
|
668
|
-
}
|
|
669
|
-
|
|
1059
|
+
printWranglerBanner();
|
|
670
1060
|
if (args["experimental-public"]) {
|
|
671
1061
|
console.warn(
|
|
672
1062
|
"🚨 The --experimental-public field is experimental and will change in the future."
|
|
@@ -678,7 +1068,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
678
1068
|
);
|
|
679
1069
|
}
|
|
680
1070
|
|
|
681
|
-
const
|
|
1071
|
+
const configPath =
|
|
1072
|
+
(args.config as ConfigPath) ||
|
|
1073
|
+
(args.script && findWranglerToml(path.dirname(args.script)));
|
|
1074
|
+
const config = readConfig(configPath, args.env);
|
|
1075
|
+
const entry = await getEntry(args, config, "publish");
|
|
682
1076
|
|
|
683
1077
|
if (args.latest) {
|
|
684
1078
|
console.warn(
|
|
@@ -686,28 +1080,20 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
686
1080
|
);
|
|
687
1081
|
}
|
|
688
1082
|
|
|
689
|
-
|
|
690
|
-
if (!args.local) {
|
|
691
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
692
|
-
if (!loggedIn) {
|
|
693
|
-
// didn't login, let's just quit
|
|
694
|
-
console.log("Did not login, quitting...");
|
|
695
|
-
return;
|
|
696
|
-
}
|
|
697
|
-
if (!config.account_id) {
|
|
698
|
-
config.account_id = await getAccountId();
|
|
699
|
-
if (!config.account_id) {
|
|
700
|
-
throw new Error("No account id found, quitting...");
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
// -- snip, end --
|
|
1083
|
+
const accountId = await requireAuth(config);
|
|
706
1084
|
|
|
1085
|
+
const assetPaths = getAssetPaths(
|
|
1086
|
+
config,
|
|
1087
|
+
args["experimental-public"] || args.site,
|
|
1088
|
+
args.siteInclude,
|
|
1089
|
+
args.siteExclude
|
|
1090
|
+
);
|
|
707
1091
|
await publish({
|
|
708
|
-
config
|
|
709
|
-
|
|
710
|
-
|
|
1092
|
+
config,
|
|
1093
|
+
accountId,
|
|
1094
|
+
name: getScriptName(args, config),
|
|
1095
|
+
rules: getRules(config),
|
|
1096
|
+
entry,
|
|
711
1097
|
env: args.env,
|
|
712
1098
|
compatibilityDate: args.latest
|
|
713
1099
|
? new Date().toISOString().substring(0, 10)
|
|
@@ -717,8 +1103,9 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
717
1103
|
jsxFactory: args["jsx-factory"],
|
|
718
1104
|
jsxFragment: args["jsx-fragment"],
|
|
719
1105
|
routes: args.routes,
|
|
720
|
-
|
|
721
|
-
|
|
1106
|
+
assetPaths,
|
|
1107
|
+
legacyEnv: isLegacyEnv(args, config),
|
|
1108
|
+
experimentalPublic: args["experimental-public"] !== undefined,
|
|
722
1109
|
});
|
|
723
1110
|
}
|
|
724
1111
|
);
|
|
@@ -726,12 +1113,12 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
726
1113
|
// tail
|
|
727
1114
|
wrangler.command(
|
|
728
1115
|
"tail [name]",
|
|
729
|
-
"🦚 Starts a log tailing session for a
|
|
1116
|
+
"🦚 Starts a log tailing session for a published Worker.",
|
|
730
1117
|
(yargs) => {
|
|
731
1118
|
return (
|
|
732
1119
|
yargs
|
|
733
1120
|
.positional("name", {
|
|
734
|
-
describe: "
|
|
1121
|
+
describe: "Name of the worker",
|
|
735
1122
|
type: "string",
|
|
736
1123
|
})
|
|
737
1124
|
// TODO: auto-detect if this should be json or pretty based on atty
|
|
@@ -743,6 +1130,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
743
1130
|
.option("status", {
|
|
744
1131
|
choices: ["ok", "error", "canceled"],
|
|
745
1132
|
describe: "Filter by invocation status",
|
|
1133
|
+
array: true,
|
|
746
1134
|
})
|
|
747
1135
|
.option("header", {
|
|
748
1136
|
type: "string",
|
|
@@ -751,6 +1139,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
751
1139
|
.option("method", {
|
|
752
1140
|
type: "string",
|
|
753
1141
|
describe: "Filter by HTTP method",
|
|
1142
|
+
array: true,
|
|
754
1143
|
})
|
|
755
1144
|
.option("sampling-rate", {
|
|
756
1145
|
type: "number",
|
|
@@ -760,54 +1149,64 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
760
1149
|
type: "string",
|
|
761
1150
|
describe: "Filter by a text match in console.log messages",
|
|
762
1151
|
})
|
|
1152
|
+
.option("ip", {
|
|
1153
|
+
type: "string",
|
|
1154
|
+
describe:
|
|
1155
|
+
'Filter by the IP address the request originates from. Use "self" to filter for your own IP',
|
|
1156
|
+
array: true,
|
|
1157
|
+
})
|
|
763
1158
|
.option("env", {
|
|
764
1159
|
type: "string",
|
|
765
1160
|
describe: "Perform on a specific environment",
|
|
1161
|
+
alias: "e",
|
|
1162
|
+
})
|
|
1163
|
+
.option("debug", {
|
|
1164
|
+
type: "boolean",
|
|
1165
|
+
hidden: true,
|
|
1166
|
+
default: false,
|
|
1167
|
+
describe:
|
|
1168
|
+
"If a log would have been filtered out, send it through anyway alongside the filter which would have blocked it.",
|
|
766
1169
|
})
|
|
767
1170
|
);
|
|
768
|
-
// TODO: filter by client ip, which can be 'self' or an ip address
|
|
769
1171
|
},
|
|
770
1172
|
async (args) => {
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
if (!(args.name || config.name)) {
|
|
774
|
-
throw new Error("Missing script name");
|
|
1173
|
+
if (args.format === "pretty") {
|
|
1174
|
+
printWranglerBanner();
|
|
775
1175
|
}
|
|
776
|
-
const
|
|
777
|
-
args.env ? `-${args.env}` : ""
|
|
778
|
-
}`;
|
|
1176
|
+
const config = readConfig(args.config as ConfigPath, args.env);
|
|
779
1177
|
|
|
780
|
-
|
|
1178
|
+
const scriptName = getScriptName(args, config);
|
|
781
1179
|
|
|
782
|
-
if (!
|
|
783
|
-
|
|
784
|
-
if (!loggedIn) {
|
|
785
|
-
// didn't login, let's just quit
|
|
786
|
-
console.log("Did not login, quitting...");
|
|
787
|
-
return;
|
|
788
|
-
}
|
|
789
|
-
if (!config.account_id) {
|
|
790
|
-
config.account_id = await getAccountId();
|
|
791
|
-
if (!config.account_id) {
|
|
792
|
-
throw new Error("No account id found, quitting...");
|
|
793
|
-
}
|
|
794
|
-
}
|
|
1180
|
+
if (!scriptName) {
|
|
1181
|
+
throw new Error("Missing script name");
|
|
795
1182
|
}
|
|
796
1183
|
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
const accountId = config.account_id;
|
|
1184
|
+
const accountId = await requireAuth(config);
|
|
800
1185
|
|
|
801
|
-
const
|
|
802
|
-
status: args.status as "ok" | "error" | "canceled",
|
|
1186
|
+
const cliFilters: TailCLIFilters = {
|
|
1187
|
+
status: args.status as ("ok" | "error" | "canceled")[],
|
|
803
1188
|
header: args.header,
|
|
804
1189
|
method: args.method,
|
|
805
|
-
|
|
1190
|
+
samplingRate: args["sampling-rate"],
|
|
806
1191
|
search: args.search,
|
|
1192
|
+
clientIp: args.ip,
|
|
807
1193
|
};
|
|
808
1194
|
|
|
809
|
-
const
|
|
810
|
-
|
|
1195
|
+
const filters = translateCLICommandToFilterMessage(
|
|
1196
|
+
cliFilters,
|
|
1197
|
+
args.debug
|
|
1198
|
+
);
|
|
1199
|
+
|
|
1200
|
+
const { tail, expiration, deleteTail } = await createTail(
|
|
1201
|
+
accountId,
|
|
1202
|
+
scriptName,
|
|
1203
|
+
filters,
|
|
1204
|
+
!isLegacyEnv(args, config) ? args.env : undefined
|
|
1205
|
+
);
|
|
1206
|
+
|
|
1207
|
+
const scriptDisplayName = `${scriptName}${
|
|
1208
|
+
args.env && !isLegacyEnv(args, config) ? ` (${args.env})` : ""
|
|
1209
|
+
}`;
|
|
811
1210
|
|
|
812
1211
|
console.log(
|
|
813
1212
|
`successfully created tail, expires at ${expiration.toLocaleString()}`
|
|
@@ -818,24 +1217,32 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
818
1217
|
await deleteTail();
|
|
819
1218
|
});
|
|
820
1219
|
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
1220
|
+
const printLog: (data: RawData) => void =
|
|
1221
|
+
args.format === "pretty" ? prettyPrintLogs : jsonPrintLogs;
|
|
1222
|
+
|
|
1223
|
+
tail.on("message", printLog);
|
|
824
1224
|
|
|
825
1225
|
while (tail.readyState !== tail.OPEN) {
|
|
826
1226
|
switch (tail.readyState) {
|
|
827
1227
|
case tail.CONNECTING:
|
|
828
|
-
await setTimeout(
|
|
1228
|
+
await setTimeout(100);
|
|
829
1229
|
break;
|
|
830
1230
|
case tail.CLOSING:
|
|
831
|
-
await setTimeout(
|
|
1231
|
+
await setTimeout(100);
|
|
832
1232
|
break;
|
|
833
1233
|
case tail.CLOSED:
|
|
834
|
-
|
|
1234
|
+
throw new Error(
|
|
1235
|
+
`Connection to ${scriptDisplayName} closed unexpectedly.`
|
|
1236
|
+
);
|
|
835
1237
|
}
|
|
836
1238
|
}
|
|
837
1239
|
|
|
838
|
-
console.log(`Connected to ${
|
|
1240
|
+
console.log(`Connected to ${scriptDisplayName}, waiting for logs...`);
|
|
1241
|
+
|
|
1242
|
+
tail.on("close", async () => {
|
|
1243
|
+
tail.terminate();
|
|
1244
|
+
await deleteTail();
|
|
1245
|
+
});
|
|
839
1246
|
}
|
|
840
1247
|
);
|
|
841
1248
|
|
|
@@ -846,14 +1253,12 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
846
1253
|
(yargs) => {
|
|
847
1254
|
return yargs
|
|
848
1255
|
.positional("method", {
|
|
1256
|
+
type: "string",
|
|
849
1257
|
describe: "Type of request to preview your worker",
|
|
850
|
-
choices: ["GET", "POST"],
|
|
851
|
-
default: ["GET"],
|
|
852
1258
|
})
|
|
853
1259
|
.positional("body", {
|
|
854
1260
|
type: "string",
|
|
855
1261
|
describe: "Body string to post to your preview worker request.",
|
|
856
|
-
default: "Null",
|
|
857
1262
|
})
|
|
858
1263
|
.option("env", {
|
|
859
1264
|
type: "string",
|
|
@@ -865,15 +1270,93 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
865
1270
|
type: "boolean",
|
|
866
1271
|
});
|
|
867
1272
|
},
|
|
868
|
-
() => {
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
1273
|
+
async (args) => {
|
|
1274
|
+
if (args.method || args.body) {
|
|
1275
|
+
throw new DeprecationError(
|
|
1276
|
+
"The `wrangler preview` command has been deprecated.\n" +
|
|
1277
|
+
"Try using `wrangler dev` to to try out a worker during development.\n"
|
|
1278
|
+
);
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
// Delegate to `wrangler dev`
|
|
1282
|
+
console.warn(
|
|
1283
|
+
"***************************************************\n" +
|
|
1284
|
+
"The `wrangler preview` command has been deprecated.\n" +
|
|
1285
|
+
"Attempting to run `wrangler dev` instead.\n" +
|
|
1286
|
+
"***************************************************\n"
|
|
1287
|
+
);
|
|
1288
|
+
|
|
1289
|
+
const config = readConfig(args.config as ConfigPath, args.env);
|
|
1290
|
+
const entry = await getEntry({}, config, "dev");
|
|
1291
|
+
|
|
1292
|
+
const accountId = await requireAuth(config);
|
|
1293
|
+
|
|
1294
|
+
const { waitUntilExit } = render(
|
|
1295
|
+
<Dev
|
|
1296
|
+
name={config.name}
|
|
1297
|
+
entry={entry}
|
|
1298
|
+
rules={getRules(config)}
|
|
1299
|
+
env={args.env}
|
|
1300
|
+
zone={undefined}
|
|
1301
|
+
legacyEnv={isLegacyEnv(args, config)}
|
|
1302
|
+
buildCommand={config.build || {}}
|
|
1303
|
+
initialMode={args.local ? "local" : "remote"}
|
|
1304
|
+
jsxFactory={config.jsx_factory}
|
|
1305
|
+
jsxFragment={config.jsx_fragment}
|
|
1306
|
+
upstreamProtocol={config.dev.upstream_protocol}
|
|
1307
|
+
localProtocol={config.dev.local_protocol}
|
|
1308
|
+
enableLocalPersistence={false}
|
|
1309
|
+
accountId={accountId}
|
|
1310
|
+
assetPaths={undefined}
|
|
1311
|
+
port={config.dev?.port}
|
|
1312
|
+
ip={config.dev.ip}
|
|
1313
|
+
public={undefined}
|
|
1314
|
+
compatibilityDate={
|
|
1315
|
+
config.compatibility_date ||
|
|
1316
|
+
new Date().toISOString().substring(0, 10)
|
|
1317
|
+
}
|
|
1318
|
+
compatibilityFlags={
|
|
1319
|
+
(args["compatibility-flags"] as string[]) ||
|
|
1320
|
+
config.compatibility_flags
|
|
1321
|
+
}
|
|
1322
|
+
usageModel={config.usage_model}
|
|
1323
|
+
bindings={{
|
|
1324
|
+
kv_namespaces: config.kv_namespaces?.map(
|
|
1325
|
+
({ binding, preview_id, id: _id }) => {
|
|
1326
|
+
// In `dev`, we make folks use a separate kv namespace called
|
|
1327
|
+
// `preview_id` instead of `id` so that they don't
|
|
1328
|
+
// break production data. So here we check that a `preview_id`
|
|
1329
|
+
// has actually been configured.
|
|
1330
|
+
// This whole block of code will be obsoleted in the future
|
|
1331
|
+
// when we have copy-on-write for previews on edge workers.
|
|
1332
|
+
if (!preview_id) {
|
|
1333
|
+
// TODO: This error has to be a _lot_ better, ideally just asking
|
|
1334
|
+
// to create a preview namespace for the user automatically
|
|
1335
|
+
throw new Error(
|
|
1336
|
+
`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`
|
|
1337
|
+
); // Ugh, I really don't like this message very much
|
|
1338
|
+
}
|
|
1339
|
+
return {
|
|
1340
|
+
binding,
|
|
1341
|
+
id: preview_id,
|
|
1342
|
+
};
|
|
1343
|
+
}
|
|
1344
|
+
),
|
|
1345
|
+
vars: config.vars,
|
|
1346
|
+
wasm_modules: config.wasm_modules,
|
|
1347
|
+
text_blobs: config.text_blobs,
|
|
1348
|
+
durable_objects: config.durable_objects,
|
|
1349
|
+
r2_buckets: config.r2_buckets,
|
|
1350
|
+
unsafe: config.unsafe?.bindings,
|
|
1351
|
+
}}
|
|
1352
|
+
inspectorPort={await getPort({ port: 9229 })}
|
|
1353
|
+
/>
|
|
872
1354
|
);
|
|
1355
|
+
await waitUntilExit();
|
|
873
1356
|
}
|
|
874
1357
|
);
|
|
875
1358
|
|
|
876
|
-
// route
|
|
1359
|
+
// [DEPRECATED] route
|
|
877
1360
|
wrangler.command(
|
|
878
1361
|
"route",
|
|
879
1362
|
false, // I think we want to hide this command
|
|
@@ -882,7 +1365,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
882
1365
|
return routeYargs
|
|
883
1366
|
.command(
|
|
884
1367
|
"list",
|
|
885
|
-
"List
|
|
1368
|
+
"List the routes associated with a zone",
|
|
886
1369
|
(yargs) => {
|
|
887
1370
|
return yargs
|
|
888
1371
|
.option("env", {
|
|
@@ -891,26 +1374,28 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
891
1374
|
})
|
|
892
1375
|
.option("zone", {
|
|
893
1376
|
type: "string",
|
|
894
|
-
describe: "
|
|
1377
|
+
describe: "Zone id",
|
|
895
1378
|
})
|
|
896
1379
|
.positional("zone", {
|
|
897
|
-
describe: "
|
|
1380
|
+
describe: "Zone id",
|
|
898
1381
|
type: "string",
|
|
899
1382
|
});
|
|
900
1383
|
},
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
1384
|
+
() => {
|
|
1385
|
+
// "👯 [DEPRECATED]. Use wrangler.toml to manage routes.
|
|
1386
|
+
const deprecationNotice =
|
|
1387
|
+
"`wrangler route list` has been deprecated.";
|
|
1388
|
+
const futureRoutes =
|
|
1389
|
+
"Refer to wrangler.toml for a list of routes the worker will be deployed to upon publishing.";
|
|
1390
|
+
const presentRoutes =
|
|
1391
|
+
"Refer to the Cloudflare Dashboard to see the routes this worker is currently running on.";
|
|
1392
|
+
throw new DeprecationError(
|
|
1393
|
+
`${deprecationNotice}\n${futureRoutes}\n${presentRoutes}`
|
|
1394
|
+
);
|
|
910
1395
|
}
|
|
911
1396
|
)
|
|
912
1397
|
.command(
|
|
913
|
-
"delete
|
|
1398
|
+
"delete",
|
|
914
1399
|
"Delete a route associated with a zone",
|
|
915
1400
|
(yargs) => {
|
|
916
1401
|
return yargs
|
|
@@ -927,21 +1412,22 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
927
1412
|
describe: "Perform on a specific environment",
|
|
928
1413
|
});
|
|
929
1414
|
},
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
console.log(
|
|
939
|
-
await fetchResult(`/zones/${zone}/workers/routes/${args.id}`, {
|
|
940
|
-
method: "DELETE",
|
|
941
|
-
})
|
|
942
|
-
);
|
|
1415
|
+
() => {
|
|
1416
|
+
// "👯 [DEPRECATED]. Use wrangler.toml to manage routes.
|
|
1417
|
+
const deprecationNotice =
|
|
1418
|
+
"`wrangler route delete` has been deprecated.";
|
|
1419
|
+
const shouldDo =
|
|
1420
|
+
"Remove the unwanted route(s) from wrangler.toml and run `wrangler publish` to remove your worker from those routes.";
|
|
1421
|
+
throw new DeprecationError(`${deprecationNotice}\n${shouldDo}`);
|
|
943
1422
|
}
|
|
944
1423
|
);
|
|
1424
|
+
},
|
|
1425
|
+
() => {
|
|
1426
|
+
// "👯 [DEPRECATED]. Use wrangler.toml to manage routes.
|
|
1427
|
+
const deprecationNotice = "`wrangler route` has been deprecated.";
|
|
1428
|
+
const shouldDo =
|
|
1429
|
+
"Please use wrangler.toml and/or `wrangler publish --routes` to modify routes";
|
|
1430
|
+
throw new DeprecationError(`${deprecationNotice}\n${shouldDo}`);
|
|
945
1431
|
}
|
|
946
1432
|
);
|
|
947
1433
|
|
|
@@ -955,7 +1441,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
955
1441
|
},
|
|
956
1442
|
() => {
|
|
957
1443
|
throw new DeprecationError(
|
|
958
|
-
"`wrangler subdomain` has been deprecated, please refer to
|
|
1444
|
+
"`wrangler subdomain` has been deprecated, please refer to https://github.com/cloudflare/wrangler2/blob/main/docs/deprecations.md#subdomain for alternatives"
|
|
959
1445
|
);
|
|
960
1446
|
}
|
|
961
1447
|
);
|
|
@@ -966,173 +1452,177 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
966
1452
|
"🤫 Generate a secret that can be referenced in the worker script",
|
|
967
1453
|
(secretYargs) => {
|
|
968
1454
|
return secretYargs
|
|
1455
|
+
.command(subHelp)
|
|
969
1456
|
.command(
|
|
970
1457
|
"put <key>",
|
|
971
1458
|
"Create or update a secret variable for a script",
|
|
972
1459
|
(yargs) => {
|
|
973
1460
|
return yargs
|
|
974
1461
|
.positional("key", {
|
|
975
|
-
describe: "The variable name to be accessible in the script
|
|
1462
|
+
describe: "The variable name to be accessible in the script",
|
|
976
1463
|
type: "string",
|
|
977
1464
|
})
|
|
978
1465
|
.option("name", {
|
|
979
|
-
describe: "
|
|
1466
|
+
describe: "Name of the worker",
|
|
980
1467
|
type: "string",
|
|
981
1468
|
})
|
|
982
1469
|
.option("env", {
|
|
983
1470
|
type: "string",
|
|
984
1471
|
describe:
|
|
985
|
-
"Binds the secret to the
|
|
1472
|
+
"Binds the secret to the Worker of the specific environment",
|
|
1473
|
+
alias: "e",
|
|
986
1474
|
});
|
|
987
1475
|
},
|
|
988
1476
|
async (args) => {
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
"--local not implemented for this command yet"
|
|
992
|
-
);
|
|
993
|
-
}
|
|
994
|
-
const config = args.config as Config;
|
|
1477
|
+
printWranglerBanner();
|
|
1478
|
+
const config = readConfig(args.config as ConfigPath, args.env);
|
|
995
1479
|
|
|
996
|
-
|
|
997
|
-
const scriptName = args.name || config.name;
|
|
1480
|
+
const scriptName = getScriptName(args, config);
|
|
998
1481
|
if (!scriptName) {
|
|
999
1482
|
throw new Error("Missing script name");
|
|
1000
1483
|
}
|
|
1001
1484
|
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
if (!args.local) {
|
|
1005
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1006
|
-
if (!loggedIn) {
|
|
1007
|
-
// didn't login, let's just quit
|
|
1008
|
-
console.log("Did not login, quitting...");
|
|
1009
|
-
return;
|
|
1010
|
-
}
|
|
1011
|
-
if (!config.account_id) {
|
|
1012
|
-
config.account_id = await getAccountId();
|
|
1013
|
-
if (!config.account_id) {
|
|
1014
|
-
throw new Error("No account id found, quitting...");
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
1485
|
+
const isInteractive = process.stdin.isTTY;
|
|
1486
|
+
const accountId = await requireAuth(config, isInteractive);
|
|
1018
1487
|
|
|
1019
|
-
|
|
1488
|
+
const secretValue = isInteractive
|
|
1489
|
+
? await prompt("Enter a secret value:", "password")
|
|
1490
|
+
: await readFromStdin();
|
|
1020
1491
|
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1492
|
+
console.log(
|
|
1493
|
+
`🌀 Creating the secret for script ${scriptName} ${
|
|
1494
|
+
args.env && !isLegacyEnv(args, config) ? `(${args.env})` : ""
|
|
1495
|
+
}`
|
|
1024
1496
|
);
|
|
1497
|
+
|
|
1025
1498
|
async function submitSecret() {
|
|
1026
|
-
|
|
1027
|
-
|
|
1499
|
+
const url =
|
|
1500
|
+
!args.env || isLegacyEnv(args, config)
|
|
1501
|
+
? `/accounts/${accountId}/workers/scripts/${scriptName}/secrets`
|
|
1502
|
+
: `/accounts/${accountId}/workers/services/${scriptName}/environments/${args.env}/secrets`;
|
|
1503
|
+
|
|
1504
|
+
return await fetchResult(url, {
|
|
1505
|
+
method: "PUT",
|
|
1506
|
+
headers: { "Content-Type": "application/json" },
|
|
1507
|
+
body: JSON.stringify({
|
|
1508
|
+
name: args.key,
|
|
1509
|
+
text: secretValue,
|
|
1510
|
+
type: "secret_text",
|
|
1511
|
+
}),
|
|
1512
|
+
});
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
const createDraftWorker = async () => {
|
|
1516
|
+
// TODO: log a warning
|
|
1517
|
+
await fetchResult(
|
|
1518
|
+
!args["legacy-env"] && args.env
|
|
1519
|
+
? `/accounts/${accountId}/workers/services/${scriptName}/environments/${args.env}`
|
|
1520
|
+
: `/accounts/${accountId}/workers/scripts/${scriptName}`,
|
|
1028
1521
|
{
|
|
1029
1522
|
method: "PUT",
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1523
|
+
body: createWorkerUploadForm({
|
|
1524
|
+
name: scriptName,
|
|
1525
|
+
main: {
|
|
1526
|
+
name: scriptName,
|
|
1527
|
+
content: `export default { fetch() {} }`,
|
|
1528
|
+
type: "esm",
|
|
1529
|
+
},
|
|
1530
|
+
bindings: {
|
|
1531
|
+
kv_namespaces: [],
|
|
1532
|
+
vars: {},
|
|
1533
|
+
durable_objects: { bindings: [] },
|
|
1534
|
+
r2_buckets: [],
|
|
1535
|
+
wasm_modules: {},
|
|
1536
|
+
text_blobs: {},
|
|
1537
|
+
unsafe: [],
|
|
1538
|
+
},
|
|
1539
|
+
modules: [],
|
|
1540
|
+
migrations: undefined,
|
|
1541
|
+
compatibility_date: undefined,
|
|
1542
|
+
compatibility_flags: undefined,
|
|
1543
|
+
usage_model: undefined,
|
|
1035
1544
|
}),
|
|
1036
1545
|
}
|
|
1037
1546
|
);
|
|
1547
|
+
};
|
|
1548
|
+
|
|
1549
|
+
function isMissingWorkerError(e: unknown): e is { code: 10007 } {
|
|
1550
|
+
return (
|
|
1551
|
+
typeof e === "object" &&
|
|
1552
|
+
e !== null &&
|
|
1553
|
+
(e as { code: 10007 }).code === 10007
|
|
1554
|
+
);
|
|
1038
1555
|
}
|
|
1039
1556
|
|
|
1040
1557
|
try {
|
|
1041
|
-
|
|
1558
|
+
await submitSecret();
|
|
1042
1559
|
} catch (e) {
|
|
1043
|
-
if (e
|
|
1044
|
-
//
|
|
1045
|
-
await
|
|
1046
|
-
|
|
1047
|
-
{
|
|
1048
|
-
method: "PUT",
|
|
1049
|
-
// @ts-expect-error TODO: fix this error!
|
|
1050
|
-
body: toFormData({
|
|
1051
|
-
main: {
|
|
1052
|
-
name: scriptName,
|
|
1053
|
-
content: `export default { fetch() {} }`,
|
|
1054
|
-
type: "esm",
|
|
1055
|
-
},
|
|
1056
|
-
bindings: {
|
|
1057
|
-
kv_namespaces: [],
|
|
1058
|
-
vars: {},
|
|
1059
|
-
durable_objects: { bindings: [] },
|
|
1060
|
-
},
|
|
1061
|
-
modules: [],
|
|
1062
|
-
}),
|
|
1063
|
-
}
|
|
1064
|
-
);
|
|
1065
|
-
|
|
1066
|
-
// and then try again
|
|
1067
|
-
console.log(await submitSecret());
|
|
1560
|
+
if (isMissingWorkerError(e)) {
|
|
1561
|
+
// create a draft worker and try again
|
|
1562
|
+
await createDraftWorker();
|
|
1563
|
+
await submitSecret();
|
|
1068
1564
|
// TODO: delete the draft worker if this failed too?
|
|
1565
|
+
} else {
|
|
1566
|
+
throw e;
|
|
1069
1567
|
}
|
|
1070
1568
|
}
|
|
1569
|
+
|
|
1570
|
+
console.log(`✨ Success! Uploaded secret ${args.key}`);
|
|
1071
1571
|
}
|
|
1072
1572
|
)
|
|
1073
1573
|
.command(
|
|
1074
1574
|
"delete <key>",
|
|
1075
1575
|
"Delete a secret variable from a script",
|
|
1076
1576
|
(yargs) => {
|
|
1577
|
+
printWranglerBanner();
|
|
1077
1578
|
return yargs
|
|
1078
1579
|
.positional("key", {
|
|
1079
|
-
describe: "The variable name to be accessible in the script
|
|
1580
|
+
describe: "The variable name to be accessible in the script",
|
|
1080
1581
|
type: "string",
|
|
1081
1582
|
})
|
|
1082
1583
|
.option("name", {
|
|
1083
|
-
describe: "
|
|
1584
|
+
describe: "Name of the worker",
|
|
1084
1585
|
type: "string",
|
|
1085
1586
|
})
|
|
1086
1587
|
.option("env", {
|
|
1087
1588
|
type: "string",
|
|
1088
1589
|
describe:
|
|
1089
|
-
"Binds the secret to the
|
|
1590
|
+
"Binds the secret to the Worker of the specific environment",
|
|
1591
|
+
alias: "e",
|
|
1090
1592
|
});
|
|
1091
1593
|
},
|
|
1092
1594
|
async (args) => {
|
|
1093
|
-
|
|
1094
|
-
throw new NotImplementedError(
|
|
1095
|
-
"--local not implemented for this command yet"
|
|
1096
|
-
);
|
|
1097
|
-
}
|
|
1098
|
-
const config = args.config as Config;
|
|
1595
|
+
const config = readConfig(args.config as ConfigPath, args.env);
|
|
1099
1596
|
|
|
1100
|
-
|
|
1101
|
-
const scriptName = args.name || config.name;
|
|
1597
|
+
const scriptName = getScriptName(args, config);
|
|
1102
1598
|
if (!scriptName) {
|
|
1103
1599
|
throw new Error("Missing script name");
|
|
1104
1600
|
}
|
|
1105
1601
|
|
|
1106
|
-
|
|
1602
|
+
const accountId = await requireAuth(config);
|
|
1107
1603
|
|
|
1108
|
-
if (
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
if (!config.account_id) {
|
|
1118
|
-
throw new Error("No account id found, quitting...");
|
|
1119
|
-
}
|
|
1120
|
-
}
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
// -- snip, end --
|
|
1124
|
-
|
|
1125
|
-
if (await confirm("Are you sure you want to delete this secret?")) {
|
|
1604
|
+
if (
|
|
1605
|
+
await confirm(
|
|
1606
|
+
`Are you sure you want to permanently delete the variable ${
|
|
1607
|
+
args.key
|
|
1608
|
+
} on the script ${scriptName}${
|
|
1609
|
+
args.env && !isLegacyEnv(args, config) ? ` (${args.env})` : ""
|
|
1610
|
+
}?`
|
|
1611
|
+
)
|
|
1612
|
+
) {
|
|
1126
1613
|
console.log(
|
|
1127
|
-
|
|
1614
|
+
`🌀 Deleting the secret ${args.key} on script ${scriptName}${
|
|
1615
|
+
args.env && !isLegacyEnv(args, config) ? ` (${args.env})` : ""
|
|
1616
|
+
}`
|
|
1128
1617
|
);
|
|
1129
1618
|
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
`/accounts/${
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
);
|
|
1619
|
+
const url =
|
|
1620
|
+
!args.env || isLegacyEnv(args, config)
|
|
1621
|
+
? `/accounts/${accountId}/workers/scripts/${scriptName}/secrets`
|
|
1622
|
+
: `/accounts/${accountId}/workers/services/${scriptName}/environments/${args.env}/secrets`;
|
|
1623
|
+
|
|
1624
|
+
await fetchResult(`${url}/${args.key}`, { method: "DELETE" });
|
|
1625
|
+
console.log(`✨ Success! Deleted secret ${args.key}`);
|
|
1136
1626
|
}
|
|
1137
1627
|
}
|
|
1138
1628
|
)
|
|
@@ -1142,53 +1632,32 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1142
1632
|
(yargs) => {
|
|
1143
1633
|
return yargs
|
|
1144
1634
|
.option("name", {
|
|
1145
|
-
describe: "
|
|
1635
|
+
describe: "Name of the worker",
|
|
1146
1636
|
type: "string",
|
|
1147
1637
|
})
|
|
1148
1638
|
.option("env", {
|
|
1149
1639
|
type: "string",
|
|
1150
1640
|
describe:
|
|
1151
|
-
"Binds the secret to the
|
|
1641
|
+
"Binds the secret to the Worker of the specific environment.",
|
|
1642
|
+
alias: "e",
|
|
1152
1643
|
});
|
|
1153
1644
|
},
|
|
1154
1645
|
async (args) => {
|
|
1155
|
-
|
|
1156
|
-
throw new NotImplementedError(
|
|
1157
|
-
"--local not implemented for this command yet"
|
|
1158
|
-
);
|
|
1159
|
-
}
|
|
1160
|
-
const config = args.config as Config;
|
|
1646
|
+
const config = readConfig(args.config as ConfigPath, args.env);
|
|
1161
1647
|
|
|
1162
|
-
|
|
1163
|
-
const scriptName = args.name || config.name;
|
|
1648
|
+
const scriptName = getScriptName(args, config);
|
|
1164
1649
|
if (!scriptName) {
|
|
1165
1650
|
throw new Error("Missing script name");
|
|
1166
1651
|
}
|
|
1167
1652
|
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
if (!args.local) {
|
|
1171
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1172
|
-
if (!loggedIn) {
|
|
1173
|
-
// didn't login, let's just quit
|
|
1174
|
-
console.log("Did not login, quitting...");
|
|
1175
|
-
return;
|
|
1176
|
-
}
|
|
1177
|
-
if (!config.account_id) {
|
|
1178
|
-
config.account_id = await getAccountId();
|
|
1179
|
-
if (!config.account_id) {
|
|
1180
|
-
throw new Error("No account id found, quitting...");
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
}
|
|
1653
|
+
const accountId = await requireAuth(config);
|
|
1184
1654
|
|
|
1185
|
-
|
|
1655
|
+
const url =
|
|
1656
|
+
!args.env || isLegacyEnv(args, config)
|
|
1657
|
+
? `/accounts/${accountId}/workers/scripts/${scriptName}/secrets`
|
|
1658
|
+
: `/accounts/${accountId}/workers/services/${scriptName}/environments/${args.env}/secrets`;
|
|
1186
1659
|
|
|
1187
|
-
console.log(
|
|
1188
|
-
await fetchResult(
|
|
1189
|
-
`/accounts/${config.account_id}/workers/scripts/${scriptName}/secrets`
|
|
1190
|
-
)
|
|
1191
|
-
);
|
|
1660
|
+
console.log(JSON.stringify(await fetchResult(url), null, " "));
|
|
1192
1661
|
}
|
|
1193
1662
|
);
|
|
1194
1663
|
}
|
|
@@ -1201,6 +1670,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1201
1670
|
"🗂️ Interact with your Workers KV Namespaces",
|
|
1202
1671
|
(namespaceYargs) => {
|
|
1203
1672
|
return namespaceYargs
|
|
1673
|
+
.command(subHelp)
|
|
1204
1674
|
.command(
|
|
1205
1675
|
"create <namespace>",
|
|
1206
1676
|
"Create a new namespace",
|
|
@@ -1209,10 +1679,12 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1209
1679
|
.positional("namespace", {
|
|
1210
1680
|
describe: "The name of the new namespace",
|
|
1211
1681
|
type: "string",
|
|
1682
|
+
demandOption: true,
|
|
1212
1683
|
})
|
|
1213
1684
|
.option("env", {
|
|
1214
1685
|
type: "string",
|
|
1215
1686
|
describe: "Perform on a specific environment",
|
|
1687
|
+
alias: "e",
|
|
1216
1688
|
})
|
|
1217
1689
|
.option("preview", {
|
|
1218
1690
|
type: "boolean",
|
|
@@ -1220,6 +1692,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1220
1692
|
});
|
|
1221
1693
|
},
|
|
1222
1694
|
async (args) => {
|
|
1695
|
+
printWranglerBanner();
|
|
1223
1696
|
if (args._.length > 2) {
|
|
1224
1697
|
const extraArgs = args._.slice(2).join(" ");
|
|
1225
1698
|
throw new CommandLineArgsError(
|
|
@@ -1233,7 +1706,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1233
1706
|
);
|
|
1234
1707
|
}
|
|
1235
1708
|
|
|
1236
|
-
const config = args.config as
|
|
1709
|
+
const config = readConfig(args.config as ConfigPath, args.env);
|
|
1237
1710
|
if (!config.name) {
|
|
1238
1711
|
console.warn(
|
|
1239
1712
|
"No configured name present, using `worker` as a prefix for the title"
|
|
@@ -1245,41 +1718,12 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1245
1718
|
const preview = args.preview ? "_preview" : "";
|
|
1246
1719
|
const title = `${name}${environment}-${args.namespace}${preview}`;
|
|
1247
1720
|
|
|
1248
|
-
|
|
1249
|
-
const { Miniflare } = await import("miniflare");
|
|
1250
|
-
const mf = new Miniflare({
|
|
1251
|
-
kvPersist: (args.kvPersist as string) || true,
|
|
1252
|
-
// TODO: these options shouldn't be required
|
|
1253
|
-
script: ` `, // has to be a string with at least one char
|
|
1254
|
-
});
|
|
1255
|
-
await mf.getKVNamespace(title); // this should "create" the namespace
|
|
1256
|
-
console.log(`✨ Success! Created KV namespace ${title}`);
|
|
1257
|
-
return;
|
|
1258
|
-
}
|
|
1259
|
-
|
|
1260
|
-
// -- snip, extract --
|
|
1261
|
-
|
|
1262
|
-
if (!args.local) {
|
|
1263
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1264
|
-
if (!loggedIn) {
|
|
1265
|
-
// didn't login, let's just quit
|
|
1266
|
-
console.log("Did not login, quitting...");
|
|
1267
|
-
return;
|
|
1268
|
-
}
|
|
1269
|
-
if (!config.account_id) {
|
|
1270
|
-
config.account_id = await getAccountId();
|
|
1271
|
-
if (!config.account_id) {
|
|
1272
|
-
throw new Error("No account id found, quitting...");
|
|
1273
|
-
}
|
|
1274
|
-
}
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
|
-
// -- snip, end --
|
|
1721
|
+
const accountId = await requireAuth(config);
|
|
1278
1722
|
|
|
1279
1723
|
// TODO: generate a binding name stripping non alphanumeric chars
|
|
1280
1724
|
|
|
1281
1725
|
console.log(`🌀 Creating namespace with title "${title}"`);
|
|
1282
|
-
const namespaceId = await createNamespace(
|
|
1726
|
+
const namespaceId = await createNamespace(accountId, title);
|
|
1283
1727
|
|
|
1284
1728
|
console.log("✨ Success!");
|
|
1285
1729
|
const envString = args.env ? ` under [env.${args.env}]` : "";
|
|
@@ -1299,41 +1743,14 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1299
1743
|
"Outputs a list of all KV namespaces associated with your account id.",
|
|
1300
1744
|
{},
|
|
1301
1745
|
async (args) => {
|
|
1302
|
-
|
|
1303
|
-
throw new NotImplementedError(
|
|
1304
|
-
`local mode is not yet supported for this command`
|
|
1305
|
-
);
|
|
1306
|
-
}
|
|
1307
|
-
|
|
1308
|
-
const config = args.config as Config;
|
|
1309
|
-
|
|
1310
|
-
// -- snip, extract --
|
|
1311
|
-
|
|
1312
|
-
if (!args.local) {
|
|
1313
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1314
|
-
if (!loggedIn) {
|
|
1315
|
-
// didn't login, let's just quit
|
|
1316
|
-
console.log("Did not login, quitting...");
|
|
1317
|
-
return;
|
|
1318
|
-
}
|
|
1319
|
-
if (!config.account_id) {
|
|
1320
|
-
config.account_id = await getAccountId();
|
|
1321
|
-
if (!config.account_id) {
|
|
1322
|
-
throw new Error("No account id found, quitting...");
|
|
1323
|
-
}
|
|
1324
|
-
}
|
|
1325
|
-
}
|
|
1746
|
+
const config = readConfig(args.config as ConfigPath, undefined);
|
|
1326
1747
|
|
|
1327
|
-
|
|
1748
|
+
const accountId = await requireAuth(config);
|
|
1328
1749
|
|
|
1329
1750
|
// TODO: we should show bindings if they exist for given ids
|
|
1330
1751
|
|
|
1331
1752
|
console.log(
|
|
1332
|
-
JSON.stringify(
|
|
1333
|
-
await listNamespaces(config.account_id),
|
|
1334
|
-
null,
|
|
1335
|
-
" "
|
|
1336
|
-
)
|
|
1753
|
+
JSON.stringify(await listNamespaces(accountId), null, " ")
|
|
1337
1754
|
);
|
|
1338
1755
|
}
|
|
1339
1756
|
)
|
|
@@ -1354,6 +1771,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1354
1771
|
.option("env", {
|
|
1355
1772
|
type: "string",
|
|
1356
1773
|
describe: "Perform on a specific environment",
|
|
1774
|
+
alias: "e",
|
|
1357
1775
|
})
|
|
1358
1776
|
.option("preview", {
|
|
1359
1777
|
type: "boolean",
|
|
@@ -1361,44 +1779,22 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1361
1779
|
});
|
|
1362
1780
|
},
|
|
1363
1781
|
async (args) => {
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
`local mode is not yet supported for this command`
|
|
1367
|
-
);
|
|
1368
|
-
}
|
|
1369
|
-
const config = args.config as Config;
|
|
1782
|
+
printWranglerBanner();
|
|
1783
|
+
const config = readConfig(args.config as ConfigPath, args.env);
|
|
1370
1784
|
|
|
1371
1785
|
let id;
|
|
1372
1786
|
try {
|
|
1373
|
-
id = getNamespaceId(args);
|
|
1787
|
+
id = getNamespaceId(args, config);
|
|
1374
1788
|
} catch (e) {
|
|
1375
1789
|
throw new CommandLineArgsError(
|
|
1376
|
-
"Not able to delete namespace.\n" + e.message
|
|
1790
|
+
"Not able to delete namespace.\n" + ((e as Error).message ?? e)
|
|
1377
1791
|
);
|
|
1378
1792
|
}
|
|
1379
1793
|
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
if (!args.local) {
|
|
1383
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1384
|
-
if (!loggedIn) {
|
|
1385
|
-
// didn't login, let's just quit
|
|
1386
|
-
console.log("Did not login, quitting...");
|
|
1387
|
-
return;
|
|
1388
|
-
}
|
|
1389
|
-
|
|
1390
|
-
if (!config.account_id) {
|
|
1391
|
-
config.account_id = await getAccountId();
|
|
1392
|
-
if (!config.account_id) {
|
|
1393
|
-
throw new Error("No account id found, quitting...");
|
|
1394
|
-
}
|
|
1395
|
-
}
|
|
1396
|
-
}
|
|
1397
|
-
|
|
1398
|
-
// -- snip, end --
|
|
1794
|
+
const accountId = await requireAuth(config);
|
|
1399
1795
|
|
|
1400
1796
|
await fetchResult<{ id: string }>(
|
|
1401
|
-
`/accounts/${
|
|
1797
|
+
`/accounts/${accountId}/storage/kv/namespaces/${id}`,
|
|
1402
1798
|
{ method: "DELETE" }
|
|
1403
1799
|
);
|
|
1404
1800
|
|
|
@@ -1430,6 +1826,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1430
1826
|
"🔑 Individually manage Workers KV key-value pairs",
|
|
1431
1827
|
(kvKeyYargs) => {
|
|
1432
1828
|
return kvKeyYargs
|
|
1829
|
+
.command(subHelp)
|
|
1433
1830
|
.command(
|
|
1434
1831
|
"put <key> [value]",
|
|
1435
1832
|
"Writes a single key/value pair to the given namespace.",
|
|
@@ -1437,24 +1834,26 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1437
1834
|
return yargs
|
|
1438
1835
|
.positional("key", {
|
|
1439
1836
|
type: "string",
|
|
1440
|
-
describe: "The key to write to
|
|
1837
|
+
describe: "The key to write to",
|
|
1838
|
+
demandOption: true,
|
|
1441
1839
|
})
|
|
1442
1840
|
.positional("value", {
|
|
1443
1841
|
type: "string",
|
|
1444
|
-
describe: "The value to write
|
|
1842
|
+
describe: "The value to write",
|
|
1445
1843
|
})
|
|
1446
1844
|
.option("binding", {
|
|
1447
1845
|
type: "string",
|
|
1448
|
-
describe: "The binding of the namespace to write to
|
|
1846
|
+
describe: "The binding of the namespace to write to",
|
|
1449
1847
|
})
|
|
1450
1848
|
.option("namespace-id", {
|
|
1451
1849
|
type: "string",
|
|
1452
|
-
describe: "The id of the namespace to write to
|
|
1850
|
+
describe: "The id of the namespace to write to",
|
|
1453
1851
|
})
|
|
1454
1852
|
.check(demandOneOfOption("binding", "namespace-id"))
|
|
1455
1853
|
.option("env", {
|
|
1456
1854
|
type: "string",
|
|
1457
1855
|
describe: "Perform on a specific environment",
|
|
1856
|
+
alias: "e",
|
|
1458
1857
|
})
|
|
1459
1858
|
.option("preview", {
|
|
1460
1859
|
type: "boolean",
|
|
@@ -1462,7 +1861,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1462
1861
|
})
|
|
1463
1862
|
.option("ttl", {
|
|
1464
1863
|
type: "number",
|
|
1465
|
-
describe: "Time for which the entries should be visible
|
|
1864
|
+
describe: "Time for which the entries should be visible",
|
|
1466
1865
|
})
|
|
1467
1866
|
.option("expiration", {
|
|
1468
1867
|
type: "number",
|
|
@@ -1471,16 +1870,19 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1471
1870
|
})
|
|
1472
1871
|
.option("path", {
|
|
1473
1872
|
type: "string",
|
|
1474
|
-
describe: "Read value from the file at a given path
|
|
1873
|
+
describe: "Read value from the file at a given path",
|
|
1475
1874
|
})
|
|
1476
1875
|
.check(demandOneOfOption("value", "path"));
|
|
1477
1876
|
},
|
|
1478
1877
|
async ({ key, ttl, expiration, ...args }) => {
|
|
1479
|
-
|
|
1878
|
+
printWranglerBanner();
|
|
1879
|
+
const config = readConfig(args.config as ConfigPath, args.env);
|
|
1880
|
+
const namespaceId = getNamespaceId(args, config);
|
|
1881
|
+
// One of `args.path` and `args.value` must be defined
|
|
1480
1882
|
const value = args.path
|
|
1481
|
-
?
|
|
1482
|
-
:
|
|
1483
|
-
|
|
1883
|
+
? readFileSync(args.path)
|
|
1884
|
+
: // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1885
|
+
args.value!;
|
|
1484
1886
|
|
|
1485
1887
|
if (args.path) {
|
|
1486
1888
|
console.log(
|
|
@@ -1492,38 +1894,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1492
1894
|
);
|
|
1493
1895
|
}
|
|
1494
1896
|
|
|
1495
|
-
|
|
1496
|
-
const { Miniflare } = await import("miniflare");
|
|
1497
|
-
const mf = new Miniflare({
|
|
1498
|
-
kvPersist: (args.kvPersist as string) || true,
|
|
1499
|
-
// TODO: these options shouldn't be required
|
|
1500
|
-
script: ` `, // has to be a string with at least one char
|
|
1501
|
-
});
|
|
1502
|
-
const ns = await mf.getKVNamespace(namespaceId);
|
|
1503
|
-
await ns.put(key, value, { expiration, expirationTtl: ttl });
|
|
1504
|
-
return;
|
|
1505
|
-
}
|
|
1506
|
-
// -- snip, extract --
|
|
1507
|
-
|
|
1508
|
-
if (!args.local) {
|
|
1509
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1510
|
-
if (!loggedIn) {
|
|
1511
|
-
// didn't login, let's just quit
|
|
1512
|
-
console.log("Did not login, quitting...");
|
|
1513
|
-
return;
|
|
1514
|
-
}
|
|
1515
|
-
|
|
1516
|
-
if (!config.account_id) {
|
|
1517
|
-
config.account_id = await getAccountId();
|
|
1518
|
-
if (!config.account_id) {
|
|
1519
|
-
throw new Error("No account id found, quitting...");
|
|
1520
|
-
}
|
|
1521
|
-
}
|
|
1522
|
-
}
|
|
1523
|
-
|
|
1524
|
-
// -- snip, end --
|
|
1897
|
+
const accountId = await requireAuth(config);
|
|
1525
1898
|
|
|
1526
|
-
await putKeyValue(
|
|
1899
|
+
await putKeyValue(accountId, namespaceId, {
|
|
1900
|
+
key,
|
|
1901
|
+
value,
|
|
1527
1902
|
expiration,
|
|
1528
1903
|
expiration_ttl: ttl,
|
|
1529
1904
|
});
|
|
@@ -1546,6 +1921,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1546
1921
|
.option("env", {
|
|
1547
1922
|
type: "string",
|
|
1548
1923
|
describe: "Perform on a specific environment",
|
|
1924
|
+
alias: "e",
|
|
1549
1925
|
})
|
|
1550
1926
|
.option("preview", {
|
|
1551
1927
|
type: "boolean",
|
|
@@ -1560,46 +1936,17 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1560
1936
|
},
|
|
1561
1937
|
async ({ prefix, ...args }) => {
|
|
1562
1938
|
// TODO: support for limit+cursor (pagination)
|
|
1939
|
+
const config = readConfig(args.config as ConfigPath, args.env);
|
|
1940
|
+
const namespaceId = getNamespaceId(args, config);
|
|
1563
1941
|
|
|
1564
|
-
const
|
|
1565
|
-
const config = args.config as Config;
|
|
1942
|
+
const accountId = await requireAuth(config);
|
|
1566
1943
|
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
// TODO: these options shouldn't be required
|
|
1572
|
-
script: ` `, // has to be a string with at least one char
|
|
1573
|
-
});
|
|
1574
|
-
const ns = await mf.getKVNamespace(namespaceId);
|
|
1575
|
-
const listResponse = await ns.list({ prefix });
|
|
1576
|
-
console.log(JSON.stringify(listResponse.keys, null, " ")); // TODO: paginate, collate
|
|
1577
|
-
return;
|
|
1578
|
-
}
|
|
1579
|
-
|
|
1580
|
-
// -- snip, extract --
|
|
1581
|
-
|
|
1582
|
-
if (!args.local) {
|
|
1583
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1584
|
-
if (!loggedIn) {
|
|
1585
|
-
// didn't login, let's just quit
|
|
1586
|
-
console.log("Did not login, quitting...");
|
|
1587
|
-
return;
|
|
1588
|
-
}
|
|
1589
|
-
|
|
1590
|
-
if (!config.account_id) {
|
|
1591
|
-
config.account_id = await getAccountId();
|
|
1592
|
-
if (!config.account_id) {
|
|
1593
|
-
throw new Error("No account id found, quitting...");
|
|
1594
|
-
}
|
|
1595
|
-
}
|
|
1596
|
-
}
|
|
1597
|
-
|
|
1598
|
-
// -- snip, end --
|
|
1599
|
-
|
|
1600
|
-
console.log(
|
|
1601
|
-
await listNamespaceKeys(config.account_id, namespaceId, prefix)
|
|
1944
|
+
const results = await listNamespaceKeys(
|
|
1945
|
+
accountId,
|
|
1946
|
+
namespaceId,
|
|
1947
|
+
prefix
|
|
1602
1948
|
);
|
|
1949
|
+
console.log(JSON.stringify(results, undefined, 2));
|
|
1603
1950
|
}
|
|
1604
1951
|
)
|
|
1605
1952
|
.command(
|
|
@@ -1610,6 +1957,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1610
1957
|
.positional("key", {
|
|
1611
1958
|
describe: "The key value to get.",
|
|
1612
1959
|
type: "string",
|
|
1960
|
+
demandOption: true,
|
|
1613
1961
|
})
|
|
1614
1962
|
.option("binding", {
|
|
1615
1963
|
type: "string",
|
|
@@ -1623,6 +1971,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1623
1971
|
.option("env", {
|
|
1624
1972
|
type: "string",
|
|
1625
1973
|
describe: "Perform on a specific environment",
|
|
1974
|
+
alias: "e",
|
|
1626
1975
|
})
|
|
1627
1976
|
.option("preview", {
|
|
1628
1977
|
type: "boolean",
|
|
@@ -1636,46 +1985,12 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1636
1985
|
});
|
|
1637
1986
|
},
|
|
1638
1987
|
async ({ key, ...args }) => {
|
|
1639
|
-
const
|
|
1640
|
-
const
|
|
1641
|
-
|
|
1642
|
-
if (args.local) {
|
|
1643
|
-
const { Miniflare } = await import("miniflare");
|
|
1644
|
-
const mf = new Miniflare({
|
|
1645
|
-
kvPersist: (args.kvPersist as string) || true,
|
|
1646
|
-
// TODO: these options shouldn't be required
|
|
1647
|
-
script: ` `, // has to be a string with at least one char
|
|
1648
|
-
});
|
|
1649
|
-
const ns = await mf.getKVNamespace(namespaceId);
|
|
1650
|
-
console.log(await ns.get(key));
|
|
1651
|
-
return;
|
|
1652
|
-
}
|
|
1653
|
-
|
|
1654
|
-
// -- snip, extract --
|
|
1988
|
+
const config = readConfig(args.config as ConfigPath, args.env);
|
|
1989
|
+
const namespaceId = getNamespaceId(args, config);
|
|
1655
1990
|
|
|
1656
|
-
|
|
1657
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1658
|
-
if (!loggedIn) {
|
|
1659
|
-
// didn't login, let's just quit
|
|
1660
|
-
console.log("Did not login, quitting...");
|
|
1661
|
-
return;
|
|
1662
|
-
}
|
|
1663
|
-
|
|
1664
|
-
if (!config.account_id) {
|
|
1665
|
-
config.account_id = await getAccountId();
|
|
1666
|
-
if (!config.account_id) {
|
|
1667
|
-
throw new Error("No account id found, quitting...");
|
|
1668
|
-
}
|
|
1669
|
-
}
|
|
1670
|
-
}
|
|
1991
|
+
const accountId = await requireAuth(config);
|
|
1671
1992
|
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
console.log(
|
|
1675
|
-
await fetchRaw(
|
|
1676
|
-
`/accounts/${config.account_id}/storage/kv/namespaces/${namespaceId}/values/${key}`
|
|
1677
|
-
)
|
|
1678
|
-
);
|
|
1993
|
+
console.log(await getKeyValue(accountId, namespaceId, key));
|
|
1679
1994
|
}
|
|
1680
1995
|
)
|
|
1681
1996
|
.command(
|
|
@@ -1686,6 +2001,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1686
2001
|
.positional("key", {
|
|
1687
2002
|
describe: "The key value to delete",
|
|
1688
2003
|
type: "string",
|
|
2004
|
+
demandOption: true,
|
|
1689
2005
|
})
|
|
1690
2006
|
.option("binding", {
|
|
1691
2007
|
type: "string",
|
|
@@ -1699,6 +2015,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1699
2015
|
.option("env", {
|
|
1700
2016
|
type: "string",
|
|
1701
2017
|
describe: "Perform on a specific environment",
|
|
2018
|
+
alias: "e",
|
|
1702
2019
|
})
|
|
1703
2020
|
.option("preview", {
|
|
1704
2021
|
type: "boolean",
|
|
@@ -1706,48 +2023,18 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1706
2023
|
});
|
|
1707
2024
|
},
|
|
1708
2025
|
async ({ key, ...args }) => {
|
|
1709
|
-
|
|
2026
|
+
printWranglerBanner();
|
|
2027
|
+
const config = readConfig(args.config as ConfigPath, args.env);
|
|
2028
|
+
const namespaceId = getNamespaceId(args, config);
|
|
1710
2029
|
|
|
1711
2030
|
console.log(
|
|
1712
2031
|
`deleting the key "${key}" on namespace ${namespaceId}`
|
|
1713
2032
|
);
|
|
1714
2033
|
|
|
1715
|
-
|
|
1716
|
-
const { Miniflare } = await import("miniflare");
|
|
1717
|
-
const mf = new Miniflare({
|
|
1718
|
-
kvPersist: (args.kvPersist as string) || true,
|
|
1719
|
-
// TODO: these options shouldn't be required
|
|
1720
|
-
script: ` `, // has to be a string with at least one char
|
|
1721
|
-
});
|
|
1722
|
-
const ns = await mf.getKVNamespace(namespaceId);
|
|
1723
|
-
console.log(await ns.delete(key));
|
|
1724
|
-
return;
|
|
1725
|
-
}
|
|
1726
|
-
|
|
1727
|
-
const config = args.config as Config;
|
|
1728
|
-
|
|
1729
|
-
// -- snip, extract --
|
|
1730
|
-
|
|
1731
|
-
if (!args.local) {
|
|
1732
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1733
|
-
if (!loggedIn) {
|
|
1734
|
-
// didn't login, let's just quit
|
|
1735
|
-
console.log("Did not login, quitting...");
|
|
1736
|
-
return;
|
|
1737
|
-
}
|
|
1738
|
-
|
|
1739
|
-
if (!config.account_id) {
|
|
1740
|
-
config.account_id = await getAccountId();
|
|
1741
|
-
if (!config.account_id) {
|
|
1742
|
-
throw new Error("No account id found, quitting...");
|
|
1743
|
-
}
|
|
1744
|
-
}
|
|
1745
|
-
}
|
|
1746
|
-
|
|
1747
|
-
// -- snip, end --
|
|
2034
|
+
const accountId = await requireAuth(config);
|
|
1748
2035
|
|
|
1749
2036
|
await fetchResult(
|
|
1750
|
-
`/accounts/${
|
|
2037
|
+
`/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${key}`,
|
|
1751
2038
|
{ method: "DELETE" }
|
|
1752
2039
|
);
|
|
1753
2040
|
}
|
|
@@ -1761,6 +2048,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1761
2048
|
"💪 Interact with multiple Workers KV key-value pairs at once",
|
|
1762
2049
|
(kvBulkYargs) => {
|
|
1763
2050
|
return kvBulkYargs
|
|
2051
|
+
.command(subHelp)
|
|
1764
2052
|
.command(
|
|
1765
2053
|
"put <filename>",
|
|
1766
2054
|
"Upload multiple key-value pairs to a namespace",
|
|
@@ -1769,19 +2057,21 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1769
2057
|
.positional("filename", {
|
|
1770
2058
|
describe: `The JSON file of key-value pairs to upload, in form [{"key":..., "value":...}"...]`,
|
|
1771
2059
|
type: "string",
|
|
2060
|
+
demandOption: true,
|
|
1772
2061
|
})
|
|
1773
2062
|
.option("binding", {
|
|
1774
2063
|
type: "string",
|
|
1775
|
-
describe: "The name of the namespace to
|
|
2064
|
+
describe: "The name of the namespace to insert values into",
|
|
1776
2065
|
})
|
|
1777
2066
|
.option("namespace-id", {
|
|
1778
2067
|
type: "string",
|
|
1779
|
-
describe: "The id of the namespace to
|
|
2068
|
+
describe: "The id of the namespace to insert values into",
|
|
1780
2069
|
})
|
|
1781
2070
|
.check(demandOneOfOption("binding", "namespace-id"))
|
|
1782
2071
|
.option("env", {
|
|
1783
2072
|
type: "string",
|
|
1784
2073
|
describe: "Perform on a specific environment",
|
|
2074
|
+
alias: "e",
|
|
1785
2075
|
})
|
|
1786
2076
|
.option("preview", {
|
|
1787
2077
|
type: "boolean",
|
|
@@ -1789,78 +2079,91 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1789
2079
|
});
|
|
1790
2080
|
},
|
|
1791
2081
|
async ({ filename, ...args }) => {
|
|
2082
|
+
printWranglerBanner();
|
|
1792
2083
|
// The simplest implementation I could think of.
|
|
1793
2084
|
// This could be made more efficient with a streaming parser/uploader
|
|
1794
2085
|
// but we'll do that in the future if needed.
|
|
1795
2086
|
|
|
1796
|
-
const
|
|
1797
|
-
const
|
|
1798
|
-
const content =
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
parsedContent = JSON.parse(content);
|
|
1802
|
-
} catch (err) {
|
|
2087
|
+
const config = readConfig(args.config as ConfigPath, args.env);
|
|
2088
|
+
const namespaceId = getNamespaceId(args, config);
|
|
2089
|
+
const content = parseJSON(readFileSync(filename), filename);
|
|
2090
|
+
|
|
2091
|
+
if (!Array.isArray(content)) {
|
|
1803
2092
|
throw new Error(
|
|
1804
|
-
`
|
|
2093
|
+
`Unexpected JSON input from "${filename}".\n` +
|
|
2094
|
+
`Expected an array of key-value objects but got type "${typeof content}".`
|
|
1805
2095
|
);
|
|
1806
2096
|
}
|
|
1807
2097
|
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
// -- snip, extract --
|
|
1832
|
-
|
|
1833
|
-
if (!args.local) {
|
|
1834
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1835
|
-
if (!loggedIn) {
|
|
1836
|
-
// didn't login, let's just quit
|
|
1837
|
-
console.log("Did not login, quitting...");
|
|
1838
|
-
return;
|
|
1839
|
-
}
|
|
1840
|
-
|
|
1841
|
-
if (!config.account_id) {
|
|
1842
|
-
config.account_id = await getAccountId();
|
|
1843
|
-
if (!config.account_id) {
|
|
1844
|
-
throw new Error("No account id found, quitting...");
|
|
2098
|
+
const errors: string[] = [];
|
|
2099
|
+
const warnings: string[] = [];
|
|
2100
|
+
for (let i = 0; i < content.length; i++) {
|
|
2101
|
+
const keyValue = content[i];
|
|
2102
|
+
if (typeof keyValue !== "object") {
|
|
2103
|
+
errors.push(
|
|
2104
|
+
`The item at index ${i} is type: "${typeof keyValue}" - ${JSON.stringify(
|
|
2105
|
+
keyValue
|
|
2106
|
+
)}`
|
|
2107
|
+
);
|
|
2108
|
+
} else if (!isKeyValue(keyValue)) {
|
|
2109
|
+
errors.push(
|
|
2110
|
+
`The item at index ${i} is ${JSON.stringify(keyValue)}`
|
|
2111
|
+
);
|
|
2112
|
+
} else {
|
|
2113
|
+
const props = unexpectedKeyValueProps(keyValue);
|
|
2114
|
+
if (props.length > 0) {
|
|
2115
|
+
warnings.push(
|
|
2116
|
+
`The item at index ${i} contains unexpected properties: ${JSON.stringify(
|
|
2117
|
+
props
|
|
2118
|
+
)}.`
|
|
2119
|
+
);
|
|
1845
2120
|
}
|
|
1846
2121
|
}
|
|
1847
2122
|
}
|
|
2123
|
+
if (warnings.length > 0) {
|
|
2124
|
+
console.warn(
|
|
2125
|
+
`Unexpected key-value properties in "${filename}".\n` +
|
|
2126
|
+
warnings.join("\n")
|
|
2127
|
+
);
|
|
2128
|
+
}
|
|
2129
|
+
if (errors.length > 0) {
|
|
2130
|
+
throw new Error(
|
|
2131
|
+
`Unexpected JSON input from "${filename}".\n` +
|
|
2132
|
+
`Each item in the array should be an object that matches:\n\n` +
|
|
2133
|
+
`interface KeyValue {\n` +
|
|
2134
|
+
` key: string;\n` +
|
|
2135
|
+
` value: string;\n` +
|
|
2136
|
+
` expiration?: number;\n` +
|
|
2137
|
+
` expiration_ttl?: number;\n` +
|
|
2138
|
+
` metadata?: object;\n` +
|
|
2139
|
+
` base64?: boolean;\n` +
|
|
2140
|
+
`}\n\n` +
|
|
2141
|
+
errors.join("\n")
|
|
2142
|
+
);
|
|
2143
|
+
}
|
|
1848
2144
|
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
2145
|
+
const accountId = await requireAuth(config);
|
|
2146
|
+
await putBulkKeyValue(
|
|
2147
|
+
accountId,
|
|
2148
|
+
namespaceId,
|
|
2149
|
+
content,
|
|
2150
|
+
(index, total) => {
|
|
2151
|
+
console.log(`Uploaded ${index} of ${total}.`);
|
|
2152
|
+
}
|
|
1853
2153
|
);
|
|
2154
|
+
|
|
2155
|
+
console.log("Success!");
|
|
1854
2156
|
}
|
|
1855
2157
|
)
|
|
1856
2158
|
.command(
|
|
1857
2159
|
"delete <filename>",
|
|
1858
|
-
"
|
|
2160
|
+
"Delete multiple key-value pairs from a namespace",
|
|
1859
2161
|
(yargs) => {
|
|
1860
2162
|
return yargs
|
|
1861
2163
|
.positional("filename", {
|
|
1862
|
-
describe: `The JSON file of
|
|
2164
|
+
describe: `The JSON file of keys to delete, in the form ["key1", "key2", ...]`,
|
|
1863
2165
|
type: "string",
|
|
2166
|
+
demandOption: true,
|
|
1864
2167
|
})
|
|
1865
2168
|
.option("binding", {
|
|
1866
2169
|
type: "string",
|
|
@@ -1874,101 +2177,197 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1874
2177
|
.option("env", {
|
|
1875
2178
|
type: "string",
|
|
1876
2179
|
describe: "Perform on a specific environment",
|
|
2180
|
+
alias: "e",
|
|
1877
2181
|
})
|
|
1878
2182
|
.option("preview", {
|
|
1879
2183
|
type: "boolean",
|
|
1880
2184
|
describe: "Interact with a preview namespace",
|
|
2185
|
+
})
|
|
2186
|
+
.option("force", {
|
|
2187
|
+
type: "boolean",
|
|
2188
|
+
alias: "f",
|
|
2189
|
+
describe: "Do not ask for confirmation before deleting",
|
|
1881
2190
|
});
|
|
1882
2191
|
},
|
|
1883
2192
|
async ({ filename, ...args }) => {
|
|
1884
|
-
|
|
1885
|
-
const config = args.config as
|
|
1886
|
-
const
|
|
1887
|
-
let parsedContent;
|
|
1888
|
-
try {
|
|
1889
|
-
parsedContent = JSON.parse(content);
|
|
1890
|
-
} catch (err) {
|
|
1891
|
-
throw new Error(
|
|
1892
|
-
`Could not parse json from ${filename}.\n${err.message ?? err}`
|
|
1893
|
-
);
|
|
1894
|
-
}
|
|
2193
|
+
printWranglerBanner();
|
|
2194
|
+
const config = readConfig(args.config as ConfigPath, args.env);
|
|
2195
|
+
const namespaceId = getNamespaceId(args, config);
|
|
1895
2196
|
|
|
1896
|
-
if (args.
|
|
1897
|
-
const
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
const ns = await mf.getKVNamespace(namespaceId);
|
|
1904
|
-
for (const key of parsedContent) {
|
|
1905
|
-
await ns.delete(key);
|
|
2197
|
+
if (!args.force) {
|
|
2198
|
+
const result = await confirm(
|
|
2199
|
+
`Are you sure you want to delete all the keys read from "${filename}" from kv-namespace with id "${namespaceId}"?`
|
|
2200
|
+
);
|
|
2201
|
+
if (!result) {
|
|
2202
|
+
console.log(`Not deleting keys read from "${filename}".`);
|
|
2203
|
+
return;
|
|
1906
2204
|
}
|
|
1907
|
-
|
|
1908
|
-
return;
|
|
1909
2205
|
}
|
|
1910
2206
|
|
|
1911
|
-
|
|
2207
|
+
const content = parseJSON(
|
|
2208
|
+
readFileSync(filename),
|
|
2209
|
+
filename
|
|
2210
|
+
) as string[];
|
|
1912
2211
|
|
|
1913
|
-
if (!
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
}
|
|
2212
|
+
if (!Array.isArray(content)) {
|
|
2213
|
+
throw new Error(
|
|
2214
|
+
`Unexpected JSON input from "${filename}".\n` +
|
|
2215
|
+
`Expected an array of strings but got:\n${content}`
|
|
2216
|
+
);
|
|
2217
|
+
}
|
|
1920
2218
|
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
2219
|
+
const errors: string[] = [];
|
|
2220
|
+
for (let i = 0; i < content.length; i++) {
|
|
2221
|
+
const key = content[i];
|
|
2222
|
+
if (typeof key !== "string") {
|
|
2223
|
+
errors.push(
|
|
2224
|
+
`The item at index ${i} is type: "${typeof key}" - ${JSON.stringify(
|
|
2225
|
+
key
|
|
2226
|
+
)}`
|
|
2227
|
+
);
|
|
1926
2228
|
}
|
|
1927
2229
|
}
|
|
2230
|
+
if (errors.length > 0) {
|
|
2231
|
+
throw new Error(
|
|
2232
|
+
`Unexpected JSON input from "${filename}".\n` +
|
|
2233
|
+
`Expected an array of strings.\n` +
|
|
2234
|
+
errors.join("\n")
|
|
2235
|
+
);
|
|
2236
|
+
}
|
|
1928
2237
|
|
|
1929
|
-
|
|
2238
|
+
const accountId = await requireAuth(config);
|
|
1930
2239
|
|
|
1931
|
-
|
|
1932
|
-
|
|
2240
|
+
await deleteBulkKeyValue(
|
|
2241
|
+
accountId,
|
|
2242
|
+
namespaceId,
|
|
2243
|
+
content,
|
|
2244
|
+
(index, total) => {
|
|
2245
|
+
console.log(`Deleted ${index} of ${total}.`);
|
|
2246
|
+
}
|
|
1933
2247
|
);
|
|
2248
|
+
|
|
2249
|
+
console.log("Success!");
|
|
1934
2250
|
}
|
|
1935
2251
|
);
|
|
1936
2252
|
}
|
|
1937
2253
|
);
|
|
1938
2254
|
|
|
1939
|
-
wrangler.command("pages", "⚡️ Configure Cloudflare Pages",
|
|
2255
|
+
wrangler.command("pages", "⚡️ Configure Cloudflare Pages", (pagesYargs) =>
|
|
2256
|
+
pages(pagesYargs.command(subHelp))
|
|
2257
|
+
);
|
|
2258
|
+
|
|
2259
|
+
wrangler.command("r2", "📦 Interact with an R2 store", (r2Yargs) => {
|
|
2260
|
+
return r2Yargs
|
|
2261
|
+
.command(subHelp)
|
|
2262
|
+
.command("bucket", "Manage R2 buckets", (r2BucketYargs) => {
|
|
2263
|
+
r2BucketYargs.command(
|
|
2264
|
+
"create <name>",
|
|
2265
|
+
"Create a new R2 bucket",
|
|
2266
|
+
(yargs) => {
|
|
2267
|
+
return yargs.positional("name", {
|
|
2268
|
+
describe: "The name of the new bucket",
|
|
2269
|
+
type: "string",
|
|
2270
|
+
demandOption: true,
|
|
2271
|
+
});
|
|
2272
|
+
},
|
|
2273
|
+
async (args) => {
|
|
2274
|
+
printWranglerBanner();
|
|
2275
|
+
// We expect three values in `_`: `r2`, `bucket`, `create`.
|
|
2276
|
+
if (args._.length > 3) {
|
|
2277
|
+
const extraArgs = args._.slice(3).join(" ");
|
|
2278
|
+
throw new CommandLineArgsError(
|
|
2279
|
+
`Unexpected additional positional arguments "${extraArgs}".`
|
|
2280
|
+
);
|
|
2281
|
+
}
|
|
2282
|
+
|
|
2283
|
+
const config = readConfig(args.config as ConfigPath, undefined);
|
|
2284
|
+
|
|
2285
|
+
const accountId = await requireAuth(config);
|
|
2286
|
+
|
|
2287
|
+
console.log(`Creating bucket ${args.name}.`);
|
|
2288
|
+
await createR2Bucket(accountId, args.name);
|
|
2289
|
+
console.log(`Created bucket ${args.name}.`);
|
|
2290
|
+
}
|
|
2291
|
+
);
|
|
2292
|
+
|
|
2293
|
+
r2BucketYargs.command("list", "List R2 buckets", {}, async (args) => {
|
|
2294
|
+
const config = readConfig(args.config as ConfigPath, undefined);
|
|
2295
|
+
|
|
2296
|
+
const accountId = await requireAuth(config);
|
|
2297
|
+
|
|
2298
|
+
console.log(JSON.stringify(await listR2Buckets(accountId), null, 2));
|
|
2299
|
+
});
|
|
2300
|
+
|
|
2301
|
+
r2BucketYargs.command(
|
|
2302
|
+
"delete <name>",
|
|
2303
|
+
"Delete an R2 bucket",
|
|
2304
|
+
(yargs) => {
|
|
2305
|
+
return yargs.positional("name", {
|
|
2306
|
+
describe: "The name of the bucket to delete",
|
|
2307
|
+
type: "string",
|
|
2308
|
+
demandOption: true,
|
|
2309
|
+
});
|
|
2310
|
+
},
|
|
2311
|
+
async (args) => {
|
|
2312
|
+
printWranglerBanner();
|
|
2313
|
+
// We expect three values in `_`: `r2`, `bucket`, `delete`.
|
|
2314
|
+
if (args._.length > 3) {
|
|
2315
|
+
const extraArgs = args._.slice(3).join(" ");
|
|
2316
|
+
throw new CommandLineArgsError(
|
|
2317
|
+
`Unexpected additional positional arguments "${extraArgs}".`
|
|
2318
|
+
);
|
|
2319
|
+
}
|
|
2320
|
+
|
|
2321
|
+
const config = readConfig(args.config as ConfigPath, undefined);
|
|
2322
|
+
|
|
2323
|
+
const accountId = await requireAuth(config);
|
|
2324
|
+
|
|
2325
|
+
console.log(`Deleting bucket ${args.name}.`);
|
|
2326
|
+
await deleteR2Bucket(accountId, args.name);
|
|
2327
|
+
console.log(`Deleted bucket ${args.name}.`);
|
|
2328
|
+
}
|
|
2329
|
+
);
|
|
2330
|
+
return r2BucketYargs;
|
|
2331
|
+
});
|
|
2332
|
+
});
|
|
1940
2333
|
|
|
1941
2334
|
wrangler
|
|
2335
|
+
.option("legacy-env", {
|
|
2336
|
+
type: "boolean",
|
|
2337
|
+
describe: "Use legacy environments",
|
|
2338
|
+
})
|
|
1942
2339
|
.option("config", {
|
|
1943
2340
|
alias: "c",
|
|
1944
2341
|
describe: "Path to .toml configuration file",
|
|
1945
2342
|
type: "string",
|
|
1946
|
-
async coerce(arg) {
|
|
1947
|
-
return await readConfig(arg);
|
|
1948
|
-
},
|
|
1949
|
-
})
|
|
1950
|
-
.option("local", {
|
|
1951
|
-
alias: "l",
|
|
1952
|
-
describe: "Run on my machine",
|
|
1953
|
-
type: "boolean",
|
|
1954
|
-
default: false, // I bet this will a point of contention. We'll revisit it.
|
|
1955
2343
|
});
|
|
1956
2344
|
|
|
1957
|
-
wrangler.group(["config", "help", "version"], "Flags:");
|
|
2345
|
+
wrangler.group(["config", "help", "version", "legacy-env"], "Flags:");
|
|
1958
2346
|
wrangler.help().alias("h", "help");
|
|
1959
2347
|
wrangler.version(wranglerVersion).alias("v", "version");
|
|
1960
2348
|
wrangler.exitProcess(false);
|
|
1961
2349
|
|
|
1962
|
-
await initialiseUserConfig();
|
|
1963
|
-
|
|
1964
2350
|
try {
|
|
1965
2351
|
await wrangler.parse();
|
|
1966
2352
|
} catch (e) {
|
|
1967
2353
|
if (e instanceof CommandLineArgsError) {
|
|
1968
2354
|
wrangler.showHelp("error");
|
|
1969
2355
|
console.error(""); // Just adds a bit of space
|
|
2356
|
+
console.error(e.message);
|
|
2357
|
+
} else if (e instanceof ParseError) {
|
|
2358
|
+
console.error("");
|
|
2359
|
+
e.notes.push({
|
|
2360
|
+
text: "\nIf you think this is a bug, please open an issue at: https://github.com/cloudflare/wrangler2/issues/new",
|
|
2361
|
+
});
|
|
2362
|
+
console.error(formatMessage(e));
|
|
2363
|
+
} else {
|
|
2364
|
+
console.error(e instanceof Error ? e.message : e);
|
|
2365
|
+
console.error(""); // Just adds a bit of space
|
|
2366
|
+
console.error(
|
|
2367
|
+
`${fgGreenColor}%s${resetColor}`,
|
|
2368
|
+
"If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
|
|
2369
|
+
);
|
|
1970
2370
|
}
|
|
1971
|
-
console.error(e.message);
|
|
1972
2371
|
throw e;
|
|
1973
2372
|
}
|
|
1974
2373
|
}
|