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