wrangler 0.0.0-ece06ea → 0.0.0-ecef68635
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -15
- package/bin/wrangler.js +94 -31
- package/config-schema.json +3074 -0
- package/kv-asset-handler.js +1 -0
- package/package.json +155 -75
- package/templates/__tests__/pages-dev-util.test.ts +128 -0
- package/templates/__tests__/tsconfig-sanity.ts +12 -0
- package/templates/__tests__/tsconfig.json +8 -0
- package/templates/checked-fetch.js +30 -0
- package/templates/facade.d.ts +19 -0
- package/templates/gitignore +170 -0
- package/templates/init-tests/test-jest-new-worker.js +23 -0
- package/templates/init-tests/test-vitest-new-worker.js +24 -0
- package/templates/init-tests/test-vitest-new-worker.ts +25 -0
- package/templates/middleware/common.ts +67 -0
- package/templates/middleware/loader-modules.ts +134 -0
- package/templates/middleware/loader-sw.ts +229 -0
- package/templates/middleware/middleware-ensure-req-body-drained.ts +18 -0
- package/templates/middleware/middleware-miniflare3-json-error.ts +32 -0
- package/templates/middleware/middleware-mock-analytics-engine.d.ts +3 -0
- package/templates/middleware/middleware-mock-analytics-engine.ts +30 -0
- package/templates/middleware/middleware-pretty-error.ts +40 -0
- package/templates/middleware/middleware-scheduled.ts +29 -0
- package/templates/middleware/middleware-serve-static-assets.d.ts +6 -0
- package/templates/middleware/middleware-serve-static-assets.ts +56 -0
- package/templates/modules-watch-stub.js +4 -0
- package/templates/new-worker-scheduled.js +17 -0
- package/templates/new-worker-scheduled.ts +32 -0
- package/templates/new-worker.js +15 -0
- package/templates/new-worker.ts +33 -0
- package/templates/no-op-worker.js +10 -0
- package/templates/pages-dev-pipeline.ts +32 -0
- package/templates/pages-dev-util.ts +55 -0
- package/templates/pages-shim.ts +9 -0
- package/templates/pages-template-plugin.ts +190 -0
- package/templates/pages-template-worker.ts +198 -0
- package/templates/startDevWorker/InspectorProxyWorker.ts +664 -0
- package/templates/startDevWorker/ProxyWorker.ts +336 -0
- package/templates/tsconfig-sanity.ts +11 -0
- package/templates/tsconfig.init.json +22 -0
- package/templates/tsconfig.json +8 -0
- package/wrangler-dist/InspectorProxyWorker.js +464 -0
- package/wrangler-dist/InspectorProxyWorker.js.map +6 -0
- package/wrangler-dist/ProxyWorker.js +241 -0
- package/wrangler-dist/ProxyWorker.js.map +6 -0
- package/wrangler-dist/cli.d.ts +26463 -0
- package/wrangler-dist/cli.js +206335 -125492
- package/wrangler-dist/wasm-sync.wasm +0 -0
- package/import_meta_url.js +0 -3
- package/miniflare-config-stubs/.env.empty +0 -0
- package/miniflare-config-stubs/package.empty.json +0 -1
- package/miniflare-config-stubs/wrangler.empty.toml +0 -0
- package/src/__tests__/clipboardy-mock.js +0 -4
- package/src/__tests__/fixtures/init/.gitkeep +0 -0
- package/src/__tests__/index.test.ts +0 -153
- package/src/__tests__/mock-cfetch.js +0 -46
- package/src/api/form_data.ts +0 -158
- package/src/api/inspect.ts +0 -441
- package/src/api/preview.ts +0 -123
- package/src/api/worker.ts +0 -161
- package/src/cfetch.ts +0 -72
- package/src/cli.ts +0 -10
- package/src/config.ts +0 -124
- package/src/dev.tsx +0 -736
- package/src/dialogs.tsx +0 -85
- package/src/index.tsx +0 -1845
- package/src/kv.tsx +0 -211
- package/src/pages.tsx +0 -344
- package/src/publish.ts +0 -354
- package/src/sites.tsx +0 -115
- package/src/tail.tsx +0 -71
- package/src/user.tsx +0 -1029
- package/src/util/fetch.ts +0 -74
- package/static-asset-facade.js +0 -47
- package/vendor/@cloudflare/kv-asset-handler/CHANGELOG.md +0 -332
- package/vendor/@cloudflare/kv-asset-handler/LICENSE_APACHE +0 -176
- package/vendor/@cloudflare/kv-asset-handler/LICENSE_MIT +0 -25
- package/vendor/@cloudflare/kv-asset-handler/README.md +0 -245
- package/vendor/@cloudflare/kv-asset-handler/dist/index.d.ts +0 -32
- package/vendor/@cloudflare/kv-asset-handler/dist/index.js +0 -354
- package/vendor/@cloudflare/kv-asset-handler/dist/mocks.d.ts +0 -13
- package/vendor/@cloudflare/kv-asset-handler/dist/mocks.js +0 -148
- package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.d.ts +0 -1
- package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.js +0 -436
- package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.d.ts +0 -1
- package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.js +0 -40
- package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.d.ts +0 -1
- package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.js +0 -42
- package/vendor/@cloudflare/kv-asset-handler/dist/types.d.ts +0 -26
- package/vendor/@cloudflare/kv-asset-handler/dist/types.js +0 -31
- package/vendor/@cloudflare/kv-asset-handler/package.json +0 -52
- package/vendor/@cloudflare/kv-asset-handler/src/index.ts +0 -296
- package/vendor/@cloudflare/kv-asset-handler/src/mocks.ts +0 -136
- package/vendor/@cloudflare/kv-asset-handler/src/test/getAssetFromKV.ts +0 -464
- package/vendor/@cloudflare/kv-asset-handler/src/test/mapRequestToAsset.ts +0 -33
- package/vendor/@cloudflare/kv-asset-handler/src/test/serveSinglePageApp.ts +0 -42
- package/vendor/@cloudflare/kv-asset-handler/src/types.ts +0 -39
- package/vendor/wrangler-mime/CHANGELOG.md +0 -289
- package/vendor/wrangler-mime/LICENSE +0 -21
- package/vendor/wrangler-mime/Mime.js +0 -97
- package/vendor/wrangler-mime/README.md +0 -187
- package/vendor/wrangler-mime/cli.js +0 -46
- package/vendor/wrangler-mime/index.js +0 -4
- package/vendor/wrangler-mime/lite.js +0 -4
- package/vendor/wrangler-mime/package.json +0 -52
- package/vendor/wrangler-mime/types/other.js +0 -1
- package/vendor/wrangler-mime/types/standard.js +0 -1
- package/wrangler-dist/cli.js.map +0 -7
package/src/index.tsx
DELETED
|
@@ -1,1845 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { render } from "ink";
|
|
3
|
-
import { Dev } from "./dev";
|
|
4
|
-
import { readFile } from "node:fs/promises";
|
|
5
|
-
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
|
-
import { version as wranglerVersion } from "../package.json";
|
|
13
|
-
import {
|
|
14
|
-
login,
|
|
15
|
-
logout,
|
|
16
|
-
listScopes,
|
|
17
|
-
initialise as initialiseUserConfig,
|
|
18
|
-
loginOrRefreshIfRequired,
|
|
19
|
-
getAccountId,
|
|
20
|
-
} from "./user";
|
|
21
|
-
import {
|
|
22
|
-
getNamespaceId,
|
|
23
|
-
listNamespaces,
|
|
24
|
-
listNamespaceKeys,
|
|
25
|
-
putKeyValue,
|
|
26
|
-
putBulkKeyValue,
|
|
27
|
-
deleteBulkKeyValue,
|
|
28
|
-
} from "./kv";
|
|
29
|
-
|
|
30
|
-
import { pages } from "./pages";
|
|
31
|
-
|
|
32
|
-
import cfetch from "./cfetch";
|
|
33
|
-
|
|
34
|
-
import publish from "./publish";
|
|
35
|
-
import path from "path/posix";
|
|
36
|
-
import { writeFile } from "node:fs/promises";
|
|
37
|
-
import { toFormData } from "./api/form_data";
|
|
38
|
-
|
|
39
|
-
import { createTail } from "./tail";
|
|
40
|
-
import onExit from "signal-exit";
|
|
41
|
-
import { setTimeout } from "node:timers/promises";
|
|
42
|
-
import * as fs from "node:fs";
|
|
43
|
-
import { execa } from "execa";
|
|
44
|
-
|
|
45
|
-
async function readConfig(path?: string): Promise<Config> {
|
|
46
|
-
const config: Config = {};
|
|
47
|
-
if (!path) {
|
|
48
|
-
path = await findUp("wrangler.toml");
|
|
49
|
-
// TODO - terminate this early instead of going all the way to the root
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (path) {
|
|
53
|
-
const tml: string = await readFile(path, "utf-8");
|
|
54
|
-
const parsed = TOML.parse(tml) as Config;
|
|
55
|
-
Object.assign(config, parsed);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const inheritedFields = [
|
|
59
|
-
"name",
|
|
60
|
-
"account_id",
|
|
61
|
-
"workers_dev",
|
|
62
|
-
"compatibility_date",
|
|
63
|
-
"compatibility_flags",
|
|
64
|
-
"zone_id",
|
|
65
|
-
"routes",
|
|
66
|
-
"route",
|
|
67
|
-
"jsx_factory",
|
|
68
|
-
"jsx_fragment",
|
|
69
|
-
"polyfill_node",
|
|
70
|
-
"site",
|
|
71
|
-
"triggers",
|
|
72
|
-
"usage_model",
|
|
73
|
-
];
|
|
74
|
-
|
|
75
|
-
Object.keys(config.env || {}).forEach((env) => {
|
|
76
|
-
inheritedFields.forEach((field) => {
|
|
77
|
-
if (config[field] !== undefined && config.env[env][field] === undefined) {
|
|
78
|
-
config.env[env][field] = config[field]; // TODO: - shallow copy?
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
const mirroredFields = ["vars", "kv_namespaces", "durable_objects"];
|
|
84
|
-
Object.keys(config.env || {}).forEach((env) => {
|
|
85
|
-
mirroredFields.forEach((field) => {
|
|
86
|
-
// if it exists on top level, it should exist on env defns
|
|
87
|
-
Object.keys(config[field] || {}).forEach((fieldKey) => {
|
|
88
|
-
if (!(fieldKey in config.env[env][field])) {
|
|
89
|
-
console.error(
|
|
90
|
-
`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}".`
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
// todo: validate, add defaults
|
|
98
|
-
// let's just do some basics for now
|
|
99
|
-
|
|
100
|
-
// @ts-expect-error we're being sneaky here for now
|
|
101
|
-
config.__path__ = path;
|
|
102
|
-
|
|
103
|
-
return config;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// a helper to demand one of a set of options
|
|
107
|
-
// via https://github.com/yargs/yargs/issues/1093#issuecomment-491299261
|
|
108
|
-
function demandOneOfOption(...options: string[]) {
|
|
109
|
-
return function (argv: yargs.Arguments) {
|
|
110
|
-
const count = options.filter((option) => argv[option]).length;
|
|
111
|
-
const lastOption = options.pop();
|
|
112
|
-
|
|
113
|
-
if (count === 0) {
|
|
114
|
-
throw new Error(
|
|
115
|
-
`Exactly one of the arguments ${options.join(
|
|
116
|
-
", "
|
|
117
|
-
)} and ${lastOption} is required`
|
|
118
|
-
);
|
|
119
|
-
} else if (count > 1) {
|
|
120
|
-
throw new Error(
|
|
121
|
-
`Arguments ${options.join(
|
|
122
|
-
", "
|
|
123
|
-
)} and ${lastOption} are mutually exclusive`
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return true;
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export async function main(argv: string[]): Promise<void> {
|
|
132
|
-
const yargs = makeCLI(hideBin(process.argv))
|
|
133
|
-
.command(
|
|
134
|
-
// the default is to simply print the help menu
|
|
135
|
-
["*"],
|
|
136
|
-
false,
|
|
137
|
-
() => {},
|
|
138
|
-
() => {
|
|
139
|
-
yargs.showHelp("log");
|
|
140
|
-
}
|
|
141
|
-
)
|
|
142
|
-
.scriptName("wrangler")
|
|
143
|
-
.wrap(null);
|
|
144
|
-
|
|
145
|
-
// you will note that we use the form for all commands where we use the builder function
|
|
146
|
-
// to define options and subcommands. Further we return the result of this builder even
|
|
147
|
-
// tho it's not completely necessary. The reason is that it's required for type inference
|
|
148
|
-
// of the args in the handle function.I wish we could enforce this pattern, but this
|
|
149
|
-
// comment will have to do for now.
|
|
150
|
-
|
|
151
|
-
// also annoying that choices[] doesn't get inferred as an enum. bleh.
|
|
152
|
-
|
|
153
|
-
// [DEPRECATED] generate
|
|
154
|
-
yargs.command(
|
|
155
|
-
// we definitely want to move away from us cloning github templates
|
|
156
|
-
// we can do something better here, let's see
|
|
157
|
-
"generate [name] [template]",
|
|
158
|
-
false,
|
|
159
|
-
(yargs) => {
|
|
160
|
-
return yargs
|
|
161
|
-
.positional("name", {
|
|
162
|
-
describe: "Name of the Workers project",
|
|
163
|
-
default: "worker",
|
|
164
|
-
})
|
|
165
|
-
.positional("template", {
|
|
166
|
-
describe: "a link to a GitHub template",
|
|
167
|
-
default: "https://github.com/cloudflare/worker-template",
|
|
168
|
-
});
|
|
169
|
-
},
|
|
170
|
-
() => {
|
|
171
|
-
// "👯 [DEPRECATED]. Scaffold a Cloudflare Workers project from a public GitHub repository.",
|
|
172
|
-
console.error(
|
|
173
|
-
"`wrangler generate` has been deprecated, please refer to TODO://some/path for alternatives"
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
);
|
|
177
|
-
|
|
178
|
-
// init
|
|
179
|
-
yargs.command(
|
|
180
|
-
"init [name]",
|
|
181
|
-
"📥 Create a wrangler.toml configuration file",
|
|
182
|
-
(yargs) => {
|
|
183
|
-
return yargs.positional("name", {
|
|
184
|
-
describe: "The name of your worker.",
|
|
185
|
-
type: "string",
|
|
186
|
-
});
|
|
187
|
-
},
|
|
188
|
-
async () => {
|
|
189
|
-
const destination = path.join(process.cwd(), "wrangler.toml");
|
|
190
|
-
if (fs.existsSync(destination)) {
|
|
191
|
-
console.error(`${destination} already exists.`);
|
|
192
|
-
} else {
|
|
193
|
-
const compatibilityDate = new Date().toISOString().substring(0, 10);
|
|
194
|
-
try {
|
|
195
|
-
await writeFile(
|
|
196
|
-
destination,
|
|
197
|
-
`compatibility_date = "${compatibilityDate}"` + "\n"
|
|
198
|
-
);
|
|
199
|
-
console.log(`✨ Succesfully created wrangler.toml`);
|
|
200
|
-
// TODO: suggest next steps?
|
|
201
|
-
} catch (err) {
|
|
202
|
-
console.error(`Failed to create wrangler.toml`);
|
|
203
|
-
console.error(err);
|
|
204
|
-
throw err;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// if no package.json, ask, and if yes, create one
|
|
209
|
-
let pathToPackageJson = await findUp("package.json");
|
|
210
|
-
|
|
211
|
-
if (!pathToPackageJson) {
|
|
212
|
-
if (
|
|
213
|
-
await confirm("No package.json found. Would you like to create one?")
|
|
214
|
-
) {
|
|
215
|
-
await writeFile(
|
|
216
|
-
path.join(process.cwd(), "package.json"),
|
|
217
|
-
JSON.stringify(
|
|
218
|
-
{
|
|
219
|
-
name: "worker",
|
|
220
|
-
version: "0.0.1",
|
|
221
|
-
},
|
|
222
|
-
null,
|
|
223
|
-
" "
|
|
224
|
-
) + "\n"
|
|
225
|
-
);
|
|
226
|
-
console.log(`✨ Created package.json`);
|
|
227
|
-
pathToPackageJson = path.join(process.cwd(), "package.json");
|
|
228
|
-
} else {
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// if workers-types doesn't exist as a dependency
|
|
234
|
-
// offer to install it
|
|
235
|
-
// and make a tsconfig?
|
|
236
|
-
let pathToTSConfig = await findUp("tsconfig.json");
|
|
237
|
-
if (!pathToTSConfig) {
|
|
238
|
-
if (await confirm("Would you like to use typescript?")) {
|
|
239
|
-
await writeFile(
|
|
240
|
-
path.join(process.cwd(), "tsconfig.json"),
|
|
241
|
-
JSON.stringify(
|
|
242
|
-
{
|
|
243
|
-
compilerOptions: {
|
|
244
|
-
target: "ES2020",
|
|
245
|
-
module: "CommonJS",
|
|
246
|
-
lib: ["ES2020"],
|
|
247
|
-
types: ["@cloudflare/workers-types"],
|
|
248
|
-
},
|
|
249
|
-
},
|
|
250
|
-
null,
|
|
251
|
-
" "
|
|
252
|
-
) + "\n"
|
|
253
|
-
);
|
|
254
|
-
await execa("npm", [
|
|
255
|
-
"install",
|
|
256
|
-
"@cloudflare/workers-types",
|
|
257
|
-
"--save-dev",
|
|
258
|
-
]);
|
|
259
|
-
console.log(
|
|
260
|
-
`✨ Created tsconfig.json, installed @cloudflare/workers-types into devDependencies`
|
|
261
|
-
);
|
|
262
|
-
pathToTSConfig = path.join(process.cwd(), "tsconfig.json");
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
);
|
|
267
|
-
|
|
268
|
-
// build
|
|
269
|
-
yargs.command(
|
|
270
|
-
"build",
|
|
271
|
-
false,
|
|
272
|
-
(yargs) => {
|
|
273
|
-
return yargs.option("env", {
|
|
274
|
-
describe: "Perform on a specific environment",
|
|
275
|
-
});
|
|
276
|
-
},
|
|
277
|
-
() => {
|
|
278
|
-
// "[DEPRECATED] 🦀 Build your project (if applicable)",
|
|
279
|
-
console.error(
|
|
280
|
-
"`wrangler build` has been deprecated, please refer to TODO://some/path for alternatives"
|
|
281
|
-
);
|
|
282
|
-
}
|
|
283
|
-
);
|
|
284
|
-
|
|
285
|
-
// login
|
|
286
|
-
yargs.command(
|
|
287
|
-
// this needs scopes as an option?
|
|
288
|
-
"login",
|
|
289
|
-
false, // we don't need to show this in the menu
|
|
290
|
-
// "🔓 Login to Cloudflare",
|
|
291
|
-
(yargs) => {
|
|
292
|
-
// TODO: This needs some copy editing
|
|
293
|
-
// I mean, this entire app does, but this too.
|
|
294
|
-
return yargs
|
|
295
|
-
.option("scopes-list", {
|
|
296
|
-
describe: "list all the available OAuth scopes with descriptions.",
|
|
297
|
-
})
|
|
298
|
-
.option("scopes", {
|
|
299
|
-
describe: "allows to choose your set of OAuth scopes.",
|
|
300
|
-
array: true,
|
|
301
|
-
type: "string",
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
// TODO: scopes
|
|
305
|
-
},
|
|
306
|
-
async (args) => {
|
|
307
|
-
if (args["scopes-list"]) {
|
|
308
|
-
listScopes();
|
|
309
|
-
return;
|
|
310
|
-
}
|
|
311
|
-
if (args.scopes) {
|
|
312
|
-
if (args.scopes.length === 0) {
|
|
313
|
-
// don't allow no scopes to be passed, that would be weird
|
|
314
|
-
listScopes();
|
|
315
|
-
return;
|
|
316
|
-
}
|
|
317
|
-
await login({ scopes: args.scopes });
|
|
318
|
-
return;
|
|
319
|
-
}
|
|
320
|
-
await login();
|
|
321
|
-
|
|
322
|
-
// TODO: would be nice if it optionally saved login
|
|
323
|
-
// creds inside node_modules/.cache or something
|
|
324
|
-
// this way you could have multiple users on a single machine
|
|
325
|
-
}
|
|
326
|
-
);
|
|
327
|
-
|
|
328
|
-
// logout
|
|
329
|
-
yargs.command(
|
|
330
|
-
// this needs scopes as an option?
|
|
331
|
-
"logout",
|
|
332
|
-
false, // we don't need to show this in the menu
|
|
333
|
-
// "🚪 Logout from Cloudflare",
|
|
334
|
-
() => {},
|
|
335
|
-
async () => {
|
|
336
|
-
await logout();
|
|
337
|
-
}
|
|
338
|
-
);
|
|
339
|
-
|
|
340
|
-
// whoami
|
|
341
|
-
yargs.command(
|
|
342
|
-
"whoami",
|
|
343
|
-
false, // we don't need to show this the menu
|
|
344
|
-
// "🕵️ Retrieve your user info and test your auth config",
|
|
345
|
-
() => {},
|
|
346
|
-
(args) => {
|
|
347
|
-
console.log(":whoami", args);
|
|
348
|
-
}
|
|
349
|
-
);
|
|
350
|
-
|
|
351
|
-
// config
|
|
352
|
-
yargs.command(
|
|
353
|
-
"config",
|
|
354
|
-
false,
|
|
355
|
-
() => {},
|
|
356
|
-
() => {
|
|
357
|
-
// "🕵️ Authenticate Wrangler with a Cloudflare API Token",
|
|
358
|
-
console.error(
|
|
359
|
-
"`wrangler config` has been deprecated, please refer to TODO://some/path for alternatives"
|
|
360
|
-
);
|
|
361
|
-
}
|
|
362
|
-
);
|
|
363
|
-
|
|
364
|
-
// dev
|
|
365
|
-
yargs.command(
|
|
366
|
-
"dev <filename>",
|
|
367
|
-
"👂 Start a local server for developing your worker",
|
|
368
|
-
(yargs) => {
|
|
369
|
-
return yargs
|
|
370
|
-
.positional("filename", { describe: "entry point", type: "string" })
|
|
371
|
-
.option("name", {
|
|
372
|
-
describe: "name of the script",
|
|
373
|
-
type: "string",
|
|
374
|
-
})
|
|
375
|
-
.option("format", {
|
|
376
|
-
choices: ["modules", "service-worker"] as const,
|
|
377
|
-
describe: "Choose an entry type",
|
|
378
|
-
})
|
|
379
|
-
.option("env", {
|
|
380
|
-
describe: "Perform on a specific environment",
|
|
381
|
-
type: "string",
|
|
382
|
-
// TODO: get choices for the toml file?
|
|
383
|
-
})
|
|
384
|
-
.option("ip", {
|
|
385
|
-
describe: "IP address to listen on",
|
|
386
|
-
type: "string",
|
|
387
|
-
default: "127.0.0.1",
|
|
388
|
-
})
|
|
389
|
-
.option("port", {
|
|
390
|
-
describe: "Port to listen on, defaults to 8787",
|
|
391
|
-
type: "number",
|
|
392
|
-
default: 8787,
|
|
393
|
-
})
|
|
394
|
-
.option("host", {
|
|
395
|
-
type: "string",
|
|
396
|
-
describe:
|
|
397
|
-
"Host to forward requests to, defaults to the zone of project",
|
|
398
|
-
})
|
|
399
|
-
.option("local-protocol", {
|
|
400
|
-
default: "http",
|
|
401
|
-
describe: "Protocol to listen to requests on, defaults to http.",
|
|
402
|
-
choices: ["http", "https"],
|
|
403
|
-
})
|
|
404
|
-
.option("public", {
|
|
405
|
-
describe: "Static assets to be served",
|
|
406
|
-
type: "string",
|
|
407
|
-
})
|
|
408
|
-
.option("site", {
|
|
409
|
-
describe: "Root folder of static assets for Workers Sites",
|
|
410
|
-
type: "string",
|
|
411
|
-
})
|
|
412
|
-
.option("upstream-protocol", {
|
|
413
|
-
default: "https",
|
|
414
|
-
describe:
|
|
415
|
-
"Protocol to forward requests to host on, defaults to https.",
|
|
416
|
-
choices: ["http", "https"],
|
|
417
|
-
})
|
|
418
|
-
.option("jsx-factory", {
|
|
419
|
-
describe: "The function that is called for each JSX element",
|
|
420
|
-
type: "string",
|
|
421
|
-
})
|
|
422
|
-
.option("jsx-fragment", {
|
|
423
|
-
describe: "The function that is called for each JSX fragment",
|
|
424
|
-
type: "string",
|
|
425
|
-
})
|
|
426
|
-
.option("polyfill-node", {
|
|
427
|
-
describe: "Try to polyfill node builtins",
|
|
428
|
-
type: "boolean",
|
|
429
|
-
});
|
|
430
|
-
},
|
|
431
|
-
async (args) => {
|
|
432
|
-
const { filename, format } = args;
|
|
433
|
-
const config = args.config as Config;
|
|
434
|
-
|
|
435
|
-
// -- snip, extract --
|
|
436
|
-
|
|
437
|
-
if (!args.local) {
|
|
438
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
439
|
-
if (!loggedIn) {
|
|
440
|
-
// didn't login, let's just quit
|
|
441
|
-
console.log("Did not login, quitting...");
|
|
442
|
-
return;
|
|
443
|
-
}
|
|
444
|
-
if (!config.account_id) {
|
|
445
|
-
config.account_id = await getAccountId();
|
|
446
|
-
if (!config.account_id) {
|
|
447
|
-
console.error("No account id found, quitting...");
|
|
448
|
-
return;
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
// -- snip, end --
|
|
454
|
-
|
|
455
|
-
const envRootObj = args.env ? config.env[args.env] || {} : config;
|
|
456
|
-
|
|
457
|
-
const polyfillNode = args["polyfill-node"] ?? config.polyfill_node;
|
|
458
|
-
if (polyfillNode) {
|
|
459
|
-
console.warn(
|
|
460
|
-
"Using polyfills for node builtin modules. These are not meant to be completely reliable, and have serious tradeoffs. Please see https://github.com/ionic-team/rollup-plugin-node-polyfills/ for more details."
|
|
461
|
-
);
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
render(
|
|
465
|
-
<Dev
|
|
466
|
-
name={args.name || config.name}
|
|
467
|
-
entry={filename}
|
|
468
|
-
format={format}
|
|
469
|
-
initialMode={args.local ? "local" : "remote"}
|
|
470
|
-
jsxFactory={args["jsx-factory"] || envRootObj?.jsx_factory}
|
|
471
|
-
jsxFragment={args["jsx-fragment"] || envRootObj?.jsx_fragment}
|
|
472
|
-
accountId={config.account_id}
|
|
473
|
-
site={args.site || config.site?.bucket}
|
|
474
|
-
port={args.port || config.dev?.port}
|
|
475
|
-
polyfillNode={polyfillNode}
|
|
476
|
-
public={args.public}
|
|
477
|
-
compatibilityDate={config.compatibility_date}
|
|
478
|
-
compatibilityFlags={config.compatibility_flags}
|
|
479
|
-
usageModel={config.usage_model}
|
|
480
|
-
variables={{
|
|
481
|
-
...(envRootObj?.vars || {}),
|
|
482
|
-
...(envRootObj?.kv_namespaces || []).reduce(
|
|
483
|
-
(obj, { binding, preview_id }) => {
|
|
484
|
-
if (!preview_id) {
|
|
485
|
-
// TODO: This error has to be a _lot_ better, ideally just asking
|
|
486
|
-
// to create a preview namespace for the user automatically
|
|
487
|
-
throw new Error(
|
|
488
|
-
"kv namespaces need a preview id during dev mode"
|
|
489
|
-
);
|
|
490
|
-
}
|
|
491
|
-
return { ...obj, [binding]: { namespaceId: preview_id } };
|
|
492
|
-
},
|
|
493
|
-
{}
|
|
494
|
-
),
|
|
495
|
-
...(envRootObj?.durable_objects?.bindings || []).reduce(
|
|
496
|
-
(obj, { name, class_name, script_name }) => {
|
|
497
|
-
return { ...obj, [name]: { class_name, script_name } };
|
|
498
|
-
},
|
|
499
|
-
{}
|
|
500
|
-
),
|
|
501
|
-
}}
|
|
502
|
-
/>
|
|
503
|
-
);
|
|
504
|
-
}
|
|
505
|
-
);
|
|
506
|
-
|
|
507
|
-
// publish
|
|
508
|
-
yargs.command(
|
|
509
|
-
"publish [script]",
|
|
510
|
-
"🆙 Publish your Worker to Cloudflare.",
|
|
511
|
-
(yargs) => {
|
|
512
|
-
return yargs
|
|
513
|
-
.option("env", {
|
|
514
|
-
type: "string",
|
|
515
|
-
describe: "Perform on a specific environment",
|
|
516
|
-
})
|
|
517
|
-
.positional("script", {
|
|
518
|
-
describe: "script to upload",
|
|
519
|
-
type: "string",
|
|
520
|
-
})
|
|
521
|
-
.option("name", {
|
|
522
|
-
describe: "name to use when uploading",
|
|
523
|
-
type: "string",
|
|
524
|
-
})
|
|
525
|
-
.option("public", {
|
|
526
|
-
describe: "Static assets to be served",
|
|
527
|
-
type: "string",
|
|
528
|
-
})
|
|
529
|
-
.option("site", {
|
|
530
|
-
describe: "Root folder of static assets for Workers Sites",
|
|
531
|
-
type: "string",
|
|
532
|
-
})
|
|
533
|
-
.option("triggers", {
|
|
534
|
-
describe: "cron schedules to attach",
|
|
535
|
-
alias: ["schedule", "schedules"],
|
|
536
|
-
type: "array",
|
|
537
|
-
})
|
|
538
|
-
.option("routes", {
|
|
539
|
-
describe: "routes to upload",
|
|
540
|
-
alias: "route",
|
|
541
|
-
type: "array",
|
|
542
|
-
})
|
|
543
|
-
.option("services", {
|
|
544
|
-
describe: "experimental support for services",
|
|
545
|
-
type: "boolean",
|
|
546
|
-
default: "false",
|
|
547
|
-
hidden: true,
|
|
548
|
-
})
|
|
549
|
-
.option("jsx-factory", {
|
|
550
|
-
describe: "The function that is called for each JSX element",
|
|
551
|
-
type: "string",
|
|
552
|
-
})
|
|
553
|
-
.option("jsx-fragment", {
|
|
554
|
-
describe: "The function that is called for each JSX fragment",
|
|
555
|
-
type: "string",
|
|
556
|
-
})
|
|
557
|
-
.option("polyfill-node", {
|
|
558
|
-
describe: "Try to polyfill node builtins",
|
|
559
|
-
type: "boolean",
|
|
560
|
-
});
|
|
561
|
-
},
|
|
562
|
-
async (args) => {
|
|
563
|
-
if (args.local) {
|
|
564
|
-
console.error("🚫 Local publishing is not yet supported");
|
|
565
|
-
return;
|
|
566
|
-
}
|
|
567
|
-
const config = args.config as Config;
|
|
568
|
-
|
|
569
|
-
// -- snip, extract --
|
|
570
|
-
if (!args.local) {
|
|
571
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
572
|
-
if (!loggedIn) {
|
|
573
|
-
// didn't login, let's just quit
|
|
574
|
-
console.log("Did not login, quitting...");
|
|
575
|
-
return;
|
|
576
|
-
}
|
|
577
|
-
if (!config.account_id) {
|
|
578
|
-
config.account_id = await getAccountId();
|
|
579
|
-
if (!config.account_id) {
|
|
580
|
-
console.error("No account id found, quitting...");
|
|
581
|
-
return;
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
// -- snip, end --
|
|
587
|
-
|
|
588
|
-
const polyfillNode = args["polyfill-node"] ?? config.polyfill_node;
|
|
589
|
-
if (polyfillNode) {
|
|
590
|
-
console.warn(
|
|
591
|
-
"Using polyfills for node builtin modules. These are not meant to be completely reliable, and have serious tradeoffs. Please see https://github.com/ionic-team/rollup-plugin-node-polyfills/ for more details."
|
|
592
|
-
);
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
await publish({
|
|
596
|
-
config: args.config as Config,
|
|
597
|
-
name: args.name,
|
|
598
|
-
script: args.script,
|
|
599
|
-
env: args.env,
|
|
600
|
-
triggers: args.triggers,
|
|
601
|
-
jsxFactory: args["jsx-factory"],
|
|
602
|
-
jsxFragment: args["jsx-fragment"],
|
|
603
|
-
polyfillNode: args["polyfill-node"],
|
|
604
|
-
routes: args.routes,
|
|
605
|
-
public: args.public,
|
|
606
|
-
site: args.site,
|
|
607
|
-
});
|
|
608
|
-
}
|
|
609
|
-
);
|
|
610
|
-
|
|
611
|
-
// tail
|
|
612
|
-
yargs.command(
|
|
613
|
-
"tail [name]",
|
|
614
|
-
"🦚 Starts a log tailing session for a deployed Worker.",
|
|
615
|
-
(yargs) => {
|
|
616
|
-
return (
|
|
617
|
-
yargs
|
|
618
|
-
.positional("name", {
|
|
619
|
-
describe: "name of the worker",
|
|
620
|
-
type: "string",
|
|
621
|
-
})
|
|
622
|
-
// TODO: auto-detect if this should be json or pretty based on atty
|
|
623
|
-
.option("format", {
|
|
624
|
-
default: "json",
|
|
625
|
-
choices: ["json", "pretty"],
|
|
626
|
-
describe: "The format of log entries",
|
|
627
|
-
})
|
|
628
|
-
.option("status", {
|
|
629
|
-
choices: ["ok", "error", "canceled"],
|
|
630
|
-
describe: "Filter by invocation status",
|
|
631
|
-
})
|
|
632
|
-
.option("header", {
|
|
633
|
-
type: "string",
|
|
634
|
-
describe: "Filter by HTTP header",
|
|
635
|
-
})
|
|
636
|
-
.option("method", {
|
|
637
|
-
type: "string",
|
|
638
|
-
describe: "Filter by HTTP method",
|
|
639
|
-
})
|
|
640
|
-
.option("sampling-rate", {
|
|
641
|
-
type: "number",
|
|
642
|
-
describe: "Adds a percentage of requests to log sampling rate",
|
|
643
|
-
})
|
|
644
|
-
.option("search", {
|
|
645
|
-
type: "string",
|
|
646
|
-
describe: "Filter by a text match in console.log messages",
|
|
647
|
-
})
|
|
648
|
-
.option("env", {
|
|
649
|
-
type: "string",
|
|
650
|
-
describe: "Perform on a specific environment",
|
|
651
|
-
})
|
|
652
|
-
);
|
|
653
|
-
// TODO: filter by client ip, which can be 'self' or an ip address
|
|
654
|
-
},
|
|
655
|
-
async (args) => {
|
|
656
|
-
const config = args.config as Config;
|
|
657
|
-
|
|
658
|
-
if (!(args.name || config.name)) {
|
|
659
|
-
console.error("Missing script name");
|
|
660
|
-
return;
|
|
661
|
-
}
|
|
662
|
-
const scriptName = `${args.name || config.name}${
|
|
663
|
-
args.env ? `-${args.env}` : ""
|
|
664
|
-
}`;
|
|
665
|
-
|
|
666
|
-
// -- snip, extract --
|
|
667
|
-
|
|
668
|
-
if (!args.local) {
|
|
669
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
670
|
-
if (!loggedIn) {
|
|
671
|
-
// didn't login, let's just quit
|
|
672
|
-
console.log("Did not login, quitting...");
|
|
673
|
-
return;
|
|
674
|
-
}
|
|
675
|
-
if (!config.account_id) {
|
|
676
|
-
config.account_id = await getAccountId();
|
|
677
|
-
if (!config.account_id) {
|
|
678
|
-
console.error("No account id found, quitting...");
|
|
679
|
-
return;
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
// -- snip, end --
|
|
685
|
-
|
|
686
|
-
const accountId = config.account_id;
|
|
687
|
-
|
|
688
|
-
const filters = {
|
|
689
|
-
status: args.status as "ok" | "error" | "canceled",
|
|
690
|
-
header: args.header,
|
|
691
|
-
method: args.method,
|
|
692
|
-
"sampling-rate": args["sampling-rate"],
|
|
693
|
-
search: args.search,
|
|
694
|
-
};
|
|
695
|
-
|
|
696
|
-
const { tail, expiration, /* sendHeartbeat, */ deleteTail } =
|
|
697
|
-
await createTail(accountId, scriptName, filters);
|
|
698
|
-
|
|
699
|
-
console.log(
|
|
700
|
-
`successfully created tail, expires at ${expiration.toLocaleString()}`
|
|
701
|
-
);
|
|
702
|
-
|
|
703
|
-
onExit(() => {
|
|
704
|
-
tail.terminate();
|
|
705
|
-
deleteTail();
|
|
706
|
-
});
|
|
707
|
-
|
|
708
|
-
tail.on("message", (data) => {
|
|
709
|
-
console.log(JSON.stringify(JSON.parse(data.toString()), null, " "));
|
|
710
|
-
});
|
|
711
|
-
|
|
712
|
-
while (tail.readyState !== tail.OPEN) {
|
|
713
|
-
switch (tail.readyState) {
|
|
714
|
-
case tail.CONNECTING:
|
|
715
|
-
await setTimeout(1000);
|
|
716
|
-
break;
|
|
717
|
-
case tail.CLOSING:
|
|
718
|
-
await setTimeout(1000);
|
|
719
|
-
break;
|
|
720
|
-
case tail.CLOSED:
|
|
721
|
-
process.exit(1);
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
console.log(`Connected to ${scriptName}, waiting for logs...`);
|
|
726
|
-
}
|
|
727
|
-
);
|
|
728
|
-
|
|
729
|
-
// preview
|
|
730
|
-
yargs.command(
|
|
731
|
-
"preview [method] [body]",
|
|
732
|
-
false,
|
|
733
|
-
(yargs) => {
|
|
734
|
-
return yargs
|
|
735
|
-
.positional("method", {
|
|
736
|
-
describe: "Type of request to preview your worker",
|
|
737
|
-
choices: ["GET", "POST"],
|
|
738
|
-
default: ["GET"],
|
|
739
|
-
})
|
|
740
|
-
.positional("body", {
|
|
741
|
-
type: "string",
|
|
742
|
-
describe: "Body string to post to your preview worker request.",
|
|
743
|
-
default: "Null",
|
|
744
|
-
})
|
|
745
|
-
.option("env", {
|
|
746
|
-
type: "string",
|
|
747
|
-
describe: "Perform on a specific environment",
|
|
748
|
-
})
|
|
749
|
-
.option("watch", {
|
|
750
|
-
default: true,
|
|
751
|
-
describe: "Enable live preview",
|
|
752
|
-
type: "boolean",
|
|
753
|
-
});
|
|
754
|
-
},
|
|
755
|
-
() => {
|
|
756
|
-
// "🔬 [DEPRECATED] Preview your code temporarily on cloudflareworkers.com"
|
|
757
|
-
console.error(
|
|
758
|
-
"`wrangler preview` has been deprecated, please refer to TODO://some/path for alternatives"
|
|
759
|
-
);
|
|
760
|
-
}
|
|
761
|
-
);
|
|
762
|
-
|
|
763
|
-
// route
|
|
764
|
-
yargs.command(
|
|
765
|
-
"route",
|
|
766
|
-
false, // I think we want to hide this command
|
|
767
|
-
// "➡️ List or delete worker routes",
|
|
768
|
-
(yargs) => {
|
|
769
|
-
return yargs
|
|
770
|
-
.command(
|
|
771
|
-
"list",
|
|
772
|
-
"List a route associated with a zone",
|
|
773
|
-
(yargs) => {
|
|
774
|
-
return yargs
|
|
775
|
-
.option("env", {
|
|
776
|
-
type: "string",
|
|
777
|
-
describe: "Perform on a specific environment",
|
|
778
|
-
})
|
|
779
|
-
.option("zone", {
|
|
780
|
-
type: "string",
|
|
781
|
-
describe: "zone id",
|
|
782
|
-
})
|
|
783
|
-
.positional("zone", {
|
|
784
|
-
describe: "zone id",
|
|
785
|
-
type: "string",
|
|
786
|
-
});
|
|
787
|
-
},
|
|
788
|
-
async (args) => {
|
|
789
|
-
console.log(":route list", args);
|
|
790
|
-
// TODO: use environment (current wrangler doesn't do so?)
|
|
791
|
-
const zone = args.zone || (args.config as Config).zone_id;
|
|
792
|
-
if (!zone) {
|
|
793
|
-
console.error("missing zone id");
|
|
794
|
-
return;
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
console.log(await cfetch(`/zones/${zone}/workers/routes`));
|
|
798
|
-
}
|
|
799
|
-
)
|
|
800
|
-
.command(
|
|
801
|
-
"delete <id>",
|
|
802
|
-
"Delete a route associated with a zone",
|
|
803
|
-
(yargs) => {
|
|
804
|
-
return yargs
|
|
805
|
-
.positional("id", {
|
|
806
|
-
describe: "The hash of the route ID to delete.",
|
|
807
|
-
type: "string",
|
|
808
|
-
})
|
|
809
|
-
.option("zone", {
|
|
810
|
-
type: "string",
|
|
811
|
-
describe: "zone id",
|
|
812
|
-
})
|
|
813
|
-
.option("env", {
|
|
814
|
-
type: "string",
|
|
815
|
-
describe: "Perform on a specific environment",
|
|
816
|
-
});
|
|
817
|
-
},
|
|
818
|
-
async (args) => {
|
|
819
|
-
console.log(":route delete", args);
|
|
820
|
-
// TODO: use environment (current wrangler doesn't do so?)
|
|
821
|
-
const zone = args.zone || (args.config as Config).zone_id;
|
|
822
|
-
if (!zone) {
|
|
823
|
-
throw new Error("missing zone id");
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
console.log(
|
|
827
|
-
await cfetch(`/zones/${zone}/workers/routes/${args.id}`, {
|
|
828
|
-
method: "DELETE",
|
|
829
|
-
})
|
|
830
|
-
);
|
|
831
|
-
}
|
|
832
|
-
);
|
|
833
|
-
}
|
|
834
|
-
);
|
|
835
|
-
|
|
836
|
-
// subdomain
|
|
837
|
-
yargs.command(
|
|
838
|
-
"subdomain [name]",
|
|
839
|
-
false,
|
|
840
|
-
// "👷 Create or change your workers.dev subdomain.",
|
|
841
|
-
(yargs) => {
|
|
842
|
-
return yargs.positional("name", { type: "string" });
|
|
843
|
-
},
|
|
844
|
-
() => {
|
|
845
|
-
console.error(
|
|
846
|
-
"`wrangler subdomain` has been deprecated, please refer to TODO://some/path for alternatives"
|
|
847
|
-
);
|
|
848
|
-
}
|
|
849
|
-
);
|
|
850
|
-
|
|
851
|
-
// secret
|
|
852
|
-
yargs.command(
|
|
853
|
-
"secret",
|
|
854
|
-
"🤫 Generate a secret that can be referenced in the worker script",
|
|
855
|
-
(yargs) => {
|
|
856
|
-
return yargs
|
|
857
|
-
.command(
|
|
858
|
-
"put <key>",
|
|
859
|
-
"Create or update a secret variable for a script",
|
|
860
|
-
(yargs) => {
|
|
861
|
-
return yargs
|
|
862
|
-
.positional("key", {
|
|
863
|
-
describe: "The variable name to be accessible in the script.",
|
|
864
|
-
type: "string",
|
|
865
|
-
})
|
|
866
|
-
.option("name", {
|
|
867
|
-
describe: "name of the script",
|
|
868
|
-
type: "string",
|
|
869
|
-
})
|
|
870
|
-
.option("env", {
|
|
871
|
-
type: "string",
|
|
872
|
-
describe:
|
|
873
|
-
"Binds the secret to the script of the specific environment.",
|
|
874
|
-
});
|
|
875
|
-
},
|
|
876
|
-
async (args) => {
|
|
877
|
-
if (args.local) {
|
|
878
|
-
console.error("--local not implemented for this command yet");
|
|
879
|
-
return;
|
|
880
|
-
}
|
|
881
|
-
const config = args.config as Config;
|
|
882
|
-
|
|
883
|
-
// TODO: use environment (how does current wrangler do it?)
|
|
884
|
-
const scriptName = args.name || config.name;
|
|
885
|
-
if (!scriptName) {
|
|
886
|
-
console.error("Missing script name");
|
|
887
|
-
return;
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
// -- snip, extract --
|
|
891
|
-
|
|
892
|
-
if (!args.local) {
|
|
893
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
894
|
-
if (!loggedIn) {
|
|
895
|
-
// didn't login, let's just quit
|
|
896
|
-
console.log("Did not login, quitting...");
|
|
897
|
-
return;
|
|
898
|
-
}
|
|
899
|
-
if (!config.account_id) {
|
|
900
|
-
config.account_id = await getAccountId();
|
|
901
|
-
if (!config.account_id) {
|
|
902
|
-
console.error("No account id found, quitting...");
|
|
903
|
-
return;
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
// -- snip, end --
|
|
909
|
-
|
|
910
|
-
const secretValue = await prompt(
|
|
911
|
-
"Enter a secret value:",
|
|
912
|
-
"password"
|
|
913
|
-
);
|
|
914
|
-
async function submitSecret() {
|
|
915
|
-
return await cfetch(
|
|
916
|
-
`/accounts/${config.account_id}/workers/scripts/${scriptName}/secrets/`,
|
|
917
|
-
{
|
|
918
|
-
method: "PUT",
|
|
919
|
-
headers: { "Content-Type": "application/json" },
|
|
920
|
-
body: JSON.stringify({
|
|
921
|
-
name: args.key,
|
|
922
|
-
text: secretValue,
|
|
923
|
-
type: "secret_text",
|
|
924
|
-
}),
|
|
925
|
-
}
|
|
926
|
-
);
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
try {
|
|
930
|
-
console.log(await submitSecret());
|
|
931
|
-
} catch (e) {
|
|
932
|
-
if (e.code === 10007) {
|
|
933
|
-
// upload a draft worker
|
|
934
|
-
await cfetch(
|
|
935
|
-
`/accounts/${config.account_id}/workers/scripts/${scriptName}`,
|
|
936
|
-
{
|
|
937
|
-
method: "PUT",
|
|
938
|
-
// @ts-expect-error TODO: fix this error!
|
|
939
|
-
body: toFormData({
|
|
940
|
-
main: {
|
|
941
|
-
name: scriptName,
|
|
942
|
-
content: `export default { fetch() {} }`,
|
|
943
|
-
type: "esm",
|
|
944
|
-
},
|
|
945
|
-
variables: {},
|
|
946
|
-
modules: [],
|
|
947
|
-
}),
|
|
948
|
-
}
|
|
949
|
-
);
|
|
950
|
-
|
|
951
|
-
// and then try again
|
|
952
|
-
console.log(await submitSecret());
|
|
953
|
-
// TODO: delete the draft worker if this failed too?
|
|
954
|
-
}
|
|
955
|
-
}
|
|
956
|
-
}
|
|
957
|
-
)
|
|
958
|
-
.command(
|
|
959
|
-
"delete <key>",
|
|
960
|
-
"Delete a secret variable from a script",
|
|
961
|
-
(yargs) => {
|
|
962
|
-
return yargs
|
|
963
|
-
.positional("key", {
|
|
964
|
-
describe: "The variable name to be accessible in the script.",
|
|
965
|
-
type: "string",
|
|
966
|
-
})
|
|
967
|
-
.option("name", {
|
|
968
|
-
describe: "name of the script",
|
|
969
|
-
type: "string",
|
|
970
|
-
})
|
|
971
|
-
.option("env", {
|
|
972
|
-
type: "string",
|
|
973
|
-
describe:
|
|
974
|
-
"Binds the secret to the script of the specific environment.",
|
|
975
|
-
});
|
|
976
|
-
},
|
|
977
|
-
async (args) => {
|
|
978
|
-
if (args.local) {
|
|
979
|
-
console.error("--local not implemented for this command yet");
|
|
980
|
-
return;
|
|
981
|
-
}
|
|
982
|
-
const config = args.config as Config;
|
|
983
|
-
|
|
984
|
-
// TODO: use environment (how does current wrangler do it?)
|
|
985
|
-
const scriptName = args.name || config.name;
|
|
986
|
-
if (!scriptName) {
|
|
987
|
-
throw new Error("Missing script name");
|
|
988
|
-
}
|
|
989
|
-
|
|
990
|
-
// -- snip, extract --
|
|
991
|
-
|
|
992
|
-
if (!args.local) {
|
|
993
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
994
|
-
if (!loggedIn) {
|
|
995
|
-
// didn't login, let's just quit
|
|
996
|
-
console.log("Did not login, quitting...");
|
|
997
|
-
return;
|
|
998
|
-
}
|
|
999
|
-
if (!config.account_id) {
|
|
1000
|
-
config.account_id = await getAccountId();
|
|
1001
|
-
if (!config.account_id) {
|
|
1002
|
-
console.error("No account id found, quitting...");
|
|
1003
|
-
return;
|
|
1004
|
-
}
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
// -- snip, end --
|
|
1009
|
-
|
|
1010
|
-
if (await confirm("Are you sure you want to delete this secret?")) {
|
|
1011
|
-
console.log(
|
|
1012
|
-
`Deleting the secret ${args.key} on script ${scriptName}.`
|
|
1013
|
-
);
|
|
1014
|
-
|
|
1015
|
-
console.log(
|
|
1016
|
-
await cfetch(
|
|
1017
|
-
`/accounts/${config.account_id}/workers/scripts/${scriptName}/secrets/${args.key}`,
|
|
1018
|
-
{ method: "DELETE" }
|
|
1019
|
-
)
|
|
1020
|
-
);
|
|
1021
|
-
}
|
|
1022
|
-
}
|
|
1023
|
-
)
|
|
1024
|
-
.command(
|
|
1025
|
-
"list",
|
|
1026
|
-
"List all secrets for a script",
|
|
1027
|
-
(yargs) => {
|
|
1028
|
-
return yargs
|
|
1029
|
-
.option("name", {
|
|
1030
|
-
describe: "name of the script",
|
|
1031
|
-
type: "string",
|
|
1032
|
-
})
|
|
1033
|
-
.option("env", {
|
|
1034
|
-
type: "string",
|
|
1035
|
-
describe:
|
|
1036
|
-
"Binds the secret to the script of the specific environment.",
|
|
1037
|
-
});
|
|
1038
|
-
},
|
|
1039
|
-
async (args) => {
|
|
1040
|
-
if (args.local) {
|
|
1041
|
-
console.error("--local not implemented for this command yet");
|
|
1042
|
-
return;
|
|
1043
|
-
}
|
|
1044
|
-
const config = args.config as Config;
|
|
1045
|
-
|
|
1046
|
-
// TODO: use environment (how does current wrangler do it?)
|
|
1047
|
-
const scriptName = args.name || config.name;
|
|
1048
|
-
if (!scriptName) {
|
|
1049
|
-
console.error("Missing script name");
|
|
1050
|
-
return;
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
// -- snip, extract --
|
|
1054
|
-
|
|
1055
|
-
if (!args.local) {
|
|
1056
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1057
|
-
if (!loggedIn) {
|
|
1058
|
-
// didn't login, let's just quit
|
|
1059
|
-
console.log("Did not login, quitting...");
|
|
1060
|
-
return;
|
|
1061
|
-
}
|
|
1062
|
-
if (!config.account_id) {
|
|
1063
|
-
config.account_id = await getAccountId();
|
|
1064
|
-
if (!config.account_id) {
|
|
1065
|
-
console.error("No account id found, quitting...");
|
|
1066
|
-
return;
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1069
|
-
}
|
|
1070
|
-
|
|
1071
|
-
// -- snip, end --
|
|
1072
|
-
|
|
1073
|
-
console.log(
|
|
1074
|
-
await cfetch(
|
|
1075
|
-
`/accounts/${config.account_id}/workers/scripts/${scriptName}/secrets`
|
|
1076
|
-
)
|
|
1077
|
-
);
|
|
1078
|
-
}
|
|
1079
|
-
);
|
|
1080
|
-
}
|
|
1081
|
-
);
|
|
1082
|
-
|
|
1083
|
-
// kv
|
|
1084
|
-
// :namespace
|
|
1085
|
-
yargs.command(
|
|
1086
|
-
"kv:namespace",
|
|
1087
|
-
"🗂️ Interact with your Workers KV Namespaces",
|
|
1088
|
-
(yargs) => {
|
|
1089
|
-
return yargs
|
|
1090
|
-
.command(
|
|
1091
|
-
"create <namespace>",
|
|
1092
|
-
"Create a new namespace",
|
|
1093
|
-
(yargs) => {
|
|
1094
|
-
return yargs
|
|
1095
|
-
.positional("namespace", {
|
|
1096
|
-
describe: "The name of the new namespace",
|
|
1097
|
-
type: "string",
|
|
1098
|
-
})
|
|
1099
|
-
.option("env", {
|
|
1100
|
-
type: "string",
|
|
1101
|
-
describe: "Perform on a specific environment",
|
|
1102
|
-
})
|
|
1103
|
-
.option("preview", {
|
|
1104
|
-
type: "boolean",
|
|
1105
|
-
describe: "Interact with a preview namespace",
|
|
1106
|
-
});
|
|
1107
|
-
},
|
|
1108
|
-
async (args) => {
|
|
1109
|
-
if (args._.length !== 2) {
|
|
1110
|
-
throw new Error(
|
|
1111
|
-
`Did you forget to add quotes around "${
|
|
1112
|
-
args.namespace
|
|
1113
|
-
} ${args._.slice(2).join(" ")}"?`
|
|
1114
|
-
);
|
|
1115
|
-
}
|
|
1116
|
-
const config = args.config as Config;
|
|
1117
|
-
if (!config.name) {
|
|
1118
|
-
console.warn(
|
|
1119
|
-
"No configured name present, using `worker` as a prefix for the title"
|
|
1120
|
-
);
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
const title = `${config.name || "worker"}${
|
|
1124
|
-
args.env ? `-${args.env}` : ""
|
|
1125
|
-
}-${args.namespace}${args.preview ? "_preview" : ""}`;
|
|
1126
|
-
|
|
1127
|
-
if (/[\W]+/.test(args.namespace)) {
|
|
1128
|
-
throw new Error("invalid binding name, needs to be js friendly");
|
|
1129
|
-
}
|
|
1130
|
-
|
|
1131
|
-
if (args.local) {
|
|
1132
|
-
const { Miniflare } = await import("miniflare");
|
|
1133
|
-
const mf = new Miniflare({
|
|
1134
|
-
kvPersist: (args.kvPersist as string) || true,
|
|
1135
|
-
// TODO: these options shouldn't be required
|
|
1136
|
-
script: ` `, // has to be a string with at least one char
|
|
1137
|
-
});
|
|
1138
|
-
mf.getKVNamespace(title); // this should "create" the namespace
|
|
1139
|
-
console.log(`✨ Success! Created KV namespace ${title}`);
|
|
1140
|
-
return;
|
|
1141
|
-
}
|
|
1142
|
-
|
|
1143
|
-
// -- snip, extract --
|
|
1144
|
-
|
|
1145
|
-
if (!args.local) {
|
|
1146
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1147
|
-
if (!loggedIn) {
|
|
1148
|
-
// didn't login, let's just quit
|
|
1149
|
-
console.log("Did not login, quitting...");
|
|
1150
|
-
return;
|
|
1151
|
-
}
|
|
1152
|
-
if (!config.account_id) {
|
|
1153
|
-
config.account_id = await getAccountId();
|
|
1154
|
-
if (!config.account_id) {
|
|
1155
|
-
console.error("No account id found, quitting...");
|
|
1156
|
-
return;
|
|
1157
|
-
}
|
|
1158
|
-
}
|
|
1159
|
-
}
|
|
1160
|
-
|
|
1161
|
-
// -- snip, end --
|
|
1162
|
-
|
|
1163
|
-
// TODO: generate a binding name stripping non alphanumeric chars
|
|
1164
|
-
|
|
1165
|
-
console.log(`🌀 Creating namespace with title "${title}"`);
|
|
1166
|
-
|
|
1167
|
-
const response = await cfetch<{ id: string }>(
|
|
1168
|
-
`/accounts/${config.account_id}/storage/kv/namespaces`,
|
|
1169
|
-
{
|
|
1170
|
-
method: "POST",
|
|
1171
|
-
headers: {
|
|
1172
|
-
"Content-Type": "application/json",
|
|
1173
|
-
},
|
|
1174
|
-
body: JSON.stringify({
|
|
1175
|
-
title,
|
|
1176
|
-
}),
|
|
1177
|
-
}
|
|
1178
|
-
);
|
|
1179
|
-
|
|
1180
|
-
console.log("✨ Success!");
|
|
1181
|
-
console.log(
|
|
1182
|
-
`Add the following to your configuration file in your kv_namespaces array${
|
|
1183
|
-
args.env ? ` under [env.${args.env}]` : ""
|
|
1184
|
-
}:`
|
|
1185
|
-
);
|
|
1186
|
-
console.log(
|
|
1187
|
-
`{ binding = "${args.namespace}", ${
|
|
1188
|
-
args.preview ? "preview_" : ""
|
|
1189
|
-
}id = "${response.id}" }`
|
|
1190
|
-
);
|
|
1191
|
-
}
|
|
1192
|
-
)
|
|
1193
|
-
.command(
|
|
1194
|
-
"list",
|
|
1195
|
-
"Outputs a list of all KV namespaces associated with your account id.",
|
|
1196
|
-
{},
|
|
1197
|
-
async (args) => {
|
|
1198
|
-
if (args.local) {
|
|
1199
|
-
console.error(`local mode is not yet supported for this command`);
|
|
1200
|
-
return;
|
|
1201
|
-
}
|
|
1202
|
-
|
|
1203
|
-
const config = args.config as Config;
|
|
1204
|
-
|
|
1205
|
-
// -- snip, extract --
|
|
1206
|
-
|
|
1207
|
-
if (!args.local) {
|
|
1208
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1209
|
-
if (!loggedIn) {
|
|
1210
|
-
// didn't login, let's just quit
|
|
1211
|
-
console.log("Did not login, quitting...");
|
|
1212
|
-
return;
|
|
1213
|
-
}
|
|
1214
|
-
if (!config.account_id) {
|
|
1215
|
-
config.account_id = await getAccountId();
|
|
1216
|
-
if (!config.account_id) {
|
|
1217
|
-
console.error("No account id found, quitting...");
|
|
1218
|
-
return;
|
|
1219
|
-
}
|
|
1220
|
-
}
|
|
1221
|
-
}
|
|
1222
|
-
|
|
1223
|
-
// -- snip, end --
|
|
1224
|
-
|
|
1225
|
-
// TODO: we should show bindings if they exist for given ids
|
|
1226
|
-
|
|
1227
|
-
console.log(
|
|
1228
|
-
JSON.stringify(
|
|
1229
|
-
await listNamespaces(config.account_id),
|
|
1230
|
-
null,
|
|
1231
|
-
" "
|
|
1232
|
-
)
|
|
1233
|
-
);
|
|
1234
|
-
}
|
|
1235
|
-
)
|
|
1236
|
-
.command(
|
|
1237
|
-
"delete",
|
|
1238
|
-
"Deletes a given namespace.",
|
|
1239
|
-
(yargs) => {
|
|
1240
|
-
return yargs
|
|
1241
|
-
.option("binding", {
|
|
1242
|
-
type: "string",
|
|
1243
|
-
describe: "The name of the namespace to delete",
|
|
1244
|
-
})
|
|
1245
|
-
.option("namespace-id", {
|
|
1246
|
-
type: "string",
|
|
1247
|
-
describe: "The id of the namespace to delete",
|
|
1248
|
-
})
|
|
1249
|
-
.check(demandOneOfOption("binding", "namespace-id"))
|
|
1250
|
-
.option("env", {
|
|
1251
|
-
type: "string",
|
|
1252
|
-
describe: "Perform on a specific environment",
|
|
1253
|
-
})
|
|
1254
|
-
.option("preview", {
|
|
1255
|
-
type: "boolean",
|
|
1256
|
-
describe: "Interact with a preview namespace",
|
|
1257
|
-
});
|
|
1258
|
-
},
|
|
1259
|
-
async (args) => {
|
|
1260
|
-
if (args.local) {
|
|
1261
|
-
console.error(`local mode is not yet supported for this command`);
|
|
1262
|
-
return;
|
|
1263
|
-
}
|
|
1264
|
-
const config = args.config as Config;
|
|
1265
|
-
|
|
1266
|
-
const id =
|
|
1267
|
-
args["namespace-id"] ||
|
|
1268
|
-
(args.env
|
|
1269
|
-
? config.env[args.env] || {}
|
|
1270
|
-
: config
|
|
1271
|
-
).kv_namespaces.find(
|
|
1272
|
-
(namespace) => namespace.binding === args.binding
|
|
1273
|
-
)[args.preview ? "preview_id" : "id"];
|
|
1274
|
-
if (!id) {
|
|
1275
|
-
throw new Error("Are you sure? id not found");
|
|
1276
|
-
}
|
|
1277
|
-
|
|
1278
|
-
// -- snip, extract --
|
|
1279
|
-
|
|
1280
|
-
if (!args.local) {
|
|
1281
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1282
|
-
if (!loggedIn) {
|
|
1283
|
-
// didn't login, let's just quit
|
|
1284
|
-
console.log("Did not login, quitting...");
|
|
1285
|
-
return;
|
|
1286
|
-
}
|
|
1287
|
-
|
|
1288
|
-
if (!config.account_id) {
|
|
1289
|
-
config.account_id = await getAccountId();
|
|
1290
|
-
if (!config.account_id) {
|
|
1291
|
-
console.error("No account id found, quitting...");
|
|
1292
|
-
return;
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
}
|
|
1296
|
-
|
|
1297
|
-
// -- snip, end --
|
|
1298
|
-
|
|
1299
|
-
await cfetch<{ id: string }>(
|
|
1300
|
-
`/accounts/${config.account_id}/storage/kv/namespaces/${id}`,
|
|
1301
|
-
{ method: "DELETE" }
|
|
1302
|
-
);
|
|
1303
|
-
|
|
1304
|
-
// TODO: recommend they remove it from wrangler.toml
|
|
1305
|
-
|
|
1306
|
-
// test-mf wrangler kv:namespace delete --namespace-id 2a7d3d8b23fc4159b5afa489d6cfd388
|
|
1307
|
-
// Are you sure you want to delete namespace 2a7d3d8b23fc4159b5afa489d6cfd388? [y/n]
|
|
1308
|
-
// n
|
|
1309
|
-
// 💁 Not deleting namespace 2a7d3d8b23fc4159b5afa489d6cfd388
|
|
1310
|
-
// ➜ test-mf wrangler kv:namespace delete --namespace-id 2a7d3d8b23fc4159b5afa489d6cfd388
|
|
1311
|
-
// Are you sure you want to delete namespace 2a7d3d8b23fc4159b5afa489d6cfd388? [y/n]
|
|
1312
|
-
// y
|
|
1313
|
-
// 🌀 Deleting namespace 2a7d3d8b23fc4159b5afa489d6cfd388
|
|
1314
|
-
// ✨ Success
|
|
1315
|
-
// ⚠️ Make sure to remove this "kv-namespace" entry from your configuration file!
|
|
1316
|
-
// ➜ test-mf
|
|
1317
|
-
|
|
1318
|
-
// TODO: do it automatically
|
|
1319
|
-
|
|
1320
|
-
// TODO: delete the preview namespace as well?
|
|
1321
|
-
}
|
|
1322
|
-
);
|
|
1323
|
-
}
|
|
1324
|
-
);
|
|
1325
|
-
|
|
1326
|
-
// :key
|
|
1327
|
-
yargs.command(
|
|
1328
|
-
"kv:key",
|
|
1329
|
-
"🔑 Individually manage Workers KV key-value pairs",
|
|
1330
|
-
(yargs) => {
|
|
1331
|
-
return yargs
|
|
1332
|
-
.command(
|
|
1333
|
-
"put <key> <value>",
|
|
1334
|
-
"Writes a single key/value pair to the given namespace.",
|
|
1335
|
-
(yargs) => {
|
|
1336
|
-
return yargs
|
|
1337
|
-
.positional("key", {
|
|
1338
|
-
type: "string",
|
|
1339
|
-
describe: "The key to write to.",
|
|
1340
|
-
})
|
|
1341
|
-
.positional("value", {
|
|
1342
|
-
type: "string",
|
|
1343
|
-
describe: "The value to write.",
|
|
1344
|
-
})
|
|
1345
|
-
.option("binding", {
|
|
1346
|
-
type: "string",
|
|
1347
|
-
describe: "The binding of the namespace to write to.",
|
|
1348
|
-
})
|
|
1349
|
-
.option("namespace-id", {
|
|
1350
|
-
type: "string",
|
|
1351
|
-
describe: "The id of the namespace to write to.",
|
|
1352
|
-
})
|
|
1353
|
-
.check(demandOneOfOption("binding", "namespace-id"))
|
|
1354
|
-
.option("env", {
|
|
1355
|
-
type: "string",
|
|
1356
|
-
describe: "Perform on a specific environment",
|
|
1357
|
-
})
|
|
1358
|
-
.option("preview", {
|
|
1359
|
-
type: "boolean",
|
|
1360
|
-
describe: "Interact with a preview namespace",
|
|
1361
|
-
})
|
|
1362
|
-
.option("ttl", {
|
|
1363
|
-
type: "number",
|
|
1364
|
-
describe: "Time for which the entries should be visible.",
|
|
1365
|
-
})
|
|
1366
|
-
.option("expiration", {
|
|
1367
|
-
type: "number",
|
|
1368
|
-
describe:
|
|
1369
|
-
"Time since the UNIX epoch after which the entry expires",
|
|
1370
|
-
})
|
|
1371
|
-
.option("path", {
|
|
1372
|
-
type: "string",
|
|
1373
|
-
describe: "Read value from the file at a given path.",
|
|
1374
|
-
});
|
|
1375
|
-
},
|
|
1376
|
-
async ({ key, ttl, expiration, ...args }) => {
|
|
1377
|
-
const namespaceId = getNamespaceId(args);
|
|
1378
|
-
const value = args.path
|
|
1379
|
-
? await readFile(args.path, "utf-8")
|
|
1380
|
-
: args.value;
|
|
1381
|
-
const config = args.config as Config;
|
|
1382
|
-
|
|
1383
|
-
console.log(`writing ${key}=${value} to namespace ${namespaceId}`);
|
|
1384
|
-
if (args.local) {
|
|
1385
|
-
const { Miniflare } = await import("miniflare");
|
|
1386
|
-
const mf = new Miniflare({
|
|
1387
|
-
kvPersist: (args.kvPersist as string) || true,
|
|
1388
|
-
// TODO: these options shouldn't be required
|
|
1389
|
-
script: ` `, // has to be a string with at least one char
|
|
1390
|
-
});
|
|
1391
|
-
const ns = await mf.getKVNamespace(namespaceId);
|
|
1392
|
-
await ns.put(key, value, { expiration, expirationTtl: ttl });
|
|
1393
|
-
return;
|
|
1394
|
-
}
|
|
1395
|
-
// -- snip, extract --
|
|
1396
|
-
|
|
1397
|
-
if (!args.local) {
|
|
1398
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1399
|
-
if (!loggedIn) {
|
|
1400
|
-
// didn't login, let's just quit
|
|
1401
|
-
console.log("Did not login, quitting...");
|
|
1402
|
-
return;
|
|
1403
|
-
}
|
|
1404
|
-
|
|
1405
|
-
if (!config.account_id) {
|
|
1406
|
-
config.account_id = await getAccountId();
|
|
1407
|
-
if (!config.account_id) {
|
|
1408
|
-
console.error("No account id found, quitting...");
|
|
1409
|
-
return;
|
|
1410
|
-
}
|
|
1411
|
-
}
|
|
1412
|
-
}
|
|
1413
|
-
|
|
1414
|
-
// -- snip, end --
|
|
1415
|
-
|
|
1416
|
-
await putKeyValue(config.account_id, namespaceId, key, value, {
|
|
1417
|
-
expiration,
|
|
1418
|
-
expiration_ttl: ttl,
|
|
1419
|
-
});
|
|
1420
|
-
}
|
|
1421
|
-
)
|
|
1422
|
-
.command(
|
|
1423
|
-
"list",
|
|
1424
|
-
"Outputs a list of all keys in a given namespace.",
|
|
1425
|
-
(yargs) => {
|
|
1426
|
-
return yargs
|
|
1427
|
-
.option("binding", {
|
|
1428
|
-
type: "string",
|
|
1429
|
-
describe: "The name of the namespace to list",
|
|
1430
|
-
})
|
|
1431
|
-
.option("namespace-id", {
|
|
1432
|
-
type: "string",
|
|
1433
|
-
describe: "The id of the namespace to list",
|
|
1434
|
-
})
|
|
1435
|
-
.check(demandOneOfOption("binding", "namespace-id"))
|
|
1436
|
-
.option("env", {
|
|
1437
|
-
type: "string",
|
|
1438
|
-
describe: "Perform on a specific environment",
|
|
1439
|
-
})
|
|
1440
|
-
.option("prefix", {
|
|
1441
|
-
type: "string",
|
|
1442
|
-
describe: "A prefix to filter listed keys",
|
|
1443
|
-
});
|
|
1444
|
-
},
|
|
1445
|
-
async ({ prefix, ...args }) => {
|
|
1446
|
-
// TODO: support for limit+cursor (pagination)
|
|
1447
|
-
|
|
1448
|
-
const namespaceId = getNamespaceId(args);
|
|
1449
|
-
const config = args.config as Config;
|
|
1450
|
-
|
|
1451
|
-
if (args.local) {
|
|
1452
|
-
const { Miniflare } = await import("miniflare");
|
|
1453
|
-
const mf = new Miniflare({
|
|
1454
|
-
kvPersist: (args.kvPersist as string) || true,
|
|
1455
|
-
// TODO: these options shouldn't be required
|
|
1456
|
-
script: ` `, // has to be a string with at least one char
|
|
1457
|
-
});
|
|
1458
|
-
const ns = await mf.getKVNamespace(namespaceId);
|
|
1459
|
-
const listResponse = await ns.list({ prefix });
|
|
1460
|
-
console.log(JSON.stringify(listResponse.keys, null, " ")); // TODO: paginate, collate
|
|
1461
|
-
return;
|
|
1462
|
-
}
|
|
1463
|
-
|
|
1464
|
-
// -- snip, extract --
|
|
1465
|
-
|
|
1466
|
-
if (!args.local) {
|
|
1467
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1468
|
-
if (!loggedIn) {
|
|
1469
|
-
// didn't login, let's just quit
|
|
1470
|
-
console.log("Did not login, quitting...");
|
|
1471
|
-
return;
|
|
1472
|
-
}
|
|
1473
|
-
|
|
1474
|
-
if (!config.account_id) {
|
|
1475
|
-
config.account_id = await getAccountId();
|
|
1476
|
-
if (!config.account_id) {
|
|
1477
|
-
console.error("No account id found, quitting...");
|
|
1478
|
-
return;
|
|
1479
|
-
}
|
|
1480
|
-
}
|
|
1481
|
-
}
|
|
1482
|
-
|
|
1483
|
-
// -- snip, end --
|
|
1484
|
-
|
|
1485
|
-
console.log(
|
|
1486
|
-
await listNamespaceKeys(config.account_id, namespaceId, prefix)
|
|
1487
|
-
);
|
|
1488
|
-
}
|
|
1489
|
-
)
|
|
1490
|
-
.command(
|
|
1491
|
-
"get <key>",
|
|
1492
|
-
"Reads a single value by key from the given namespace.",
|
|
1493
|
-
(yargs) => {
|
|
1494
|
-
return yargs
|
|
1495
|
-
.positional("key", {
|
|
1496
|
-
describe: "The key value to get.",
|
|
1497
|
-
type: "string",
|
|
1498
|
-
})
|
|
1499
|
-
.option("binding", {
|
|
1500
|
-
type: "string",
|
|
1501
|
-
describe: "The name of the namespace to get from",
|
|
1502
|
-
})
|
|
1503
|
-
.option("namespace-id", {
|
|
1504
|
-
type: "string",
|
|
1505
|
-
describe: "The id of the namespace to get from",
|
|
1506
|
-
})
|
|
1507
|
-
.check(demandOneOfOption("binding", "namespace-id"))
|
|
1508
|
-
.option("env", {
|
|
1509
|
-
type: "string",
|
|
1510
|
-
describe: "Perform on a specific environment",
|
|
1511
|
-
})
|
|
1512
|
-
.option("preview", {
|
|
1513
|
-
type: "boolean",
|
|
1514
|
-
describe: "Interact with a preview namespace",
|
|
1515
|
-
});
|
|
1516
|
-
},
|
|
1517
|
-
async ({ key, ...args }) => {
|
|
1518
|
-
const namespaceId = getNamespaceId(args);
|
|
1519
|
-
const config = args.config as Config;
|
|
1520
|
-
|
|
1521
|
-
if (args.local) {
|
|
1522
|
-
const { Miniflare } = await import("miniflare");
|
|
1523
|
-
const mf = new Miniflare({
|
|
1524
|
-
kvPersist: (args.kvPersist as string) || true,
|
|
1525
|
-
// TODO: these options shouldn't be required
|
|
1526
|
-
script: ` `, // has to be a string with at least one char
|
|
1527
|
-
});
|
|
1528
|
-
const ns = await mf.getKVNamespace(namespaceId);
|
|
1529
|
-
console.log(await ns.get(key));
|
|
1530
|
-
return;
|
|
1531
|
-
}
|
|
1532
|
-
|
|
1533
|
-
// -- snip, extract --
|
|
1534
|
-
|
|
1535
|
-
if (!args.local) {
|
|
1536
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1537
|
-
if (!loggedIn) {
|
|
1538
|
-
// didn't login, let's just quit
|
|
1539
|
-
console.log("Did not login, quitting...");
|
|
1540
|
-
return;
|
|
1541
|
-
}
|
|
1542
|
-
|
|
1543
|
-
if (!config.account_id) {
|
|
1544
|
-
config.account_id = await getAccountId();
|
|
1545
|
-
if (!config.account_id) {
|
|
1546
|
-
console.error("No account id found, quitting...");
|
|
1547
|
-
return;
|
|
1548
|
-
}
|
|
1549
|
-
}
|
|
1550
|
-
}
|
|
1551
|
-
|
|
1552
|
-
// -- snip, end --
|
|
1553
|
-
|
|
1554
|
-
// annoyingly, the API for this one doesn't return the
|
|
1555
|
-
// data in the 'standard' format. goddamit.
|
|
1556
|
-
// That's why we have the fallthrough response in cfetch.
|
|
1557
|
-
// Oh well.
|
|
1558
|
-
console.log(
|
|
1559
|
-
await cfetch(
|
|
1560
|
-
`/accounts/${config.account_id}/storage/kv/namespaces/${namespaceId}/values/${key}`
|
|
1561
|
-
)
|
|
1562
|
-
);
|
|
1563
|
-
}
|
|
1564
|
-
)
|
|
1565
|
-
.command(
|
|
1566
|
-
"delete <key>",
|
|
1567
|
-
"Removes a single key value pair from the given namespace.",
|
|
1568
|
-
(yargs) => {
|
|
1569
|
-
return yargs
|
|
1570
|
-
.positional("key", {
|
|
1571
|
-
describe: "The key value to delete",
|
|
1572
|
-
type: "string",
|
|
1573
|
-
})
|
|
1574
|
-
.option("binding", {
|
|
1575
|
-
type: "string",
|
|
1576
|
-
describe: "The name of the namespace to delete from",
|
|
1577
|
-
})
|
|
1578
|
-
.option("namespace-id", {
|
|
1579
|
-
type: "string",
|
|
1580
|
-
describe: "The id of the namespace to delete from",
|
|
1581
|
-
})
|
|
1582
|
-
.check(demandOneOfOption("binding", "namespace-id"))
|
|
1583
|
-
.option("env", {
|
|
1584
|
-
type: "string",
|
|
1585
|
-
describe: "Perform on a specific environment",
|
|
1586
|
-
})
|
|
1587
|
-
.option("preview", {
|
|
1588
|
-
type: "boolean",
|
|
1589
|
-
describe: "Interact with a preview namespace",
|
|
1590
|
-
});
|
|
1591
|
-
},
|
|
1592
|
-
async ({ key, ...args }) => {
|
|
1593
|
-
const namespaceId = getNamespaceId(args);
|
|
1594
|
-
|
|
1595
|
-
if (args.local) {
|
|
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 --
|
|
1629
|
-
|
|
1630
|
-
await cfetch(
|
|
1631
|
-
`/accounts/${config.account_id}/storage/kv/namespaces/${namespaceId}/values/${key}`,
|
|
1632
|
-
{ method: "DELETE" }
|
|
1633
|
-
);
|
|
1634
|
-
}
|
|
1635
|
-
);
|
|
1636
|
-
}
|
|
1637
|
-
);
|
|
1638
|
-
|
|
1639
|
-
// :bulk
|
|
1640
|
-
yargs.command(
|
|
1641
|
-
"kv:bulk",
|
|
1642
|
-
"💪 Interact with multiple Workers KV key-value pairs at once",
|
|
1643
|
-
(yargs) => {
|
|
1644
|
-
return yargs
|
|
1645
|
-
.command(
|
|
1646
|
-
"put <filename>",
|
|
1647
|
-
"Upload multiple key-value pairs to a namespace",
|
|
1648
|
-
(yargs) => {
|
|
1649
|
-
return yargs
|
|
1650
|
-
.positional("filename", {
|
|
1651
|
-
describe: `The JSON file of key-value pairs to upload, in form [{"key":..., "value":...}"...]`,
|
|
1652
|
-
type: "string",
|
|
1653
|
-
})
|
|
1654
|
-
.option("binding", {
|
|
1655
|
-
type: "string",
|
|
1656
|
-
describe: "The name of the namespace to put to",
|
|
1657
|
-
})
|
|
1658
|
-
.option("namespace-id", {
|
|
1659
|
-
type: "string",
|
|
1660
|
-
describe: "The id of the namespace to put to",
|
|
1661
|
-
})
|
|
1662
|
-
.check(demandOneOfOption("binding", "namespace-id"))
|
|
1663
|
-
.option("env", {
|
|
1664
|
-
type: "string",
|
|
1665
|
-
describe: "Perform on a specific environment",
|
|
1666
|
-
})
|
|
1667
|
-
.option("preview", {
|
|
1668
|
-
type: "boolean",
|
|
1669
|
-
describe: "Interact with a preview namespace",
|
|
1670
|
-
});
|
|
1671
|
-
},
|
|
1672
|
-
async ({ filename, ...args }) => {
|
|
1673
|
-
// The simplest implementation I could think of.
|
|
1674
|
-
// This could be made more efficient with a streaming parser/uploader
|
|
1675
|
-
// but we'll do that in the future if needed.
|
|
1676
|
-
|
|
1677
|
-
const namespaceId = getNamespaceId(args);
|
|
1678
|
-
const config = args.config as Config;
|
|
1679
|
-
const content = await readFile(filename, "utf-8");
|
|
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
|
-
}
|
|
1707
|
-
|
|
1708
|
-
return;
|
|
1709
|
-
}
|
|
1710
|
-
|
|
1711
|
-
// -- snip, extract --
|
|
1712
|
-
|
|
1713
|
-
if (!args.local) {
|
|
1714
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1715
|
-
if (!loggedIn) {
|
|
1716
|
-
// didn't login, let's just quit
|
|
1717
|
-
console.log("Did not login, quitting...");
|
|
1718
|
-
return;
|
|
1719
|
-
}
|
|
1720
|
-
|
|
1721
|
-
if (!config.account_id) {
|
|
1722
|
-
config.account_id = await getAccountId();
|
|
1723
|
-
if (!config.account_id) {
|
|
1724
|
-
console.error("No account id found, quitting...");
|
|
1725
|
-
return;
|
|
1726
|
-
}
|
|
1727
|
-
}
|
|
1728
|
-
}
|
|
1729
|
-
|
|
1730
|
-
// -- snip, end --
|
|
1731
|
-
|
|
1732
|
-
console.log(
|
|
1733
|
-
await putBulkKeyValue(config.account_id, namespaceId, content)
|
|
1734
|
-
);
|
|
1735
|
-
}
|
|
1736
|
-
)
|
|
1737
|
-
.command(
|
|
1738
|
-
"delete <filename>",
|
|
1739
|
-
"Upload multiple key-value pairs to a namespace",
|
|
1740
|
-
(yargs) => {
|
|
1741
|
-
return yargs
|
|
1742
|
-
.positional("filename", {
|
|
1743
|
-
describe: `The JSON file of key-value pairs to upload, in form ["key1", "key2", ...]`,
|
|
1744
|
-
type: "string",
|
|
1745
|
-
})
|
|
1746
|
-
.option("binding", {
|
|
1747
|
-
type: "string",
|
|
1748
|
-
describe: "The name of the namespace to delete from",
|
|
1749
|
-
})
|
|
1750
|
-
.option("namespace-id", {
|
|
1751
|
-
type: "string",
|
|
1752
|
-
describe: "The id of the namespace to delete from",
|
|
1753
|
-
})
|
|
1754
|
-
.check(demandOneOfOption("binding", "namespace-id"))
|
|
1755
|
-
.option("env", {
|
|
1756
|
-
type: "string",
|
|
1757
|
-
describe: "Perform on a specific environment",
|
|
1758
|
-
})
|
|
1759
|
-
.option("preview", {
|
|
1760
|
-
type: "boolean",
|
|
1761
|
-
describe: "Interact with a preview namespace",
|
|
1762
|
-
});
|
|
1763
|
-
},
|
|
1764
|
-
async ({ filename, ...args }) => {
|
|
1765
|
-
const namespaceId = getNamespaceId(args);
|
|
1766
|
-
const config = args.config as Config;
|
|
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
|
-
}
|
|
1775
|
-
|
|
1776
|
-
if (args.local) {
|
|
1777
|
-
const { Miniflare } = await import("miniflare");
|
|
1778
|
-
const mf = new Miniflare({
|
|
1779
|
-
kvPersist: (args.kvPersist as string) || true,
|
|
1780
|
-
// TODO: these options shouldn't be required
|
|
1781
|
-
script: ` `, // has to be a string with at least one char
|
|
1782
|
-
});
|
|
1783
|
-
const ns = await mf.getKVNamespace(namespaceId);
|
|
1784
|
-
for (const key of parsedContent) {
|
|
1785
|
-
await ns.delete(key);
|
|
1786
|
-
}
|
|
1787
|
-
|
|
1788
|
-
return;
|
|
1789
|
-
}
|
|
1790
|
-
|
|
1791
|
-
// -- snip, extract --
|
|
1792
|
-
|
|
1793
|
-
if (!args.local) {
|
|
1794
|
-
const loggedIn = await loginOrRefreshIfRequired();
|
|
1795
|
-
if (!loggedIn) {
|
|
1796
|
-
// didn't login, let's just quit
|
|
1797
|
-
console.log("Did not login, quitting...");
|
|
1798
|
-
return;
|
|
1799
|
-
}
|
|
1800
|
-
|
|
1801
|
-
if (!config.account_id) {
|
|
1802
|
-
config.account_id = await getAccountId();
|
|
1803
|
-
if (!config.account_id) {
|
|
1804
|
-
console.error("No account id found, quitting...");
|
|
1805
|
-
return;
|
|
1806
|
-
}
|
|
1807
|
-
}
|
|
1808
|
-
}
|
|
1809
|
-
|
|
1810
|
-
// -- snip, end --
|
|
1811
|
-
|
|
1812
|
-
console.log(
|
|
1813
|
-
await deleteBulkKeyValue(config.account_id, namespaceId, content)
|
|
1814
|
-
);
|
|
1815
|
-
}
|
|
1816
|
-
);
|
|
1817
|
-
}
|
|
1818
|
-
);
|
|
1819
|
-
|
|
1820
|
-
yargs.command("pages", "⚡️ Configure Cloudflare Pages", pages);
|
|
1821
|
-
|
|
1822
|
-
yargs
|
|
1823
|
-
.option("config", {
|
|
1824
|
-
describe: "Path to .toml configuration file",
|
|
1825
|
-
type: "string",
|
|
1826
|
-
async coerce(arg) {
|
|
1827
|
-
return await readConfig(arg);
|
|
1828
|
-
},
|
|
1829
|
-
})
|
|
1830
|
-
.option("local", {
|
|
1831
|
-
describe: "Run on my machine",
|
|
1832
|
-
type: "boolean",
|
|
1833
|
-
default: false, // I bet this will a point of contention. We'll revisit it.
|
|
1834
|
-
});
|
|
1835
|
-
|
|
1836
|
-
yargs.group(["config", "help", "version"], "Flags:");
|
|
1837
|
-
yargs.version(wranglerVersion);
|
|
1838
|
-
await initialiseUserConfig();
|
|
1839
|
-
|
|
1840
|
-
await yargs.parse(argv, (err, argv, output) => {
|
|
1841
|
-
if (output) {
|
|
1842
|
-
console.log(output);
|
|
1843
|
-
}
|
|
1844
|
-
});
|
|
1845
|
-
}
|