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