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