wrangler 0.0.13 → 0.0.17
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 +20 -11
- package/pages/functions/buildWorker.ts +1 -1
- package/pages/functions/filepath-routing.test.ts +112 -28
- package/pages/functions/filepath-routing.ts +44 -51
- package/pages/functions/routes.ts +11 -18
- package/pages/functions/template-worker.ts +3 -9
- package/src/__tests__/dev.test.tsx +42 -5
- package/src/__tests__/guess-worker-format.test.ts +66 -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 +30 -0
- package/src/__tests__/helpers/mock-bin.ts +36 -0
- package/src/__tests__/{mock-cfetch.ts → helpers/mock-cfetch.ts} +43 -9
- package/src/__tests__/helpers/mock-console.ts +62 -0
- package/src/__tests__/{mock-dialogs.ts → helpers/mock-dialogs.ts} +1 -1
- package/src/__tests__/helpers/mock-kv.ts +40 -0
- package/src/__tests__/helpers/mock-user.ts +27 -0
- package/src/__tests__/helpers/mock-web-socket.ts +37 -0
- package/src/__tests__/{run-in-tmp.ts → helpers/run-in-tmp.ts} +1 -1
- package/src/__tests__/helpers/run-wrangler.ts +16 -0
- package/src/__tests__/helpers/write-wrangler-toml.ts +20 -0
- package/src/__tests__/index.test.ts +418 -71
- package/src/__tests__/jest.setup.ts +30 -2
- package/src/__tests__/kv.test.ts +147 -252
- package/src/__tests__/logout.test.ts +50 -0
- package/src/__tests__/package-manager.test.ts +206 -0
- package/src/__tests__/publish.test.ts +1136 -291
- package/src/__tests__/r2.test.ts +206 -0
- package/src/__tests__/secret.test.ts +210 -0
- package/src/__tests__/sentry.test.ts +146 -0
- package/src/__tests__/tail.test.ts +246 -0
- package/src/__tests__/whoami.test.tsx +6 -47
- package/src/api/form_data.ts +75 -25
- package/src/api/preview.ts +2 -2
- package/src/api/worker.ts +34 -15
- package/src/bundle.ts +127 -0
- package/src/cfetch/index.ts +7 -15
- package/src/cfetch/internal.ts +41 -6
- package/src/cli.ts +10 -0
- package/src/config.ts +125 -95
- package/src/dev.tsx +300 -193
- package/src/dialogs.tsx +2 -2
- package/src/guess-worker-format.ts +68 -0
- package/src/index.tsx +578 -192
- package/src/inspect.ts +29 -10
- package/src/kv.tsx +23 -17
- package/src/module-collection.ts +32 -12
- package/src/open-in-browser.ts +13 -0
- package/src/package-manager.ts +120 -0
- package/src/pages.tsx +28 -23
- package/src/paths.ts +26 -0
- package/src/proxy.ts +88 -14
- package/src/publish.ts +260 -297
- package/src/r2.ts +50 -0
- package/src/reporting.ts +115 -0
- package/src/sites.tsx +28 -27
- package/src/tail.tsx +178 -9
- package/src/user.tsx +58 -44
- 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/wrangler-dist/cli.js +124315 -104677
- package/wrangler-dist/cli.js.map +3 -3
- package/src/__tests__/mock-console.ts +0 -34
- package/src/__tests__/run-wrangler.ts +0 -8
package/src/index.tsx
CHANGED
|
@@ -1,25 +1,19 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import { readFile, 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";
|
|
2
7
|
import { render } from "ink";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
8
|
+
import React from "react";
|
|
9
|
+
import onExit from "signal-exit";
|
|
5
10
|
import makeCLI from "yargs";
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
11
|
+
import { version as wranglerVersion } from "../package.json";
|
|
12
|
+
import { toFormData } from "./api/form_data";
|
|
13
|
+
import { fetchResult } from "./cfetch";
|
|
9
14
|
import { normaliseAndValidateEnvironmentsConfig } from "./config";
|
|
10
|
-
import
|
|
11
|
-
import { getAssetPaths } from "./sites";
|
|
15
|
+
import Dev from "./dev";
|
|
12
16
|
import { confirm, prompt } from "./dialogs";
|
|
13
|
-
import { version as wranglerVersion } from "../package.json";
|
|
14
|
-
import {
|
|
15
|
-
login,
|
|
16
|
-
logout,
|
|
17
|
-
listScopes,
|
|
18
|
-
initialise as initialiseUserConfig,
|
|
19
|
-
loginOrRefreshIfRequired,
|
|
20
|
-
getAccountId,
|
|
21
|
-
validateScopeKeys,
|
|
22
|
-
} from "./user";
|
|
23
17
|
import {
|
|
24
18
|
getNamespaceId,
|
|
25
19
|
listNamespaces,
|
|
@@ -29,32 +23,60 @@ import {
|
|
|
29
23
|
deleteBulkKeyValue,
|
|
30
24
|
createNamespace,
|
|
31
25
|
isValidNamespaceBinding,
|
|
26
|
+
getKeyValue,
|
|
32
27
|
} from "./kv";
|
|
33
|
-
|
|
28
|
+
import { getPackageManager } from "./package-manager";
|
|
34
29
|
import { pages } from "./pages";
|
|
35
|
-
|
|
36
|
-
import { fetchResult, fetchRaw } from "./cfetch";
|
|
37
|
-
|
|
38
30
|
import publish from "./publish";
|
|
39
|
-
import
|
|
40
|
-
import {
|
|
41
|
-
import {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
import {
|
|
31
|
+
import { createR2Bucket, deleteR2Bucket, listR2Buckets } from "./r2";
|
|
32
|
+
import { getAssetPaths } from "./sites";
|
|
33
|
+
import {
|
|
34
|
+
createTail,
|
|
35
|
+
jsonPrintLogs,
|
|
36
|
+
prettyPrintLogs,
|
|
37
|
+
translateCliFiltersToApiFilters,
|
|
38
|
+
} from "./tail";
|
|
39
|
+
import {
|
|
40
|
+
login,
|
|
41
|
+
logout,
|
|
42
|
+
listScopes,
|
|
43
|
+
initialise as initialiseUserConfig,
|
|
44
|
+
loginOrRefreshIfRequired,
|
|
45
|
+
getAccountId,
|
|
46
|
+
validateScopeKeys,
|
|
47
|
+
} from "./user";
|
|
48
48
|
import { whoami } from "./whoami";
|
|
49
49
|
|
|
50
|
+
import type { Entry } from "./bundle";
|
|
51
|
+
import type { Config } from "./config";
|
|
52
|
+
import type { TailCLIFilters } from "./tail";
|
|
53
|
+
import type { RawData } from "ws";
|
|
54
|
+
import type Yargs from "yargs";
|
|
55
|
+
|
|
50
56
|
const resetColor = "\x1b[0m";
|
|
51
57
|
const fgGreenColor = "\x1b[32m";
|
|
52
58
|
|
|
59
|
+
// a set of binding types that are known to be supported by wrangler
|
|
60
|
+
const knownBindings = [
|
|
61
|
+
"plain_text",
|
|
62
|
+
"json",
|
|
63
|
+
"kv_namespace",
|
|
64
|
+
"durable_object_namespace",
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
type ConfigPath = string | undefined;
|
|
68
|
+
|
|
69
|
+
async function findWranglerToml(
|
|
70
|
+
referencePath: string = process.cwd()
|
|
71
|
+
): Promise<ConfigPath> {
|
|
72
|
+
const configPath = await findUp("wrangler.toml", { cwd: referencePath });
|
|
73
|
+
return configPath;
|
|
74
|
+
}
|
|
75
|
+
|
|
53
76
|
async function readConfig(configPath?: string): Promise<Config> {
|
|
54
77
|
const config: Config = {};
|
|
55
78
|
if (!configPath) {
|
|
56
|
-
configPath = await
|
|
57
|
-
// TODO - terminate this early instead of going all the way to the root
|
|
79
|
+
configPath = await findWranglerToml();
|
|
58
80
|
}
|
|
59
81
|
|
|
60
82
|
if (configPath) {
|
|
@@ -65,21 +87,108 @@ async function readConfig(configPath?: string): Promise<Config> {
|
|
|
65
87
|
|
|
66
88
|
normaliseAndValidateEnvironmentsConfig(config);
|
|
67
89
|
|
|
90
|
+
// The field "experimental_services" doesn't exist anymore
|
|
91
|
+
// in the config, but we still want to error about any older usage.
|
|
92
|
+
// TODO: remove this error before GA.
|
|
68
93
|
if ("experimental_services" in config) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
`The "experimental_services" field is no longer supported. Instead, use [[unsafe.bindings]] to enable experimental features. Add this to your wrangler.toml:
|
|
96
|
+
|
|
97
|
+
${TOML.stringify({
|
|
98
|
+
unsafe: {
|
|
99
|
+
bindings: (config.experimental_services || []).map((serviceDefinition) => {
|
|
100
|
+
return {
|
|
101
|
+
name: serviceDefinition.name,
|
|
102
|
+
type: "service",
|
|
103
|
+
service: serviceDefinition.service,
|
|
104
|
+
environment: serviceDefinition.environment,
|
|
105
|
+
};
|
|
106
|
+
}),
|
|
107
|
+
},
|
|
108
|
+
})}`
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (configPath && "wasm_modules" in config) {
|
|
113
|
+
// rewrite wasm_module paths to be absolute
|
|
114
|
+
const modules: Record<string, string> = {};
|
|
115
|
+
for (const [name, filePath] of Object.entries(config.wasm_modules || {})) {
|
|
116
|
+
modules[name] = path.relative(
|
|
117
|
+
process.cwd(),
|
|
118
|
+
path.join(path.dirname(configPath), filePath)
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
config.wasm_modules = modules;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if ("unsafe" in config) {
|
|
69
125
|
console.warn(
|
|
70
|
-
"
|
|
126
|
+
"'unsafe' fields are experimental and may change or break at any time."
|
|
71
127
|
);
|
|
72
128
|
}
|
|
73
129
|
|
|
74
130
|
// todo: validate, add defaults
|
|
75
131
|
// let's just do some basics for now
|
|
76
132
|
|
|
77
|
-
|
|
133
|
+
for (const binding of config.unsafe?.bindings ?? []) {
|
|
134
|
+
if (knownBindings.includes(binding.type)) {
|
|
135
|
+
console.warn(
|
|
136
|
+
`Raw '${binding.type}' bindings are not directly supported by wrangler. Consider migrating to a ` +
|
|
137
|
+
`format for '${binding.type}' bindings that is supported by wrangler for optimal support: ` +
|
|
138
|
+
"https://developers.cloudflare.com/workers/cli-wrangler/configuration"
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// @ts-expect-error we're being sneaky here
|
|
78
144
|
config.__path__ = configPath;
|
|
79
145
|
|
|
80
146
|
return config;
|
|
81
147
|
}
|
|
82
148
|
|
|
149
|
+
function getEntry(
|
|
150
|
+
args: { _: (string | number)[]; script: string | undefined },
|
|
151
|
+
config: Config
|
|
152
|
+
): Entry {
|
|
153
|
+
// @ts-expect-error a hidden field
|
|
154
|
+
const wranglerTomlPath = config.__path__;
|
|
155
|
+
let file: string;
|
|
156
|
+
let directory = process.cwd();
|
|
157
|
+
if (args.script) {
|
|
158
|
+
// If the script name comes from the command line it is relative to the current working directory.
|
|
159
|
+
file = path.resolve(args.script);
|
|
160
|
+
} else {
|
|
161
|
+
// If the script name comes from the config, then it is relative to the wrangler.toml file.
|
|
162
|
+
if (config.build?.upload?.main === undefined) {
|
|
163
|
+
throw new Error(
|
|
164
|
+
`Missing entry-point: The entry-point should be specified via the command line (e.g. \`wrangler ${args._[0]} path/to/script\`) or the \`build.upload.main\` config field.`
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
directory = path.resolve(
|
|
168
|
+
path.dirname(wranglerTomlPath),
|
|
169
|
+
config.build.upload.dir || ""
|
|
170
|
+
);
|
|
171
|
+
file = path.resolve(directory, config.build.upload.main);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (!config.build?.command) {
|
|
175
|
+
let fileExists = false;
|
|
176
|
+
try {
|
|
177
|
+
// Use require.resolve to use node's resolution algorithm,
|
|
178
|
+
// this lets us use paths without explicit .js extension
|
|
179
|
+
// TODO: we should probably remove this, because it doesn't
|
|
180
|
+
// take into consideration other extensions like .tsx, .ts, .jsx, etc
|
|
181
|
+
fileExists = fs.existsSync(require.resolve(file));
|
|
182
|
+
} catch (e) {
|
|
183
|
+
// fail silently, usually means require.resolve threw MODULE_NOT_FOUND
|
|
184
|
+
}
|
|
185
|
+
if (fileExists === false) {
|
|
186
|
+
throw new Error(`Could not resolve "${file}".`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return { file, directory };
|
|
190
|
+
}
|
|
191
|
+
|
|
83
192
|
// a helper to demand one of a set of options
|
|
84
193
|
// via https://github.com/yargs/yargs/issues/1093#issuecomment-491299261
|
|
85
194
|
function demandOneOfOption(...options: string[]) {
|
|
@@ -176,10 +285,16 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
176
285
|
"init [name]",
|
|
177
286
|
"📥 Create a wrangler.toml configuration file",
|
|
178
287
|
(yargs) => {
|
|
179
|
-
return yargs
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
288
|
+
return yargs
|
|
289
|
+
.positional("name", {
|
|
290
|
+
describe: "The name of your worker.",
|
|
291
|
+
type: "string",
|
|
292
|
+
})
|
|
293
|
+
.option("yes", {
|
|
294
|
+
describe: 'Answer "yes" to any prompts for new projects.',
|
|
295
|
+
type: "boolean",
|
|
296
|
+
alias: "y",
|
|
297
|
+
});
|
|
183
298
|
},
|
|
184
299
|
async (args) => {
|
|
185
300
|
if ("type" in args) {
|
|
@@ -192,7 +307,9 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
192
307
|
throw new CommandLineArgsError(message);
|
|
193
308
|
}
|
|
194
309
|
|
|
195
|
-
const
|
|
310
|
+
const packageManager = await getPackageManager(process.cwd());
|
|
311
|
+
|
|
312
|
+
const destination = "./wrangler.toml";
|
|
196
313
|
if (fs.existsSync(destination)) {
|
|
197
314
|
console.warn(`${destination} file already exists!`);
|
|
198
315
|
const shouldContinue = await confirm(
|
|
@@ -206,41 +323,48 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
206
323
|
try {
|
|
207
324
|
await writeFile(
|
|
208
325
|
destination,
|
|
209
|
-
|
|
326
|
+
TOML.stringify({
|
|
327
|
+
name: args.name || path.basename(path.resolve(process.cwd())),
|
|
328
|
+
compatibility_date: compatibilityDate,
|
|
329
|
+
}) + "\n"
|
|
210
330
|
);
|
|
211
331
|
console.log(`✨ Successfully created wrangler.toml`);
|
|
212
332
|
// TODO: suggest next steps?
|
|
213
333
|
} catch (err) {
|
|
214
334
|
throw new Error(
|
|
215
|
-
`Failed to create wrangler.toml.\n${err.message ?? err}`
|
|
335
|
+
`Failed to create wrangler.toml.\n${(err as Error).message ?? err}`
|
|
216
336
|
);
|
|
217
337
|
}
|
|
218
338
|
}
|
|
219
339
|
|
|
220
340
|
let pathToPackageJson = await findUp("package.json");
|
|
341
|
+
let shouldCreatePackageJson = false;
|
|
342
|
+
const yesFlag = args.yes ?? false;
|
|
221
343
|
if (!pathToPackageJson) {
|
|
222
344
|
// If no package.json exists, ask to create one
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
345
|
+
shouldCreatePackageJson =
|
|
346
|
+
yesFlag ||
|
|
347
|
+
(await confirm(
|
|
348
|
+
"No package.json found. Would you like to create one?"
|
|
349
|
+
));
|
|
350
|
+
|
|
226
351
|
if (shouldCreatePackageJson) {
|
|
227
352
|
await writeFile(
|
|
228
|
-
|
|
353
|
+
"./package.json",
|
|
229
354
|
JSON.stringify(
|
|
230
355
|
{
|
|
231
|
-
name:
|
|
232
|
-
version: "0.0.
|
|
356
|
+
name: args.name || path.basename(path.resolve(process.cwd())),
|
|
357
|
+
version: "0.0.0",
|
|
233
358
|
devDependencies: {
|
|
234
359
|
wrangler: wranglerVersion,
|
|
235
360
|
},
|
|
361
|
+
private: true,
|
|
236
362
|
},
|
|
237
363
|
null,
|
|
238
364
|
" "
|
|
239
365
|
) + "\n"
|
|
240
366
|
);
|
|
241
|
-
await
|
|
242
|
-
stdio: "inherit",
|
|
243
|
-
});
|
|
367
|
+
await packageManager.install();
|
|
244
368
|
console.log(`✨ Created package.json`);
|
|
245
369
|
pathToPackageJson = path.join(process.cwd(), "package.json");
|
|
246
370
|
} else {
|
|
@@ -258,47 +382,38 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
258
382
|
packageJson.dependencies?.wrangler
|
|
259
383
|
)
|
|
260
384
|
) {
|
|
261
|
-
const shouldInstall =
|
|
262
|
-
|
|
263
|
-
|
|
385
|
+
const shouldInstall =
|
|
386
|
+
yesFlag ||
|
|
387
|
+
(await confirm(
|
|
388
|
+
"Would you like to install wrangler into your package.json?"
|
|
389
|
+
));
|
|
264
390
|
if (shouldInstall) {
|
|
265
|
-
await
|
|
266
|
-
"npm",
|
|
267
|
-
[
|
|
268
|
-
"install",
|
|
269
|
-
`wrangler@${wranglerVersion}`,
|
|
270
|
-
"--save-dev",
|
|
271
|
-
"--prefer-offline",
|
|
272
|
-
],
|
|
273
|
-
{
|
|
274
|
-
stdio: "inherit",
|
|
275
|
-
}
|
|
276
|
-
);
|
|
391
|
+
await packageManager.addDevDeps(`wrangler@${wranglerVersion}`);
|
|
277
392
|
console.log(`✨ Installed wrangler`);
|
|
278
393
|
}
|
|
279
394
|
}
|
|
280
395
|
}
|
|
281
396
|
|
|
397
|
+
let isTypescriptProject = false;
|
|
282
398
|
let pathToTSConfig = await findUp("tsconfig.json");
|
|
283
399
|
if (!pathToTSConfig) {
|
|
284
400
|
// If there's no tsconfig, offer to create one
|
|
285
401
|
// and install @cloudflare/workers-types
|
|
286
|
-
if (await confirm("Would you like to use
|
|
402
|
+
if (yesFlag || (await confirm("Would you like to use TypeScript?"))) {
|
|
403
|
+
isTypescriptProject = true;
|
|
287
404
|
await writeFile(
|
|
288
|
-
|
|
405
|
+
"./tsconfig.json",
|
|
289
406
|
JSON.stringify(
|
|
290
407
|
{
|
|
291
408
|
compilerOptions: {
|
|
292
|
-
target: "
|
|
293
|
-
module: "
|
|
409
|
+
target: "es2021",
|
|
410
|
+
module: "es2022",
|
|
294
411
|
moduleResolution: "node",
|
|
295
|
-
esModuleInterop: true,
|
|
296
412
|
allowJs: true,
|
|
297
413
|
allowSyntheticDefaultImports: true,
|
|
298
414
|
isolatedModules: true,
|
|
299
415
|
noEmit: true,
|
|
300
|
-
lib: ["
|
|
301
|
-
jsx: "react",
|
|
416
|
+
lib: ["es2021"],
|
|
302
417
|
resolveJsonModule: true,
|
|
303
418
|
types: ["@cloudflare/workers-types"],
|
|
304
419
|
},
|
|
@@ -307,22 +422,18 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
307
422
|
" "
|
|
308
423
|
) + "\n"
|
|
309
424
|
);
|
|
310
|
-
await
|
|
311
|
-
"
|
|
312
|
-
|
|
313
|
-
"install",
|
|
314
|
-
"@cloudflare/workers-types",
|
|
315
|
-
"--save-dev",
|
|
316
|
-
"--prefer-offline",
|
|
317
|
-
],
|
|
318
|
-
{ stdio: "inherit" }
|
|
425
|
+
await packageManager.addDevDeps(
|
|
426
|
+
"@cloudflare/workers-types",
|
|
427
|
+
"typescript"
|
|
319
428
|
);
|
|
429
|
+
|
|
320
430
|
console.log(
|
|
321
431
|
`✨ Created tsconfig.json, installed @cloudflare/workers-types into devDependencies`
|
|
322
432
|
);
|
|
323
433
|
pathToTSConfig = path.join(process.cwd(), "tsconfig.json");
|
|
324
434
|
}
|
|
325
435
|
} else {
|
|
436
|
+
isTypescriptProject = true;
|
|
326
437
|
// If there's a tsconfig, check if @cloudflare/workers-types
|
|
327
438
|
// is already installed, and offer to install it if not
|
|
328
439
|
const packageJson = JSON.parse(
|
|
@@ -338,18 +449,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
338
449
|
"Would you like to install the type definitions for Workers into your package.json?"
|
|
339
450
|
);
|
|
340
451
|
if (shouldInstall) {
|
|
341
|
-
await
|
|
342
|
-
"npm",
|
|
343
|
-
[
|
|
344
|
-
"install",
|
|
345
|
-
"@cloudflare/workers-types",
|
|
346
|
-
"--save-dev",
|
|
347
|
-
"--prefer-offline",
|
|
348
|
-
],
|
|
349
|
-
{
|
|
350
|
-
stdio: "inherit",
|
|
351
|
-
}
|
|
352
|
-
);
|
|
452
|
+
await packageManager.addDevDeps("@cloudflare/workers-types");
|
|
353
453
|
// We don't update the tsconfig.json because
|
|
354
454
|
// it could be complicated in existing projects
|
|
355
455
|
// and we don't want to break them. Instead, we simply
|
|
@@ -357,8 +457,102 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
357
457
|
console.log(
|
|
358
458
|
`✨ Installed @cloudflare/workers-types.\nPlease add "@cloudflare/workers-types" to compilerOptions.types in your tsconfig.json`
|
|
359
459
|
);
|
|
360
|
-
}
|
|
361
|
-
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const packageJsonContent = JSON.parse(
|
|
465
|
+
await readFile(pathToPackageJson, "utf-8")
|
|
466
|
+
);
|
|
467
|
+
const shouldWritePackageJsonScripts =
|
|
468
|
+
!packageJsonContent.scripts?.start &&
|
|
469
|
+
!packageJsonContent.scripts?.deploy &&
|
|
470
|
+
shouldCreatePackageJson;
|
|
471
|
+
async function writePackageJsonScripts(
|
|
472
|
+
isWritingScripts: boolean,
|
|
473
|
+
packagePath: string,
|
|
474
|
+
scriptPath: string
|
|
475
|
+
) {
|
|
476
|
+
if (isWritingScripts) {
|
|
477
|
+
await writeFile(
|
|
478
|
+
packagePath,
|
|
479
|
+
JSON.stringify(
|
|
480
|
+
{
|
|
481
|
+
...packageJsonContent,
|
|
482
|
+
scripts: {
|
|
483
|
+
...packageJsonContent.scripts,
|
|
484
|
+
start: `wrangler dev ${scriptPath}`,
|
|
485
|
+
deploy: `wrangler publish ${scriptPath}`,
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
null,
|
|
489
|
+
" "
|
|
490
|
+
) + "\n"
|
|
491
|
+
);
|
|
492
|
+
console.log(`To start developing on your worker, run npm start.`);
|
|
493
|
+
console.log(
|
|
494
|
+
`To publish your worker on to the internet, run npm run deploy.`
|
|
495
|
+
);
|
|
496
|
+
} else {
|
|
497
|
+
console.log(
|
|
498
|
+
`To start developing on your worker, npx wrangler dev ${scriptPath}`
|
|
499
|
+
);
|
|
500
|
+
console.log(
|
|
501
|
+
`To publish your worker on to the internet, npx wrangler publish ${scriptPath}`
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
if (isTypescriptProject) {
|
|
506
|
+
if (!fs.existsSync("./src/index.ts")) {
|
|
507
|
+
let shouldCreateSource = false;
|
|
508
|
+
|
|
509
|
+
shouldCreateSource =
|
|
510
|
+
yesFlag ||
|
|
511
|
+
(await confirm(
|
|
512
|
+
`Would you like to create a Worker at src/index.ts?`
|
|
513
|
+
));
|
|
514
|
+
|
|
515
|
+
if (shouldCreateSource) {
|
|
516
|
+
await mkdir("./src", { recursive: true });
|
|
517
|
+
await writeFile(
|
|
518
|
+
"./src/index.ts",
|
|
519
|
+
await readFile(
|
|
520
|
+
path.join(__dirname, "../templates/new-worker.ts"),
|
|
521
|
+
"utf-8"
|
|
522
|
+
)
|
|
523
|
+
);
|
|
524
|
+
|
|
525
|
+
await writePackageJsonScripts(
|
|
526
|
+
shouldWritePackageJsonScripts,
|
|
527
|
+
pathToPackageJson,
|
|
528
|
+
"src/index.ts"
|
|
529
|
+
);
|
|
530
|
+
|
|
531
|
+
console.log(`✨ Created src/index.ts`);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
} else {
|
|
535
|
+
if (!fs.existsSync("./src/index.js")) {
|
|
536
|
+
const shouldCreateSource = await confirm(
|
|
537
|
+
`Would you like to create a Worker at src/index.js?`
|
|
538
|
+
);
|
|
539
|
+
if (shouldCreateSource) {
|
|
540
|
+
await mkdir("./src", { recursive: true });
|
|
541
|
+
await writeFile(
|
|
542
|
+
path.join("./src/index.js"),
|
|
543
|
+
await readFile(
|
|
544
|
+
path.join(__dirname, "../templates/new-worker.js"),
|
|
545
|
+
"utf-8"
|
|
546
|
+
)
|
|
547
|
+
);
|
|
548
|
+
|
|
549
|
+
await writePackageJsonScripts(
|
|
550
|
+
shouldWritePackageJsonScripts,
|
|
551
|
+
pathToPackageJson,
|
|
552
|
+
"src/index.js"
|
|
553
|
+
);
|
|
554
|
+
|
|
555
|
+
console.log(`✨ Created src/index.js`);
|
|
362
556
|
}
|
|
363
557
|
}
|
|
364
558
|
}
|
|
@@ -467,14 +661,13 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
467
661
|
|
|
468
662
|
// dev
|
|
469
663
|
wrangler.command(
|
|
470
|
-
"dev
|
|
664
|
+
"dev [script]",
|
|
471
665
|
"👂 Start a local server for developing your worker",
|
|
472
666
|
(yargs) => {
|
|
473
667
|
return yargs
|
|
474
|
-
.positional("
|
|
668
|
+
.positional("script", {
|
|
475
669
|
describe: "entry point",
|
|
476
670
|
type: "string",
|
|
477
|
-
demandOption: true,
|
|
478
671
|
})
|
|
479
672
|
.option("name", {
|
|
480
673
|
describe: "name of the script",
|
|
@@ -556,11 +749,18 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
556
749
|
.option("jsx-fragment", {
|
|
557
750
|
describe: "The function that is called for each JSX fragment",
|
|
558
751
|
type: "string",
|
|
752
|
+
})
|
|
753
|
+
.option("experimental-enable-local-persistence", {
|
|
754
|
+
describe: "Enable persistence for this session (only for local mode)",
|
|
755
|
+
type: "boolean",
|
|
559
756
|
});
|
|
560
757
|
},
|
|
561
758
|
async (args) => {
|
|
562
|
-
const
|
|
563
|
-
|
|
759
|
+
const config = await readConfig(
|
|
760
|
+
(args.config as ConfigPath) ||
|
|
761
|
+
(args.script && (await findWranglerToml(path.dirname(args.script))))
|
|
762
|
+
);
|
|
763
|
+
const entry = getEntry(args, config);
|
|
564
764
|
|
|
565
765
|
if (args["experimental-public"]) {
|
|
566
766
|
console.warn(
|
|
@@ -617,12 +817,16 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
617
817
|
const { waitUntilExit } = render(
|
|
618
818
|
<Dev
|
|
619
819
|
name={args.name || config.name}
|
|
620
|
-
entry={
|
|
820
|
+
entry={entry}
|
|
821
|
+
env={args.env}
|
|
621
822
|
buildCommand={config.build || {}}
|
|
622
|
-
format={format}
|
|
823
|
+
format={args.format || config.build?.upload?.format}
|
|
623
824
|
initialMode={args.local ? "local" : "remote"}
|
|
624
825
|
jsxFactory={args["jsx-factory"] || envRootObj?.jsx_factory}
|
|
625
826
|
jsxFragment={args["jsx-fragment"] || envRootObj?.jsx_fragment}
|
|
827
|
+
enableLocalPersistence={
|
|
828
|
+
args["experimental-enable-local-persistence"] || false
|
|
829
|
+
}
|
|
626
830
|
accountId={config.account_id}
|
|
627
831
|
assetPaths={getAssetPaths(
|
|
628
832
|
config,
|
|
@@ -665,8 +869,10 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
665
869
|
}
|
|
666
870
|
),
|
|
667
871
|
vars: envRootObj.vars,
|
|
872
|
+
wasm_modules: config.wasm_modules,
|
|
668
873
|
durable_objects: envRootObj.durable_objects,
|
|
669
|
-
|
|
874
|
+
r2_buckets: envRootObj.r2_buckets,
|
|
875
|
+
unsafe: envRootObj.unsafe?.bindings,
|
|
670
876
|
}}
|
|
671
877
|
/>
|
|
672
878
|
);
|
|
@@ -692,6 +898,10 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
692
898
|
describe: "name to use when uploading",
|
|
693
899
|
type: "string",
|
|
694
900
|
})
|
|
901
|
+
.option("format", {
|
|
902
|
+
choices: ["modules", "service-worker"] as const,
|
|
903
|
+
describe: "Choose an entry type",
|
|
904
|
+
})
|
|
695
905
|
.option("compatibility-date", {
|
|
696
906
|
describe: "Date to use for compatibility checks",
|
|
697
907
|
type: "string",
|
|
@@ -736,12 +946,6 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
736
946
|
alias: "route",
|
|
737
947
|
type: "array",
|
|
738
948
|
})
|
|
739
|
-
.option("services", {
|
|
740
|
-
describe: "experimental support for services",
|
|
741
|
-
type: "boolean",
|
|
742
|
-
default: "false",
|
|
743
|
-
hidden: true,
|
|
744
|
-
})
|
|
745
949
|
.option("jsx-factory", {
|
|
746
950
|
describe: "The function that is called for each JSX element",
|
|
747
951
|
type: "string",
|
|
@@ -769,7 +973,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
769
973
|
);
|
|
770
974
|
}
|
|
771
975
|
|
|
772
|
-
const config =
|
|
976
|
+
const config = await readConfig(
|
|
977
|
+
(args.config as ConfigPath) ||
|
|
978
|
+
(args.script && (await findWranglerToml(path.dirname(args.script))))
|
|
979
|
+
);
|
|
980
|
+
const entry = getEntry(args, config);
|
|
773
981
|
|
|
774
982
|
if (args.latest) {
|
|
775
983
|
console.warn(
|
|
@@ -802,9 +1010,10 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
802
1010
|
args.siteExclude
|
|
803
1011
|
);
|
|
804
1012
|
await publish({
|
|
805
|
-
config
|
|
1013
|
+
config,
|
|
806
1014
|
name: args.name,
|
|
807
|
-
|
|
1015
|
+
format: args.format || config.build?.upload?.format,
|
|
1016
|
+
entry,
|
|
808
1017
|
env: args.env,
|
|
809
1018
|
compatibilityDate: args.latest
|
|
810
1019
|
? new Date().toISOString().substring(0, 10)
|
|
@@ -815,7 +1024,6 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
815
1024
|
jsxFragment: args["jsx-fragment"],
|
|
816
1025
|
routes: args.routes,
|
|
817
1026
|
assetPaths,
|
|
818
|
-
format: undefined, // TODO: add args for this
|
|
819
1027
|
legacyEnv: undefined, // TODO: get this from somewhere... config?
|
|
820
1028
|
experimentalPublic: args["experimental-public"] !== undefined,
|
|
821
1029
|
});
|
|
@@ -842,6 +1050,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
842
1050
|
.option("status", {
|
|
843
1051
|
choices: ["ok", "error", "canceled"],
|
|
844
1052
|
describe: "Filter by invocation status",
|
|
1053
|
+
array: true,
|
|
845
1054
|
})
|
|
846
1055
|
.option("header", {
|
|
847
1056
|
type: "string",
|
|
@@ -850,6 +1059,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
850
1059
|
.option("method", {
|
|
851
1060
|
type: "string",
|
|
852
1061
|
describe: "Filter by HTTP method",
|
|
1062
|
+
array: true,
|
|
853
1063
|
})
|
|
854
1064
|
.option("sampling-rate", {
|
|
855
1065
|
type: "number",
|
|
@@ -859,12 +1069,18 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
859
1069
|
type: "string",
|
|
860
1070
|
describe: "Filter by a text match in console.log messages",
|
|
861
1071
|
})
|
|
1072
|
+
.option("ip", {
|
|
1073
|
+
type: "string",
|
|
1074
|
+
describe:
|
|
1075
|
+
'Filter by the IP address the request originates from. Use "self" to filter for your own IP',
|
|
1076
|
+
array: true,
|
|
1077
|
+
})
|
|
1078
|
+
// TODO: is this deprecated now with services / environments / etc?
|
|
862
1079
|
.option("env", {
|
|
863
1080
|
type: "string",
|
|
864
1081
|
describe: "Perform on a specific environment",
|
|
865
1082
|
})
|
|
866
1083
|
);
|
|
867
|
-
// TODO: filter by client ip, which can be 'self' or an ip address
|
|
868
1084
|
},
|
|
869
1085
|
async (args) => {
|
|
870
1086
|
if (args.local) {
|
|
@@ -873,14 +1089,13 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
873
1089
|
);
|
|
874
1090
|
}
|
|
875
1091
|
|
|
876
|
-
const config = args.config as
|
|
1092
|
+
const config = await readConfig(args.config as ConfigPath);
|
|
877
1093
|
|
|
878
|
-
|
|
1094
|
+
const shortScriptName = args.name || config.name;
|
|
1095
|
+
if (!shortScriptName) {
|
|
879
1096
|
throw new Error("Missing script name");
|
|
880
1097
|
}
|
|
881
|
-
const scriptName = `${args.
|
|
882
|
-
args.env ? `-${args.env}` : ""
|
|
883
|
-
}`;
|
|
1098
|
+
const scriptName = `${shortScriptName}${args.env ? `-${args.env}` : ""}`;
|
|
884
1099
|
|
|
885
1100
|
// -- snip, extract --
|
|
886
1101
|
const loggedIn = await loginOrRefreshIfRequired();
|
|
@@ -900,14 +1115,17 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
900
1115
|
|
|
901
1116
|
const accountId = config.account_id;
|
|
902
1117
|
|
|
903
|
-
const
|
|
904
|
-
status: args.status as "ok" | "error" | "canceled"
|
|
1118
|
+
const cliFilters: TailCLIFilters = {
|
|
1119
|
+
status: args.status as Array<"ok" | "error" | "canceled">,
|
|
905
1120
|
header: args.header,
|
|
906
1121
|
method: args.method,
|
|
907
|
-
|
|
1122
|
+
samplingRate: args["sampling-rate"],
|
|
908
1123
|
search: args.search,
|
|
1124
|
+
clientIp: args.ip,
|
|
909
1125
|
};
|
|
910
1126
|
|
|
1127
|
+
const filters = translateCliFiltersToApiFilters(cliFilters);
|
|
1128
|
+
|
|
911
1129
|
const { tail, expiration, /* sendHeartbeat, */ deleteTail } =
|
|
912
1130
|
await createTail(accountId, scriptName, filters);
|
|
913
1131
|
|
|
@@ -920,9 +1138,10 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
920
1138
|
await deleteTail();
|
|
921
1139
|
});
|
|
922
1140
|
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
1141
|
+
const printLog: (data: RawData) => void =
|
|
1142
|
+
args.format === "pretty" ? prettyPrintLogs : jsonPrintLogs;
|
|
1143
|
+
|
|
1144
|
+
tail.on("message", printLog);
|
|
926
1145
|
|
|
927
1146
|
while (tail.readyState !== tail.OPEN) {
|
|
928
1147
|
switch (tail.readyState) {
|
|
@@ -938,6 +1157,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
938
1157
|
}
|
|
939
1158
|
|
|
940
1159
|
console.log(`Connected to ${scriptName}, waiting for logs...`);
|
|
1160
|
+
|
|
1161
|
+
tail.on("close", async () => {
|
|
1162
|
+
tail.terminate();
|
|
1163
|
+
await deleteTail();
|
|
1164
|
+
});
|
|
941
1165
|
}
|
|
942
1166
|
);
|
|
943
1167
|
|
|
@@ -1003,7 +1227,8 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1003
1227
|
async (args) => {
|
|
1004
1228
|
console.log(":route list", args);
|
|
1005
1229
|
// TODO: use environment (current wrangler doesn't do so?)
|
|
1006
|
-
const
|
|
1230
|
+
const config = await readConfig(args.config as ConfigPath);
|
|
1231
|
+
const zone = args.zone || config.zone_id;
|
|
1007
1232
|
if (!zone) {
|
|
1008
1233
|
throw new Error("missing zone id");
|
|
1009
1234
|
}
|
|
@@ -1032,7 +1257,8 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1032
1257
|
async (args) => {
|
|
1033
1258
|
console.log(":route delete", args);
|
|
1034
1259
|
// TODO: use environment (current wrangler doesn't do so?)
|
|
1035
|
-
const
|
|
1260
|
+
const config = await readConfig(args.config as ConfigPath);
|
|
1261
|
+
const zone = args.zone || config.zone_id;
|
|
1036
1262
|
if (!zone) {
|
|
1037
1263
|
throw new Error("missing zone id");
|
|
1038
1264
|
}
|
|
@@ -1088,12 +1314,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1088
1314
|
});
|
|
1089
1315
|
},
|
|
1090
1316
|
async (args) => {
|
|
1091
|
-
|
|
1092
|
-
throw new NotImplementedError(
|
|
1093
|
-
"--local not implemented for this command yet"
|
|
1094
|
-
);
|
|
1095
|
-
}
|
|
1096
|
-
const config = args.config as Config;
|
|
1317
|
+
const config = await readConfig(args.config as ConfigPath);
|
|
1097
1318
|
|
|
1098
1319
|
// TODO: use environment (how does current wrangler do it?)
|
|
1099
1320
|
const scriptName = args.name || config.name;
|
|
@@ -1101,6 +1322,10 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1101
1322
|
throw new Error("Missing script name");
|
|
1102
1323
|
}
|
|
1103
1324
|
|
|
1325
|
+
if (args.local) {
|
|
1326
|
+
console.warn("`wrangler secret put` is a no-op in --local mode");
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1104
1329
|
if (!args.local) {
|
|
1105
1330
|
// -- snip, extract --
|
|
1106
1331
|
const loggedIn = await loginOrRefreshIfRequired();
|
|
@@ -1123,6 +1348,13 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1123
1348
|
"Enter a secret value:",
|
|
1124
1349
|
"password"
|
|
1125
1350
|
);
|
|
1351
|
+
|
|
1352
|
+
if (args.local) {
|
|
1353
|
+
return;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
console.log(`🌀 Creating the secret for script ${scriptName}`);
|
|
1357
|
+
|
|
1126
1358
|
async function submitSecret() {
|
|
1127
1359
|
return await fetchResult(
|
|
1128
1360
|
`/accounts/${config.account_id}/workers/scripts/${scriptName}/secrets/`,
|
|
@@ -1139,16 +1371,17 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1139
1371
|
}
|
|
1140
1372
|
|
|
1141
1373
|
try {
|
|
1142
|
-
|
|
1374
|
+
await submitSecret();
|
|
1143
1375
|
} catch (e) {
|
|
1376
|
+
// @ts-expect-error non-standard property on Error
|
|
1144
1377
|
if (e.code === 10007) {
|
|
1145
1378
|
// upload a draft worker
|
|
1146
1379
|
await fetchResult(
|
|
1147
1380
|
`/accounts/${config.account_id}/workers/scripts/${scriptName}`,
|
|
1148
1381
|
{
|
|
1149
1382
|
method: "PUT",
|
|
1150
|
-
// @ts-expect-error TODO: fix this error!
|
|
1151
1383
|
body: toFormData({
|
|
1384
|
+
name: scriptName,
|
|
1152
1385
|
main: {
|
|
1153
1386
|
name: scriptName,
|
|
1154
1387
|
content: `export default { fetch() {} }`,
|
|
@@ -1158,17 +1391,25 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1158
1391
|
kv_namespaces: [],
|
|
1159
1392
|
vars: {},
|
|
1160
1393
|
durable_objects: { bindings: [] },
|
|
1394
|
+
r2_buckets: [],
|
|
1395
|
+
wasm_modules: {},
|
|
1396
|
+
unsafe: [],
|
|
1161
1397
|
},
|
|
1162
1398
|
modules: [],
|
|
1399
|
+
migrations: undefined,
|
|
1400
|
+
compatibility_date: undefined,
|
|
1401
|
+
compatibility_flags: undefined,
|
|
1402
|
+
usage_model: undefined,
|
|
1163
1403
|
}),
|
|
1164
1404
|
}
|
|
1165
1405
|
);
|
|
1166
1406
|
|
|
1167
1407
|
// and then try again
|
|
1168
|
-
|
|
1408
|
+
await submitSecret();
|
|
1169
1409
|
// TODO: delete the draft worker if this failed too?
|
|
1170
1410
|
}
|
|
1171
1411
|
}
|
|
1412
|
+
console.log(`✨ Success! Uploaded secret ${args.key}`);
|
|
1172
1413
|
}
|
|
1173
1414
|
)
|
|
1174
1415
|
.command(
|
|
@@ -1191,12 +1432,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1191
1432
|
});
|
|
1192
1433
|
},
|
|
1193
1434
|
async (args) => {
|
|
1194
|
-
|
|
1195
|
-
throw new NotImplementedError(
|
|
1196
|
-
"--local not implemented for this command yet"
|
|
1197
|
-
);
|
|
1198
|
-
}
|
|
1199
|
-
const config = args.config as Config;
|
|
1435
|
+
const config = await readConfig(args.config as ConfigPath);
|
|
1200
1436
|
|
|
1201
1437
|
// TODO: use environment (how does current wrangler do it?)
|
|
1202
1438
|
const scriptName = args.name || config.name;
|
|
@@ -1204,6 +1440,12 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1204
1440
|
throw new Error("Missing script name");
|
|
1205
1441
|
}
|
|
1206
1442
|
|
|
1443
|
+
if (args.local) {
|
|
1444
|
+
console.warn(
|
|
1445
|
+
"`wrangler secret delete` is a no-op in --local mode"
|
|
1446
|
+
);
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1207
1449
|
if (!args.local) {
|
|
1208
1450
|
// -- snip, extract --
|
|
1209
1451
|
const loggedIn = await loginOrRefreshIfRequired();
|
|
@@ -1222,17 +1464,24 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1222
1464
|
// -- snip, end --
|
|
1223
1465
|
}
|
|
1224
1466
|
|
|
1225
|
-
if (
|
|
1467
|
+
if (
|
|
1468
|
+
await confirm(
|
|
1469
|
+
`Are you sure you want to permanently delete the variable ${args.key} on the script ${scriptName}?`
|
|
1470
|
+
)
|
|
1471
|
+
) {
|
|
1226
1472
|
console.log(
|
|
1227
|
-
|
|
1473
|
+
`🌀 Deleting the secret ${args.key} on script ${scriptName}.`
|
|
1228
1474
|
);
|
|
1229
1475
|
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1476
|
+
if (args.local) {
|
|
1477
|
+
return;
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
await fetchResult(
|
|
1481
|
+
`/accounts/${config.account_id}/workers/scripts/${scriptName}/secrets/${args.key}`,
|
|
1482
|
+
{ method: "DELETE" }
|
|
1235
1483
|
);
|
|
1484
|
+
console.log(`✨ Success! Deleted secret ${args.key}`);
|
|
1236
1485
|
}
|
|
1237
1486
|
}
|
|
1238
1487
|
)
|
|
@@ -1252,12 +1501,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1252
1501
|
});
|
|
1253
1502
|
},
|
|
1254
1503
|
async (args) => {
|
|
1255
|
-
|
|
1256
|
-
throw new NotImplementedError(
|
|
1257
|
-
"--local not implemented for this command yet"
|
|
1258
|
-
);
|
|
1259
|
-
}
|
|
1260
|
-
const config = args.config as Config;
|
|
1504
|
+
const config = await readConfig(args.config as ConfigPath);
|
|
1261
1505
|
|
|
1262
1506
|
// TODO: use environment (how does current wrangler do it?)
|
|
1263
1507
|
const scriptName = args.name || config.name;
|
|
@@ -1265,6 +1509,10 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1265
1509
|
throw new Error("Missing script name");
|
|
1266
1510
|
}
|
|
1267
1511
|
|
|
1512
|
+
if (args.local) {
|
|
1513
|
+
console.warn("`wrangler secret list` is a no-op in --local mode");
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1268
1516
|
if (!args.local) {
|
|
1269
1517
|
// -- snip, extract --
|
|
1270
1518
|
const loggedIn = await loginOrRefreshIfRequired();
|
|
@@ -1283,9 +1531,17 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1283
1531
|
// -- snip, end --
|
|
1284
1532
|
}
|
|
1285
1533
|
|
|
1534
|
+
if (args.local) {
|
|
1535
|
+
return;
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1286
1538
|
console.log(
|
|
1287
|
-
|
|
1288
|
-
|
|
1539
|
+
JSON.stringify(
|
|
1540
|
+
await fetchResult(
|
|
1541
|
+
`/accounts/${config.account_id}/workers/scripts/${scriptName}/secrets`
|
|
1542
|
+
),
|
|
1543
|
+
null,
|
|
1544
|
+
" "
|
|
1289
1545
|
)
|
|
1290
1546
|
);
|
|
1291
1547
|
}
|
|
@@ -1333,7 +1589,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1333
1589
|
);
|
|
1334
1590
|
}
|
|
1335
1591
|
|
|
1336
|
-
const config = args.config as
|
|
1592
|
+
const config = await readConfig(args.config as ConfigPath);
|
|
1337
1593
|
if (!config.name) {
|
|
1338
1594
|
console.warn(
|
|
1339
1595
|
"No configured name present, using `worker` as a prefix for the title"
|
|
@@ -1398,7 +1654,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1398
1654
|
"Outputs a list of all KV namespaces associated with your account id.",
|
|
1399
1655
|
{},
|
|
1400
1656
|
async (args) => {
|
|
1401
|
-
const config = args.config as
|
|
1657
|
+
const config = await readConfig(args.config as ConfigPath);
|
|
1402
1658
|
|
|
1403
1659
|
if (args.local) {
|
|
1404
1660
|
throw new NotImplementedError(
|
|
@@ -1457,7 +1713,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1457
1713
|
});
|
|
1458
1714
|
},
|
|
1459
1715
|
async (args) => {
|
|
1460
|
-
const config = args.config as
|
|
1716
|
+
const config = await readConfig(args.config as ConfigPath);
|
|
1461
1717
|
|
|
1462
1718
|
if (args.local) {
|
|
1463
1719
|
throw new NotImplementedError(
|
|
@@ -1466,10 +1722,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1466
1722
|
} else {
|
|
1467
1723
|
let id;
|
|
1468
1724
|
try {
|
|
1469
|
-
id = getNamespaceId(args);
|
|
1725
|
+
id = getNamespaceId(args, config);
|
|
1470
1726
|
} catch (e) {
|
|
1471
1727
|
throw new CommandLineArgsError(
|
|
1472
|
-
"Not able to delete namespace.\n" +
|
|
1728
|
+
"Not able to delete namespace.\n" +
|
|
1729
|
+
((e as Error).message ?? e)
|
|
1473
1730
|
);
|
|
1474
1731
|
}
|
|
1475
1732
|
|
|
@@ -1570,13 +1827,13 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1570
1827
|
.check(demandOneOfOption("value", "path"));
|
|
1571
1828
|
},
|
|
1572
1829
|
async ({ key, ttl, expiration, ...args }) => {
|
|
1573
|
-
const
|
|
1830
|
+
const config = await readConfig(args.config as ConfigPath);
|
|
1831
|
+
const namespaceId = getNamespaceId(args, config);
|
|
1574
1832
|
// One of `args.path` and `args.value` must be defined
|
|
1575
1833
|
const value = args.path
|
|
1576
1834
|
? await readFile(args.path, "utf-8")
|
|
1577
1835
|
: // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1578
1836
|
args.value!;
|
|
1579
|
-
const config = args.config as Config;
|
|
1580
1837
|
|
|
1581
1838
|
if (args.path) {
|
|
1582
1839
|
console.log(
|
|
@@ -1652,9 +1909,8 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1652
1909
|
},
|
|
1653
1910
|
async ({ prefix, ...args }) => {
|
|
1654
1911
|
// TODO: support for limit+cursor (pagination)
|
|
1655
|
-
|
|
1656
|
-
const namespaceId = getNamespaceId(args);
|
|
1657
|
-
const config = args.config as Config;
|
|
1912
|
+
const config = await readConfig(args.config as ConfigPath);
|
|
1913
|
+
const namespaceId = getNamespaceId(args, config);
|
|
1658
1914
|
|
|
1659
1915
|
if (args.local) {
|
|
1660
1916
|
const { Miniflare } = await import("miniflare");
|
|
@@ -1727,8 +1983,8 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1727
1983
|
});
|
|
1728
1984
|
},
|
|
1729
1985
|
async ({ key, ...args }) => {
|
|
1730
|
-
const
|
|
1731
|
-
const
|
|
1986
|
+
const config = await readConfig(args.config as ConfigPath);
|
|
1987
|
+
const namespaceId = getNamespaceId(args, config);
|
|
1732
1988
|
|
|
1733
1989
|
if (args.local) {
|
|
1734
1990
|
const { Miniflare } = await import("miniflare");
|
|
@@ -1758,13 +2014,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1758
2014
|
}
|
|
1759
2015
|
}
|
|
1760
2016
|
// -- snip, end --
|
|
1761
|
-
}
|
|
1762
2017
|
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
);
|
|
2018
|
+
console.log(
|
|
2019
|
+
await getKeyValue(config.account_id, namespaceId, key)
|
|
2020
|
+
);
|
|
2021
|
+
}
|
|
1768
2022
|
}
|
|
1769
2023
|
)
|
|
1770
2024
|
.command(
|
|
@@ -1796,7 +2050,8 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1796
2050
|
});
|
|
1797
2051
|
},
|
|
1798
2052
|
async ({ key, ...args }) => {
|
|
1799
|
-
const
|
|
2053
|
+
const config = await readConfig(args.config as ConfigPath);
|
|
2054
|
+
const namespaceId = getNamespaceId(args, config);
|
|
1800
2055
|
|
|
1801
2056
|
console.log(
|
|
1802
2057
|
`deleting the key "${key}" on namespace ${namespaceId}`
|
|
@@ -1814,8 +2069,6 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1814
2069
|
return;
|
|
1815
2070
|
}
|
|
1816
2071
|
|
|
1817
|
-
const config = args.config as Config;
|
|
1818
|
-
|
|
1819
2072
|
if (!args.local) {
|
|
1820
2073
|
// -- snip, extract --
|
|
1821
2074
|
const loggedIn = await loginOrRefreshIfRequired();
|
|
@@ -1881,16 +2134,17 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1881
2134
|
// The simplest implementation I could think of.
|
|
1882
2135
|
// This could be made more efficient with a streaming parser/uploader
|
|
1883
2136
|
// but we'll do that in the future if needed.
|
|
1884
|
-
|
|
1885
|
-
const namespaceId = getNamespaceId(args);
|
|
1886
|
-
const config = args.config as Config;
|
|
2137
|
+
const config = await readConfig(args.config as ConfigPath);
|
|
2138
|
+
const namespaceId = getNamespaceId(args, config);
|
|
1887
2139
|
const content = await readFile(filename, "utf-8");
|
|
1888
2140
|
let parsedContent;
|
|
1889
2141
|
try {
|
|
1890
2142
|
parsedContent = JSON.parse(content);
|
|
1891
2143
|
} catch (err) {
|
|
1892
2144
|
throw new Error(
|
|
1893
|
-
`Could not parse json from ${filename}.\n${
|
|
2145
|
+
`Could not parse json from ${filename}.\n${
|
|
2146
|
+
(err as Error).message ?? err
|
|
2147
|
+
}`
|
|
1894
2148
|
);
|
|
1895
2149
|
}
|
|
1896
2150
|
|
|
@@ -1965,15 +2219,18 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1965
2219
|
});
|
|
1966
2220
|
},
|
|
1967
2221
|
async ({ filename, ...args }) => {
|
|
1968
|
-
const
|
|
1969
|
-
const
|
|
2222
|
+
const config = await readConfig(args.config as ConfigPath);
|
|
2223
|
+
const namespaceId = getNamespaceId(args, config);
|
|
2224
|
+
|
|
1970
2225
|
const content = await readFile(filename, "utf-8");
|
|
1971
2226
|
let parsedContent;
|
|
1972
2227
|
try {
|
|
1973
2228
|
parsedContent = JSON.parse(content);
|
|
1974
2229
|
} catch (err) {
|
|
1975
2230
|
throw new Error(
|
|
1976
|
-
`Could not parse json from ${filename}.\n${
|
|
2231
|
+
`Could not parse json from ${filename}.\n${
|
|
2232
|
+
(err as Error).message ?? err
|
|
2233
|
+
}`
|
|
1977
2234
|
);
|
|
1978
2235
|
}
|
|
1979
2236
|
|
|
@@ -2020,14 +2277,144 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2020
2277
|
|
|
2021
2278
|
wrangler.command("pages", "⚡️ Configure Cloudflare Pages", pages);
|
|
2022
2279
|
|
|
2280
|
+
wrangler.command("r2", "📦 Interact with an R2 store", (r2Yargs) => {
|
|
2281
|
+
return r2Yargs.command("bucket", "Manage R2 buckets", (r2BucketYargs) => {
|
|
2282
|
+
r2BucketYargs.command(
|
|
2283
|
+
"create <name>",
|
|
2284
|
+
"Create a new R2 bucket",
|
|
2285
|
+
(yargs) => {
|
|
2286
|
+
return yargs.positional("name", {
|
|
2287
|
+
describe: "The name of the new bucket",
|
|
2288
|
+
type: "string",
|
|
2289
|
+
demandOption: true,
|
|
2290
|
+
});
|
|
2291
|
+
},
|
|
2292
|
+
async (args) => {
|
|
2293
|
+
// We expect three values in `_`: `r2`, `bucket`, `create`.
|
|
2294
|
+
if (args._.length > 3) {
|
|
2295
|
+
const extraArgs = args._.slice(3).join(" ");
|
|
2296
|
+
throw new CommandLineArgsError(
|
|
2297
|
+
`Unexpected additional positional arguments "${extraArgs}".`
|
|
2298
|
+
);
|
|
2299
|
+
}
|
|
2300
|
+
|
|
2301
|
+
const config = await readConfig(args.config as ConfigPath);
|
|
2302
|
+
|
|
2303
|
+
if (args.local) {
|
|
2304
|
+
throw new NotImplementedError(
|
|
2305
|
+
`local mode is not yet supported for this command`
|
|
2306
|
+
);
|
|
2307
|
+
} else {
|
|
2308
|
+
// -- snip, extract --
|
|
2309
|
+
const loggedIn = await loginOrRefreshIfRequired();
|
|
2310
|
+
if (!loggedIn) {
|
|
2311
|
+
// didn't login, let's just quit
|
|
2312
|
+
console.log("Did not login, quitting...");
|
|
2313
|
+
return;
|
|
2314
|
+
}
|
|
2315
|
+
|
|
2316
|
+
if (!config.account_id) {
|
|
2317
|
+
config.account_id = await getAccountId();
|
|
2318
|
+
if (!config.account_id) {
|
|
2319
|
+
throw new Error("No account id found, quitting...");
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2322
|
+
// -- snip, end --
|
|
2323
|
+
|
|
2324
|
+
console.log(`Creating bucket ${args.name}.`);
|
|
2325
|
+
await createR2Bucket(config.account_id, args.name);
|
|
2326
|
+
console.log(`Created bucket ${args.name}.`);
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
);
|
|
2330
|
+
|
|
2331
|
+
r2BucketYargs.command("list", "List R2 buckets", {}, async (args) => {
|
|
2332
|
+
const config = await readConfig(args.config as ConfigPath);
|
|
2333
|
+
|
|
2334
|
+
if (args.local) {
|
|
2335
|
+
throw new NotImplementedError(
|
|
2336
|
+
`local mode is not yet supported for this command`
|
|
2337
|
+
);
|
|
2338
|
+
} else {
|
|
2339
|
+
// -- snip, extract --
|
|
2340
|
+
const loggedIn = await loginOrRefreshIfRequired();
|
|
2341
|
+
if (!loggedIn) {
|
|
2342
|
+
// didn't login, let's just quit
|
|
2343
|
+
console.log("Did not login, quitting...");
|
|
2344
|
+
return;
|
|
2345
|
+
}
|
|
2346
|
+
|
|
2347
|
+
if (!config.account_id) {
|
|
2348
|
+
config.account_id = await getAccountId();
|
|
2349
|
+
if (!config.account_id) {
|
|
2350
|
+
throw new Error("No account id found, quitting...");
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
// -- snip, end --
|
|
2354
|
+
|
|
2355
|
+
console.log(
|
|
2356
|
+
JSON.stringify(await listR2Buckets(config.account_id), null, 2)
|
|
2357
|
+
);
|
|
2358
|
+
}
|
|
2359
|
+
});
|
|
2360
|
+
|
|
2361
|
+
r2BucketYargs.command(
|
|
2362
|
+
"delete <name>",
|
|
2363
|
+
"Delete an R2 bucket",
|
|
2364
|
+
(yargs) => {
|
|
2365
|
+
return yargs.positional("name", {
|
|
2366
|
+
describe: "The name of the bucket to delete",
|
|
2367
|
+
type: "string",
|
|
2368
|
+
demandOption: true,
|
|
2369
|
+
});
|
|
2370
|
+
},
|
|
2371
|
+
async (args) => {
|
|
2372
|
+
// We expect three values in `_`: `r2`, `bucket`, `delete`.
|
|
2373
|
+
if (args._.length > 3) {
|
|
2374
|
+
const extraArgs = args._.slice(3).join(" ");
|
|
2375
|
+
throw new CommandLineArgsError(
|
|
2376
|
+
`Unexpected additional positional arguments "${extraArgs}".`
|
|
2377
|
+
);
|
|
2378
|
+
}
|
|
2379
|
+
|
|
2380
|
+
const config = await readConfig(args.config as ConfigPath);
|
|
2381
|
+
|
|
2382
|
+
if (args.local) {
|
|
2383
|
+
throw new NotImplementedError(
|
|
2384
|
+
`local mode is not yet supported for this command`
|
|
2385
|
+
);
|
|
2386
|
+
} else {
|
|
2387
|
+
// -- snip, extract --
|
|
2388
|
+
const loggedIn = await loginOrRefreshIfRequired();
|
|
2389
|
+
if (!loggedIn) {
|
|
2390
|
+
// didn't login, let's just quit
|
|
2391
|
+
console.log("Did not login, quitting...");
|
|
2392
|
+
return;
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
if (!config.account_id) {
|
|
2396
|
+
config.account_id = await getAccountId();
|
|
2397
|
+
if (!config.account_id) {
|
|
2398
|
+
throw new Error("No account id found, quitting...");
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
// -- snip, end --
|
|
2402
|
+
|
|
2403
|
+
console.log(`Deleting bucket ${args.name}.`);
|
|
2404
|
+
await deleteR2Bucket(config.account_id, args.name);
|
|
2405
|
+
console.log(`Deleted bucket ${args.name}.`);
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
);
|
|
2409
|
+
return r2BucketYargs;
|
|
2410
|
+
});
|
|
2411
|
+
});
|
|
2412
|
+
|
|
2023
2413
|
wrangler
|
|
2024
2414
|
.option("config", {
|
|
2025
2415
|
alias: "c",
|
|
2026
2416
|
describe: "Path to .toml configuration file",
|
|
2027
2417
|
type: "string",
|
|
2028
|
-
async coerce(arg) {
|
|
2029
|
-
return await readConfig(arg);
|
|
2030
|
-
},
|
|
2031
2418
|
})
|
|
2032
2419
|
.option("local", {
|
|
2033
2420
|
alias: "l",
|
|
@@ -2041,9 +2428,8 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2041
2428
|
wrangler.version(wranglerVersion).alias("v", "version");
|
|
2042
2429
|
wrangler.exitProcess(false);
|
|
2043
2430
|
|
|
2044
|
-
await initialiseUserConfig();
|
|
2045
|
-
|
|
2046
2431
|
try {
|
|
2432
|
+
await initialiseUserConfig();
|
|
2047
2433
|
await wrangler.parse();
|
|
2048
2434
|
} catch (e) {
|
|
2049
2435
|
if (e instanceof CommandLineArgsError) {
|
|
@@ -2051,7 +2437,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2051
2437
|
console.error(""); // Just adds a bit of space
|
|
2052
2438
|
console.error(e.message);
|
|
2053
2439
|
} else {
|
|
2054
|
-
console.error(e.message);
|
|
2440
|
+
console.error(e instanceof Error ? e.message : e);
|
|
2055
2441
|
console.error(""); // Just adds a bit of space
|
|
2056
2442
|
console.error(
|
|
2057
2443
|
`${fgGreenColor}%s${resetColor}`,
|