wrangler 2.6.1 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/wrangler.js +9 -1
- package/miniflare-dist/index.mjs +1 -1
- package/package.json +12 -10
- package/src/__tests__/api-dev.test.ts +65 -36
- package/src/__tests__/api-devregistry.test.js +14 -6
- package/src/__tests__/configuration.test.ts +2 -31
- package/src/__tests__/{d1.test.ts → d1/d1.test.ts} +48 -5
- package/src/__tests__/d1/splitter.test.ts +255 -0
- package/src/__tests__/delete.test.ts +5 -2
- package/src/__tests__/deployments.test.ts +20 -6
- package/src/__tests__/dev.test.tsx +52 -19
- package/src/__tests__/generate.test.ts +7 -4
- package/src/__tests__/helpers/mock-auth-domain.ts +20 -0
- package/src/__tests__/helpers/mock-cfetch.ts +2 -57
- package/src/__tests__/helpers/mock-dialogs.ts +70 -86
- package/src/__tests__/helpers/mock-oauth-flow.ts +64 -49
- package/src/__tests__/helpers/mock-process.ts +8 -13
- package/src/__tests__/helpers/msw/blob-worker.cjs +19 -0
- package/src/__tests__/helpers/msw/read-file-sync.js +61 -0
- package/src/__tests__/index.test.ts +46 -42
- package/src/__tests__/init.test.ts +782 -522
- package/src/__tests__/jest.setup.ts +20 -24
- package/src/__tests__/kv.test.ts +286 -173
- package/src/__tests__/logout.test.ts +1 -1
- package/src/__tests__/metrics.test.ts +5 -7
- package/src/__tests__/middleware.scheduled.test.ts +40 -30
- package/src/__tests__/middleware.test.ts +144 -120
- package/src/__tests__/pages.test.ts +1618 -1161
- package/src/__tests__/publish.test.ts +174 -125
- package/src/__tests__/r2.test.ts +2 -2
- package/src/__tests__/secret.test.ts +183 -126
- package/src/__tests__/tail.test.ts +6 -0
- package/src/__tests__/tsconfig-sanity.ts +12 -0
- package/src/__tests__/tsconfig.json +8 -0
- package/src/__tests__/tsconfig.tsbuildinfo +1 -0
- package/src/__tests__/whoami.test.tsx +1 -96
- package/src/api/dev.ts +78 -41
- package/src/api/index.ts +1 -1
- package/src/{bundle-reporter.tsx → bundle-reporter.ts} +0 -0
- package/src/cfetch/index.ts +0 -2
- package/src/cfetch/internal.ts +16 -18
- package/src/cli.ts +2 -2
- package/src/config/index.ts +2 -1
- package/src/config/validation.ts +1 -2
- package/src/create-worker-upload-form.ts +2 -2
- package/src/d1/{delete.tsx → delete.ts} +0 -0
- package/src/d1/execute.tsx +8 -37
- package/src/d1/migrations/apply.tsx +32 -19
- package/src/d1/migrations/{index.tsx → index.ts} +0 -0
- package/src/d1/splitter.ts +161 -0
- package/src/d1/{types.tsx → types.ts} +0 -0
- package/src/delete.ts +3 -8
- package/src/deployments.ts +6 -0
- package/src/deprecated/index.ts +2 -295
- package/src/dev/dev.tsx +2 -2
- package/src/dev/{get-local-persistence-path.tsx → get-local-persistence-path.ts} +0 -0
- package/src/dev/local.tsx +16 -4
- package/src/dev/remote.tsx +28 -1
- package/src/dev/start-server.ts +19 -11
- package/src/dev/use-esbuild.ts +1 -1
- package/src/{dev-registry.tsx → dev-registry.ts} +0 -0
- package/src/dev.tsx +35 -11
- package/src/dialogs.ts +136 -0
- package/src/dispatch-namespace.ts +1 -1
- package/src/docs/index.ts +97 -0
- package/src/environment-variables/factory.ts +88 -0
- package/src/environment-variables/misc-variables.ts +30 -0
- package/src/generate/index.ts +300 -0
- package/src/{index.tsx → index.ts} +16 -10
- package/src/init.ts +106 -60
- package/src/jest.d.ts +4 -0
- package/src/logger.ts +15 -3
- package/src/metrics/metrics-config.ts +1 -1
- package/src/metrics/send-event.ts +2 -1
- package/src/miniflare-cli/assets.ts +4 -0
- package/src/miniflare-cli/index.ts +1 -5
- package/src/miniflare-cli/tsconfig.json +9 -0
- package/src/miniflare-cli/tsconfig.tsbuildinfo +1 -0
- package/src/miniflare-cli/types.ts +11 -0
- package/src/pages/{build.tsx → build.ts} +0 -0
- package/src/pages/{deployment-tails.tsx → deployment-tails.ts} +0 -0
- package/src/pages/{dev.tsx → dev.ts} +53 -55
- package/src/pages/functions/buildWorker.ts +1 -1
- package/src/pages/functions/tsconfig.json +8 -0
- package/src/pages/functions/tsconfig.tsbuildinfo +1 -0
- package/src/pages/{functions.tsx → functions.ts} +0 -0
- package/src/pages/{hash.tsx → hash.ts} +0 -0
- package/src/pages/{index.tsx → index.ts} +0 -0
- package/src/pages/projects.tsx +3 -5
- package/src/pages/publish.tsx +16 -5
- package/src/pages/upload.tsx +27 -6
- package/src/publish/publish.ts +9 -7
- package/src/pubsub/{pubsub-commands.tsx → pubsub-commands.ts} +1 -1
- package/src/secret/index.ts +1 -1
- package/src/{sites.tsx → sites.ts} +0 -0
- package/src/tail/index.ts +2 -3
- package/src/tsconfig-sanity.ts +16 -0
- package/src/user/access.ts +0 -1
- package/src/user/auth-variables.ts +113 -0
- package/src/user/choose-account.tsx +1 -31
- package/src/user/index.ts +0 -1
- package/src/user/{user.tsx → user.ts} +107 -73
- package/src/{whoami.tsx → whoami.ts} +37 -71
- package/templates/__tests__/tsconfig-sanity.ts +12 -0
- package/templates/__tests__/tsconfig.json +8 -0
- package/templates/__tests__/tsconfig.tsbuildinfo +1 -0
- package/templates/d1-beta-facade.js +36 -0
- package/templates/facade.d.ts +14 -0
- package/templates/first-party-worker-module-facade.ts +4 -3
- package/templates/format-dev-errors.ts +7 -6
- package/templates/init-tests/test-jest-new-worker.js +3 -5
- package/templates/init-tests/test-vitest-new-worker.js +3 -5
- package/templates/init-tests/test-vitest-new-worker.ts +25 -0
- package/templates/middleware/loader-modules.ts +0 -2
- package/templates/middleware/loader-sw.ts +6 -0
- package/templates/pages-dev-pipeline.ts +4 -1
- package/templates/pages-shim.ts +4 -1
- package/templates/pages-template-plugin.ts +12 -7
- package/templates/serve-static-assets.ts +16 -14
- package/templates/tsconfig-sanity.ts +11 -0
- package/templates/tsconfig.init.json +106 -0
- package/templates/tsconfig.json +5 -103
- package/templates/tsconfig.tsbuildinfo +1 -0
- package/wrangler-dist/cli.d.ts +58 -60
- package/wrangler-dist/cli.js +34498 -55459
- package/wrangler-dist/wasm-sync.wasm +0 -0
- package/src/__tests__/dialogs.test.tsx +0 -40
- package/src/dialogs.tsx +0 -168
- package/src/environment-variables.ts +0 -50
- package/src/user/env-vars.ts +0 -46
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { cloneIntoDirectory, initializeGit } from "../git-client";
|
|
4
|
+
import { CommandLineArgsError, printWranglerBanner } from "../index";
|
|
5
|
+
import { initHandler } from "../init";
|
|
6
|
+
import { logger } from "../logger";
|
|
7
|
+
import type {
|
|
8
|
+
CommonYargsOptions,
|
|
9
|
+
YargsOptionsToInterface,
|
|
10
|
+
} from "../yargs-types";
|
|
11
|
+
import type { Argv } from "yargs";
|
|
12
|
+
|
|
13
|
+
export function generateOptions(yargs: Argv<CommonYargsOptions>) {
|
|
14
|
+
return yargs
|
|
15
|
+
.positional("name", {
|
|
16
|
+
describe: "Name of the Workers project",
|
|
17
|
+
type: "string",
|
|
18
|
+
demandOption: true,
|
|
19
|
+
})
|
|
20
|
+
.positional("template", {
|
|
21
|
+
type: "string",
|
|
22
|
+
describe: "The URL of a GitHub template",
|
|
23
|
+
})
|
|
24
|
+
.option("type", {
|
|
25
|
+
alias: "t",
|
|
26
|
+
type: "string",
|
|
27
|
+
hidden: true,
|
|
28
|
+
deprecated: true,
|
|
29
|
+
})
|
|
30
|
+
.option("site", {
|
|
31
|
+
alias: "s",
|
|
32
|
+
type: "boolean",
|
|
33
|
+
hidden: true,
|
|
34
|
+
deprecated: true,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
type GenerateArgs = YargsOptionsToInterface<typeof generateOptions>;
|
|
38
|
+
|
|
39
|
+
// Originally, generate was a rust function: https://github.com/cloudflare/wrangler/blob/master/src/cli/mod.rs#L106-L123
|
|
40
|
+
export async function generateHandler(args: GenerateArgs) {
|
|
41
|
+
// somehow, `init` marks name as required but then also runs fine
|
|
42
|
+
// with the name omitted, and then substitutes it at runtime with ""
|
|
43
|
+
// delegate to `wrangler init` if no template is specified
|
|
44
|
+
if (args.template === undefined) {
|
|
45
|
+
return initHandler({
|
|
46
|
+
name: args.name,
|
|
47
|
+
template: undefined,
|
|
48
|
+
site: undefined,
|
|
49
|
+
yes: undefined,
|
|
50
|
+
fromDash: undefined,
|
|
51
|
+
"from-dash": undefined,
|
|
52
|
+
v: undefined,
|
|
53
|
+
config: undefined,
|
|
54
|
+
env: undefined,
|
|
55
|
+
type: undefined,
|
|
56
|
+
_: args._,
|
|
57
|
+
$0: args.$0,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// print down here cuz `init` prints it own its own
|
|
62
|
+
await printWranglerBanner();
|
|
63
|
+
|
|
64
|
+
if (args.type) {
|
|
65
|
+
let message = "The --type option is no longer supported.";
|
|
66
|
+
if (args.type === "webpack") {
|
|
67
|
+
message +=
|
|
68
|
+
"\nIf you wish to use webpack then you will need to create a custom build.";
|
|
69
|
+
// TODO: Add a link to docs
|
|
70
|
+
}
|
|
71
|
+
throw new CommandLineArgsError(message);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (args.name && isRemote(args.name)) {
|
|
75
|
+
[args.template, args.name] = [args.name, args.template];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const creationDirectory = generateWorkerDirectoryName(args.name);
|
|
79
|
+
|
|
80
|
+
if (args.site) {
|
|
81
|
+
const gitDirectory =
|
|
82
|
+
creationDirectory !== process.cwd()
|
|
83
|
+
? path.basename(creationDirectory)
|
|
84
|
+
: "my-site";
|
|
85
|
+
const message =
|
|
86
|
+
"The --site option is no longer supported.\n" +
|
|
87
|
+
"If you wish to create a brand new Worker Sites project then clone the `worker-sites-template` starter repository:\n\n" +
|
|
88
|
+
"```\n" +
|
|
89
|
+
`git clone --depth=1 --branch=wrangler2 https://github.com/cloudflare/worker-sites-template ${gitDirectory}\n` +
|
|
90
|
+
`cd ${gitDirectory}\n` +
|
|
91
|
+
"```\n\n" +
|
|
92
|
+
"Find out more about how to create and maintain Sites projects at https://developers.cloudflare.com/workers/platform/sites.\n" +
|
|
93
|
+
"Have you considered using Cloudflare Pages instead? See https://pages.cloudflare.com/.";
|
|
94
|
+
throw new CommandLineArgsError(message);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
logger.log(
|
|
98
|
+
`Creating a worker in ${path.basename(creationDirectory)} from ${
|
|
99
|
+
args.template
|
|
100
|
+
}`
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
const { remote, subdirectory } = parseTemplatePath(args.template);
|
|
104
|
+
|
|
105
|
+
await cloneIntoDirectory(remote, creationDirectory, subdirectory);
|
|
106
|
+
await initializeGit(creationDirectory);
|
|
107
|
+
|
|
108
|
+
logger.log("✨ Success!");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Creates a path based on the current working directory and a worker name.
|
|
113
|
+
* Automatically increments a counter when searching for an available directory.
|
|
114
|
+
*
|
|
115
|
+
* Running `wrangler generate worker https://some-git-repo` in a directory
|
|
116
|
+
* with the structure:
|
|
117
|
+
* ```
|
|
118
|
+
* - workers
|
|
119
|
+
* |
|
|
120
|
+
* | - worker
|
|
121
|
+
* | | - wrangler.toml
|
|
122
|
+
* | | ...
|
|
123
|
+
* |
|
|
124
|
+
* | - worker-1
|
|
125
|
+
* | | - wrangler.toml
|
|
126
|
+
* | | ...
|
|
127
|
+
* ```
|
|
128
|
+
*
|
|
129
|
+
* will result in a new worker called `worker-2` being generated.
|
|
130
|
+
*
|
|
131
|
+
* @param workerName the name of the generated worker
|
|
132
|
+
* @returns an absolute path to the directory to generate the worker into
|
|
133
|
+
*/
|
|
134
|
+
function generateWorkerDirectoryName(workerName: string): string {
|
|
135
|
+
let workerDirectoryPath = path.resolve(process.cwd(), workerName);
|
|
136
|
+
let i = 1;
|
|
137
|
+
|
|
138
|
+
while (fs.existsSync(workerDirectoryPath)) {
|
|
139
|
+
workerDirectoryPath = path.resolve(process.cwd(), `${workerName}-${i}`);
|
|
140
|
+
i++;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return workerDirectoryPath;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Checks if an arg is a template, which can be useful if the order
|
|
148
|
+
* of template & worker name args is switched
|
|
149
|
+
*
|
|
150
|
+
* @param arg a template to generate from, or a folder to generate into
|
|
151
|
+
* @returns true if the given arg was remote (a template)
|
|
152
|
+
*/
|
|
153
|
+
function isRemote(arg: string) {
|
|
154
|
+
return /^(https?|ftps?|file|git|ssh):\/\//.test(arg) || arg.includes(":");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* unreadable regex basically copied from degit. i put some named capture groups in,
|
|
159
|
+
* but uhh...there's not much to do short of using pomsky or some other tool.
|
|
160
|
+
*
|
|
161
|
+
* notably: this only supports `https://` and `git@` urls,
|
|
162
|
+
* and is missing support for:
|
|
163
|
+
* - `http`
|
|
164
|
+
* - `ftp(s)`
|
|
165
|
+
* - `file`
|
|
166
|
+
* - `ssh`
|
|
167
|
+
*/
|
|
168
|
+
const TEMPLATE_REGEX =
|
|
169
|
+
/^(?:(?:https:\/\/)?(?<httpsUrl>[^:/]+\.[^:/]+)\/|git@(?<gitUrl>[^:/]+)[:/]|(?<shorthandUrl>[^/]+):)?(?<user>[^/\s]+)\/(?<repository>[^/\s#]+)(?:(?<subdirectoryPath>(?:\/[^/\s#]+)+))?(?:\/)?(?:#(?<tag>.+))?/;
|
|
170
|
+
|
|
171
|
+
// there are a few URL formats we support:
|
|
172
|
+
// - `user/repo` -> assume github, use "https://github.com/user/repo.git"
|
|
173
|
+
// - `https://<httpsUrl>
|
|
174
|
+
// - `git@<gitUrl>`
|
|
175
|
+
// - `(bb|bitbucket|gh|github|gl|gitlab):user/repo` -> parse shorthand into https url
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* There's no URL, so assume a github repo
|
|
179
|
+
*/
|
|
180
|
+
type NoUrl = {
|
|
181
|
+
httpsUrl: undefined;
|
|
182
|
+
gitUrl: undefined;
|
|
183
|
+
shorthandUrl: undefined;
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* A https url (e.g. https://bitbucket.org/user/repo)
|
|
188
|
+
*/
|
|
189
|
+
type HttpsUrl = Omit<NoUrl, "httpsUrl"> & { httpsUrl: string };
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* A git url (e.g. git@gitlab.com:user/repo)
|
|
193
|
+
*/
|
|
194
|
+
type GitUrl = Omit<NoUrl, "gitUrl"> & { gitUrl: string };
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* A shorthand url (e.g. github:user/repo)
|
|
198
|
+
*/
|
|
199
|
+
type ShorthandUrl = Omit<NoUrl, "shorthandUrl"> & { shorthandUrl: string };
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Union of all possible URL groups. Exactly one will be present, the rest
|
|
203
|
+
* will be `undefined`.
|
|
204
|
+
*/
|
|
205
|
+
type TemplateRegexUrlGroup = NoUrl | HttpsUrl | GitUrl | ShorthandUrl;
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Possible matches of `TEMPLATE_REGEX` against a passed-in template arg
|
|
209
|
+
*/
|
|
210
|
+
type TemplateRegexGroups = {
|
|
211
|
+
/** The user the repo is under */
|
|
212
|
+
user: string;
|
|
213
|
+
|
|
214
|
+
/** The repo name */
|
|
215
|
+
repository: string;
|
|
216
|
+
|
|
217
|
+
/** Optional, path to subdirectory containing template. Begins with `/` */
|
|
218
|
+
subdirectoryPath?: string;
|
|
219
|
+
|
|
220
|
+
/** Optional tag (or branch, etc.) to clone */
|
|
221
|
+
tag?: string;
|
|
222
|
+
} & TemplateRegexUrlGroup;
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Parses a regex match on any of the URL groups into a URL base
|
|
226
|
+
*
|
|
227
|
+
* @param urlGroup a regex hit for a URL of any sort
|
|
228
|
+
* @returns the protocol and domain name of the url to clone from
|
|
229
|
+
*/
|
|
230
|
+
function toUrlBase({ httpsUrl, gitUrl, shorthandUrl }: TemplateRegexUrlGroup) {
|
|
231
|
+
if (httpsUrl !== undefined) {
|
|
232
|
+
return `https://${httpsUrl}`;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (gitUrl !== undefined) {
|
|
236
|
+
return `git@${gitUrl}`;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (shorthandUrl !== undefined) {
|
|
240
|
+
switch (shorthandUrl) {
|
|
241
|
+
case "github":
|
|
242
|
+
case "gh":
|
|
243
|
+
return "https://github.com";
|
|
244
|
+
case "gitlab":
|
|
245
|
+
case "gl":
|
|
246
|
+
return "https://gitlab.com";
|
|
247
|
+
case "bitbucket":
|
|
248
|
+
case "bb":
|
|
249
|
+
return "https://bitbucket.org";
|
|
250
|
+
default:
|
|
251
|
+
throw new Error(
|
|
252
|
+
`Unable to parse shorthand ${shorthandUrl}. Supported options are "bitbucket" ("bb"), "github" ("gh"), and "gitlab" ("gl")`
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return "https://github.com";
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Parses a template string (e.g. "user/repo", "github:user/repo/path/to/subdirectory")
|
|
262
|
+
* into a remote URL to clone from and an optional subdirectory to filter for
|
|
263
|
+
*
|
|
264
|
+
* @param templatePath the template string to parse
|
|
265
|
+
* @returns an object containing the remote url and an optional subdirectory to clone
|
|
266
|
+
*/
|
|
267
|
+
function parseTemplatePath(templatePath: string): {
|
|
268
|
+
remote: string;
|
|
269
|
+
subdirectory?: string;
|
|
270
|
+
} {
|
|
271
|
+
if (!templatePath.includes("/")) {
|
|
272
|
+
// template is a cloudflare canonical template, it doesn't include a slash in the name
|
|
273
|
+
return {
|
|
274
|
+
remote: "https://github.com/cloudflare/templates.git",
|
|
275
|
+
subdirectory: templatePath,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const groups = TEMPLATE_REGEX.exec(templatePath)?.groups as unknown as
|
|
280
|
+
| TemplateRegexGroups
|
|
281
|
+
| undefined;
|
|
282
|
+
|
|
283
|
+
if (!groups) {
|
|
284
|
+
throw new Error(`Unable to parse ${templatePath} as a template`);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const { user, repository, subdirectoryPath, tag, ...urlGroups } = groups;
|
|
288
|
+
|
|
289
|
+
const urlBase = toUrlBase(urlGroups);
|
|
290
|
+
const isHttp = urlBase.startsWith("http");
|
|
291
|
+
|
|
292
|
+
const remote = `${urlBase}${isHttp ? "/" : ":"}${user}/${repository}.git${
|
|
293
|
+
tag ? `#${tag}` : ""
|
|
294
|
+
}`;
|
|
295
|
+
|
|
296
|
+
// remove starting /
|
|
297
|
+
const subdirectory = subdirectoryPath?.slice(1);
|
|
298
|
+
|
|
299
|
+
return { remote, subdirectory };
|
|
300
|
+
}
|
|
@@ -15,8 +15,6 @@ import {
|
|
|
15
15
|
buildOptions,
|
|
16
16
|
configHandler,
|
|
17
17
|
noOpOptions,
|
|
18
|
-
generateHandler,
|
|
19
|
-
generateOptions,
|
|
20
18
|
previewHandler,
|
|
21
19
|
previewOptions,
|
|
22
20
|
route,
|
|
@@ -26,6 +24,8 @@ import {
|
|
|
26
24
|
} from "./deprecated";
|
|
27
25
|
import { devHandler, devOptions } from "./dev";
|
|
28
26
|
import { workerNamespaceCommands } from "./dispatch-namespace";
|
|
27
|
+
import { docsHandler, docsOptions } from "./docs";
|
|
28
|
+
import { generateHandler, generateOptions } from "./generate";
|
|
29
29
|
import { initHandler, initOptions } from "./init";
|
|
30
30
|
import { kvNamespace, kvKey, kvBulk } from "./kv";
|
|
31
31
|
import { logBuildFailure, logger } from "./logger";
|
|
@@ -264,24 +264,30 @@ export function createCLIParser(argv: string[]) {
|
|
|
264
264
|
// I wish we could enforce this pattern, but this comment will have to do for now.
|
|
265
265
|
// (It's also annoying that choices[] doesn't get inferred as an enum. 🤷♂.)
|
|
266
266
|
|
|
267
|
-
//
|
|
267
|
+
// docs
|
|
268
268
|
wrangler.command(
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
generateOptions,
|
|
274
|
-
generateHandler
|
|
269
|
+
"docs [command]",
|
|
270
|
+
"📚 Open wrangler's docs in your browser",
|
|
271
|
+
docsOptions,
|
|
272
|
+
docsHandler
|
|
275
273
|
);
|
|
276
274
|
|
|
277
275
|
// init
|
|
278
276
|
wrangler.command(
|
|
279
277
|
"init [name]",
|
|
280
|
-
"📥
|
|
278
|
+
"📥 Initialize a basic Worker project, including a wrangler.toml file",
|
|
281
279
|
initOptions,
|
|
282
280
|
initHandler
|
|
283
281
|
);
|
|
284
282
|
|
|
283
|
+
// generate
|
|
284
|
+
wrangler.command(
|
|
285
|
+
"generate [name] [template]",
|
|
286
|
+
"✨ Generate a new Worker project from an existing Worker template. See https://github.com/cloudflare/templates",
|
|
287
|
+
generateOptions,
|
|
288
|
+
generateHandler
|
|
289
|
+
);
|
|
290
|
+
|
|
285
291
|
// [DEPRECATED] build
|
|
286
292
|
wrangler.command("build", false, buildOptions, buildHandler);
|
|
287
293
|
|
package/src/init.ts
CHANGED
|
@@ -22,10 +22,14 @@ import type { Route, SimpleRoute } from "./config/environment";
|
|
|
22
22
|
import type { WorkerMetadata } from "./create-worker-upload-form";
|
|
23
23
|
import type { ConfigPath } from "./index";
|
|
24
24
|
import type { PackageManager } from "./package-manager";
|
|
25
|
-
import type {
|
|
26
|
-
import type {
|
|
25
|
+
import type { PackageJSON } from "./parse";
|
|
26
|
+
import type {
|
|
27
|
+
CommonYargsOptions,
|
|
28
|
+
YargsOptionsToInterface,
|
|
29
|
+
} from "./yargs-types";
|
|
30
|
+
import type { Argv } from "yargs";
|
|
27
31
|
|
|
28
|
-
export
|
|
32
|
+
export function initOptions(yargs: Argv<CommonYargsOptions>) {
|
|
29
33
|
return yargs
|
|
30
34
|
.positional("name", {
|
|
31
35
|
describe: "The name of your worker",
|
|
@@ -49,18 +53,14 @@ export async function initOptions(yargs: Argv<CommonYargsOptions>) {
|
|
|
49
53
|
alias: "y",
|
|
50
54
|
})
|
|
51
55
|
.option("from-dash", {
|
|
52
|
-
describe:
|
|
56
|
+
describe:
|
|
57
|
+
"The name of the Worker you wish to download from the Cloudflare dashboard for local development.",
|
|
53
58
|
type: "string",
|
|
54
59
|
requiresArg: true,
|
|
55
60
|
});
|
|
56
61
|
}
|
|
57
62
|
|
|
58
|
-
|
|
59
|
-
name: string;
|
|
60
|
-
type?: string;
|
|
61
|
-
site?: boolean;
|
|
62
|
-
yes?: boolean;
|
|
63
|
-
}
|
|
63
|
+
type InitArgs = YargsOptionsToInterface<typeof initOptions>;
|
|
64
64
|
|
|
65
65
|
export type ServiceMetadataRes = {
|
|
66
66
|
id: string;
|
|
@@ -109,7 +109,7 @@ export type CronTriggersRes = {
|
|
|
109
109
|
];
|
|
110
110
|
};
|
|
111
111
|
|
|
112
|
-
export async function initHandler(args:
|
|
112
|
+
export async function initHandler(args: InitArgs) {
|
|
113
113
|
await printWranglerBanner();
|
|
114
114
|
if (args.type) {
|
|
115
115
|
let message = "The --type option is no longer supported.";
|
|
@@ -124,7 +124,7 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
|
|
|
124
124
|
const devDepsToInstall: string[] = [];
|
|
125
125
|
const instructions: string[] = [];
|
|
126
126
|
let shouldRunPackageManagerInstall = false;
|
|
127
|
-
const fromDashScriptName = args
|
|
127
|
+
const fromDashScriptName = args.fromDash;
|
|
128
128
|
const creationDirectory = path.resolve(
|
|
129
129
|
process.cwd(),
|
|
130
130
|
(args.name ? args.name : fromDashScriptName) ?? ""
|
|
@@ -165,6 +165,27 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
|
|
|
165
165
|
);
|
|
166
166
|
let justCreatedWranglerToml = false;
|
|
167
167
|
|
|
168
|
+
let accountId = "";
|
|
169
|
+
let serviceMetadata: undefined | ServiceMetadataRes;
|
|
170
|
+
|
|
171
|
+
// If --from-dash, check that script actually exists
|
|
172
|
+
if (fromDashScriptName) {
|
|
173
|
+
const config = readConfig(args.config as ConfigPath, args);
|
|
174
|
+
accountId = await requireAuth(config);
|
|
175
|
+
try {
|
|
176
|
+
serviceMetadata = await fetchResult<ServiceMetadataRes>(
|
|
177
|
+
`/accounts/${accountId}/workers/services/${fromDashScriptName}`
|
|
178
|
+
);
|
|
179
|
+
} catch (err) {
|
|
180
|
+
if ((err as { code?: number }).code === 10090) {
|
|
181
|
+
throw new Error(
|
|
182
|
+
"wrangler couldn't find a Worker script with that name in your account.\nRun `wrangler whoami` to confirm you're logged into the correct account."
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
throw err;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
168
189
|
if (fs.existsSync(wranglerTomlDestination)) {
|
|
169
190
|
let shouldContinue = false;
|
|
170
191
|
logger.warn(
|
|
@@ -309,7 +330,7 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
|
|
|
309
330
|
isTypescriptProject = true;
|
|
310
331
|
await writeFile(
|
|
311
332
|
path.join(creationDirectory, "./tsconfig.json"),
|
|
312
|
-
readFileSync(path.join(getBasePath(), "templates/tsconfig.json"))
|
|
333
|
+
readFileSync(path.join(getBasePath(), "templates/tsconfig.init.json"))
|
|
313
334
|
);
|
|
314
335
|
devDepsToInstall.push("@cloudflare/workers-types");
|
|
315
336
|
devDepsToInstall.push("typescript");
|
|
@@ -411,7 +432,7 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
|
|
|
411
432
|
: `wrangler publish ${scriptPath}`,
|
|
412
433
|
...(isAddingTestScripts && { test: testRunner }),
|
|
413
434
|
},
|
|
414
|
-
},
|
|
435
|
+
} as PackageJSON,
|
|
415
436
|
null,
|
|
416
437
|
2
|
|
417
438
|
) + "\n"
|
|
@@ -449,19 +470,15 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
|
|
|
449
470
|
);
|
|
450
471
|
if (fromDashScriptName) {
|
|
451
472
|
logger.warn(
|
|
452
|
-
|
|
453
|
-
Edits made via the Dashboard will not be synchronized locally and will be overridden by your local code and config when you publish.`
|
|
473
|
+
"After running `wrangler init --from-dash`, modifying your worker via the Cloudflare dashboard is discouraged.\nEdits made via the Dashboard will not be synchronized locally and will be overridden by your local code and config when you publish."
|
|
454
474
|
);
|
|
455
|
-
|
|
456
|
-
const accountId = await requireAuth(config);
|
|
475
|
+
|
|
457
476
|
await mkdir(path.join(creationDirectory, "./src"), {
|
|
458
477
|
recursive: true,
|
|
459
478
|
});
|
|
460
|
-
|
|
461
|
-
`/accounts/${accountId}/workers/services/${fromDashScriptName}`
|
|
462
|
-
);
|
|
479
|
+
|
|
463
480
|
const defaultEnvironment =
|
|
464
|
-
|
|
481
|
+
serviceMetadata?.default_environment.environment;
|
|
465
482
|
// I want the default environment, assuming it's the most up to date code.
|
|
466
483
|
const dashScript = await fetchDashboardScript(
|
|
467
484
|
`/accounts/${accountId}/workers/services/${fromDashScriptName}/environments/${defaultEnvironment}/content`
|
|
@@ -479,7 +496,7 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
|
|
|
479
496
|
scriptPath: "src/index.ts",
|
|
480
497
|
extraToml: (await getWorkerConfig(accountId, fromDashScriptName, {
|
|
481
498
|
defaultEnvironment,
|
|
482
|
-
environments:
|
|
499
|
+
environments: serviceMetadata?.environments,
|
|
483
500
|
})) as TOML.JsonMap,
|
|
484
501
|
});
|
|
485
502
|
} else {
|
|
@@ -493,6 +510,7 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
|
|
|
493
510
|
await mkdir(path.join(creationDirectory, "./src"), {
|
|
494
511
|
recursive: true,
|
|
495
512
|
});
|
|
513
|
+
|
|
496
514
|
await writeFile(
|
|
497
515
|
path.join(creationDirectory, "./src/index.ts"),
|
|
498
516
|
readFileSync(path.join(getBasePath(), `templates/${template}`))
|
|
@@ -505,10 +523,43 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
|
|
|
505
523
|
)}`
|
|
506
524
|
);
|
|
507
525
|
|
|
526
|
+
shouldCreateTests =
|
|
527
|
+
yesFlag ||
|
|
528
|
+
(await confirm(
|
|
529
|
+
"Would you like us to write your first test with Vitest?"
|
|
530
|
+
));
|
|
531
|
+
|
|
532
|
+
if (shouldCreateTests) {
|
|
533
|
+
if (yesFlag) {
|
|
534
|
+
logger.info("Your project will use Vitest to run your tests.");
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
newWorkerTestType = "vitest";
|
|
538
|
+
devDepsToInstall.push(newWorkerTestType);
|
|
539
|
+
|
|
540
|
+
await writeFile(
|
|
541
|
+
path.join(creationDirectory, "./src/index.test.ts"),
|
|
542
|
+
readFileSync(
|
|
543
|
+
path.join(
|
|
544
|
+
getBasePath(),
|
|
545
|
+
`templates/init-tests/test-${newWorkerTestType}-new-worker.ts`
|
|
546
|
+
)
|
|
547
|
+
)
|
|
548
|
+
);
|
|
549
|
+
logger.log(
|
|
550
|
+
`✨ Created ${path.relative(
|
|
551
|
+
process.cwd(),
|
|
552
|
+
path.join(creationDirectory, "./src/index.test.ts")
|
|
553
|
+
)}`
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
|
|
508
557
|
await writePackageJsonScriptsAndUpdateWranglerToml({
|
|
509
558
|
isWritingScripts: shouldWritePackageJsonScripts,
|
|
559
|
+
isAddingTests: shouldCreateTests,
|
|
510
560
|
isCreatingWranglerToml: justCreatedWranglerToml,
|
|
511
561
|
packagePath: pathToPackageJson,
|
|
562
|
+
testRunner: newWorkerTestType,
|
|
512
563
|
scriptPath: "src/index.ts",
|
|
513
564
|
extraToml: getNewWorkerToml(newWorkerType),
|
|
514
565
|
});
|
|
@@ -524,20 +575,15 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
|
|
|
524
575
|
|
|
525
576
|
if (fromDashScriptName) {
|
|
526
577
|
logger.warn(
|
|
527
|
-
|
|
528
|
-
Edits made via the Dashboard will not be synchronized locally and will be overridden by your local code and config when you publish.`
|
|
578
|
+
"After running `wrangler init --from-dash`, modifying your worker via the Cloudflare dashboard is discouraged.\nEdits made via the Dashboard will not be synchronized locally and will be overridden by your local code and config when you publish."
|
|
529
579
|
);
|
|
530
|
-
|
|
531
|
-
const accountId = await requireAuth(config);
|
|
580
|
+
|
|
532
581
|
await mkdir(path.join(creationDirectory, "./src"), {
|
|
533
582
|
recursive: true,
|
|
534
583
|
});
|
|
535
584
|
|
|
536
|
-
const serviceMetaData = await fetchResult<ServiceMetadataRes>(
|
|
537
|
-
`/accounts/${accountId}/workers/services/${fromDashScriptName}`
|
|
538
|
-
);
|
|
539
585
|
const defaultEnvironment =
|
|
540
|
-
|
|
586
|
+
serviceMetadata?.default_environment.environment;
|
|
541
587
|
|
|
542
588
|
// I want the default environment, assuming it's the most up to date code.
|
|
543
589
|
const dashScript = await fetchDashboardScript(
|
|
@@ -557,7 +603,7 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
|
|
|
557
603
|
//? Should we have Environment argument for `wrangler init --from-dash` - Jacob
|
|
558
604
|
extraToml: (await getWorkerConfig(accountId, fromDashScriptName, {
|
|
559
605
|
defaultEnvironment,
|
|
560
|
-
environments:
|
|
606
|
+
environments: serviceMetadata?.environments,
|
|
561
607
|
})) as TOML.JsonMap,
|
|
562
608
|
});
|
|
563
609
|
} else {
|
|
@@ -588,7 +634,7 @@ export async function initHandler(args: ArgumentsCamelCase<InitArgs>) {
|
|
|
588
634
|
(await confirm("Would you like us to write your first test?"));
|
|
589
635
|
|
|
590
636
|
if (shouldCreateTests) {
|
|
591
|
-
newWorkerTestType = await getNewWorkerTestType();
|
|
637
|
+
newWorkerTestType = await getNewWorkerTestType(yesFlag);
|
|
592
638
|
devDepsToInstall.push(newWorkerTestType);
|
|
593
639
|
await writeFile(
|
|
594
640
|
path.join(creationDirectory, "./src/index.test.js"),
|
|
@@ -678,41 +724,41 @@ async function installPackages(
|
|
|
678
724
|
}
|
|
679
725
|
|
|
680
726
|
async function getNewWorkerType(newWorkerFilename: string) {
|
|
681
|
-
return select(
|
|
682
|
-
|
|
683
|
-
[
|
|
727
|
+
return select(`Would you like to create a Worker at ${newWorkerFilename}?`, {
|
|
728
|
+
choices: [
|
|
684
729
|
{
|
|
685
730
|
value: "none",
|
|
686
|
-
|
|
731
|
+
title: "None",
|
|
687
732
|
},
|
|
688
733
|
{
|
|
689
734
|
value: "fetch",
|
|
690
|
-
|
|
735
|
+
title: "Fetch handler",
|
|
691
736
|
},
|
|
692
737
|
{
|
|
693
738
|
value: "scheduled",
|
|
694
|
-
|
|
739
|
+
title: "Scheduled handler",
|
|
695
740
|
},
|
|
696
741
|
],
|
|
697
|
-
1
|
|
698
|
-
)
|
|
742
|
+
defaultOption: 1,
|
|
743
|
+
});
|
|
699
744
|
}
|
|
700
745
|
|
|
701
|
-
async function getNewWorkerTestType() {
|
|
702
|
-
return
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
746
|
+
async function getNewWorkerTestType(yesFlag?: boolean) {
|
|
747
|
+
return yesFlag
|
|
748
|
+
? "jest"
|
|
749
|
+
: select(`Which test runner would you like to use?`, {
|
|
750
|
+
choices: [
|
|
751
|
+
{
|
|
752
|
+
value: "vitest",
|
|
753
|
+
title: "Vitest",
|
|
754
|
+
},
|
|
755
|
+
{
|
|
756
|
+
value: "jest",
|
|
757
|
+
title: "Jest",
|
|
758
|
+
},
|
|
759
|
+
],
|
|
760
|
+
defaultOption: 1,
|
|
761
|
+
});
|
|
716
762
|
}
|
|
717
763
|
|
|
718
764
|
function getNewWorkerTemplate(
|
|
@@ -770,8 +816,8 @@ async function getWorkerConfig(
|
|
|
770
816
|
defaultEnvironment,
|
|
771
817
|
environments,
|
|
772
818
|
}: {
|
|
773
|
-
defaultEnvironment: string;
|
|
774
|
-
environments: ServiceMetadataRes["environments"];
|
|
819
|
+
defaultEnvironment: string | undefined;
|
|
820
|
+
environments: ServiceMetadataRes["environments"] | undefined;
|
|
775
821
|
}
|
|
776
822
|
): Promise<RawConfig> {
|
|
777
823
|
const [bindings, routes, serviceEnvMetadata, cronTriggers] =
|
|
@@ -870,7 +916,7 @@ async function getWorkerConfig(
|
|
|
870
916
|
];
|
|
871
917
|
}
|
|
872
918
|
break;
|
|
873
|
-
case "
|
|
919
|
+
case "dispatch_namespace":
|
|
874
920
|
{
|
|
875
921
|
configObj.dispatch_namespaces = [
|
|
876
922
|
...(configObj.dispatch_namespaces ?? []),
|
|
@@ -967,7 +1013,7 @@ async function getWorkerConfig(
|
|
|
967
1013
|
crons: cronTriggers.schedules.map((scheduled) => scheduled.cron),
|
|
968
1014
|
},
|
|
969
1015
|
env: environments
|
|
970
|
-
|
|
1016
|
+
?.filter((env) => env.environment !== "production")
|
|
971
1017
|
// `env` can have multiple Environments, with different configs.
|
|
972
1018
|
.reduce((envObj, { environment }) => {
|
|
973
1019
|
return { ...envObj, [environment]: {} };
|
package/src/jest.d.ts
ADDED