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