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