wrangler 0.0.0-e3cab74 → 0.0.0-e452a35
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/Cloudflare_CA.pem +18 -0
- package/README.md +27 -14
- package/bin/wrangler.js +49 -5
- package/miniflare-dist/index.mjs +4886 -0
- package/package.json +42 -28
- package/pages/functions/buildPlugin.ts +105 -0
- package/pages/functions/buildWorker.ts +93 -4
- package/pages/functions/filepath-routing.test.ts +136 -25
- package/pages/functions/filepath-routing.ts +14 -3
- package/pages/functions/routes.ts +6 -1
- package/pages/functions/template-plugin.ts +147 -0
- package/pages/functions/template-worker.ts +21 -8
- package/src/__tests__/config-cache.test.ts +36 -0
- package/src/__tests__/configuration.test.ts +1514 -367
- package/src/__tests__/dev.test.tsx +870 -84
- package/src/__tests__/guess-worker-format.test.ts +37 -18
- package/src/__tests__/helpers/mock-account-id.ts +22 -4
- package/src/__tests__/helpers/mock-cfetch.ts +8 -4
- package/src/__tests__/helpers/mock-console.ts +35 -10
- package/src/__tests__/helpers/mock-dialogs.ts +26 -1
- package/src/__tests__/helpers/mock-http-server.ts +46 -0
- package/src/__tests__/helpers/mock-istty.ts +27 -0
- package/src/__tests__/helpers/mock-kv.ts +9 -16
- package/src/__tests__/helpers/mock-oauth-flow.ts +255 -0
- package/src/__tests__/helpers/mock-stdin.ts +103 -0
- package/src/__tests__/helpers/run-in-tmp.ts +10 -0
- package/src/__tests__/helpers/write-worker-source.ts +31 -0
- package/src/__tests__/https-options.test.ts +130 -0
- package/src/__tests__/index.test.ts +137 -747
- package/src/__tests__/init.test.ts +1557 -0
- package/src/__tests__/jest.setup.ts +28 -8
- package/src/__tests__/kv.test.ts +598 -258
- package/src/__tests__/logger.test.ts +115 -0
- package/src/__tests__/pages.test.ts +657 -0
- package/src/__tests__/parse.test.ts +8 -0
- package/src/__tests__/publish.test.ts +4003 -941
- package/src/__tests__/r2.test.ts +69 -34
- package/src/__tests__/route.test.ts +45 -0
- package/src/__tests__/secret.test.ts +228 -73
- package/src/__tests__/tail.test.ts +146 -20
- package/src/__tests__/user.test.ts +131 -0
- package/src/__tests__/whoami.test.tsx +26 -7
- package/src/abort.d.ts +3 -0
- package/src/bundle.ts +74 -7
- package/src/cfetch/index.ts +21 -4
- package/src/cfetch/internal.ts +20 -14
- package/src/cli.ts +5 -11
- package/src/config/README.md +7 -7
- package/src/config/config.ts +69 -100
- package/src/config/environment.ts +119 -4
- package/src/config/index.ts +177 -4
- package/src/config/validation-helpers.ts +228 -23
- package/src/config/validation.ts +687 -174
- package/src/config-cache.ts +45 -0
- package/src/{api/preview.ts → create-worker-preview.ts} +74 -36
- package/src/{api/form_data.ts → create-worker-upload-form.ts} +55 -18
- package/src/dev/dev-vars.ts +36 -0
- package/src/dev/dev.tsx +422 -0
- package/src/dev/local.tsx +318 -0
- package/src/dev/remote.tsx +227 -0
- package/src/dev/use-esbuild.ts +118 -0
- package/src/dialogs.tsx +16 -6
- package/src/durable.ts +102 -0
- package/src/entry.ts +279 -14
- package/src/environment-variables.ts +3 -1
- package/src/errors.ts +11 -0
- package/src/https-options.ts +123 -0
- package/src/index.tsx +1268 -806
- package/src/inspect.ts +64 -11
- package/src/intl-polyfill.d.ts +139 -0
- package/src/{kv.tsx → kv.ts} +195 -62
- package/src/logger.ts +66 -0
- package/src/miniflare-cli/README.md +30 -0
- package/src/miniflare-cli/enum-keys.ts +17 -0
- package/src/miniflare-cli/index.ts +41 -0
- package/src/miniflare-cli/request-context.ts +40 -0
- package/src/module-collection.ts +94 -6
- package/src/open-in-browser.ts +9 -3
- package/src/package-manager.ts +9 -8
- package/src/pages.tsx +1057 -75
- package/src/parse.ts +24 -5
- package/src/proxy.ts +143 -54
- package/src/publish.ts +444 -229
- package/src/selfsigned.d.ts +29 -0
- package/src/sites.tsx +98 -44
- package/src/tail/index.ts +2 -2
- package/src/tail/printing.ts +13 -8
- package/src/update-check.ts +19 -0
- package/src/user.tsx +263 -109
- package/src/whoami.tsx +2 -1
- package/src/{api/worker.ts → worker.ts} +24 -30
- package/templates/gitignore +171 -0
- package/templates/new-worker.ts +16 -1
- package/templates/static-asset-facade.js +1 -1
- package/wrangler-dist/cli.js +55345 -69246
- package/src/__tests__/helpers/mock-user.ts +0 -27
- package/src/__tests__/logout.test.ts +0 -50
- package/src/__tests__/sentry.test.ts +0 -146
- package/src/dev.tsx +0 -961
- package/src/guess-worker-format.ts +0 -68
- package/src/reporting.ts +0 -115
- package/wrangler-dist/cli.js.map +0 -7
package/src/index.tsx
CHANGED
|
@@ -3,33 +3,51 @@ import { writeFile, mkdir } from "node:fs/promises";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { setTimeout } from "node:timers/promises";
|
|
5
5
|
import TOML from "@iarna/toml";
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import { execa } from "execa";
|
|
6
8
|
import { findUp } from "find-up";
|
|
7
9
|
import getPort from "get-port";
|
|
8
10
|
import { render } from "ink";
|
|
9
11
|
import React from "react";
|
|
10
12
|
import onExit from "signal-exit";
|
|
13
|
+
import supportsColor from "supports-color";
|
|
14
|
+
import { setGlobalDispatcher, ProxyAgent } from "undici";
|
|
11
15
|
import makeCLI from "yargs";
|
|
12
16
|
import { version as wranglerVersion } from "../package.json";
|
|
13
|
-
import { toFormData } from "./api/form_data";
|
|
14
17
|
import { fetchResult } from "./cfetch";
|
|
15
18
|
import { findWranglerToml, readConfig } from "./config";
|
|
16
|
-
import
|
|
19
|
+
import { createWorkerUploadForm } from "./create-worker-upload-form";
|
|
20
|
+
import Dev from "./dev/dev";
|
|
21
|
+
import { getVarsForDev } from "./dev/dev-vars";
|
|
17
22
|
import { confirm, prompt } from "./dialogs";
|
|
18
23
|
import { getEntry } from "./entry";
|
|
24
|
+
import { DeprecationError } from "./errors";
|
|
19
25
|
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
getKVNamespaceId,
|
|
27
|
+
listKVNamespaces,
|
|
28
|
+
listKVNamespaceKeys,
|
|
29
|
+
putKVKeyValue,
|
|
30
|
+
putKVBulkKeyValue,
|
|
31
|
+
deleteKVBulkKeyValue,
|
|
32
|
+
createKVNamespace,
|
|
33
|
+
isValidKVNamespaceBinding,
|
|
34
|
+
getKVKeyValue,
|
|
35
|
+
isKVKeyValue,
|
|
36
|
+
unexpectedKVKeyValueProps,
|
|
37
|
+
deleteKVNamespace,
|
|
38
|
+
deleteKVKeyValue,
|
|
29
39
|
} from "./kv";
|
|
40
|
+
import { logger } from "./logger";
|
|
30
41
|
import { getPackageManager } from "./package-manager";
|
|
31
|
-
import { pages } from "./pages";
|
|
32
|
-
import {
|
|
42
|
+
import { pages, pagesBetaWarning } from "./pages";
|
|
43
|
+
import {
|
|
44
|
+
formatMessage,
|
|
45
|
+
ParseError,
|
|
46
|
+
parseJSON,
|
|
47
|
+
parsePackageJSON,
|
|
48
|
+
parseTOML,
|
|
49
|
+
readFileSync,
|
|
50
|
+
} from "./parse";
|
|
33
51
|
import publish from "./publish";
|
|
34
52
|
import { createR2Bucket, deleteR2Bucket, listR2Buckets } from "./r2";
|
|
35
53
|
import { getAssetPaths } from "./sites";
|
|
@@ -39,26 +57,38 @@ import {
|
|
|
39
57
|
prettyPrintLogs,
|
|
40
58
|
translateCLICommandToFilterMessage,
|
|
41
59
|
} from "./tail";
|
|
60
|
+
import { updateCheck } from "./update-check";
|
|
42
61
|
import {
|
|
43
62
|
login,
|
|
44
63
|
logout,
|
|
45
64
|
listScopes,
|
|
46
|
-
initialise as initialiseUserConfig,
|
|
47
|
-
loginOrRefreshIfRequired,
|
|
48
|
-
getAccountId,
|
|
49
65
|
validateScopeKeys,
|
|
66
|
+
requireAuth,
|
|
50
67
|
} from "./user";
|
|
51
68
|
import { whoami } from "./whoami";
|
|
52
69
|
|
|
53
70
|
import type { Config } from "./config";
|
|
54
71
|
import type { TailCLIFilters } from "./tail";
|
|
55
72
|
import type { RawData } from "ws";
|
|
73
|
+
import type { CommandModule } from "yargs";
|
|
56
74
|
import type Yargs from "yargs";
|
|
57
75
|
|
|
58
76
|
type ConfigPath = string | undefined;
|
|
59
77
|
|
|
60
78
|
const resetColor = "\x1b[0m";
|
|
61
79
|
const fgGreenColor = "\x1b[32m";
|
|
80
|
+
const DEFAULT_LOCAL_PORT = 8787;
|
|
81
|
+
|
|
82
|
+
const proxy =
|
|
83
|
+
process.env.https_proxy ||
|
|
84
|
+
process.env.HTTPS_PROXY ||
|
|
85
|
+
process.env.http_proxy ||
|
|
86
|
+
process.env.HTTP_PROXY ||
|
|
87
|
+
undefined;
|
|
88
|
+
|
|
89
|
+
if (proxy) {
|
|
90
|
+
setGlobalDispatcher(new ProxyAgent(proxy));
|
|
91
|
+
}
|
|
62
92
|
|
|
63
93
|
function getRules(config: Config): Config["rules"] {
|
|
64
94
|
const rules = config.rules ?? config.build?.upload?.rules ?? [];
|
|
@@ -70,8 +100,8 @@ function getRules(config: Config): Config["rules"] {
|
|
|
70
100
|
}
|
|
71
101
|
|
|
72
102
|
if (config.build?.upload?.rules) {
|
|
73
|
-
|
|
74
|
-
`Deprecation
|
|
103
|
+
logger.warn(
|
|
104
|
+
`Deprecation: 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:
|
|
75
105
|
|
|
76
106
|
${TOML.stringify({ rules: config.build.upload.rules })}`
|
|
77
107
|
);
|
|
@@ -79,25 +109,89 @@ ${TOML.stringify({ rules: config.build.upload.rules })}`
|
|
|
79
109
|
return rules;
|
|
80
110
|
}
|
|
81
111
|
|
|
82
|
-
function
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
112
|
+
async function printWranglerBanner() {
|
|
113
|
+
// Let's not print this in tests
|
|
114
|
+
if (typeof jest !== "undefined") {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const text = ` ⛅️ wrangler ${wranglerVersion} ${await updateCheck()}`;
|
|
119
|
+
|
|
120
|
+
logger.log(
|
|
121
|
+
text +
|
|
122
|
+
"\n" +
|
|
123
|
+
(supportsColor.stdout
|
|
124
|
+
? chalk.hex("#FF8800")("-".repeat(text.length))
|
|
125
|
+
: "-".repeat(text.length))
|
|
86
126
|
);
|
|
87
127
|
}
|
|
88
128
|
|
|
129
|
+
function isLegacyEnv(config: Config): boolean {
|
|
130
|
+
// We only read from config here, because we've already accounted for
|
|
131
|
+
// args["legacy-env"] in https://github.com/cloudflare/wrangler2/blob/b24aeb5722370c2e04bce97a84a1fa1e55725d79/packages/wrangler/src/config/validation.ts#L94-L98
|
|
132
|
+
return config.legacy_env;
|
|
133
|
+
}
|
|
134
|
+
|
|
89
135
|
function getScriptName(
|
|
90
136
|
args: { name: string | undefined; env: string | undefined },
|
|
91
137
|
config: Config
|
|
92
138
|
): string | undefined {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
139
|
+
if (args.name && isLegacyEnv(config) && args.env) {
|
|
140
|
+
throw new CommandLineArgsError(
|
|
141
|
+
"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:" +
|
|
142
|
+
`
|
|
143
|
+
[env.${args.env}]
|
|
144
|
+
name = "${args.name}"
|
|
145
|
+
`
|
|
146
|
+
);
|
|
96
147
|
}
|
|
97
148
|
|
|
98
|
-
return
|
|
99
|
-
|
|
100
|
-
|
|
149
|
+
return args.name ?? config.name;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Alternative to the getScriptName() because special Legacy cases allowed "name", and "env" together in Wrangler1
|
|
154
|
+
*/
|
|
155
|
+
function getLegacyScriptName(
|
|
156
|
+
args: { name: string | undefined; env: string | undefined },
|
|
157
|
+
config: Config
|
|
158
|
+
) {
|
|
159
|
+
return args.name && args.env && isLegacyEnv(config)
|
|
160
|
+
? `${args.name}-${args.env}`
|
|
161
|
+
: args.name ?? config.name;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Get a promise to the streamed input from stdin.
|
|
166
|
+
*
|
|
167
|
+
* This function can be used to grab the incoming stream of data from, say,
|
|
168
|
+
* piping the output of another process into the wrangler process.
|
|
169
|
+
*/
|
|
170
|
+
function readFromStdin(): Promise<string> {
|
|
171
|
+
return new Promise((resolve, reject) => {
|
|
172
|
+
const stdin = process.stdin;
|
|
173
|
+
const chunks: string[] = [];
|
|
174
|
+
|
|
175
|
+
// When there is data ready to be read, the `readable` event will be triggered.
|
|
176
|
+
// In the handler for `readable` we call `read()` over and over until all the available data has been read.
|
|
177
|
+
stdin.on("readable", () => {
|
|
178
|
+
let chunk;
|
|
179
|
+
while (null !== (chunk = stdin.read())) {
|
|
180
|
+
chunks.push(chunk);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// When the streamed data is complete the `end` event will be triggered.
|
|
185
|
+
// In the handler for `end` we join the chunks together and resolve the promise.
|
|
186
|
+
stdin.on("end", () => {
|
|
187
|
+
resolve(chunks.join(""));
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// If there is an `error` event then the handler will reject the promise.
|
|
191
|
+
stdin.on("error", (err) => {
|
|
192
|
+
reject(err);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
101
195
|
}
|
|
102
196
|
|
|
103
197
|
// a helper to demand one of a set of options
|
|
@@ -125,22 +219,27 @@ function demandOneOfOption(...options: string[]) {
|
|
|
125
219
|
};
|
|
126
220
|
}
|
|
127
221
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
222
|
+
/**
|
|
223
|
+
* Remove trailing white space from inputs.
|
|
224
|
+
* Matching Wrangler legacy behavior with handling inputs
|
|
225
|
+
*/
|
|
226
|
+
function trimTrailingWhitespace(str: string) {
|
|
227
|
+
return str.trimEnd();
|
|
133
228
|
}
|
|
134
229
|
|
|
135
|
-
|
|
230
|
+
class CommandLineArgsError extends Error {}
|
|
231
|
+
|
|
232
|
+
function createCLIParser(argv: string[]) {
|
|
136
233
|
const wrangler = makeCLI(argv)
|
|
234
|
+
.strict()
|
|
137
235
|
// We handle errors ourselves in a try-catch around `yargs.parse`.
|
|
138
236
|
// If you want the "help info" to be displayed then throw an instance of `CommandLineArgsError`.
|
|
139
237
|
// Otherwise we just log the error that was thrown without any "help info".
|
|
140
238
|
.showHelpOnFail(false)
|
|
141
239
|
.fail((msg, error) => {
|
|
142
|
-
if (!error) {
|
|
143
|
-
// If there is
|
|
240
|
+
if (!error || error.name === "YError") {
|
|
241
|
+
// If there is no error or the error is a "YError", then this came from yargs own validation
|
|
242
|
+
// Wrap it in a `CommandLineArgsError` so that we can handle it appropriately further up.
|
|
144
243
|
error = new CommandLineArgsError(msg);
|
|
145
244
|
}
|
|
146
245
|
throw error;
|
|
@@ -148,7 +247,15 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
148
247
|
.scriptName("wrangler")
|
|
149
248
|
.wrap(null);
|
|
150
249
|
|
|
151
|
-
//
|
|
250
|
+
// Default help command that supports the subcommands
|
|
251
|
+
const subHelp: CommandModule = {
|
|
252
|
+
command: ["*"],
|
|
253
|
+
handler: async (args) => {
|
|
254
|
+
setImmediate(() =>
|
|
255
|
+
wrangler.parse([...args._.map((a) => `${a}`), "--help"])
|
|
256
|
+
);
|
|
257
|
+
},
|
|
258
|
+
};
|
|
152
259
|
wrangler.command(
|
|
153
260
|
["*"],
|
|
154
261
|
false,
|
|
@@ -182,14 +289,19 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
182
289
|
default: "worker",
|
|
183
290
|
})
|
|
184
291
|
.positional("template", {
|
|
185
|
-
describe: "
|
|
292
|
+
describe: "The URL of a GitHub template",
|
|
186
293
|
default: "https://github.com/cloudflare/worker-template",
|
|
187
294
|
});
|
|
188
295
|
},
|
|
189
|
-
() => {
|
|
296
|
+
(generateArgs) => {
|
|
190
297
|
// "👯 [DEPRECATED]. Scaffold a Cloudflare Workers project from a public GitHub repository.",
|
|
191
298
|
throw new DeprecationError(
|
|
192
|
-
"`wrangler generate` has been deprecated
|
|
299
|
+
"`wrangler generate` has been deprecated.\n" +
|
|
300
|
+
"Try running `wrangler init` to generate a basic Worker, or cloning the template repository instead:\n\n" +
|
|
301
|
+
"```\n" +
|
|
302
|
+
`git clone ${generateArgs.template}\n` +
|
|
303
|
+
"```\n\n" +
|
|
304
|
+
"Please refer to https://developers.cloudflare.com/workers/wrangler/deprecations/#generate for more information."
|
|
193
305
|
);
|
|
194
306
|
}
|
|
195
307
|
);
|
|
@@ -204,6 +316,18 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
204
316
|
describe: "The name of your worker",
|
|
205
317
|
type: "string",
|
|
206
318
|
})
|
|
319
|
+
.option("type", {
|
|
320
|
+
describe: "The type of worker to create",
|
|
321
|
+
type: "string",
|
|
322
|
+
choices: ["rust", "javascript", "webpack"],
|
|
323
|
+
hidden: true,
|
|
324
|
+
deprecated: true,
|
|
325
|
+
})
|
|
326
|
+
.option("site", {
|
|
327
|
+
hidden: true,
|
|
328
|
+
type: "boolean",
|
|
329
|
+
deprecated: true,
|
|
330
|
+
})
|
|
207
331
|
.option("yes", {
|
|
208
332
|
describe: 'Answer "yes" to any prompts for new projects',
|
|
209
333
|
type: "boolean",
|
|
@@ -211,7 +335,8 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
211
335
|
});
|
|
212
336
|
},
|
|
213
337
|
async (args) => {
|
|
214
|
-
|
|
338
|
+
await printWranglerBanner();
|
|
339
|
+
if (args.type) {
|
|
215
340
|
let message = "The --type option is no longer supported.";
|
|
216
341
|
if (args.type === "webpack") {
|
|
217
342
|
message +=
|
|
@@ -221,9 +346,33 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
221
346
|
throw new CommandLineArgsError(message);
|
|
222
347
|
}
|
|
223
348
|
|
|
224
|
-
|
|
349
|
+
const devDepsToInstall: string[] = [];
|
|
350
|
+
const instructions: string[] = [];
|
|
351
|
+
let shouldRunPackageManagerInstall = false;
|
|
352
|
+
const creationDirectory = path.resolve(process.cwd(), args.name ?? "");
|
|
353
|
+
|
|
354
|
+
if (args.site) {
|
|
355
|
+
const gitDirectory =
|
|
356
|
+
creationDirectory !== process.cwd()
|
|
357
|
+
? path.basename(creationDirectory)
|
|
358
|
+
: "my-site";
|
|
359
|
+
const message =
|
|
360
|
+
"The --site option is no longer supported.\n" +
|
|
361
|
+
"If you wish to create a brand new Worker Sites project then clone the `worker-sites-template` starter repository:\n\n" +
|
|
362
|
+
"```\n" +
|
|
363
|
+
`git clone --depth=1 --branch=wrangler2 https://github.com/cloudflare/worker-sites-template ${gitDirectory}\n` +
|
|
364
|
+
`cd ${gitDirectory}\n` +
|
|
365
|
+
"```\n\n" +
|
|
366
|
+
"Find out more about how to create and maintain Sites projects at https://developers.cloudflare.com/workers/platform/sites.\n" +
|
|
367
|
+
"Have you considered using Cloudflare Pages instead? See https://pages.cloudflare.com/.";
|
|
368
|
+
throw new CommandLineArgsError(message);
|
|
369
|
+
}
|
|
225
370
|
|
|
226
|
-
|
|
371
|
+
// TODO: make sure args.name is a valid identifier for a worker name
|
|
372
|
+
const workerName = path
|
|
373
|
+
.basename(creationDirectory)
|
|
374
|
+
.toLowerCase()
|
|
375
|
+
.replaceAll(/[^a-z0-9\-_]/gm, "-");
|
|
227
376
|
|
|
228
377
|
const packageManager = await getPackageManager(creationDirectory);
|
|
229
378
|
|
|
@@ -235,10 +384,14 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
235
384
|
"./wrangler.toml"
|
|
236
385
|
);
|
|
237
386
|
let justCreatedWranglerToml = false;
|
|
238
|
-
|
|
239
|
-
args.name || path.basename(path.resolve(process.cwd()));
|
|
387
|
+
|
|
240
388
|
if (fs.existsSync(wranglerTomlDestination)) {
|
|
241
|
-
|
|
389
|
+
logger.warn(
|
|
390
|
+
`${path.relative(
|
|
391
|
+
process.cwd(),
|
|
392
|
+
wranglerTomlDestination
|
|
393
|
+
)} already exists!`
|
|
394
|
+
);
|
|
242
395
|
const shouldContinue = await confirm(
|
|
243
396
|
"Do you want to continue initializing this project?"
|
|
244
397
|
);
|
|
@@ -248,6 +401,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
248
401
|
} else {
|
|
249
402
|
await mkdir(creationDirectory, { recursive: true });
|
|
250
403
|
const compatibilityDate = new Date().toISOString().substring(0, 10);
|
|
404
|
+
|
|
251
405
|
try {
|
|
252
406
|
await writeFile(
|
|
253
407
|
wranglerTomlDestination,
|
|
@@ -256,18 +410,63 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
256
410
|
compatibility_date: compatibilityDate,
|
|
257
411
|
}) + "\n"
|
|
258
412
|
);
|
|
259
|
-
|
|
413
|
+
|
|
414
|
+
logger.log(
|
|
415
|
+
`✨ Created ${path.relative(
|
|
416
|
+
process.cwd(),
|
|
417
|
+
wranglerTomlDestination
|
|
418
|
+
)}`
|
|
419
|
+
);
|
|
260
420
|
justCreatedWranglerToml = true;
|
|
261
421
|
} catch (err) {
|
|
262
422
|
throw new Error(
|
|
263
|
-
`Failed to create
|
|
423
|
+
`Failed to create ${path.relative(
|
|
424
|
+
process.cwd(),
|
|
425
|
+
wranglerTomlDestination
|
|
426
|
+
)}.\n${(err as Error).message ?? err}`
|
|
264
427
|
);
|
|
265
428
|
}
|
|
266
429
|
}
|
|
267
430
|
|
|
268
|
-
let pathToPackageJson = await findUp("package.json");
|
|
269
|
-
let shouldCreatePackageJson = false;
|
|
270
431
|
const yesFlag = args.yes ?? false;
|
|
432
|
+
|
|
433
|
+
const isInsideGitProject = Boolean(
|
|
434
|
+
await findUp(".git", { cwd: creationDirectory, type: "directory" })
|
|
435
|
+
);
|
|
436
|
+
let isGitInstalled;
|
|
437
|
+
try {
|
|
438
|
+
isGitInstalled = (await execa("git", ["--version"])).exitCode === 0;
|
|
439
|
+
} catch (err) {
|
|
440
|
+
isGitInstalled = false;
|
|
441
|
+
}
|
|
442
|
+
if (!isInsideGitProject && isGitInstalled) {
|
|
443
|
+
const shouldInitGit =
|
|
444
|
+
yesFlag ||
|
|
445
|
+
(await confirm("Would you like to use git to manage this Worker?"));
|
|
446
|
+
if (shouldInitGit) {
|
|
447
|
+
await execa("git", ["init", "--initial-branch=main"], {
|
|
448
|
+
cwd: creationDirectory,
|
|
449
|
+
});
|
|
450
|
+
await writeFile(
|
|
451
|
+
path.join(creationDirectory, ".gitignore"),
|
|
452
|
+
readFileSync(path.join(__dirname, "../templates/gitignore"))
|
|
453
|
+
);
|
|
454
|
+
logger.log(
|
|
455
|
+
args.name && args.name !== "."
|
|
456
|
+
? `✨ Initialized git repository at ${path.relative(
|
|
457
|
+
process.cwd(),
|
|
458
|
+
creationDirectory
|
|
459
|
+
)}`
|
|
460
|
+
: `✨ Initialized git repository`
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
let pathToPackageJson = await findUp("package.json", {
|
|
466
|
+
cwd: creationDirectory,
|
|
467
|
+
});
|
|
468
|
+
let shouldCreatePackageJson = false;
|
|
469
|
+
|
|
271
470
|
if (!pathToPackageJson) {
|
|
272
471
|
// If no package.json exists, ask to create one
|
|
273
472
|
shouldCreatePackageJson =
|
|
@@ -284,7 +483,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
284
483
|
name: workerName,
|
|
285
484
|
version: "0.0.0",
|
|
286
485
|
devDependencies: {
|
|
287
|
-
wrangler: wranglerVersion
|
|
486
|
+
wrangler: `^${wranglerVersion}`,
|
|
288
487
|
},
|
|
289
488
|
private: true,
|
|
290
489
|
},
|
|
@@ -292,16 +491,19 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
292
491
|
" "
|
|
293
492
|
) + "\n"
|
|
294
493
|
);
|
|
295
|
-
|
|
296
|
-
|
|
494
|
+
|
|
495
|
+
shouldRunPackageManagerInstall = true;
|
|
297
496
|
pathToPackageJson = path.join(creationDirectory, "package.json");
|
|
497
|
+
logger.log(
|
|
498
|
+
`✨ Created ${path.relative(process.cwd(), pathToPackageJson)}`
|
|
499
|
+
);
|
|
298
500
|
} else {
|
|
299
501
|
return;
|
|
300
502
|
}
|
|
301
503
|
} else {
|
|
302
504
|
// If package.json exists and wrangler isn't installed,
|
|
303
505
|
// then ask to add wrangler to devDependencies
|
|
304
|
-
const packageJson =
|
|
506
|
+
const packageJson = parsePackageJSON(
|
|
305
507
|
readFileSync(pathToPackageJson),
|
|
306
508
|
pathToPackageJson
|
|
307
509
|
);
|
|
@@ -314,17 +516,21 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
314
516
|
const shouldInstall =
|
|
315
517
|
yesFlag ||
|
|
316
518
|
(await confirm(
|
|
317
|
-
|
|
519
|
+
`Would you like to install wrangler into ${path.relative(
|
|
520
|
+
process.cwd(),
|
|
521
|
+
pathToPackageJson
|
|
522
|
+
)}?`
|
|
318
523
|
));
|
|
319
524
|
if (shouldInstall) {
|
|
320
|
-
|
|
321
|
-
console.log(`✨ Installed wrangler`);
|
|
525
|
+
devDepsToInstall.push(`wrangler@${wranglerVersion}`);
|
|
322
526
|
}
|
|
323
527
|
}
|
|
324
528
|
}
|
|
325
529
|
|
|
326
530
|
let isTypescriptProject = false;
|
|
327
|
-
let pathToTSConfig = await findUp("tsconfig.json"
|
|
531
|
+
let pathToTSConfig = await findUp("tsconfig.json", {
|
|
532
|
+
cwd: creationDirectory,
|
|
533
|
+
});
|
|
328
534
|
if (!pathToTSConfig) {
|
|
329
535
|
// If there's no tsconfig, offer to create one
|
|
330
536
|
// and install @cloudflare/workers-types
|
|
@@ -334,21 +540,18 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
334
540
|
path.join(creationDirectory, "./tsconfig.json"),
|
|
335
541
|
readFileSync(path.join(__dirname, "../templates/tsconfig.json"))
|
|
336
542
|
);
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
"typescript"
|
|
340
|
-
);
|
|
341
|
-
|
|
342
|
-
console.log(
|
|
343
|
-
`✨ Created tsconfig.json, installed @cloudflare/workers-types into devDependencies`
|
|
344
|
-
);
|
|
543
|
+
devDepsToInstall.push("@cloudflare/workers-types");
|
|
544
|
+
devDepsToInstall.push("typescript");
|
|
345
545
|
pathToTSConfig = path.join(creationDirectory, "tsconfig.json");
|
|
546
|
+
logger.log(
|
|
547
|
+
`✨ Created ${path.relative(process.cwd(), pathToTSConfig)}`
|
|
548
|
+
);
|
|
346
549
|
}
|
|
347
550
|
} else {
|
|
348
551
|
isTypescriptProject = true;
|
|
349
552
|
// If there's a tsconfig, check if @cloudflare/workers-types
|
|
350
553
|
// is already installed, and offer to install it if not
|
|
351
|
-
const packageJson =
|
|
554
|
+
const packageJson = parsePackageJSON(
|
|
352
555
|
readFileSync(pathToPackageJson),
|
|
353
556
|
pathToPackageJson
|
|
354
557
|
);
|
|
@@ -362,19 +565,22 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
362
565
|
"Would you like to install the type definitions for Workers into your package.json?"
|
|
363
566
|
);
|
|
364
567
|
if (shouldInstall) {
|
|
365
|
-
|
|
568
|
+
devDepsToInstall.push("@cloudflare/workers-types");
|
|
366
569
|
// We don't update the tsconfig.json because
|
|
367
570
|
// it could be complicated in existing projects
|
|
368
571
|
// and we don't want to break them. Instead, we simply
|
|
369
572
|
// tell the user that they need to update their tsconfig.json
|
|
370
|
-
|
|
371
|
-
|
|
573
|
+
instructions.push(
|
|
574
|
+
`🚨 Please add "@cloudflare/workers-types" to compilerOptions.types in ${path.relative(
|
|
575
|
+
process.cwd(),
|
|
576
|
+
pathToTSConfig
|
|
577
|
+
)}`
|
|
372
578
|
);
|
|
373
579
|
}
|
|
374
580
|
}
|
|
375
581
|
}
|
|
376
582
|
|
|
377
|
-
const packageJsonContent =
|
|
583
|
+
const packageJsonContent = parsePackageJSON(
|
|
378
584
|
readFileSync(pathToPackageJson),
|
|
379
585
|
pathToPackageJson
|
|
380
586
|
);
|
|
@@ -383,6 +589,41 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
383
589
|
!packageJsonContent.scripts?.publish &&
|
|
384
590
|
shouldCreatePackageJson;
|
|
385
591
|
|
|
592
|
+
/*
|
|
593
|
+
* Passes the array of accumulated devDeps to install through to
|
|
594
|
+
* the package manager. Also generates a human-readable list
|
|
595
|
+
* of packages it installed.
|
|
596
|
+
* If there are no devDeps to install, optionally runs
|
|
597
|
+
* the package manager's install command.
|
|
598
|
+
*/
|
|
599
|
+
async function installPackages(
|
|
600
|
+
shouldRunInstall: boolean,
|
|
601
|
+
depsToInstall: string[]
|
|
602
|
+
) {
|
|
603
|
+
//lets install the devDeps they asked for
|
|
604
|
+
//and run their package manager's install command if needed
|
|
605
|
+
if (depsToInstall.length > 0) {
|
|
606
|
+
const formatter = new Intl.ListFormat("en", {
|
|
607
|
+
style: "long",
|
|
608
|
+
type: "conjunction",
|
|
609
|
+
});
|
|
610
|
+
await packageManager.addDevDeps(...depsToInstall);
|
|
611
|
+
const versionlessPackages = depsToInstall.map((dep) =>
|
|
612
|
+
dep === `wrangler@${wranglerVersion}` ? "wrangler" : dep
|
|
613
|
+
);
|
|
614
|
+
|
|
615
|
+
logger.log(
|
|
616
|
+
`✨ Installed ${formatter.format(
|
|
617
|
+
versionlessPackages
|
|
618
|
+
)} into devDependencies`
|
|
619
|
+
);
|
|
620
|
+
} else {
|
|
621
|
+
if (shouldRunInstall) {
|
|
622
|
+
await packageManager.install();
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
386
627
|
async function writePackageJsonScriptsAndUpdateWranglerToml(
|
|
387
628
|
isWritingScripts: boolean,
|
|
388
629
|
isCreatingWranglerToml: boolean,
|
|
@@ -391,7 +632,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
391
632
|
) {
|
|
392
633
|
if (isCreatingWranglerToml) {
|
|
393
634
|
// rewrite wrangler.toml with main = "path/to/script"
|
|
394
|
-
const parsedWranglerToml =
|
|
635
|
+
const parsedWranglerToml = parseTOML(
|
|
395
636
|
readFileSync(wranglerTomlDestination)
|
|
396
637
|
);
|
|
397
638
|
fs.writeFileSync(
|
|
@@ -417,7 +658,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
417
658
|
start: isCreatingWranglerToml
|
|
418
659
|
? `wrangler dev`
|
|
419
660
|
: `wrangler dev ${scriptPath}`,
|
|
420
|
-
|
|
661
|
+
deploy: isCreatingWranglerToml
|
|
421
662
|
? `wrangler publish`
|
|
422
663
|
: `wrangler publish ${scriptPath}`,
|
|
423
664
|
},
|
|
@@ -426,21 +667,21 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
426
667
|
2
|
|
427
668
|
) + "\n"
|
|
428
669
|
);
|
|
429
|
-
|
|
670
|
+
instructions.push(
|
|
430
671
|
`\nTo start developing your Worker, run \`${
|
|
431
672
|
isNamedWorker ? `cd ${args.name} && ` : ""
|
|
432
673
|
}npm start\``
|
|
433
674
|
);
|
|
434
|
-
|
|
435
|
-
`To publish your Worker to the Internet, run \`npm run
|
|
675
|
+
instructions.push(
|
|
676
|
+
`To publish your Worker to the Internet, run \`npm run deploy\``
|
|
436
677
|
);
|
|
437
678
|
} else {
|
|
438
|
-
|
|
679
|
+
instructions.push(
|
|
439
680
|
`\nTo start developing your Worker, run \`npx wrangler dev\`${
|
|
440
681
|
isCreatingWranglerToml ? "" : ` ${scriptPath}`
|
|
441
682
|
}`
|
|
442
683
|
);
|
|
443
|
-
|
|
684
|
+
instructions.push(
|
|
444
685
|
`To publish your Worker to the Internet, run \`npx wrangler publish\`${
|
|
445
686
|
isCreatingWranglerToml ? "" : ` ${scriptPath}`
|
|
446
687
|
}`
|
|
@@ -450,12 +691,13 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
450
691
|
|
|
451
692
|
if (isTypescriptProject) {
|
|
452
693
|
if (!fs.existsSync(path.join(creationDirectory, "./src/index.ts"))) {
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
shouldCreateSource =
|
|
694
|
+
const shouldCreateSource =
|
|
456
695
|
yesFlag ||
|
|
457
696
|
(await confirm(
|
|
458
|
-
`Would you like to create a Worker at
|
|
697
|
+
`Would you like to create a Worker at ${path.relative(
|
|
698
|
+
process.cwd(),
|
|
699
|
+
path.join(creationDirectory, "./src/index.ts")
|
|
700
|
+
)}?`
|
|
459
701
|
));
|
|
460
702
|
|
|
461
703
|
if (shouldCreateSource) {
|
|
@@ -467,7 +709,12 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
467
709
|
readFileSync(path.join(__dirname, "../templates/new-worker.ts"))
|
|
468
710
|
);
|
|
469
711
|
|
|
470
|
-
|
|
712
|
+
logger.log(
|
|
713
|
+
`✨ Created ${path.relative(
|
|
714
|
+
process.cwd(),
|
|
715
|
+
path.join(creationDirectory, "./src/index.ts")
|
|
716
|
+
)}`
|
|
717
|
+
);
|
|
471
718
|
|
|
472
719
|
await writePackageJsonScriptsAndUpdateWranglerToml(
|
|
473
720
|
shouldWritePackageJsonScripts,
|
|
@@ -478,20 +725,31 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
478
725
|
}
|
|
479
726
|
}
|
|
480
727
|
} else {
|
|
481
|
-
if (!fs.existsSync("./src/index.js")) {
|
|
482
|
-
const shouldCreateSource =
|
|
483
|
-
|
|
484
|
-
|
|
728
|
+
if (!fs.existsSync(path.join(creationDirectory, "./src/index.js"))) {
|
|
729
|
+
const shouldCreateSource =
|
|
730
|
+
yesFlag ||
|
|
731
|
+
(await confirm(
|
|
732
|
+
`Would you like to create a Worker at ${path.relative(
|
|
733
|
+
process.cwd(),
|
|
734
|
+
path.join(creationDirectory, "./src/index.js")
|
|
735
|
+
)}?`
|
|
736
|
+
));
|
|
737
|
+
|
|
485
738
|
if (shouldCreateSource) {
|
|
486
739
|
await mkdir(path.join(creationDirectory, "./src"), {
|
|
487
740
|
recursive: true,
|
|
488
741
|
});
|
|
489
742
|
await writeFile(
|
|
490
|
-
path.join(
|
|
743
|
+
path.join(creationDirectory, "./src/index.js"),
|
|
491
744
|
readFileSync(path.join(__dirname, "../templates/new-worker.js"))
|
|
492
745
|
);
|
|
493
746
|
|
|
494
|
-
|
|
747
|
+
logger.log(
|
|
748
|
+
`✨ Created ${path.relative(
|
|
749
|
+
process.cwd(),
|
|
750
|
+
path.join(creationDirectory, "./src/index.js")
|
|
751
|
+
)}`
|
|
752
|
+
);
|
|
495
753
|
|
|
496
754
|
await writePackageJsonScriptsAndUpdateWranglerToml(
|
|
497
755
|
shouldWritePackageJsonScripts,
|
|
@@ -502,6 +760,21 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
502
760
|
}
|
|
503
761
|
}
|
|
504
762
|
}
|
|
763
|
+
// install packages as the final step of init
|
|
764
|
+
try {
|
|
765
|
+
await installPackages(shouldRunPackageManagerInstall, devDepsToInstall);
|
|
766
|
+
} catch (e) {
|
|
767
|
+
// fetching packages could fail due to loss of internet, etc
|
|
768
|
+
// we should let folks know we failed to fetch, but their
|
|
769
|
+
// workers project is still ready to go
|
|
770
|
+
logger.error(e instanceof Error ? e.message : e);
|
|
771
|
+
instructions.push(
|
|
772
|
+
"\n🚨 wrangler was unable to fetch your npm packages, but your project is ready to go"
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
// let users know what to do now
|
|
777
|
+
instructions.forEach((instruction) => logger.log(instruction));
|
|
505
778
|
}
|
|
506
779
|
);
|
|
507
780
|
|
|
@@ -512,83 +785,34 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
512
785
|
(yargs) => {
|
|
513
786
|
return yargs.option("env", {
|
|
514
787
|
describe: "Perform on a specific environment",
|
|
788
|
+
type: "string",
|
|
515
789
|
});
|
|
516
790
|
},
|
|
517
|
-
() => {
|
|
791
|
+
async (buildArgs) => {
|
|
518
792
|
// "[DEPRECATED] 🦀 Build your project (if applicable)",
|
|
519
|
-
throw new DeprecationError(
|
|
520
|
-
"`wrangler build` has been deprecated, please refer to TODO://some/path for alternatives"
|
|
521
|
-
);
|
|
522
|
-
}
|
|
523
|
-
);
|
|
524
793
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
794
|
+
const envFlag = buildArgs.env ? ` --env=${buildArgs.env}` : "";
|
|
795
|
+
logger.log(
|
|
796
|
+
formatMessage({
|
|
797
|
+
kind: "warning",
|
|
798
|
+
text: "Deprecation: `wrangler build` has been deprecated.",
|
|
799
|
+
notes: [
|
|
800
|
+
{
|
|
801
|
+
text: "Please refer to https://developers.cloudflare.com/workers/wrangler/migration/deprecations/#build for more information.",
|
|
802
|
+
},
|
|
803
|
+
{
|
|
804
|
+
text: `Attempting to run \`wrangler publish --dry-run --outdir=dist${envFlag}\` for you instead:`,
|
|
805
|
+
},
|
|
806
|
+
],
|
|
537
807
|
})
|
|
538
|
-
|
|
539
|
-
describe: "Pick the set of applicable OAuth scopes when logging in",
|
|
540
|
-
array: true,
|
|
541
|
-
type: "string",
|
|
542
|
-
});
|
|
543
|
-
|
|
544
|
-
// TODO: scopes
|
|
545
|
-
},
|
|
546
|
-
async (args) => {
|
|
547
|
-
if (args["scopes-list"]) {
|
|
548
|
-
listScopes();
|
|
549
|
-
return;
|
|
550
|
-
}
|
|
551
|
-
if (args.scopes) {
|
|
552
|
-
if (args.scopes.length === 0) {
|
|
553
|
-
// don't allow no scopes to be passed, that would be weird
|
|
554
|
-
listScopes();
|
|
555
|
-
return;
|
|
556
|
-
}
|
|
557
|
-
if (!validateScopeKeys(args.scopes)) {
|
|
558
|
-
throw new CommandLineArgsError(
|
|
559
|
-
`One of ${args.scopes} is not a valid authentication scope. Run "wrangler login --list-scopes" to see the valid scopes.`
|
|
560
|
-
);
|
|
561
|
-
}
|
|
562
|
-
await login({ scopes: args.scopes });
|
|
563
|
-
return;
|
|
564
|
-
}
|
|
565
|
-
await login();
|
|
566
|
-
|
|
567
|
-
// TODO: would be nice if it optionally saved login
|
|
568
|
-
// credentials inside node_modules/.cache or something
|
|
569
|
-
// this way you could have multiple users on a single machine
|
|
570
|
-
}
|
|
571
|
-
);
|
|
572
|
-
|
|
573
|
-
// logout
|
|
574
|
-
wrangler.command(
|
|
575
|
-
// this needs scopes as an option?
|
|
576
|
-
"logout",
|
|
577
|
-
false, // we don't need to show this in the menu
|
|
578
|
-
// "🚪 Logout from Cloudflare",
|
|
579
|
-
() => {},
|
|
580
|
-
async () => {
|
|
581
|
-
await logout();
|
|
582
|
-
}
|
|
583
|
-
);
|
|
808
|
+
);
|
|
584
809
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
await whoami();
|
|
810
|
+
await createCLIParser([
|
|
811
|
+
"publish",
|
|
812
|
+
"--dry-run",
|
|
813
|
+
"--outdir=dist",
|
|
814
|
+
...(buildArgs.env ? ["--env", buildArgs.env] : []),
|
|
815
|
+
]).parse();
|
|
592
816
|
}
|
|
593
817
|
);
|
|
594
818
|
|
|
@@ -600,7 +824,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
600
824
|
() => {
|
|
601
825
|
// "🕵️ Authenticate Wrangler with a Cloudflare API Token",
|
|
602
826
|
throw new DeprecationError(
|
|
603
|
-
"`wrangler config` has been deprecated, please refer to
|
|
827
|
+
"`wrangler config` has been deprecated, please refer to https://developers.cloudflare.com/workers/wrangler/migration/deprecations/#config for alternatives"
|
|
604
828
|
);
|
|
605
829
|
}
|
|
606
830
|
);
|
|
@@ -618,23 +842,30 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
618
842
|
.option("name", {
|
|
619
843
|
describe: "Name of the worker",
|
|
620
844
|
type: "string",
|
|
845
|
+
requiresArg: true,
|
|
621
846
|
})
|
|
622
847
|
.option("format", {
|
|
623
848
|
choices: ["modules", "service-worker"] as const,
|
|
624
849
|
describe: "Choose an entry type",
|
|
850
|
+
deprecated: true,
|
|
625
851
|
})
|
|
626
852
|
.option("env", {
|
|
627
853
|
describe: "Perform on a specific environment",
|
|
628
854
|
type: "string",
|
|
855
|
+
requiresArg: true,
|
|
856
|
+
alias: "e",
|
|
629
857
|
})
|
|
630
858
|
.option("compatibility-date", {
|
|
631
859
|
describe: "Date to use for compatibility checks",
|
|
632
860
|
type: "string",
|
|
861
|
+
requiresArg: true,
|
|
633
862
|
})
|
|
634
863
|
.option("compatibility-flags", {
|
|
635
864
|
describe: "Flags to use for compatibility checks",
|
|
636
|
-
type: "array",
|
|
637
865
|
alias: "compatibility-flag",
|
|
866
|
+
type: "string",
|
|
867
|
+
requiresArg: true,
|
|
868
|
+
array: true,
|
|
638
869
|
})
|
|
639
870
|
.option("latest", {
|
|
640
871
|
describe: "Use the latest version of the worker runtime",
|
|
@@ -642,9 +873,9 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
642
873
|
default: true,
|
|
643
874
|
})
|
|
644
875
|
.option("ip", {
|
|
645
|
-
describe: "IP address to listen on",
|
|
876
|
+
describe: "IP address to listen on, defaults to `localhost`",
|
|
646
877
|
type: "string",
|
|
647
|
-
|
|
878
|
+
requiresArg: true,
|
|
648
879
|
})
|
|
649
880
|
.option("port", {
|
|
650
881
|
describe: "Port to listen on",
|
|
@@ -654,49 +885,66 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
654
885
|
describe: "Port for devtools to connect to",
|
|
655
886
|
type: "number",
|
|
656
887
|
})
|
|
888
|
+
.option("routes", {
|
|
889
|
+
describe: "Routes to upload",
|
|
890
|
+
alias: "route",
|
|
891
|
+
type: "string",
|
|
892
|
+
requiresArg: true,
|
|
893
|
+
array: true,
|
|
894
|
+
})
|
|
657
895
|
.option("host", {
|
|
658
896
|
type: "string",
|
|
897
|
+
requiresArg: true,
|
|
659
898
|
describe:
|
|
660
899
|
"Host to forward requests to, defaults to the zone of project",
|
|
661
900
|
})
|
|
662
901
|
.option("local-protocol", {
|
|
663
|
-
default: "http",
|
|
664
902
|
describe: "Protocol to listen to requests on, defaults to http.",
|
|
665
|
-
choices: ["http", "https"],
|
|
903
|
+
choices: ["http", "https"] as const,
|
|
666
904
|
})
|
|
667
905
|
.option("experimental-public", {
|
|
668
906
|
describe: "Static assets to be served",
|
|
669
907
|
type: "string",
|
|
908
|
+
requiresArg: true,
|
|
670
909
|
})
|
|
671
910
|
.option("site", {
|
|
672
911
|
describe: "Root folder of static assets for Workers Sites",
|
|
673
912
|
type: "string",
|
|
913
|
+
requiresArg: true,
|
|
674
914
|
})
|
|
675
915
|
.option("site-include", {
|
|
676
916
|
describe:
|
|
677
917
|
"Array of .gitignore-style patterns that match file or directory names from the sites directory. Only matched items will be uploaded.",
|
|
678
918
|
type: "string",
|
|
919
|
+
requiresArg: true,
|
|
679
920
|
array: true,
|
|
680
921
|
})
|
|
681
922
|
.option("site-exclude", {
|
|
682
923
|
describe:
|
|
683
924
|
"Array of .gitignore-style patterns that match file or directory names from the sites directory. Matched items will not be uploaded.",
|
|
684
925
|
type: "string",
|
|
926
|
+
requiresArg: true,
|
|
685
927
|
array: true,
|
|
686
928
|
})
|
|
687
929
|
.option("upstream-protocol", {
|
|
688
|
-
default: "https",
|
|
689
930
|
describe:
|
|
690
931
|
"Protocol to forward requests to host on, defaults to https.",
|
|
691
|
-
choices: ["http", "https"],
|
|
932
|
+
choices: ["http", "https"] as const,
|
|
692
933
|
})
|
|
693
934
|
.option("jsx-factory", {
|
|
694
935
|
describe: "The function that is called for each JSX element",
|
|
695
936
|
type: "string",
|
|
937
|
+
requiresArg: true,
|
|
696
938
|
})
|
|
697
939
|
.option("jsx-fragment", {
|
|
698
940
|
describe: "The function that is called for each JSX fragment",
|
|
699
941
|
type: "string",
|
|
942
|
+
requiresArg: true,
|
|
943
|
+
})
|
|
944
|
+
.option("tsconfig", {
|
|
945
|
+
describe: "Path to a custom tsconfig.json file",
|
|
946
|
+
type: "string",
|
|
947
|
+
requiresArg: true,
|
|
700
948
|
})
|
|
701
949
|
.option("local", {
|
|
702
950
|
alias: "l",
|
|
@@ -704,76 +952,194 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
704
952
|
type: "boolean",
|
|
705
953
|
default: false, // I bet this will a point of contention. We'll revisit it.
|
|
706
954
|
})
|
|
955
|
+
.option("minify", {
|
|
956
|
+
describe: "Minify the script",
|
|
957
|
+
type: "boolean",
|
|
958
|
+
})
|
|
959
|
+
.option("node-compat", {
|
|
960
|
+
describe: "Enable node.js compatibility",
|
|
961
|
+
type: "boolean",
|
|
962
|
+
})
|
|
707
963
|
.option("experimental-enable-local-persistence", {
|
|
708
964
|
describe: "Enable persistence for this session (only for local mode)",
|
|
709
965
|
type: "boolean",
|
|
966
|
+
})
|
|
967
|
+
.option("inspect", {
|
|
968
|
+
describe: "Enable dev tools",
|
|
969
|
+
type: "boolean",
|
|
970
|
+
deprecated: true,
|
|
971
|
+
})
|
|
972
|
+
.option("legacy-env", {
|
|
973
|
+
type: "boolean",
|
|
974
|
+
describe: "Use legacy environments",
|
|
975
|
+
hidden: true,
|
|
710
976
|
});
|
|
711
977
|
},
|
|
712
978
|
async (args) => {
|
|
713
|
-
|
|
979
|
+
await printWranglerBanner();
|
|
980
|
+
const configPath =
|
|
714
981
|
(args.config as ConfigPath) ||
|
|
715
|
-
|
|
716
|
-
);
|
|
717
|
-
const entry = getEntry(config, "dev"
|
|
982
|
+
(args.script && findWranglerToml(path.dirname(args.script)));
|
|
983
|
+
const config = readConfig(configPath, args);
|
|
984
|
+
const entry = await getEntry(args, config, "dev");
|
|
985
|
+
|
|
986
|
+
if (config.services && config.services.length > 0) {
|
|
987
|
+
logger.warn(
|
|
988
|
+
`This worker is bound to live services: ${config.services
|
|
989
|
+
.map(
|
|
990
|
+
(service) =>
|
|
991
|
+
`${service.binding} (${service.service}${
|
|
992
|
+
service.environment ? `@${service.environment}` : ""
|
|
993
|
+
})`
|
|
994
|
+
)
|
|
995
|
+
.join(", ")}`
|
|
996
|
+
);
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
if (args.inspect) {
|
|
1000
|
+
logger.warn(
|
|
1001
|
+
"Passing --inspect is unnecessary, now you can always connect to devtools."
|
|
1002
|
+
);
|
|
1003
|
+
}
|
|
718
1004
|
|
|
719
1005
|
if (args["experimental-public"]) {
|
|
720
|
-
|
|
721
|
-
"
|
|
1006
|
+
logger.warn(
|
|
1007
|
+
"The --experimental-public field is experimental and will change in the future."
|
|
722
1008
|
);
|
|
723
1009
|
}
|
|
724
1010
|
|
|
725
1011
|
if (args.public) {
|
|
726
1012
|
throw new Error(
|
|
727
|
-
"
|
|
1013
|
+
"The --public field has been renamed to --experimental-public, and will change behaviour in the future."
|
|
728
1014
|
);
|
|
729
1015
|
}
|
|
730
1016
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
1017
|
+
const upstreamProtocol =
|
|
1018
|
+
args["upstream-protocol"] || config.dev.upstream_protocol;
|
|
1019
|
+
if (upstreamProtocol === "http") {
|
|
1020
|
+
logger.warn(
|
|
1021
|
+
"Setting upstream-protocol to http is not currently implemented.\n" +
|
|
1022
|
+
"If this is required in your project, please add your use case to the following issue:\n" +
|
|
1023
|
+
"https://github.com/cloudflare/wrangler2/issues/583."
|
|
1024
|
+
);
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
const accountId = !args.local ? await requireAuth(config) : undefined;
|
|
1028
|
+
|
|
1029
|
+
// TODO: if worker_dev = false and no routes, then error (only for dev)
|
|
1030
|
+
|
|
1031
|
+
/**
|
|
1032
|
+
* Given something that resembles a URL,
|
|
1033
|
+
* try to extract a host from it
|
|
1034
|
+
*/
|
|
1035
|
+
function getHost(urlLike: string): string | undefined {
|
|
1036
|
+
// strip leading * / *.
|
|
1037
|
+
urlLike = urlLike.replace(/^\*(\.)?/g, "");
|
|
1038
|
+
|
|
1039
|
+
if (
|
|
1040
|
+
!(urlLike.startsWith("http://") || urlLike.startsWith("https://"))
|
|
1041
|
+
) {
|
|
1042
|
+
urlLike = "http://" + urlLike;
|
|
1043
|
+
}
|
|
1044
|
+
return new URL(urlLike).host;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
/**
|
|
1048
|
+
* Given something that resembles a host,
|
|
1049
|
+
* try to infer a zone id from it
|
|
1050
|
+
*/
|
|
1051
|
+
async function getZoneId(host: string): Promise<string | undefined> {
|
|
1052
|
+
const zones = await fetchResult<{ id: string }[]>(
|
|
1053
|
+
`/zones`,
|
|
1054
|
+
{},
|
|
1055
|
+
new URLSearchParams({ name: host })
|
|
736
1056
|
);
|
|
1057
|
+
return zones[0]?.id;
|
|
737
1058
|
}
|
|
738
1059
|
|
|
1060
|
+
// When we're given a host (in one of the above ways), we do 2 things:
|
|
1061
|
+
// - We try to extract a host from it
|
|
1062
|
+
// - We try to get a zone id from the host
|
|
1063
|
+
//
|
|
1064
|
+
// So it turns out it's particularly hard to get a 'valid' domain
|
|
1065
|
+
// from a string, so we don't even try to validate TLDs, etc.
|
|
1066
|
+
// Once we get something that looks like w.x.y.z-ish, we then try to
|
|
1067
|
+
// get a zone id for it, by lopping off subdomains until we get a hit
|
|
1068
|
+
// from the API. That's it!
|
|
1069
|
+
|
|
1070
|
+
let zone: { host: string; id: string } | undefined;
|
|
1071
|
+
|
|
739
1072
|
if (!args.local) {
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
1073
|
+
const hostLike =
|
|
1074
|
+
args.host ||
|
|
1075
|
+
config.dev.host ||
|
|
1076
|
+
(args.routes && args.routes[0]) ||
|
|
1077
|
+
config.route ||
|
|
1078
|
+
(config.routes && config.routes[0]);
|
|
1079
|
+
|
|
1080
|
+
let zoneId: string | undefined =
|
|
1081
|
+
typeof hostLike === "object" && "zone_id" in hostLike
|
|
1082
|
+
? hostLike.zone_id
|
|
1083
|
+
: undefined;
|
|
1084
|
+
|
|
1085
|
+
const host =
|
|
1086
|
+
typeof hostLike === "string"
|
|
1087
|
+
? getHost(hostLike)
|
|
1088
|
+
: typeof hostLike === "object"
|
|
1089
|
+
? "zone_name" in hostLike
|
|
1090
|
+
? getHost(hostLike.zone_name)
|
|
1091
|
+
: getHost(hostLike.pattern)
|
|
1092
|
+
: undefined;
|
|
1093
|
+
|
|
1094
|
+
const hostPieces =
|
|
1095
|
+
typeof host === "string" ? host.split(".") : undefined;
|
|
1096
|
+
|
|
1097
|
+
while (!zoneId && hostPieces && hostPieces.length > 1) {
|
|
1098
|
+
zoneId = await getZoneId(hostPieces.join("."));
|
|
1099
|
+
hostPieces.shift();
|
|
746
1100
|
}
|
|
747
1101
|
|
|
748
|
-
if (!
|
|
749
|
-
|
|
750
|
-
if (!config.account_id) {
|
|
751
|
-
throw new Error("No account id found, quitting...");
|
|
752
|
-
}
|
|
1102
|
+
if (host && !zoneId) {
|
|
1103
|
+
throw new Error(`Could not find zone for ${hostLike}`);
|
|
753
1104
|
}
|
|
754
|
-
|
|
1105
|
+
|
|
1106
|
+
zone =
|
|
1107
|
+
typeof zoneId === "string" && typeof host === "string"
|
|
1108
|
+
? {
|
|
1109
|
+
host,
|
|
1110
|
+
id: zoneId,
|
|
1111
|
+
}
|
|
1112
|
+
: undefined;
|
|
755
1113
|
}
|
|
756
1114
|
|
|
757
|
-
const
|
|
758
|
-
|
|
1115
|
+
const nodeCompat = args.nodeCompat ?? config.node_compat;
|
|
1116
|
+
if (nodeCompat) {
|
|
1117
|
+
logger.warn(
|
|
1118
|
+
"Enabling node.js compatibility mode for built-ins and globals. This is experimental and has serious tradeoffs. Please see https://github.com/ionic-team/rollup-plugin-node-polyfills/ for more details."
|
|
1119
|
+
);
|
|
1120
|
+
}
|
|
759
1121
|
|
|
760
1122
|
const { waitUntilExit } = render(
|
|
761
1123
|
<Dev
|
|
762
1124
|
name={getScriptName(args, config)}
|
|
763
1125
|
entry={entry}
|
|
764
1126
|
env={args.env}
|
|
765
|
-
zone={
|
|
1127
|
+
zone={zone}
|
|
766
1128
|
rules={getRules(config)}
|
|
767
|
-
legacyEnv={isLegacyEnv(
|
|
768
|
-
|
|
769
|
-
|
|
1129
|
+
legacyEnv={isLegacyEnv(config)}
|
|
1130
|
+
minify={args.minify ?? config.minify}
|
|
1131
|
+
nodeCompat={nodeCompat}
|
|
1132
|
+
build={config.build || {}}
|
|
770
1133
|
initialMode={args.local ? "local" : "remote"}
|
|
771
|
-
jsxFactory={args["jsx-factory"] ||
|
|
772
|
-
jsxFragment={args["jsx-fragment"] ||
|
|
1134
|
+
jsxFactory={args["jsx-factory"] || config.jsx_factory}
|
|
1135
|
+
jsxFragment={args["jsx-fragment"] || config.jsx_fragment}
|
|
1136
|
+
tsconfig={args.tsconfig ?? config.tsconfig}
|
|
1137
|
+
upstreamProtocol={upstreamProtocol}
|
|
1138
|
+
localProtocol={args["local-protocol"] || config.dev.local_protocol}
|
|
773
1139
|
enableLocalPersistence={
|
|
774
1140
|
args["experimental-enable-local-persistence"] || false
|
|
775
1141
|
}
|
|
776
|
-
accountId={
|
|
1142
|
+
accountId={accountId}
|
|
777
1143
|
assetPaths={getAssetPaths(
|
|
778
1144
|
config,
|
|
779
1145
|
args.site,
|
|
@@ -781,24 +1147,25 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
781
1147
|
args.siteExclude
|
|
782
1148
|
)}
|
|
783
1149
|
port={
|
|
784
|
-
args.port ||
|
|
1150
|
+
args.port ||
|
|
1151
|
+
config.dev.port ||
|
|
1152
|
+
(await getPort({ port: DEFAULT_LOCAL_PORT }))
|
|
785
1153
|
}
|
|
1154
|
+
ip={args.ip || config.dev.ip}
|
|
786
1155
|
inspectorPort={
|
|
787
1156
|
args["inspector-port"] ?? (await getPort({ port: 9229 }))
|
|
788
1157
|
}
|
|
789
1158
|
public={args["experimental-public"]}
|
|
790
|
-
compatibilityDate={
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
}
|
|
1159
|
+
compatibilityDate={getDevCompatibilityDate(
|
|
1160
|
+
config,
|
|
1161
|
+
args["compatibility-date"]
|
|
1162
|
+
)}
|
|
795
1163
|
compatibilityFlags={
|
|
796
|
-
|
|
797
|
-
config.compatibility_flags
|
|
1164
|
+
args["compatibility-flags"] || config.compatibility_flags
|
|
798
1165
|
}
|
|
799
|
-
usageModel={
|
|
1166
|
+
usageModel={config.usage_model}
|
|
800
1167
|
bindings={{
|
|
801
|
-
kv_namespaces:
|
|
1168
|
+
kv_namespaces: config.kv_namespaces?.map(
|
|
802
1169
|
({ binding, preview_id, id: _id }) => {
|
|
803
1170
|
// In `dev`, we make folks use a separate kv namespace called
|
|
804
1171
|
// `preview_id` instead of `id` so that they don't
|
|
@@ -819,13 +1186,30 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
819
1186
|
};
|
|
820
1187
|
}
|
|
821
1188
|
),
|
|
822
|
-
vars:
|
|
1189
|
+
vars: getVarsForDev(config),
|
|
823
1190
|
wasm_modules: config.wasm_modules,
|
|
824
1191
|
text_blobs: config.text_blobs,
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
1192
|
+
data_blobs: config.data_blobs,
|
|
1193
|
+
durable_objects: config.durable_objects,
|
|
1194
|
+
r2_buckets: config.r2_buckets?.map(
|
|
1195
|
+
({ binding, preview_bucket_name, bucket_name: _bucket_name }) => {
|
|
1196
|
+
// same idea as kv namespace preview id,
|
|
1197
|
+
// same copy-on-write TODO
|
|
1198
|
+
if (!preview_bucket_name) {
|
|
1199
|
+
throw new Error(
|
|
1200
|
+
`In development, you should use a separate r2 bucket than the one you'd use in production. Please create a new r2 bucket with "wrangler r2 bucket create <name>" and add its name as preview_bucket_name to the r2_buckets "${binding}" in your wrangler.toml`
|
|
1201
|
+
);
|
|
1202
|
+
}
|
|
1203
|
+
return {
|
|
1204
|
+
binding,
|
|
1205
|
+
bucket_name: preview_bucket_name,
|
|
1206
|
+
};
|
|
1207
|
+
}
|
|
1208
|
+
),
|
|
1209
|
+
services: config.services,
|
|
1210
|
+
unsafe: config.unsafe?.bindings,
|
|
828
1211
|
}}
|
|
1212
|
+
crons={config.triggers.crons}
|
|
829
1213
|
/>
|
|
830
1214
|
);
|
|
831
1215
|
await waitUntilExit();
|
|
@@ -840,28 +1224,41 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
840
1224
|
return yargs
|
|
841
1225
|
.option("env", {
|
|
842
1226
|
type: "string",
|
|
1227
|
+
requiresArg: true,
|
|
843
1228
|
describe: "Perform on a specific environment",
|
|
1229
|
+
alias: "e",
|
|
844
1230
|
})
|
|
845
1231
|
.positional("script", {
|
|
846
1232
|
describe: "The path to an entry point for your worker",
|
|
847
1233
|
type: "string",
|
|
1234
|
+
requiresArg: true,
|
|
848
1235
|
})
|
|
849
1236
|
.option("name", {
|
|
850
1237
|
describe: "Name of the worker",
|
|
851
1238
|
type: "string",
|
|
1239
|
+
requiresArg: true,
|
|
1240
|
+
})
|
|
1241
|
+
.option("outdir", {
|
|
1242
|
+
describe: "Output directory for the bundled worker",
|
|
1243
|
+
type: "string",
|
|
1244
|
+
requiresArg: true,
|
|
852
1245
|
})
|
|
853
1246
|
.option("format", {
|
|
854
1247
|
choices: ["modules", "service-worker"] as const,
|
|
855
1248
|
describe: "Choose an entry type",
|
|
1249
|
+
deprecated: true,
|
|
856
1250
|
})
|
|
857
1251
|
.option("compatibility-date", {
|
|
858
1252
|
describe: "Date to use for compatibility checks",
|
|
859
1253
|
type: "string",
|
|
1254
|
+
requiresArg: true,
|
|
860
1255
|
})
|
|
861
1256
|
.option("compatibility-flags", {
|
|
862
1257
|
describe: "Flags to use for compatibility checks",
|
|
863
|
-
type: "array",
|
|
864
1258
|
alias: "compatibility-flag",
|
|
1259
|
+
type: "string",
|
|
1260
|
+
requiresArg: true,
|
|
1261
|
+
array: true,
|
|
865
1262
|
})
|
|
866
1263
|
.option("latest", {
|
|
867
1264
|
describe: "Use the latest version of the worker runtime",
|
|
@@ -871,81 +1268,100 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
871
1268
|
.option("experimental-public", {
|
|
872
1269
|
describe: "Static assets to be served",
|
|
873
1270
|
type: "string",
|
|
1271
|
+
requiresArg: true,
|
|
874
1272
|
})
|
|
875
1273
|
.option("site", {
|
|
876
1274
|
describe: "Root folder of static assets for Workers Sites",
|
|
877
1275
|
type: "string",
|
|
1276
|
+
requiresArg: true,
|
|
878
1277
|
})
|
|
879
1278
|
.option("site-include", {
|
|
880
1279
|
describe:
|
|
881
1280
|
"Array of .gitignore-style patterns that match file or directory names from the sites directory. Only matched items will be uploaded.",
|
|
882
1281
|
type: "string",
|
|
1282
|
+
requiresArg: true,
|
|
883
1283
|
array: true,
|
|
884
1284
|
})
|
|
885
1285
|
.option("site-exclude", {
|
|
886
1286
|
describe:
|
|
887
1287
|
"Array of .gitignore-style patterns that match file or directory names from the sites directory. Matched items will not be uploaded.",
|
|
888
1288
|
type: "string",
|
|
1289
|
+
requiresArg: true,
|
|
889
1290
|
array: true,
|
|
890
1291
|
})
|
|
891
1292
|
.option("triggers", {
|
|
892
1293
|
describe: "cron schedules to attach",
|
|
893
1294
|
alias: ["schedule", "schedules"],
|
|
894
|
-
type: "
|
|
1295
|
+
type: "string",
|
|
1296
|
+
requiresArg: true,
|
|
1297
|
+
array: true,
|
|
895
1298
|
})
|
|
896
1299
|
.option("routes", {
|
|
897
1300
|
describe: "Routes to upload",
|
|
898
1301
|
alias: "route",
|
|
899
|
-
type: "
|
|
1302
|
+
type: "string",
|
|
1303
|
+
requiresArg: true,
|
|
1304
|
+
array: true,
|
|
900
1305
|
})
|
|
901
1306
|
.option("jsx-factory", {
|
|
902
1307
|
describe: "The function that is called for each JSX element",
|
|
903
1308
|
type: "string",
|
|
1309
|
+
requiresArg: true,
|
|
904
1310
|
})
|
|
905
1311
|
.option("jsx-fragment", {
|
|
906
1312
|
describe: "The function that is called for each JSX fragment",
|
|
907
1313
|
type: "string",
|
|
1314
|
+
requiresArg: true,
|
|
1315
|
+
})
|
|
1316
|
+
.option("tsconfig", {
|
|
1317
|
+
describe: "Path to a custom tsconfig.json file",
|
|
1318
|
+
type: "string",
|
|
1319
|
+
requiresArg: true,
|
|
1320
|
+
})
|
|
1321
|
+
.option("minify", {
|
|
1322
|
+
describe: "Minify the script",
|
|
1323
|
+
type: "boolean",
|
|
1324
|
+
})
|
|
1325
|
+
.option("node-compat", {
|
|
1326
|
+
describe: "Enable node.js compatibility",
|
|
1327
|
+
type: "boolean",
|
|
1328
|
+
})
|
|
1329
|
+
.option("dry-run", {
|
|
1330
|
+
describe: "Don't actually publish",
|
|
1331
|
+
type: "boolean",
|
|
1332
|
+
})
|
|
1333
|
+
.option("legacy-env", {
|
|
1334
|
+
type: "boolean",
|
|
1335
|
+
describe: "Use legacy environments",
|
|
1336
|
+
hidden: true,
|
|
908
1337
|
});
|
|
909
1338
|
},
|
|
910
1339
|
async (args) => {
|
|
1340
|
+
await printWranglerBanner();
|
|
911
1341
|
if (args["experimental-public"]) {
|
|
912
|
-
|
|
913
|
-
"
|
|
1342
|
+
logger.warn(
|
|
1343
|
+
"The --experimental-public field is experimental and will change in the future."
|
|
914
1344
|
);
|
|
915
1345
|
}
|
|
916
1346
|
if (args.public) {
|
|
917
1347
|
throw new Error(
|
|
918
|
-
"
|
|
1348
|
+
"The --public field has been renamed to --experimental-public, and will change behaviour in the future."
|
|
919
1349
|
);
|
|
920
1350
|
}
|
|
921
1351
|
|
|
922
|
-
const
|
|
1352
|
+
const configPath =
|
|
923
1353
|
(args.config as ConfigPath) ||
|
|
924
|
-
|
|
925
|
-
);
|
|
926
|
-
const entry = getEntry(config, "publish"
|
|
1354
|
+
(args.script && findWranglerToml(path.dirname(args.script)));
|
|
1355
|
+
const config = readConfig(configPath, args);
|
|
1356
|
+
const entry = await getEntry(args, config, "publish");
|
|
927
1357
|
|
|
928
1358
|
if (args.latest) {
|
|
929
|
-
|
|
930
|
-
"
|
|
1359
|
+
logger.warn(
|
|
1360
|
+
"Using the latest version of the Workers runtime. To silence this warning, please choose a specific version of the runtime with --compatibility-date, or add a compatibility_date to your wrangler.toml.\n"
|
|
931
1361
|
);
|
|
932
1362
|
}
|
|
933
1363
|
|
|
934
|
-
|
|
935
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
936
|
-
if (!loggedIn) {
|
|
937
|
-
// didn't login, let's just quit
|
|
938
|
-
console.log("Did not login, quitting...");
|
|
939
|
-
return;
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
if (!config.account_id) {
|
|
943
|
-
config.account_id = await getAccountId();
|
|
944
|
-
if (!config.account_id) {
|
|
945
|
-
throw new Error("No account id found, quitting...");
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
|
-
// -- snip, end --
|
|
1364
|
+
const accountId = args.dryRun ? undefined : await requireAuth(config);
|
|
949
1365
|
|
|
950
1366
|
const assetPaths = getAssetPaths(
|
|
951
1367
|
config,
|
|
@@ -953,24 +1369,30 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
953
1369
|
args.siteInclude,
|
|
954
1370
|
args.siteExclude
|
|
955
1371
|
);
|
|
1372
|
+
|
|
956
1373
|
await publish({
|
|
957
1374
|
config,
|
|
1375
|
+
accountId,
|
|
958
1376
|
name: getScriptName(args, config),
|
|
959
1377
|
rules: getRules(config),
|
|
960
|
-
format: args.format || config.build?.upload?.format,
|
|
961
1378
|
entry,
|
|
962
1379
|
env: args.env,
|
|
963
1380
|
compatibilityDate: args.latest
|
|
964
1381
|
? new Date().toISOString().substring(0, 10)
|
|
965
1382
|
: args["compatibility-date"],
|
|
966
|
-
compatibilityFlags: args["compatibility-flags"]
|
|
1383
|
+
compatibilityFlags: args["compatibility-flags"],
|
|
967
1384
|
triggers: args.triggers,
|
|
968
1385
|
jsxFactory: args["jsx-factory"],
|
|
969
1386
|
jsxFragment: args["jsx-fragment"],
|
|
1387
|
+
tsconfig: args.tsconfig,
|
|
970
1388
|
routes: args.routes,
|
|
971
1389
|
assetPaths,
|
|
972
|
-
legacyEnv: isLegacyEnv(
|
|
1390
|
+
legacyEnv: isLegacyEnv(config),
|
|
1391
|
+
minify: args.minify,
|
|
1392
|
+
nodeCompat: args.nodeCompat,
|
|
973
1393
|
experimentalPublic: args["experimental-public"] !== undefined,
|
|
1394
|
+
outDir: args.outdir,
|
|
1395
|
+
dryRun: args.dryRun,
|
|
974
1396
|
});
|
|
975
1397
|
}
|
|
976
1398
|
);
|
|
@@ -980,88 +1402,83 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
980
1402
|
"tail [name]",
|
|
981
1403
|
"🦚 Starts a log tailing session for a published Worker.",
|
|
982
1404
|
(yargs) => {
|
|
983
|
-
return
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1405
|
+
return yargs
|
|
1406
|
+
.positional("name", {
|
|
1407
|
+
describe: "Name of the worker",
|
|
1408
|
+
type: "string",
|
|
1409
|
+
})
|
|
1410
|
+
.option("format", {
|
|
1411
|
+
default: process.stdout.isTTY ? "pretty" : "json",
|
|
1412
|
+
choices: ["json", "pretty"],
|
|
1413
|
+
describe: "The format of log entries",
|
|
1414
|
+
})
|
|
1415
|
+
.option("status", {
|
|
1416
|
+
choices: ["ok", "error", "canceled"],
|
|
1417
|
+
describe: "Filter by invocation status",
|
|
1418
|
+
array: true,
|
|
1419
|
+
})
|
|
1420
|
+
.option("header", {
|
|
1421
|
+
type: "string",
|
|
1422
|
+
requiresArg: true,
|
|
1423
|
+
describe: "Filter by HTTP header",
|
|
1424
|
+
})
|
|
1425
|
+
.option("method", {
|
|
1426
|
+
type: "string",
|
|
1427
|
+
requiresArg: true,
|
|
1428
|
+
describe: "Filter by HTTP method",
|
|
1429
|
+
array: true,
|
|
1430
|
+
})
|
|
1431
|
+
.option("sampling-rate", {
|
|
1432
|
+
type: "number",
|
|
1433
|
+
describe: "Adds a percentage of requests to log sampling rate",
|
|
1434
|
+
})
|
|
1435
|
+
.option("search", {
|
|
1436
|
+
type: "string",
|
|
1437
|
+
requiresArg: true,
|
|
1438
|
+
describe: "Filter by a text match in console.log messages",
|
|
1439
|
+
})
|
|
1440
|
+
.option("ip", {
|
|
1441
|
+
type: "string",
|
|
1442
|
+
requiresArg: true,
|
|
1443
|
+
describe:
|
|
1444
|
+
'Filter by the IP address the request originates from. Use "self" to filter for your own IP',
|
|
1445
|
+
array: true,
|
|
1446
|
+
})
|
|
1447
|
+
.option("env", {
|
|
1448
|
+
type: "string",
|
|
1449
|
+
requiresArg: true,
|
|
1450
|
+
describe: "Perform on a specific environment",
|
|
1451
|
+
alias: "e",
|
|
1452
|
+
})
|
|
1453
|
+
.option("debug", {
|
|
1454
|
+
type: "boolean",
|
|
1455
|
+
hidden: true,
|
|
1456
|
+
default: false,
|
|
1457
|
+
describe:
|
|
1458
|
+
"If a log would have been filtered out, send it through anyway alongside the filter which would have blocked it.",
|
|
1459
|
+
})
|
|
1460
|
+
.option("legacy-env", {
|
|
1461
|
+
type: "boolean",
|
|
1462
|
+
describe: "Use legacy environments",
|
|
1463
|
+
hidden: true,
|
|
1464
|
+
});
|
|
1035
1465
|
},
|
|
1036
1466
|
async (args) => {
|
|
1037
|
-
|
|
1467
|
+
if (args.format === "pretty") {
|
|
1468
|
+
await printWranglerBanner();
|
|
1469
|
+
}
|
|
1470
|
+
const config = readConfig(args.config as ConfigPath, args);
|
|
1038
1471
|
|
|
1039
|
-
const scriptName =
|
|
1472
|
+
const scriptName = getLegacyScriptName(args, config);
|
|
1040
1473
|
|
|
1041
1474
|
if (!scriptName) {
|
|
1042
1475
|
throw new Error("Missing script name");
|
|
1043
1476
|
}
|
|
1044
1477
|
|
|
1045
|
-
|
|
1046
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1047
|
-
if (!loggedIn) {
|
|
1048
|
-
// didn't login, let's just quit
|
|
1049
|
-
console.log("Did not login, quitting...");
|
|
1050
|
-
return;
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
if (!config.account_id) {
|
|
1054
|
-
config.account_id = await getAccountId();
|
|
1055
|
-
if (!config.account_id) {
|
|
1056
|
-
throw new Error("No account id found, quitting...");
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
// -- snip, end --
|
|
1060
|
-
|
|
1061
|
-
const accountId = config.account_id;
|
|
1478
|
+
const accountId = await requireAuth(config);
|
|
1062
1479
|
|
|
1063
1480
|
const cliFilters: TailCLIFilters = {
|
|
1064
|
-
status: args.status as ("ok" | "error" | "canceled")[],
|
|
1481
|
+
status: args.status as ("ok" | "error" | "canceled")[] | undefined,
|
|
1065
1482
|
header: args.header,
|
|
1066
1483
|
method: args.method,
|
|
1067
1484
|
samplingRate: args["sampling-rate"],
|
|
@@ -1078,16 +1495,18 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1078
1495
|
accountId,
|
|
1079
1496
|
scriptName,
|
|
1080
1497
|
filters,
|
|
1081
|
-
!isLegacyEnv(
|
|
1498
|
+
!isLegacyEnv(config) ? args.env : undefined
|
|
1082
1499
|
);
|
|
1083
1500
|
|
|
1084
1501
|
const scriptDisplayName = `${scriptName}${
|
|
1085
|
-
args.env && !isLegacyEnv(
|
|
1502
|
+
args.env && !isLegacyEnv(config) ? ` (${args.env})` : ""
|
|
1086
1503
|
}`;
|
|
1087
1504
|
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1505
|
+
if (args.format === "pretty") {
|
|
1506
|
+
logger.log(
|
|
1507
|
+
`Successfully created tail, expires at ${expiration.toLocaleString()}`
|
|
1508
|
+
);
|
|
1509
|
+
}
|
|
1091
1510
|
|
|
1092
1511
|
onExit(async () => {
|
|
1093
1512
|
tail.terminate();
|
|
@@ -1114,7 +1533,9 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1114
1533
|
}
|
|
1115
1534
|
}
|
|
1116
1535
|
|
|
1117
|
-
|
|
1536
|
+
if (args.format === "pretty") {
|
|
1537
|
+
logger.log(`Connected to ${scriptDisplayName}, waiting for logs...`);
|
|
1538
|
+
}
|
|
1118
1539
|
|
|
1119
1540
|
tail.on("close", async () => {
|
|
1120
1541
|
tail.terminate();
|
|
@@ -1139,6 +1560,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1139
1560
|
})
|
|
1140
1561
|
.option("env", {
|
|
1141
1562
|
type: "string",
|
|
1563
|
+
requiresArg: true,
|
|
1142
1564
|
describe: "Perform on a specific environment",
|
|
1143
1565
|
})
|
|
1144
1566
|
.option("watch", {
|
|
@@ -1156,34 +1578,17 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1156
1578
|
}
|
|
1157
1579
|
|
|
1158
1580
|
// Delegate to `wrangler dev`
|
|
1159
|
-
|
|
1581
|
+
logger.warn(
|
|
1160
1582
|
"***************************************************\n" +
|
|
1161
1583
|
"The `wrangler preview` command has been deprecated.\n" +
|
|
1162
1584
|
"Attempting to run `wrangler dev` instead.\n" +
|
|
1163
1585
|
"***************************************************\n"
|
|
1164
1586
|
);
|
|
1165
1587
|
|
|
1166
|
-
const config = readConfig(args.config as ConfigPath);
|
|
1167
|
-
const entry = getEntry(config, "dev");
|
|
1168
|
-
|
|
1169
|
-
// -- snip, extract --
|
|
1170
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1171
|
-
if (!loggedIn) {
|
|
1172
|
-
// didn't login, let's just quit
|
|
1173
|
-
console.log("Did not login, quitting...");
|
|
1174
|
-
return;
|
|
1175
|
-
}
|
|
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
|
-
// -- snip, end --
|
|
1588
|
+
const config = readConfig(args.config as ConfigPath, args);
|
|
1589
|
+
const entry = await getEntry({}, config, "dev");
|
|
1184
1590
|
|
|
1185
|
-
const
|
|
1186
|
-
const envRootObj = args.env ? environments[args.env] || {} : config;
|
|
1591
|
+
const accountId = await requireAuth(config);
|
|
1187
1592
|
|
|
1188
1593
|
const { waitUntilExit } = render(
|
|
1189
1594
|
<Dev
|
|
@@ -1192,28 +1597,29 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1192
1597
|
rules={getRules(config)}
|
|
1193
1598
|
env={args.env}
|
|
1194
1599
|
zone={undefined}
|
|
1195
|
-
legacyEnv={isLegacyEnv(
|
|
1196
|
-
|
|
1197
|
-
|
|
1600
|
+
legacyEnv={isLegacyEnv(config)}
|
|
1601
|
+
build={config.build || {}}
|
|
1602
|
+
minify={undefined}
|
|
1603
|
+
nodeCompat={config.node_compat}
|
|
1198
1604
|
initialMode={args.local ? "local" : "remote"}
|
|
1199
|
-
jsxFactory={
|
|
1200
|
-
jsxFragment={
|
|
1605
|
+
jsxFactory={config.jsx_factory}
|
|
1606
|
+
jsxFragment={config.jsx_fragment}
|
|
1607
|
+
tsconfig={config.tsconfig}
|
|
1608
|
+
upstreamProtocol={config.dev.upstream_protocol}
|
|
1609
|
+
localProtocol={config.dev.local_protocol}
|
|
1201
1610
|
enableLocalPersistence={false}
|
|
1202
|
-
accountId={
|
|
1611
|
+
accountId={accountId}
|
|
1203
1612
|
assetPaths={undefined}
|
|
1204
|
-
port={
|
|
1205
|
-
|
|
1206
|
-
compatibilityDate={
|
|
1207
|
-
config.compatibility_date ||
|
|
1208
|
-
new Date().toISOString().substring(0, 10)
|
|
1209
|
-
}
|
|
1210
|
-
compatibilityFlags={
|
|
1211
|
-
(args["compatibility-flags"] as string[]) ||
|
|
1212
|
-
config.compatibility_flags
|
|
1613
|
+
port={
|
|
1614
|
+
config.dev.port || (await getPort({ port: DEFAULT_LOCAL_PORT }))
|
|
1213
1615
|
}
|
|
1616
|
+
ip={config.dev.ip}
|
|
1617
|
+
public={undefined}
|
|
1618
|
+
compatibilityDate={getDevCompatibilityDate(config)}
|
|
1619
|
+
compatibilityFlags={config.compatibility_flags}
|
|
1214
1620
|
usageModel={config.usage_model}
|
|
1215
1621
|
bindings={{
|
|
1216
|
-
kv_namespaces:
|
|
1622
|
+
kv_namespaces: config.kv_namespaces?.map(
|
|
1217
1623
|
({ binding, preview_id, id: _id }) => {
|
|
1218
1624
|
// In `dev`, we make folks use a separate kv namespace called
|
|
1219
1625
|
// `preview_id` instead of `id` so that they don't
|
|
@@ -1234,13 +1640,30 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1234
1640
|
};
|
|
1235
1641
|
}
|
|
1236
1642
|
),
|
|
1237
|
-
vars:
|
|
1643
|
+
vars: config.vars,
|
|
1238
1644
|
wasm_modules: config.wasm_modules,
|
|
1239
1645
|
text_blobs: config.text_blobs,
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1646
|
+
data_blobs: config.data_blobs,
|
|
1647
|
+
durable_objects: config.durable_objects,
|
|
1648
|
+
r2_buckets: config.r2_buckets?.map(
|
|
1649
|
+
({ binding, preview_bucket_name, bucket_name: _bucket_name }) => {
|
|
1650
|
+
// same idea as kv namespace preview id,
|
|
1651
|
+
// same copy-on-write TODO
|
|
1652
|
+
if (!preview_bucket_name) {
|
|
1653
|
+
throw new Error(
|
|
1654
|
+
`In development, you should use a separate r2 bucket than the one you'd use in production. Please create a new r2 bucket with "wrangler r2 bucket create <name>" and add its name as preview_bucket_name to the r2_buckets "${binding}" in your wrangler.toml`
|
|
1655
|
+
);
|
|
1656
|
+
}
|
|
1657
|
+
return {
|
|
1658
|
+
binding,
|
|
1659
|
+
bucket_name: preview_bucket_name,
|
|
1660
|
+
};
|
|
1661
|
+
}
|
|
1662
|
+
),
|
|
1663
|
+
services: config.services,
|
|
1664
|
+
unsafe: config.unsafe?.bindings,
|
|
1243
1665
|
}}
|
|
1666
|
+
crons={config.triggers.crons}
|
|
1244
1667
|
inspectorPort={await getPort({ port: 9229 })}
|
|
1245
1668
|
/>
|
|
1246
1669
|
);
|
|
@@ -1248,7 +1671,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1248
1671
|
}
|
|
1249
1672
|
);
|
|
1250
1673
|
|
|
1251
|
-
// route
|
|
1674
|
+
// [DEPRECATED] route
|
|
1252
1675
|
wrangler.command(
|
|
1253
1676
|
"route",
|
|
1254
1677
|
false, // I think we want to hide this command
|
|
@@ -1262,10 +1685,12 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1262
1685
|
return yargs
|
|
1263
1686
|
.option("env", {
|
|
1264
1687
|
type: "string",
|
|
1688
|
+
requiresArg: true,
|
|
1265
1689
|
describe: "Perform on a specific environment",
|
|
1266
1690
|
})
|
|
1267
1691
|
.option("zone", {
|
|
1268
1692
|
type: "string",
|
|
1693
|
+
requiresArg: true,
|
|
1269
1694
|
describe: "Zone id",
|
|
1270
1695
|
})
|
|
1271
1696
|
.positional("zone", {
|
|
@@ -1273,21 +1698,21 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1273
1698
|
type: "string",
|
|
1274
1699
|
});
|
|
1275
1700
|
},
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
const
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1701
|
+
() => {
|
|
1702
|
+
// "👯 [DEPRECATED]. Use wrangler.toml to manage routes.
|
|
1703
|
+
const deprecationNotice =
|
|
1704
|
+
"`wrangler route list` has been deprecated.";
|
|
1705
|
+
const futureRoutes =
|
|
1706
|
+
"Refer to wrangler.toml for a list of routes the worker will be deployed to upon publishing.";
|
|
1707
|
+
const presentRoutes =
|
|
1708
|
+
"Refer to the Cloudflare Dashboard to see the routes this worker is currently running on.";
|
|
1709
|
+
throw new DeprecationError(
|
|
1710
|
+
`${deprecationNotice}\n${futureRoutes}\n${presentRoutes}`
|
|
1711
|
+
);
|
|
1287
1712
|
}
|
|
1288
1713
|
)
|
|
1289
1714
|
.command(
|
|
1290
|
-
"delete
|
|
1715
|
+
"delete [id]",
|
|
1291
1716
|
"Delete a route associated with a zone",
|
|
1292
1717
|
(yargs) => {
|
|
1293
1718
|
return yargs
|
|
@@ -1297,29 +1722,31 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1297
1722
|
})
|
|
1298
1723
|
.option("zone", {
|
|
1299
1724
|
type: "string",
|
|
1725
|
+
requiresArg: true,
|
|
1300
1726
|
describe: "zone id",
|
|
1301
1727
|
})
|
|
1302
1728
|
.option("env", {
|
|
1303
1729
|
type: "string",
|
|
1730
|
+
requiresArg: true,
|
|
1304
1731
|
describe: "Perform on a specific environment",
|
|
1305
1732
|
});
|
|
1306
1733
|
},
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
const
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
}
|
|
1315
|
-
|
|
1316
|
-
console.log(
|
|
1317
|
-
await fetchResult(`/zones/${zone}/workers/routes/${args.id}`, {
|
|
1318
|
-
method: "DELETE",
|
|
1319
|
-
})
|
|
1320
|
-
);
|
|
1734
|
+
() => {
|
|
1735
|
+
// "👯 [DEPRECATED]. Use wrangler.toml to manage routes.
|
|
1736
|
+
const deprecationNotice =
|
|
1737
|
+
"`wrangler route delete` has been deprecated.";
|
|
1738
|
+
const shouldDo =
|
|
1739
|
+
"Remove the unwanted route(s) from wrangler.toml and run `wrangler publish` to remove your worker from those routes.";
|
|
1740
|
+
throw new DeprecationError(`${deprecationNotice}\n${shouldDo}`);
|
|
1321
1741
|
}
|
|
1322
1742
|
);
|
|
1743
|
+
},
|
|
1744
|
+
() => {
|
|
1745
|
+
// "👯 [DEPRECATED]. Use wrangler.toml to manage routes.
|
|
1746
|
+
const deprecationNotice = "`wrangler route` has been deprecated.";
|
|
1747
|
+
const shouldDo =
|
|
1748
|
+
"Please use wrangler.toml and/or `wrangler publish --routes` to modify routes";
|
|
1749
|
+
throw new DeprecationError(`${deprecationNotice}\n${shouldDo}`);
|
|
1323
1750
|
}
|
|
1324
1751
|
);
|
|
1325
1752
|
|
|
@@ -1333,7 +1760,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1333
1760
|
},
|
|
1334
1761
|
() => {
|
|
1335
1762
|
throw new DeprecationError(
|
|
1336
|
-
"`wrangler subdomain` has been deprecated, please refer to
|
|
1763
|
+
"`wrangler subdomain` has been deprecated, please refer to https://developers.cloudflare.com/workers/wrangler/migration/deprecations/#subdomain for alternatives"
|
|
1337
1764
|
);
|
|
1338
1765
|
}
|
|
1339
1766
|
);
|
|
@@ -1344,6 +1771,12 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1344
1771
|
"🤫 Generate a secret that can be referenced in the worker script",
|
|
1345
1772
|
(secretYargs) => {
|
|
1346
1773
|
return secretYargs
|
|
1774
|
+
.command(subHelp)
|
|
1775
|
+
.option("legacy-env", {
|
|
1776
|
+
type: "boolean",
|
|
1777
|
+
describe: "Use legacy environments",
|
|
1778
|
+
hidden: true,
|
|
1779
|
+
})
|
|
1347
1780
|
.command(
|
|
1348
1781
|
"put <key>",
|
|
1349
1782
|
"Create or update a secret variable for a script",
|
|
@@ -1356,53 +1789,45 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1356
1789
|
.option("name", {
|
|
1357
1790
|
describe: "Name of the worker",
|
|
1358
1791
|
type: "string",
|
|
1792
|
+
requiresArg: true,
|
|
1359
1793
|
})
|
|
1360
1794
|
.option("env", {
|
|
1361
1795
|
type: "string",
|
|
1796
|
+
requiresArg: true,
|
|
1362
1797
|
describe:
|
|
1363
1798
|
"Binds the secret to the Worker of the specific environment",
|
|
1799
|
+
alias: "e",
|
|
1364
1800
|
});
|
|
1365
1801
|
},
|
|
1366
1802
|
async (args) => {
|
|
1367
|
-
|
|
1803
|
+
await printWranglerBanner();
|
|
1804
|
+
const config = readConfig(args.config as ConfigPath, args);
|
|
1368
1805
|
|
|
1369
|
-
const scriptName =
|
|
1806
|
+
const scriptName = getLegacyScriptName(args, config);
|
|
1370
1807
|
if (!scriptName) {
|
|
1371
1808
|
throw new Error("Missing script name");
|
|
1372
1809
|
}
|
|
1373
1810
|
|
|
1374
|
-
|
|
1375
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1376
|
-
if (!loggedIn) {
|
|
1377
|
-
// didn't login, let's just quit
|
|
1378
|
-
console.log("Did not login, quitting...");
|
|
1379
|
-
return;
|
|
1380
|
-
}
|
|
1381
|
-
|
|
1382
|
-
if (!config.account_id) {
|
|
1383
|
-
config.account_id = await getAccountId();
|
|
1384
|
-
if (!config.account_id) {
|
|
1385
|
-
throw new Error("No account id found, quitting...");
|
|
1386
|
-
}
|
|
1387
|
-
}
|
|
1388
|
-
// -- snip, end --
|
|
1811
|
+
const accountId = await requireAuth(config);
|
|
1389
1812
|
|
|
1390
|
-
const
|
|
1391
|
-
|
|
1392
|
-
|
|
1813
|
+
const isInteractive = process.stdin.isTTY;
|
|
1814
|
+
const secretValue = trimTrailingWhitespace(
|
|
1815
|
+
isInteractive
|
|
1816
|
+
? await prompt("Enter a secret value:", "password")
|
|
1817
|
+
: await readFromStdin()
|
|
1393
1818
|
);
|
|
1394
1819
|
|
|
1395
|
-
|
|
1820
|
+
logger.log(
|
|
1396
1821
|
`🌀 Creating the secret for script ${scriptName} ${
|
|
1397
|
-
args.env && !isLegacyEnv(
|
|
1822
|
+
args.env && !isLegacyEnv(config) ? `(${args.env})` : ""
|
|
1398
1823
|
}`
|
|
1399
1824
|
);
|
|
1400
1825
|
|
|
1401
1826
|
async function submitSecret() {
|
|
1402
1827
|
const url =
|
|
1403
|
-
!args.env || isLegacyEnv(
|
|
1404
|
-
? `/accounts/${
|
|
1405
|
-
: `/accounts/${
|
|
1828
|
+
!args.env || isLegacyEnv(config)
|
|
1829
|
+
? `/accounts/${accountId}/workers/scripts/${scriptName}/secrets`
|
|
1830
|
+
: `/accounts/${accountId}/workers/services/${scriptName}/environments/${args.env}/secrets`;
|
|
1406
1831
|
|
|
1407
1832
|
return await fetchResult(url, {
|
|
1408
1833
|
method: "PUT",
|
|
@@ -1415,56 +1840,71 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1415
1840
|
});
|
|
1416
1841
|
}
|
|
1417
1842
|
|
|
1843
|
+
const createDraftWorker = async () => {
|
|
1844
|
+
// TODO: log a warning
|
|
1845
|
+
await fetchResult(
|
|
1846
|
+
!isLegacyEnv(config) && args.env
|
|
1847
|
+
? `/accounts/${accountId}/workers/services/${scriptName}/environments/${args.env}`
|
|
1848
|
+
: `/accounts/${accountId}/workers/scripts/${scriptName}`,
|
|
1849
|
+
{
|
|
1850
|
+
method: "PUT",
|
|
1851
|
+
body: createWorkerUploadForm({
|
|
1852
|
+
name: scriptName,
|
|
1853
|
+
main: {
|
|
1854
|
+
name: scriptName,
|
|
1855
|
+
content: `export default { fetch() {} }`,
|
|
1856
|
+
type: "esm",
|
|
1857
|
+
},
|
|
1858
|
+
bindings: {
|
|
1859
|
+
kv_namespaces: [],
|
|
1860
|
+
vars: {},
|
|
1861
|
+
durable_objects: { bindings: [] },
|
|
1862
|
+
r2_buckets: [],
|
|
1863
|
+
services: [],
|
|
1864
|
+
wasm_modules: {},
|
|
1865
|
+
text_blobs: {},
|
|
1866
|
+
data_blobs: {},
|
|
1867
|
+
unsafe: [],
|
|
1868
|
+
},
|
|
1869
|
+
modules: [],
|
|
1870
|
+
migrations: undefined,
|
|
1871
|
+
compatibility_date: undefined,
|
|
1872
|
+
compatibility_flags: undefined,
|
|
1873
|
+
usage_model: undefined,
|
|
1874
|
+
}),
|
|
1875
|
+
}
|
|
1876
|
+
);
|
|
1877
|
+
};
|
|
1878
|
+
|
|
1879
|
+
function isMissingWorkerError(e: unknown): e is { code: 10007 } {
|
|
1880
|
+
return (
|
|
1881
|
+
typeof e === "object" &&
|
|
1882
|
+
e !== null &&
|
|
1883
|
+
(e as { code: number }).code === 10007
|
|
1884
|
+
);
|
|
1885
|
+
}
|
|
1886
|
+
|
|
1418
1887
|
try {
|
|
1419
1888
|
await submitSecret();
|
|
1420
1889
|
} catch (e) {
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
// TODO: log a warning
|
|
1425
|
-
await fetchResult(
|
|
1426
|
-
!args["legacy-env"] && args.env
|
|
1427
|
-
? `/accounts/${config.account_id}/workers/services/${scriptName}/environments/${args.env}`
|
|
1428
|
-
: `/accounts/${config.account_id}/workers/scripts/${scriptName}`,
|
|
1429
|
-
{
|
|
1430
|
-
method: "PUT",
|
|
1431
|
-
body: toFormData({
|
|
1432
|
-
name: scriptName,
|
|
1433
|
-
main: {
|
|
1434
|
-
name: scriptName,
|
|
1435
|
-
content: `export default { fetch() {} }`,
|
|
1436
|
-
type: "esm",
|
|
1437
|
-
},
|
|
1438
|
-
bindings: {
|
|
1439
|
-
kv_namespaces: [],
|
|
1440
|
-
vars: {},
|
|
1441
|
-
durable_objects: { bindings: [] },
|
|
1442
|
-
r2_buckets: [],
|
|
1443
|
-
wasm_modules: {},
|
|
1444
|
-
text_blobs: {},
|
|
1445
|
-
unsafe: [],
|
|
1446
|
-
},
|
|
1447
|
-
modules: [],
|
|
1448
|
-
migrations: undefined,
|
|
1449
|
-
compatibility_date: undefined,
|
|
1450
|
-
compatibility_flags: undefined,
|
|
1451
|
-
usage_model: undefined,
|
|
1452
|
-
}),
|
|
1453
|
-
}
|
|
1454
|
-
);
|
|
1455
|
-
|
|
1456
|
-
// and then try again
|
|
1890
|
+
if (isMissingWorkerError(e)) {
|
|
1891
|
+
// create a draft worker and try again
|
|
1892
|
+
await createDraftWorker();
|
|
1457
1893
|
await submitSecret();
|
|
1458
1894
|
// TODO: delete the draft worker if this failed too?
|
|
1895
|
+
} else {
|
|
1896
|
+
throw e;
|
|
1459
1897
|
}
|
|
1460
1898
|
}
|
|
1461
|
-
|
|
1899
|
+
|
|
1900
|
+
logger.log(`✨ Success! Uploaded secret ${args.key}`);
|
|
1462
1901
|
}
|
|
1463
1902
|
)
|
|
1464
1903
|
.command(
|
|
1465
1904
|
"delete <key>",
|
|
1466
1905
|
"Delete a secret variable from a script",
|
|
1467
|
-
(yargs) => {
|
|
1906
|
+
async (yargs) => {
|
|
1907
|
+
await printWranglerBanner();
|
|
1468
1908
|
return yargs
|
|
1469
1909
|
.positional("key", {
|
|
1470
1910
|
describe: "The variable name to be accessible in the script",
|
|
@@ -1473,59 +1913,48 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1473
1913
|
.option("name", {
|
|
1474
1914
|
describe: "Name of the worker",
|
|
1475
1915
|
type: "string",
|
|
1916
|
+
requiresArg: true,
|
|
1476
1917
|
})
|
|
1477
1918
|
.option("env", {
|
|
1478
1919
|
type: "string",
|
|
1920
|
+
requiresArg: true,
|
|
1479
1921
|
describe:
|
|
1480
1922
|
"Binds the secret to the Worker of the specific environment",
|
|
1923
|
+
alias: "e",
|
|
1481
1924
|
});
|
|
1482
1925
|
},
|
|
1483
1926
|
async (args) => {
|
|
1484
|
-
const config = readConfig(args.config as ConfigPath);
|
|
1927
|
+
const config = readConfig(args.config as ConfigPath, args);
|
|
1485
1928
|
|
|
1486
|
-
const scriptName =
|
|
1929
|
+
const scriptName = getLegacyScriptName(args, config);
|
|
1487
1930
|
if (!scriptName) {
|
|
1488
1931
|
throw new Error("Missing script name");
|
|
1489
1932
|
}
|
|
1490
1933
|
|
|
1491
|
-
|
|
1492
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1493
|
-
if (!loggedIn) {
|
|
1494
|
-
// didn't login, let's just quit
|
|
1495
|
-
console.log("Did not login, quitting...");
|
|
1496
|
-
return;
|
|
1497
|
-
}
|
|
1498
|
-
|
|
1499
|
-
if (!config.account_id) {
|
|
1500
|
-
config.account_id = await getAccountId();
|
|
1501
|
-
if (!config.account_id) {
|
|
1502
|
-
throw new Error("No account id found, quitting...");
|
|
1503
|
-
}
|
|
1504
|
-
}
|
|
1505
|
-
// -- snip, end --
|
|
1934
|
+
const accountId = await requireAuth(config);
|
|
1506
1935
|
|
|
1507
1936
|
if (
|
|
1508
1937
|
await confirm(
|
|
1509
1938
|
`Are you sure you want to permanently delete the variable ${
|
|
1510
1939
|
args.key
|
|
1511
1940
|
} on the script ${scriptName}${
|
|
1512
|
-
args.env && !isLegacyEnv(
|
|
1941
|
+
args.env && !isLegacyEnv(config) ? ` (${args.env})` : ""
|
|
1513
1942
|
}?`
|
|
1514
1943
|
)
|
|
1515
1944
|
) {
|
|
1516
|
-
|
|
1945
|
+
logger.log(
|
|
1517
1946
|
`🌀 Deleting the secret ${args.key} on script ${scriptName}${
|
|
1518
|
-
args.env && !isLegacyEnv(
|
|
1947
|
+
args.env && !isLegacyEnv(config) ? ` (${args.env})` : ""
|
|
1519
1948
|
}`
|
|
1520
1949
|
);
|
|
1521
1950
|
|
|
1522
1951
|
const url =
|
|
1523
|
-
!args.env || isLegacyEnv(
|
|
1524
|
-
? `/accounts/${
|
|
1525
|
-
: `/accounts/${
|
|
1952
|
+
!args.env || isLegacyEnv(config)
|
|
1953
|
+
? `/accounts/${accountId}/workers/scripts/${scriptName}/secrets`
|
|
1954
|
+
: `/accounts/${accountId}/workers/services/${scriptName}/environments/${args.env}/secrets`;
|
|
1526
1955
|
|
|
1527
1956
|
await fetchResult(`${url}/${args.key}`, { method: "DELETE" });
|
|
1528
|
-
|
|
1957
|
+
logger.log(`✨ Success! Deleted secret ${args.key}`);
|
|
1529
1958
|
}
|
|
1530
1959
|
}
|
|
1531
1960
|
)
|
|
@@ -1537,43 +1966,32 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1537
1966
|
.option("name", {
|
|
1538
1967
|
describe: "Name of the worker",
|
|
1539
1968
|
type: "string",
|
|
1969
|
+
requiresArg: true,
|
|
1540
1970
|
})
|
|
1541
1971
|
.option("env", {
|
|
1542
1972
|
type: "string",
|
|
1973
|
+
requiresArg: true,
|
|
1543
1974
|
describe:
|
|
1544
1975
|
"Binds the secret to the Worker of the specific environment.",
|
|
1976
|
+
alias: "e",
|
|
1545
1977
|
});
|
|
1546
1978
|
},
|
|
1547
1979
|
async (args) => {
|
|
1548
|
-
const config = readConfig(args.config as ConfigPath);
|
|
1980
|
+
const config = readConfig(args.config as ConfigPath, args);
|
|
1549
1981
|
|
|
1550
|
-
const scriptName =
|
|
1982
|
+
const scriptName = getLegacyScriptName(args, config);
|
|
1551
1983
|
if (!scriptName) {
|
|
1552
1984
|
throw new Error("Missing script name");
|
|
1553
1985
|
}
|
|
1554
1986
|
|
|
1555
|
-
|
|
1556
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1557
|
-
if (!loggedIn) {
|
|
1558
|
-
// didn't login, let's just quit
|
|
1559
|
-
console.log("Did not login, quitting...");
|
|
1560
|
-
return;
|
|
1561
|
-
}
|
|
1562
|
-
|
|
1563
|
-
if (!config.account_id) {
|
|
1564
|
-
config.account_id = await getAccountId();
|
|
1565
|
-
if (!config.account_id) {
|
|
1566
|
-
throw new Error("No account id found, quitting...");
|
|
1567
|
-
}
|
|
1568
|
-
}
|
|
1569
|
-
// -- snip, end --
|
|
1987
|
+
const accountId = await requireAuth(config);
|
|
1570
1988
|
|
|
1571
1989
|
const url =
|
|
1572
|
-
!args.env || isLegacyEnv(
|
|
1573
|
-
? `/accounts/${
|
|
1574
|
-
: `/accounts/${
|
|
1990
|
+
!args.env || isLegacyEnv(config)
|
|
1991
|
+
? `/accounts/${accountId}/workers/scripts/${scriptName}/secrets`
|
|
1992
|
+
: `/accounts/${accountId}/workers/services/${scriptName}/environments/${args.env}/secrets`;
|
|
1575
1993
|
|
|
1576
|
-
|
|
1994
|
+
logger.log(JSON.stringify(await fetchResult(url), null, " "));
|
|
1577
1995
|
}
|
|
1578
1996
|
);
|
|
1579
1997
|
}
|
|
@@ -1586,6 +2004,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1586
2004
|
"🗂️ Interact with your Workers KV Namespaces",
|
|
1587
2005
|
(namespaceYargs) => {
|
|
1588
2006
|
return namespaceYargs
|
|
2007
|
+
.command(subHelp)
|
|
1589
2008
|
.command(
|
|
1590
2009
|
"create <namespace>",
|
|
1591
2010
|
"Create a new namespace",
|
|
@@ -1598,7 +2017,9 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1598
2017
|
})
|
|
1599
2018
|
.option("env", {
|
|
1600
2019
|
type: "string",
|
|
2020
|
+
requiresArg: true,
|
|
1601
2021
|
describe: "Perform on a specific environment",
|
|
2022
|
+
alias: "e",
|
|
1602
2023
|
})
|
|
1603
2024
|
.option("preview", {
|
|
1604
2025
|
type: "boolean",
|
|
@@ -1606,22 +2027,17 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1606
2027
|
});
|
|
1607
2028
|
},
|
|
1608
2029
|
async (args) => {
|
|
1609
|
-
|
|
1610
|
-
const extraArgs = args._.slice(2).join(" ");
|
|
1611
|
-
throw new CommandLineArgsError(
|
|
1612
|
-
`Unexpected additional positional arguments "${extraArgs}".`
|
|
1613
|
-
);
|
|
1614
|
-
}
|
|
2030
|
+
await printWranglerBanner();
|
|
1615
2031
|
|
|
1616
|
-
if (!
|
|
2032
|
+
if (!isValidKVNamespaceBinding(args.namespace)) {
|
|
1617
2033
|
throw new CommandLineArgsError(
|
|
1618
2034
|
`The namespace binding name "${args.namespace}" is invalid. It can only have alphanumeric and _ characters, and cannot begin with a number.`
|
|
1619
2035
|
);
|
|
1620
2036
|
}
|
|
1621
2037
|
|
|
1622
|
-
const config = readConfig(args.config as ConfigPath);
|
|
2038
|
+
const config = readConfig(args.config as ConfigPath, args);
|
|
1623
2039
|
if (!config.name) {
|
|
1624
|
-
|
|
2040
|
+
logger.warn(
|
|
1625
2041
|
"No configured name present, using `worker` as a prefix for the title"
|
|
1626
2042
|
);
|
|
1627
2043
|
}
|
|
@@ -1631,34 +2047,20 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1631
2047
|
const preview = args.preview ? "_preview" : "";
|
|
1632
2048
|
const title = `${name}${environment}-${args.namespace}${preview}`;
|
|
1633
2049
|
|
|
1634
|
-
|
|
1635
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1636
|
-
if (!loggedIn) {
|
|
1637
|
-
// didn't login, let's just quit
|
|
1638
|
-
console.log("Did not login, quitting...");
|
|
1639
|
-
return;
|
|
1640
|
-
}
|
|
1641
|
-
|
|
1642
|
-
if (!config.account_id) {
|
|
1643
|
-
config.account_id = await getAccountId();
|
|
1644
|
-
if (!config.account_id) {
|
|
1645
|
-
throw new Error("No account id found, quitting...");
|
|
1646
|
-
}
|
|
1647
|
-
}
|
|
1648
|
-
// -- snip, end --
|
|
2050
|
+
const accountId = await requireAuth(config);
|
|
1649
2051
|
|
|
1650
2052
|
// TODO: generate a binding name stripping non alphanumeric chars
|
|
1651
2053
|
|
|
1652
|
-
|
|
1653
|
-
const namespaceId = await
|
|
2054
|
+
logger.log(`🌀 Creating namespace with title "${title}"`);
|
|
2055
|
+
const namespaceId = await createKVNamespace(accountId, title);
|
|
1654
2056
|
|
|
1655
|
-
|
|
2057
|
+
logger.log("✨ Success!");
|
|
1656
2058
|
const envString = args.env ? ` under [env.${args.env}]` : "";
|
|
1657
2059
|
const previewString = args.preview ? "preview_" : "";
|
|
1658
|
-
|
|
2060
|
+
logger.log(
|
|
1659
2061
|
`Add the following to your configuration file in your kv_namespaces array${envString}:`
|
|
1660
2062
|
);
|
|
1661
|
-
|
|
2063
|
+
logger.log(
|
|
1662
2064
|
`{ binding = "${args.namespace}", ${previewString}id = "${namespaceId}" }`
|
|
1663
2065
|
);
|
|
1664
2066
|
|
|
@@ -1670,32 +2072,14 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1670
2072
|
"Outputs a list of all KV namespaces associated with your account id.",
|
|
1671
2073
|
{},
|
|
1672
2074
|
async (args) => {
|
|
1673
|
-
const config = readConfig(args.config as ConfigPath);
|
|
1674
|
-
|
|
1675
|
-
// -- snip, extract --
|
|
1676
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1677
|
-
if (!loggedIn) {
|
|
1678
|
-
// didn't login, let's just quit
|
|
1679
|
-
console.log("Did not login, quitting...");
|
|
1680
|
-
return;
|
|
1681
|
-
}
|
|
2075
|
+
const config = readConfig(args.config as ConfigPath, args);
|
|
1682
2076
|
|
|
1683
|
-
|
|
1684
|
-
config.account_id = await getAccountId();
|
|
1685
|
-
if (!config.account_id) {
|
|
1686
|
-
throw new Error("No account id found, quitting...");
|
|
1687
|
-
}
|
|
1688
|
-
}
|
|
1689
|
-
// -- snip, end --
|
|
2077
|
+
const accountId = await requireAuth(config);
|
|
1690
2078
|
|
|
1691
2079
|
// TODO: we should show bindings if they exist for given ids
|
|
1692
2080
|
|
|
1693
|
-
|
|
1694
|
-
JSON.stringify(
|
|
1695
|
-
await listNamespaces(config.account_id),
|
|
1696
|
-
null,
|
|
1697
|
-
" "
|
|
1698
|
-
)
|
|
2081
|
+
logger.log(
|
|
2082
|
+
JSON.stringify(await listKVNamespaces(accountId), null, " ")
|
|
1699
2083
|
);
|
|
1700
2084
|
}
|
|
1701
2085
|
)
|
|
@@ -1706,16 +2090,20 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1706
2090
|
return yargs
|
|
1707
2091
|
.option("binding", {
|
|
1708
2092
|
type: "string",
|
|
2093
|
+
requiresArg: true,
|
|
1709
2094
|
describe: "The name of the namespace to delete",
|
|
1710
2095
|
})
|
|
1711
2096
|
.option("namespace-id", {
|
|
1712
2097
|
type: "string",
|
|
2098
|
+
requiresArg: true,
|
|
1713
2099
|
describe: "The id of the namespace to delete",
|
|
1714
2100
|
})
|
|
1715
2101
|
.check(demandOneOfOption("binding", "namespace-id"))
|
|
1716
2102
|
.option("env", {
|
|
1717
2103
|
type: "string",
|
|
2104
|
+
requiresArg: true,
|
|
1718
2105
|
describe: "Perform on a specific environment",
|
|
2106
|
+
alias: "e",
|
|
1719
2107
|
})
|
|
1720
2108
|
.option("preview", {
|
|
1721
2109
|
type: "boolean",
|
|
@@ -1723,37 +2111,21 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1723
2111
|
});
|
|
1724
2112
|
},
|
|
1725
2113
|
async (args) => {
|
|
1726
|
-
|
|
2114
|
+
await printWranglerBanner();
|
|
2115
|
+
const config = readConfig(args.config as ConfigPath, args);
|
|
1727
2116
|
|
|
1728
2117
|
let id;
|
|
1729
2118
|
try {
|
|
1730
|
-
id =
|
|
2119
|
+
id = getKVNamespaceId(args, config);
|
|
1731
2120
|
} catch (e) {
|
|
1732
2121
|
throw new CommandLineArgsError(
|
|
1733
2122
|
"Not able to delete namespace.\n" + ((e as Error).message ?? e)
|
|
1734
2123
|
);
|
|
1735
2124
|
}
|
|
1736
2125
|
|
|
1737
|
-
|
|
1738
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1739
|
-
if (!loggedIn) {
|
|
1740
|
-
// didn't login, let's just quit
|
|
1741
|
-
console.log("Did not login, quitting...");
|
|
1742
|
-
return;
|
|
1743
|
-
}
|
|
1744
|
-
|
|
1745
|
-
if (!config.account_id) {
|
|
1746
|
-
config.account_id = await getAccountId();
|
|
1747
|
-
if (!config.account_id) {
|
|
1748
|
-
throw new Error("No account id found, quitting...");
|
|
1749
|
-
}
|
|
1750
|
-
}
|
|
1751
|
-
// -- snip, end --
|
|
2126
|
+
const accountId = await requireAuth(config);
|
|
1752
2127
|
|
|
1753
|
-
await
|
|
1754
|
-
`/accounts/${config.account_id}/storage/kv/namespaces/${id}`,
|
|
1755
|
-
{ method: "DELETE" }
|
|
1756
|
-
);
|
|
2128
|
+
await deleteKVNamespace(accountId, id);
|
|
1757
2129
|
|
|
1758
2130
|
// TODO: recommend they remove it from wrangler.toml
|
|
1759
2131
|
|
|
@@ -1783,6 +2155,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1783
2155
|
"🔑 Individually manage Workers KV key-value pairs",
|
|
1784
2156
|
(kvKeyYargs) => {
|
|
1785
2157
|
return kvKeyYargs
|
|
2158
|
+
.command(subHelp)
|
|
1786
2159
|
.command(
|
|
1787
2160
|
"put <key> [value]",
|
|
1788
2161
|
"Writes a single key/value pair to the given namespace.",
|
|
@@ -1799,16 +2172,20 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1799
2172
|
})
|
|
1800
2173
|
.option("binding", {
|
|
1801
2174
|
type: "string",
|
|
2175
|
+
requiresArg: true,
|
|
1802
2176
|
describe: "The binding of the namespace to write to",
|
|
1803
2177
|
})
|
|
1804
2178
|
.option("namespace-id", {
|
|
1805
2179
|
type: "string",
|
|
2180
|
+
requiresArg: true,
|
|
1806
2181
|
describe: "The id of the namespace to write to",
|
|
1807
2182
|
})
|
|
1808
2183
|
.check(demandOneOfOption("binding", "namespace-id"))
|
|
1809
2184
|
.option("env", {
|
|
1810
2185
|
type: "string",
|
|
2186
|
+
requiresArg: true,
|
|
1811
2187
|
describe: "Perform on a specific environment",
|
|
2188
|
+
alias: "e",
|
|
1812
2189
|
})
|
|
1813
2190
|
.option("preview", {
|
|
1814
2191
|
type: "boolean",
|
|
@@ -1825,13 +2202,15 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1825
2202
|
})
|
|
1826
2203
|
.option("path", {
|
|
1827
2204
|
type: "string",
|
|
2205
|
+
requiresArg: true,
|
|
1828
2206
|
describe: "Read value from the file at a given path",
|
|
1829
2207
|
})
|
|
1830
2208
|
.check(demandOneOfOption("value", "path"));
|
|
1831
2209
|
},
|
|
1832
2210
|
async ({ key, ttl, expiration, ...args }) => {
|
|
1833
|
-
|
|
1834
|
-
const
|
|
2211
|
+
await printWranglerBanner();
|
|
2212
|
+
const config = readConfig(args.config as ConfigPath, args);
|
|
2213
|
+
const namespaceId = getKVNamespaceId(args, config);
|
|
1835
2214
|
// One of `args.path` and `args.value` must be defined
|
|
1836
2215
|
const value = args.path
|
|
1837
2216
|
? readFileSync(args.path)
|
|
@@ -1839,32 +2218,20 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1839
2218
|
args.value!;
|
|
1840
2219
|
|
|
1841
2220
|
if (args.path) {
|
|
1842
|
-
|
|
1843
|
-
`
|
|
2221
|
+
logger.log(
|
|
2222
|
+
`Writing the contents of ${args.path} to the key "${key}" on namespace ${namespaceId}.`
|
|
1844
2223
|
);
|
|
1845
2224
|
} else {
|
|
1846
|
-
|
|
1847
|
-
`
|
|
2225
|
+
logger.log(
|
|
2226
|
+
`Writing the value "${value}" to key "${key}" on namespace ${namespaceId}.`
|
|
1848
2227
|
);
|
|
1849
2228
|
}
|
|
1850
2229
|
|
|
1851
|
-
|
|
1852
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1853
|
-
if (!loggedIn) {
|
|
1854
|
-
// didn't login, let's just quit
|
|
1855
|
-
console.log("Did not login, quitting...");
|
|
1856
|
-
return;
|
|
1857
|
-
}
|
|
1858
|
-
|
|
1859
|
-
if (!config.account_id) {
|
|
1860
|
-
config.account_id = await getAccountId();
|
|
1861
|
-
if (!config.account_id) {
|
|
1862
|
-
throw new Error("No account id found, quitting...");
|
|
1863
|
-
}
|
|
1864
|
-
}
|
|
1865
|
-
// -- snip, end --
|
|
2230
|
+
const accountId = await requireAuth(config);
|
|
1866
2231
|
|
|
1867
|
-
await
|
|
2232
|
+
await putKVKeyValue(accountId, namespaceId, {
|
|
2233
|
+
key,
|
|
2234
|
+
value,
|
|
1868
2235
|
expiration,
|
|
1869
2236
|
expiration_ttl: ttl,
|
|
1870
2237
|
});
|
|
@@ -1877,16 +2244,20 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1877
2244
|
return yargs
|
|
1878
2245
|
.option("binding", {
|
|
1879
2246
|
type: "string",
|
|
2247
|
+
requiresArg: true,
|
|
1880
2248
|
describe: "The name of the namespace to list",
|
|
1881
2249
|
})
|
|
1882
2250
|
.option("namespace-id", {
|
|
1883
2251
|
type: "string",
|
|
2252
|
+
requiresArg: true,
|
|
1884
2253
|
describe: "The id of the namespace to list",
|
|
1885
2254
|
})
|
|
1886
2255
|
.check(demandOneOfOption("binding", "namespace-id"))
|
|
1887
2256
|
.option("env", {
|
|
1888
2257
|
type: "string",
|
|
2258
|
+
requiresArg: true,
|
|
1889
2259
|
describe: "Perform on a specific environment",
|
|
2260
|
+
alias: "e",
|
|
1890
2261
|
})
|
|
1891
2262
|
.option("preview", {
|
|
1892
2263
|
type: "boolean",
|
|
@@ -1896,36 +2267,23 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1896
2267
|
})
|
|
1897
2268
|
.option("prefix", {
|
|
1898
2269
|
type: "string",
|
|
2270
|
+
requiresArg: true,
|
|
1899
2271
|
describe: "A prefix to filter listed keys",
|
|
1900
2272
|
});
|
|
1901
2273
|
},
|
|
1902
2274
|
async ({ prefix, ...args }) => {
|
|
1903
2275
|
// TODO: support for limit+cursor (pagination)
|
|
1904
|
-
const config = readConfig(args.config as ConfigPath);
|
|
1905
|
-
const namespaceId =
|
|
1906
|
-
|
|
1907
|
-
// -- snip, extract --
|
|
1908
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1909
|
-
if (!loggedIn) {
|
|
1910
|
-
// didn't login, let's just quit
|
|
1911
|
-
console.log("Did not login, quitting...");
|
|
1912
|
-
return;
|
|
1913
|
-
}
|
|
2276
|
+
const config = readConfig(args.config as ConfigPath, args);
|
|
2277
|
+
const namespaceId = getKVNamespaceId(args, config);
|
|
1914
2278
|
|
|
1915
|
-
|
|
1916
|
-
config.account_id = await getAccountId();
|
|
1917
|
-
if (!config.account_id) {
|
|
1918
|
-
throw new Error("No account id found, quitting...");
|
|
1919
|
-
}
|
|
1920
|
-
}
|
|
1921
|
-
// -- snip, end --
|
|
2279
|
+
const accountId = await requireAuth(config);
|
|
1922
2280
|
|
|
1923
|
-
const results = await
|
|
1924
|
-
|
|
2281
|
+
const results = await listKVNamespaceKeys(
|
|
2282
|
+
accountId,
|
|
1925
2283
|
namespaceId,
|
|
1926
2284
|
prefix
|
|
1927
2285
|
);
|
|
1928
|
-
|
|
2286
|
+
logger.log(JSON.stringify(results, undefined, 2));
|
|
1929
2287
|
}
|
|
1930
2288
|
)
|
|
1931
2289
|
.command(
|
|
@@ -1940,16 +2298,20 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1940
2298
|
})
|
|
1941
2299
|
.option("binding", {
|
|
1942
2300
|
type: "string",
|
|
2301
|
+
requiresArg: true,
|
|
1943
2302
|
describe: "The name of the namespace to get from",
|
|
1944
2303
|
})
|
|
1945
2304
|
.option("namespace-id", {
|
|
1946
2305
|
type: "string",
|
|
2306
|
+
requiresArg: true,
|
|
1947
2307
|
describe: "The id of the namespace to get from",
|
|
1948
2308
|
})
|
|
1949
2309
|
.check(demandOneOfOption("binding", "namespace-id"))
|
|
1950
2310
|
.option("env", {
|
|
1951
2311
|
type: "string",
|
|
2312
|
+
requiresArg: true,
|
|
1952
2313
|
describe: "Perform on a specific environment",
|
|
2314
|
+
alias: "e",
|
|
1953
2315
|
})
|
|
1954
2316
|
.option("preview", {
|
|
1955
2317
|
type: "boolean",
|
|
@@ -1963,26 +2325,12 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1963
2325
|
});
|
|
1964
2326
|
},
|
|
1965
2327
|
async ({ key, ...args }) => {
|
|
1966
|
-
const config = readConfig(args.config as ConfigPath);
|
|
1967
|
-
const namespaceId =
|
|
1968
|
-
|
|
1969
|
-
// -- snip, extract --
|
|
1970
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1971
|
-
if (!loggedIn) {
|
|
1972
|
-
// didn't login, let's just quit
|
|
1973
|
-
console.log("Did not login, quitting...");
|
|
1974
|
-
return;
|
|
1975
|
-
}
|
|
2328
|
+
const config = readConfig(args.config as ConfigPath, args);
|
|
2329
|
+
const namespaceId = getKVNamespaceId(args, config);
|
|
1976
2330
|
|
|
1977
|
-
|
|
1978
|
-
config.account_id = await getAccountId();
|
|
1979
|
-
if (!config.account_id) {
|
|
1980
|
-
throw new Error("No account id found, quitting...");
|
|
1981
|
-
}
|
|
1982
|
-
}
|
|
1983
|
-
// -- snip, end --
|
|
2331
|
+
const accountId = await requireAuth(config);
|
|
1984
2332
|
|
|
1985
|
-
|
|
2333
|
+
logger.log(await getKVKeyValue(accountId, namespaceId, key));
|
|
1986
2334
|
}
|
|
1987
2335
|
)
|
|
1988
2336
|
.command(
|
|
@@ -1997,16 +2345,20 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1997
2345
|
})
|
|
1998
2346
|
.option("binding", {
|
|
1999
2347
|
type: "string",
|
|
2348
|
+
requiresArg: true,
|
|
2000
2349
|
describe: "The name of the namespace to delete from",
|
|
2001
2350
|
})
|
|
2002
2351
|
.option("namespace-id", {
|
|
2003
2352
|
type: "string",
|
|
2353
|
+
requiresArg: true,
|
|
2004
2354
|
describe: "The id of the namespace to delete from",
|
|
2005
2355
|
})
|
|
2006
2356
|
.check(demandOneOfOption("binding", "namespace-id"))
|
|
2007
2357
|
.option("env", {
|
|
2008
2358
|
type: "string",
|
|
2359
|
+
requiresArg: true,
|
|
2009
2360
|
describe: "Perform on a specific environment",
|
|
2361
|
+
alias: "e",
|
|
2010
2362
|
})
|
|
2011
2363
|
.option("preview", {
|
|
2012
2364
|
type: "boolean",
|
|
@@ -2014,33 +2366,17 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2014
2366
|
});
|
|
2015
2367
|
},
|
|
2016
2368
|
async ({ key, ...args }) => {
|
|
2017
|
-
|
|
2018
|
-
const
|
|
2369
|
+
await printWranglerBanner();
|
|
2370
|
+
const config = readConfig(args.config as ConfigPath, args);
|
|
2371
|
+
const namespaceId = getKVNamespaceId(args, config);
|
|
2019
2372
|
|
|
2020
|
-
|
|
2021
|
-
`
|
|
2373
|
+
logger.log(
|
|
2374
|
+
`Deleting the key "${key}" on namespace ${namespaceId}.`
|
|
2022
2375
|
);
|
|
2023
2376
|
|
|
2024
|
-
|
|
2025
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
2026
|
-
if (!loggedIn) {
|
|
2027
|
-
// didn't login, let's just quit
|
|
2028
|
-
console.log("Did not login, quitting...");
|
|
2029
|
-
return;
|
|
2030
|
-
}
|
|
2031
|
-
|
|
2032
|
-
if (!config.account_id) {
|
|
2033
|
-
config.account_id = await getAccountId();
|
|
2034
|
-
if (!config.account_id) {
|
|
2035
|
-
throw new Error("No account id found, quitting...");
|
|
2036
|
-
}
|
|
2037
|
-
}
|
|
2038
|
-
// -- snip, end --
|
|
2377
|
+
const accountId = await requireAuth(config);
|
|
2039
2378
|
|
|
2040
|
-
await
|
|
2041
|
-
`/accounts/${config.account_id}/storage/kv/namespaces/${namespaceId}/values/${key}`,
|
|
2042
|
-
{ method: "DELETE" }
|
|
2043
|
-
);
|
|
2379
|
+
await deleteKVKeyValue(accountId, namespaceId, key);
|
|
2044
2380
|
}
|
|
2045
2381
|
);
|
|
2046
2382
|
}
|
|
@@ -2052,6 +2388,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2052
2388
|
"💪 Interact with multiple Workers KV key-value pairs at once",
|
|
2053
2389
|
(kvBulkYargs) => {
|
|
2054
2390
|
return kvBulkYargs
|
|
2391
|
+
.command(subHelp)
|
|
2055
2392
|
.command(
|
|
2056
2393
|
"put <filename>",
|
|
2057
2394
|
"Upload multiple key-value pairs to a namespace",
|
|
@@ -2064,16 +2401,20 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2064
2401
|
})
|
|
2065
2402
|
.option("binding", {
|
|
2066
2403
|
type: "string",
|
|
2404
|
+
requiresArg: true,
|
|
2067
2405
|
describe: "The name of the namespace to insert values into",
|
|
2068
2406
|
})
|
|
2069
2407
|
.option("namespace-id", {
|
|
2070
2408
|
type: "string",
|
|
2409
|
+
requiresArg: true,
|
|
2071
2410
|
describe: "The id of the namespace to insert values into",
|
|
2072
2411
|
})
|
|
2073
2412
|
.check(demandOneOfOption("binding", "namespace-id"))
|
|
2074
2413
|
.option("env", {
|
|
2075
2414
|
type: "string",
|
|
2415
|
+
requiresArg: true,
|
|
2076
2416
|
describe: "Perform on a specific environment",
|
|
2417
|
+
alias: "e",
|
|
2077
2418
|
})
|
|
2078
2419
|
.option("preview", {
|
|
2079
2420
|
type: "boolean",
|
|
@@ -2081,33 +2422,67 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2081
2422
|
});
|
|
2082
2423
|
},
|
|
2083
2424
|
async ({ filename, ...args }) => {
|
|
2425
|
+
await printWranglerBanner();
|
|
2084
2426
|
// The simplest implementation I could think of.
|
|
2085
2427
|
// This could be made more efficient with a streaming parser/uploader
|
|
2086
2428
|
// but we'll do that in the future if needed.
|
|
2087
2429
|
|
|
2088
|
-
const config = readConfig(args.config as ConfigPath);
|
|
2089
|
-
const namespaceId =
|
|
2430
|
+
const config = readConfig(args.config as ConfigPath, args);
|
|
2431
|
+
const namespaceId = getKVNamespaceId(args, config);
|
|
2090
2432
|
const content = parseJSON(readFileSync(filename), filename);
|
|
2091
2433
|
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
return;
|
|
2434
|
+
if (!Array.isArray(content)) {
|
|
2435
|
+
throw new Error(
|
|
2436
|
+
`Unexpected JSON input from "${filename}".\n` +
|
|
2437
|
+
`Expected an array of key-value objects but got type "${typeof content}".`
|
|
2438
|
+
);
|
|
2098
2439
|
}
|
|
2099
2440
|
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2441
|
+
const errors: string[] = [];
|
|
2442
|
+
const warnings: string[] = [];
|
|
2443
|
+
for (let i = 0; i < content.length; i++) {
|
|
2444
|
+
const keyValue = content[i];
|
|
2445
|
+
if (!isKVKeyValue(keyValue)) {
|
|
2446
|
+
errors.push(
|
|
2447
|
+
`The item at index ${i} is ${JSON.stringify(keyValue)}`
|
|
2448
|
+
);
|
|
2449
|
+
} else {
|
|
2450
|
+
const props = unexpectedKVKeyValueProps(keyValue);
|
|
2451
|
+
if (props.length > 0) {
|
|
2452
|
+
warnings.push(
|
|
2453
|
+
`The item at index ${i} contains unexpected properties: ${JSON.stringify(
|
|
2454
|
+
props
|
|
2455
|
+
)}.`
|
|
2456
|
+
);
|
|
2457
|
+
}
|
|
2104
2458
|
}
|
|
2105
2459
|
}
|
|
2106
|
-
|
|
2460
|
+
if (warnings.length > 0) {
|
|
2461
|
+
logger.warn(
|
|
2462
|
+
`Unexpected key-value properties in "${filename}".\n` +
|
|
2463
|
+
warnings.join("\n")
|
|
2464
|
+
);
|
|
2465
|
+
}
|
|
2466
|
+
if (errors.length > 0) {
|
|
2467
|
+
throw new Error(
|
|
2468
|
+
`Unexpected JSON input from "${filename}".\n` +
|
|
2469
|
+
`Each item in the array should be an object that matches:\n\n` +
|
|
2470
|
+
`interface KeyValue {\n` +
|
|
2471
|
+
` key: string;\n` +
|
|
2472
|
+
` value: string;\n` +
|
|
2473
|
+
` expiration?: number;\n` +
|
|
2474
|
+
` expiration_ttl?: number;\n` +
|
|
2475
|
+
` metadata?: object;\n` +
|
|
2476
|
+
` base64?: boolean;\n` +
|
|
2477
|
+
`}\n\n` +
|
|
2478
|
+
errors.join("\n")
|
|
2479
|
+
);
|
|
2480
|
+
}
|
|
2107
2481
|
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2482
|
+
const accountId = await requireAuth(config);
|
|
2483
|
+
await putKVBulkKeyValue(accountId, namespaceId, content);
|
|
2484
|
+
|
|
2485
|
+
logger.log("Success!");
|
|
2111
2486
|
}
|
|
2112
2487
|
)
|
|
2113
2488
|
.command(
|
|
@@ -2122,202 +2497,267 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2122
2497
|
})
|
|
2123
2498
|
.option("binding", {
|
|
2124
2499
|
type: "string",
|
|
2500
|
+
requiresArg: true,
|
|
2125
2501
|
describe: "The name of the namespace to delete from",
|
|
2126
2502
|
})
|
|
2127
2503
|
.option("namespace-id", {
|
|
2128
2504
|
type: "string",
|
|
2505
|
+
requiresArg: true,
|
|
2129
2506
|
describe: "The id of the namespace to delete from",
|
|
2130
2507
|
})
|
|
2131
2508
|
.check(demandOneOfOption("binding", "namespace-id"))
|
|
2132
2509
|
.option("env", {
|
|
2133
2510
|
type: "string",
|
|
2511
|
+
requiresArg: true,
|
|
2134
2512
|
describe: "Perform on a specific environment",
|
|
2513
|
+
alias: "e",
|
|
2135
2514
|
})
|
|
2136
2515
|
.option("preview", {
|
|
2137
2516
|
type: "boolean",
|
|
2138
2517
|
describe: "Interact with a preview namespace",
|
|
2518
|
+
})
|
|
2519
|
+
.option("force", {
|
|
2520
|
+
type: "boolean",
|
|
2521
|
+
alias: "f",
|
|
2522
|
+
describe: "Do not ask for confirmation before deleting",
|
|
2139
2523
|
});
|
|
2140
2524
|
},
|
|
2141
2525
|
async ({ filename, ...args }) => {
|
|
2142
|
-
|
|
2143
|
-
const
|
|
2144
|
-
const
|
|
2526
|
+
await printWranglerBanner();
|
|
2527
|
+
const config = readConfig(args.config as ConfigPath, args);
|
|
2528
|
+
const namespaceId = getKVNamespaceId(args, config);
|
|
2529
|
+
|
|
2530
|
+
if (!args.force) {
|
|
2531
|
+
const result = await confirm(
|
|
2532
|
+
`Are you sure you want to delete all the keys read from "${filename}" from kv-namespace with id "${namespaceId}"?`
|
|
2533
|
+
);
|
|
2534
|
+
if (!result) {
|
|
2535
|
+
logger.log(`Not deleting keys read from "${filename}".`);
|
|
2536
|
+
return;
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
|
|
2540
|
+
const content = parseJSON(
|
|
2541
|
+
readFileSync(filename),
|
|
2542
|
+
filename
|
|
2543
|
+
) as string[];
|
|
2145
2544
|
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
return;
|
|
2545
|
+
if (!Array.isArray(content)) {
|
|
2546
|
+
throw new Error(
|
|
2547
|
+
`Unexpected JSON input from "${filename}".\n` +
|
|
2548
|
+
`Expected an array of strings but got:\n${content}`
|
|
2549
|
+
);
|
|
2152
2550
|
}
|
|
2153
2551
|
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2552
|
+
const errors: string[] = [];
|
|
2553
|
+
for (let i = 0; i < content.length; i++) {
|
|
2554
|
+
const key = content[i];
|
|
2555
|
+
if (typeof key !== "string") {
|
|
2556
|
+
errors.push(
|
|
2557
|
+
`The item at index ${i} is type: "${typeof key}" - ${JSON.stringify(
|
|
2558
|
+
key
|
|
2559
|
+
)}`
|
|
2560
|
+
);
|
|
2158
2561
|
}
|
|
2159
2562
|
}
|
|
2160
|
-
|
|
2563
|
+
if (errors.length > 0) {
|
|
2564
|
+
throw new Error(
|
|
2565
|
+
`Unexpected JSON input from "${filename}".\n` +
|
|
2566
|
+
`Expected an array of strings.\n` +
|
|
2567
|
+
errors.join("\n")
|
|
2568
|
+
);
|
|
2569
|
+
}
|
|
2161
2570
|
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
);
|
|
2571
|
+
const accountId = await requireAuth(config);
|
|
2572
|
+
|
|
2573
|
+
await deleteKVBulkKeyValue(accountId, namespaceId, content);
|
|
2574
|
+
|
|
2575
|
+
logger.log("Success!");
|
|
2165
2576
|
}
|
|
2166
2577
|
);
|
|
2167
2578
|
}
|
|
2168
2579
|
);
|
|
2169
2580
|
|
|
2170
|
-
wrangler.command(
|
|
2581
|
+
wrangler.command(
|
|
2582
|
+
"pages",
|
|
2583
|
+
"⚡️ Configure Cloudflare Pages",
|
|
2584
|
+
async (pagesYargs) => {
|
|
2585
|
+
await pages(pagesYargs.command(subHelp).epilogue(pagesBetaWarning));
|
|
2586
|
+
}
|
|
2587
|
+
);
|
|
2171
2588
|
|
|
2172
2589
|
wrangler.command("r2", "📦 Interact with an R2 store", (r2Yargs) => {
|
|
2173
|
-
return r2Yargs
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
throw new CommandLineArgsError(
|
|
2189
|
-
`Unexpected additional positional arguments "${extraArgs}".`
|
|
2190
|
-
);
|
|
2191
|
-
}
|
|
2590
|
+
return r2Yargs
|
|
2591
|
+
.command(subHelp)
|
|
2592
|
+
.command("bucket", "Manage R2 buckets", (r2BucketYargs) => {
|
|
2593
|
+
r2BucketYargs.command(
|
|
2594
|
+
"create <name>",
|
|
2595
|
+
"Create a new R2 bucket",
|
|
2596
|
+
(yargs) => {
|
|
2597
|
+
return yargs.positional("name", {
|
|
2598
|
+
describe: "The name of the new bucket",
|
|
2599
|
+
type: "string",
|
|
2600
|
+
demandOption: true,
|
|
2601
|
+
});
|
|
2602
|
+
},
|
|
2603
|
+
async (args) => {
|
|
2604
|
+
await printWranglerBanner();
|
|
2192
2605
|
|
|
2193
|
-
|
|
2606
|
+
const config = readConfig(args.config as ConfigPath, args);
|
|
2194
2607
|
|
|
2195
|
-
|
|
2196
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
2197
|
-
if (!loggedIn) {
|
|
2198
|
-
// didn't login, let's just quit
|
|
2199
|
-
console.log("Did not login, quitting...");
|
|
2200
|
-
return;
|
|
2201
|
-
}
|
|
2608
|
+
const accountId = await requireAuth(config);
|
|
2202
2609
|
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
throw new Error("No account id found, quitting...");
|
|
2207
|
-
}
|
|
2610
|
+
logger.log(`Creating bucket ${args.name}.`);
|
|
2611
|
+
await createR2Bucket(accountId, args.name);
|
|
2612
|
+
logger.log(`Created bucket ${args.name}.`);
|
|
2208
2613
|
}
|
|
2209
|
-
|
|
2614
|
+
);
|
|
2210
2615
|
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
console.log(`Created bucket ${args.name}.`);
|
|
2214
|
-
}
|
|
2215
|
-
);
|
|
2616
|
+
r2BucketYargs.command("list", "List R2 buckets", {}, async (args) => {
|
|
2617
|
+
const config = readConfig(args.config as ConfigPath, args);
|
|
2216
2618
|
|
|
2217
|
-
|
|
2218
|
-
const config = readConfig(args.config as ConfigPath);
|
|
2619
|
+
const accountId = await requireAuth(config);
|
|
2219
2620
|
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
if (!loggedIn) {
|
|
2223
|
-
// didn't login, let's just quit
|
|
2224
|
-
console.log("Did not login, quitting...");
|
|
2225
|
-
return;
|
|
2226
|
-
}
|
|
2621
|
+
logger.log(JSON.stringify(await listR2Buckets(accountId), null, 2));
|
|
2622
|
+
});
|
|
2227
2623
|
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2624
|
+
r2BucketYargs.command(
|
|
2625
|
+
"delete <name>",
|
|
2626
|
+
"Delete an R2 bucket",
|
|
2627
|
+
(yargs) => {
|
|
2628
|
+
return yargs.positional("name", {
|
|
2629
|
+
describe: "The name of the bucket to delete",
|
|
2630
|
+
type: "string",
|
|
2631
|
+
demandOption: true,
|
|
2632
|
+
});
|
|
2633
|
+
},
|
|
2634
|
+
async (args) => {
|
|
2635
|
+
await printWranglerBanner();
|
|
2636
|
+
|
|
2637
|
+
const config = readConfig(args.config as ConfigPath, args);
|
|
2235
2638
|
|
|
2236
|
-
|
|
2237
|
-
|
|
2639
|
+
const accountId = await requireAuth(config);
|
|
2640
|
+
|
|
2641
|
+
logger.log(`Deleting bucket ${args.name}.`);
|
|
2642
|
+
await deleteR2Bucket(accountId, args.name);
|
|
2643
|
+
logger.log(`Deleted bucket ${args.name}.`);
|
|
2644
|
+
}
|
|
2238
2645
|
);
|
|
2646
|
+
return r2BucketYargs;
|
|
2239
2647
|
});
|
|
2648
|
+
});
|
|
2240
2649
|
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2650
|
+
/**
|
|
2651
|
+
* User Group: login, logout, and whoami
|
|
2652
|
+
* TODO: group commands into User group similar to .group() for flags in yargs
|
|
2653
|
+
*/
|
|
2654
|
+
// login
|
|
2655
|
+
wrangler.command(
|
|
2656
|
+
// this needs scopes as an option?
|
|
2657
|
+
"login",
|
|
2658
|
+
"🔓 Login to Cloudflare",
|
|
2659
|
+
(yargs) => {
|
|
2660
|
+
// TODO: This needs some copy editing
|
|
2661
|
+
// I mean, this entire app does, but this too.
|
|
2662
|
+
return yargs
|
|
2663
|
+
.option("scopes-list", {
|
|
2664
|
+
describe: "List all the available OAuth scopes with descriptions",
|
|
2665
|
+
})
|
|
2666
|
+
.option("scopes", {
|
|
2667
|
+
describe: "Pick the set of applicable OAuth scopes when logging in",
|
|
2668
|
+
array: true,
|
|
2669
|
+
type: "string",
|
|
2670
|
+
requiresArg: true,
|
|
2671
|
+
});
|
|
2259
2672
|
|
|
2260
|
-
|
|
2673
|
+
// TODO: scopes
|
|
2674
|
+
},
|
|
2675
|
+
async (args) => {
|
|
2676
|
+
await printWranglerBanner();
|
|
2677
|
+
if (args["scopes-list"]) {
|
|
2678
|
+
listScopes();
|
|
2679
|
+
return;
|
|
2680
|
+
}
|
|
2681
|
+
if (args.scopes) {
|
|
2682
|
+
if (args.scopes.length === 0) {
|
|
2683
|
+
// don't allow no scopes to be passed, that would be weird
|
|
2684
|
+
listScopes();
|
|
2685
|
+
return;
|
|
2686
|
+
}
|
|
2687
|
+
if (!validateScopeKeys(args.scopes)) {
|
|
2688
|
+
throw new CommandLineArgsError(
|
|
2689
|
+
`One of ${args.scopes} is not a valid authentication scope. Run "wrangler login --list-scopes" to see the valid scopes.`
|
|
2690
|
+
);
|
|
2691
|
+
}
|
|
2692
|
+
await login({ scopes: args.scopes });
|
|
2693
|
+
return;
|
|
2694
|
+
}
|
|
2695
|
+
await login();
|
|
2261
2696
|
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
return;
|
|
2268
|
-
}
|
|
2697
|
+
// TODO: would be nice if it optionally saved login
|
|
2698
|
+
// credentials inside node_modules/.cache or something
|
|
2699
|
+
// this way you could have multiple users on a single machine
|
|
2700
|
+
}
|
|
2701
|
+
);
|
|
2269
2702
|
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2703
|
+
// logout
|
|
2704
|
+
wrangler.command(
|
|
2705
|
+
// this needs scopes as an option?
|
|
2706
|
+
"logout",
|
|
2707
|
+
"🚪 Logout from Cloudflare",
|
|
2708
|
+
() => {},
|
|
2709
|
+
async () => {
|
|
2710
|
+
await printWranglerBanner();
|
|
2711
|
+
await logout();
|
|
2712
|
+
}
|
|
2713
|
+
);
|
|
2277
2714
|
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2715
|
+
// whoami
|
|
2716
|
+
wrangler.command(
|
|
2717
|
+
"whoami",
|
|
2718
|
+
"🕵️ Retrieve your user info and test your auth config",
|
|
2719
|
+
() => {},
|
|
2720
|
+
async () => {
|
|
2721
|
+
await printWranglerBanner();
|
|
2722
|
+
await whoami();
|
|
2723
|
+
}
|
|
2724
|
+
);
|
|
2286
2725
|
|
|
2287
|
-
wrangler
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
alias: "c",
|
|
2294
|
-
describe: "Path to .toml configuration file",
|
|
2295
|
-
type: "string",
|
|
2296
|
-
});
|
|
2726
|
+
wrangler.option("config", {
|
|
2727
|
+
alias: "c",
|
|
2728
|
+
describe: "Path to .toml configuration file",
|
|
2729
|
+
type: "string",
|
|
2730
|
+
requiresArg: true,
|
|
2731
|
+
});
|
|
2297
2732
|
|
|
2298
|
-
wrangler.group(["config", "help", "version"
|
|
2733
|
+
wrangler.group(["config", "help", "version"], "Flags:");
|
|
2299
2734
|
wrangler.help().alias("h", "help");
|
|
2300
2735
|
wrangler.version(wranglerVersion).alias("v", "version");
|
|
2301
2736
|
wrangler.exitProcess(false);
|
|
2302
2737
|
|
|
2738
|
+
return wrangler;
|
|
2739
|
+
}
|
|
2740
|
+
|
|
2741
|
+
export async function main(argv: string[]): Promise<void> {
|
|
2742
|
+
const wrangler = createCLIParser(argv);
|
|
2303
2743
|
try {
|
|
2304
|
-
await initialiseUserConfig();
|
|
2305
2744
|
await wrangler.parse();
|
|
2306
2745
|
} catch (e) {
|
|
2746
|
+
logger.log(""); // Just adds a bit of space
|
|
2307
2747
|
if (e instanceof CommandLineArgsError) {
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2748
|
+
logger.error(e.message);
|
|
2749
|
+
// We are not able to ask the `wrangler` CLI parser to show help for a subcommand programmatically.
|
|
2750
|
+
// The workaround is to re-run the parsing with an additional `--help` flag, which will result in the correct help message being displayed.
|
|
2751
|
+
// The `wrangler` object is "frozen"; we cannot reuse that with different args, so we must create a new CLI parser to generate the help message.
|
|
2752
|
+
await createCLIParser([...argv, "--help"]).parse();
|
|
2311
2753
|
} else if (e instanceof ParseError) {
|
|
2312
|
-
console.error("");
|
|
2313
2754
|
e.notes.push({
|
|
2314
2755
|
text: "\nIf you think this is a bug, please open an issue at: https://github.com/cloudflare/wrangler2/issues/new",
|
|
2315
2756
|
});
|
|
2316
|
-
|
|
2757
|
+
logger.log(formatMessage(e));
|
|
2317
2758
|
} else {
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
console.error(
|
|
2759
|
+
logger.error(e instanceof Error ? e.message : e);
|
|
2760
|
+
logger.log(
|
|
2321
2761
|
`${fgGreenColor}%s${resetColor}`,
|
|
2322
2762
|
"If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
|
|
2323
2763
|
);
|
|
@@ -2325,3 +2765,25 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2325
2765
|
throw e;
|
|
2326
2766
|
}
|
|
2327
2767
|
}
|
|
2768
|
+
|
|
2769
|
+
function getDevCompatibilityDate(
|
|
2770
|
+
config: Config,
|
|
2771
|
+
compatibilityDate = config.compatibility_date
|
|
2772
|
+
) {
|
|
2773
|
+
const currentDate = new Date().toISOString().substring(0, 10);
|
|
2774
|
+
if (config.configPath !== undefined && compatibilityDate === undefined) {
|
|
2775
|
+
logger.warn(
|
|
2776
|
+
`No compatibility_date was specified. Using today's date: ${currentDate}.\n` +
|
|
2777
|
+
"Add one to your wrangler.toml file:\n" +
|
|
2778
|
+
"```\n" +
|
|
2779
|
+
`compatibility_date = "${currentDate}"\n` +
|
|
2780
|
+
"```\n" +
|
|
2781
|
+
"or pass it in your terminal:\n" +
|
|
2782
|
+
"```\n" +
|
|
2783
|
+
`--compatibility-date=${currentDate}\n` +
|
|
2784
|
+
"```\n" +
|
|
2785
|
+
"See https://developers.cloudflare.com/workers/platform/compatibility-dates for more information."
|
|
2786
|
+
);
|
|
2787
|
+
}
|
|
2788
|
+
return compatibilityDate ?? currentDate;
|
|
2789
|
+
}
|