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