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