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