wrangler 2.6.2 → 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 -44
- package/src/__tests__/init.test.ts +761 -537
- 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 +1617 -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 +6 -15
- package/src/cli.ts +2 -2
- 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 +29 -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 +21 -2
- package/src/dialogs.ts +136 -0
- package/src/dispatch-namespace.ts +1 -1
- package/src/docs/index.ts +3 -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} +10 -13
- package/src/init.ts +92 -52
- package/src/jest.d.ts +4 -0
- package/src/logger.ts +15 -3
- package/src/metrics/metrics-config.ts +1 -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 +5 -4
- package/src/pages/upload.tsx +1 -1
- 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 +34440 -55514
- 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,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* This code is inspired by that of https://www.atdatabases.org/docs/split-sql-query, which is published under MIT license,
|
|
4
|
+
* and is Copyright (c) 2019 Forbes Lindesay.
|
|
5
|
+
*
|
|
6
|
+
* See https://github.com/ForbesLindesay/atdatabases/blob/103c1e7/packages/split-sql-query/src/index.ts
|
|
7
|
+
* for the original code.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Is the given `sql` string likely to contain multiple statements.
|
|
12
|
+
*
|
|
13
|
+
* If `mayContainMultipleStatements()` returns `false` you can be confident that the sql
|
|
14
|
+
* does not contain multiple statements. Otherwise you have to check further.
|
|
15
|
+
*/
|
|
16
|
+
export function mayContainMultipleStatements(sql: string): boolean {
|
|
17
|
+
const trimmed = sql.trimEnd();
|
|
18
|
+
const semiColonIndex = trimmed.indexOf(";");
|
|
19
|
+
return semiColonIndex !== -1 && semiColonIndex !== trimmed.length - 1;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Split an SQLQuery into an array of statements
|
|
24
|
+
*/
|
|
25
|
+
export default function splitSqlQuery(sql: string): string[] {
|
|
26
|
+
if (!mayContainMultipleStatements(sql)) return [sql];
|
|
27
|
+
const split = splitSqlIntoStatements(sql);
|
|
28
|
+
if (split.length === 0) {
|
|
29
|
+
return [sql];
|
|
30
|
+
} else {
|
|
31
|
+
return split;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function splitSqlIntoStatements(sql: string): string[] {
|
|
36
|
+
const statements: string[] = [];
|
|
37
|
+
let str = "";
|
|
38
|
+
const compoundStatementStack: ((s: string) => boolean)[] = [];
|
|
39
|
+
|
|
40
|
+
const iterator = sql[Symbol.iterator]();
|
|
41
|
+
let next = iterator.next();
|
|
42
|
+
while (!next.done) {
|
|
43
|
+
const char = next.value;
|
|
44
|
+
|
|
45
|
+
if (compoundStatementStack[0]?.(str + char)) {
|
|
46
|
+
compoundStatementStack.shift();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
switch (char) {
|
|
50
|
+
case `'`:
|
|
51
|
+
case `"`:
|
|
52
|
+
case "`":
|
|
53
|
+
str += char + consumeUntilMarker(iterator, char);
|
|
54
|
+
break;
|
|
55
|
+
case `$`: {
|
|
56
|
+
const dollarQuote =
|
|
57
|
+
"$" + consumeWhile(iterator, isDollarQuoteIdentifier);
|
|
58
|
+
str += dollarQuote;
|
|
59
|
+
if (dollarQuote.endsWith("$")) {
|
|
60
|
+
str += consumeUntilMarker(iterator, dollarQuote);
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
case `-`:
|
|
65
|
+
str += char;
|
|
66
|
+
next = iterator.next();
|
|
67
|
+
if (!next.done && next.value === "-") {
|
|
68
|
+
str += next.value + consumeUntilMarker(iterator, "\n");
|
|
69
|
+
break;
|
|
70
|
+
} else {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
case `/`:
|
|
74
|
+
str += char;
|
|
75
|
+
next = iterator.next();
|
|
76
|
+
if (!next.done && next.value === "*") {
|
|
77
|
+
str += next.value + consumeUntilMarker(iterator, "*/");
|
|
78
|
+
break;
|
|
79
|
+
} else {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
case `;`:
|
|
83
|
+
if (compoundStatementStack.length === 0) {
|
|
84
|
+
statements.push(str);
|
|
85
|
+
str = "";
|
|
86
|
+
} else {
|
|
87
|
+
str += char;
|
|
88
|
+
}
|
|
89
|
+
break;
|
|
90
|
+
default:
|
|
91
|
+
str += char;
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (isCompoundStatementStart(str)) {
|
|
96
|
+
compoundStatementStack.unshift(isCompoundStatementEnd);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
next = iterator.next();
|
|
100
|
+
}
|
|
101
|
+
statements.push(str);
|
|
102
|
+
|
|
103
|
+
return statements
|
|
104
|
+
.map((statement) => statement.trim())
|
|
105
|
+
.filter((statement) => statement.length > 0);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Pulls characters from the string iterator while the predicate remains true.
|
|
110
|
+
*/
|
|
111
|
+
function consumeWhile(
|
|
112
|
+
iterator: Iterator<string>,
|
|
113
|
+
predicate: (str: string) => boolean
|
|
114
|
+
) {
|
|
115
|
+
let next = iterator.next();
|
|
116
|
+
let str = "";
|
|
117
|
+
while (!next.done) {
|
|
118
|
+
str += next.value;
|
|
119
|
+
if (!predicate(str)) {
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
next = iterator.next();
|
|
123
|
+
}
|
|
124
|
+
return str;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Pulls characters from the string iterator until the `endMarker` is found.
|
|
129
|
+
*/
|
|
130
|
+
function consumeUntilMarker(iterator: Iterator<string>, endMarker: string) {
|
|
131
|
+
return consumeWhile(iterator, (str) => !str.endsWith(endMarker));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Returns true if the `str` ends with a dollar-quoted string marker.
|
|
136
|
+
* See https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING.
|
|
137
|
+
*/
|
|
138
|
+
function isDollarQuoteIdentifier(str: string) {
|
|
139
|
+
const lastChar = str.slice(-1);
|
|
140
|
+
return (
|
|
141
|
+
// The $ marks the end of the identifier
|
|
142
|
+
lastChar !== "$" &&
|
|
143
|
+
// we allow numbers, underscore and letters with diacritical marks
|
|
144
|
+
(/[0-9_]/i.test(lastChar) ||
|
|
145
|
+
lastChar.toLowerCase() !== lastChar.toUpperCase())
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Returns true if the `str` ends with a compound statement `BEGIN` marker.
|
|
151
|
+
*/
|
|
152
|
+
function isCompoundStatementStart(str: string) {
|
|
153
|
+
return /\sBEGIN\s$/.test(str);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Returns true if the `str` ends with a compound statement `END` marker.
|
|
158
|
+
*/
|
|
159
|
+
function isCompoundStatementEnd(str: string) {
|
|
160
|
+
return /\sEND[;\s]$/.test(str);
|
|
161
|
+
}
|
|
File without changes
|
package/src/delete.ts
CHANGED
|
@@ -3,8 +3,6 @@ import path from "path";
|
|
|
3
3
|
import { fetchResult } from "./cfetch";
|
|
4
4
|
import { findWranglerToml, readConfig } from "./config";
|
|
5
5
|
import { confirm } from "./dialogs";
|
|
6
|
-
import { CI } from "./is-ci";
|
|
7
|
-
import isInteractive from "./is-interactive";
|
|
8
6
|
import { deleteKVNamespace, listKVNamespaces } from "./kv/helpers";
|
|
9
7
|
import { logger } from "./logger";
|
|
10
8
|
import * as metrics from "./metrics";
|
|
@@ -71,12 +69,9 @@ export async function deleteHandler(args: DeleteArgs) {
|
|
|
71
69
|
|
|
72
70
|
assert(accountId, "Missing accountId");
|
|
73
71
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
`Are you sure you want to delete ${scriptName}? This action cannot be undone.`
|
|
78
|
-
);
|
|
79
|
-
}
|
|
72
|
+
const confirmed = await confirm(
|
|
73
|
+
`Are you sure you want to delete ${scriptName}? This action cannot be undone.`
|
|
74
|
+
);
|
|
80
75
|
|
|
81
76
|
if (confirmed) {
|
|
82
77
|
await fetchResult(
|
package/src/deployments.ts
CHANGED
|
@@ -36,6 +36,12 @@ export async function deployments(
|
|
|
36
36
|
accountId: string,
|
|
37
37
|
scriptName: string | undefined
|
|
38
38
|
) {
|
|
39
|
+
if (!scriptName) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
"Required Worker name missing. Please specify the Worker name in wrangler.toml, or pass it as an argument with `--name`"
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
39
45
|
const scriptMetadata = await fetchResult<ServiceMetadataRes>(
|
|
40
46
|
`/accounts/${accountId}/workers/services/${scriptName}`
|
|
41
47
|
);
|
package/src/deprecated/index.ts
CHANGED
|
@@ -1,305 +1,12 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
1
|
import { DeprecationError } from "../errors";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
CommandLineArgsError,
|
|
7
|
-
createCLIParser,
|
|
8
|
-
printWranglerBanner,
|
|
9
|
-
} from "../index";
|
|
10
|
-
import { initHandler } from "../init";
|
|
2
|
+
import { createCLIParser } from "../index";
|
|
11
3
|
import { logger } from "../logger";
|
|
12
4
|
import { formatMessage } from "../parse";
|
|
13
5
|
import type {
|
|
14
6
|
CommonYargsOptions,
|
|
15
7
|
YargsOptionsToInterface,
|
|
16
8
|
} from "../yargs-types";
|
|
17
|
-
import type { Argv,
|
|
18
|
-
|
|
19
|
-
// https://github.com/cloudflare/wrangler/blob/master/src/cli/mod.rs#L106-L123
|
|
20
|
-
interface GenerateArgs {
|
|
21
|
-
name?: string;
|
|
22
|
-
template?: string;
|
|
23
|
-
type?: string;
|
|
24
|
-
site?: boolean;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function generateOptions(yargs: Argv<CommonYargsOptions>) {
|
|
28
|
-
return yargs
|
|
29
|
-
.positional("name", {
|
|
30
|
-
describe: "Name of the Workers project",
|
|
31
|
-
type: "string",
|
|
32
|
-
})
|
|
33
|
-
.positional("template", {
|
|
34
|
-
type: "string",
|
|
35
|
-
describe: "The URL of a GitHub template",
|
|
36
|
-
})
|
|
37
|
-
.option("type", {
|
|
38
|
-
alias: "t",
|
|
39
|
-
type: "string",
|
|
40
|
-
hidden: true,
|
|
41
|
-
deprecated: true,
|
|
42
|
-
})
|
|
43
|
-
.option("site", {
|
|
44
|
-
alias: "s",
|
|
45
|
-
type: "boolean",
|
|
46
|
-
hidden: true,
|
|
47
|
-
deprecated: true,
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export async function generateHandler({
|
|
52
|
-
// somehow, `init` marks name as required but then also runs fine
|
|
53
|
-
// with the name omitted, and then substitutes it at runtime with ""
|
|
54
|
-
name = "",
|
|
55
|
-
template,
|
|
56
|
-
type,
|
|
57
|
-
site,
|
|
58
|
-
...args
|
|
59
|
-
}: ArgumentsCamelCase<GenerateArgs>) {
|
|
60
|
-
// delegate to `wrangler init` if no template is specified
|
|
61
|
-
if (template === undefined) {
|
|
62
|
-
return initHandler({ name, ...args });
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// print down here cuz `init` prints it own its own
|
|
66
|
-
await printWranglerBanner();
|
|
67
|
-
|
|
68
|
-
if (type) {
|
|
69
|
-
let message = "The --type option is no longer supported.";
|
|
70
|
-
if (args.type === "webpack") {
|
|
71
|
-
message +=
|
|
72
|
-
"\nIf you wish to use webpack then you will need to create a custom build.";
|
|
73
|
-
// TODO: Add a link to docs
|
|
74
|
-
}
|
|
75
|
-
throw new CommandLineArgsError(message);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (isRemote(name)) {
|
|
79
|
-
[template, name] = [name, template];
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const creationDirectory = generateWorkerDirectoryName(name);
|
|
83
|
-
|
|
84
|
-
if (site) {
|
|
85
|
-
const gitDirectory =
|
|
86
|
-
creationDirectory !== process.cwd()
|
|
87
|
-
? path.basename(creationDirectory)
|
|
88
|
-
: "my-site";
|
|
89
|
-
const message =
|
|
90
|
-
"The --site option is no longer supported.\n" +
|
|
91
|
-
"If you wish to create a brand new Worker Sites project then clone the `worker-sites-template` starter repository:\n\n" +
|
|
92
|
-
"```\n" +
|
|
93
|
-
`git clone --depth=1 --branch=wrangler2 https://github.com/cloudflare/worker-sites-template ${gitDirectory}\n` +
|
|
94
|
-
`cd ${gitDirectory}\n` +
|
|
95
|
-
"```\n\n" +
|
|
96
|
-
"Find out more about how to create and maintain Sites projects at https://developers.cloudflare.com/workers/platform/sites.\n" +
|
|
97
|
-
"Have you considered using Cloudflare Pages instead? See https://pages.cloudflare.com/.";
|
|
98
|
-
throw new CommandLineArgsError(message);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
logger.log(
|
|
102
|
-
`Creating a worker in ${path.basename(creationDirectory)} from ${template}`
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
const { remote, subdirectory } = parseTemplatePath(template);
|
|
106
|
-
|
|
107
|
-
await cloneIntoDirectory(remote, creationDirectory, subdirectory);
|
|
108
|
-
await initializeGit(creationDirectory);
|
|
109
|
-
|
|
110
|
-
logger.log("✨ Success!");
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Creates a path based on the current working directory and a worker name.
|
|
115
|
-
* Automatically increments a counter when searching for an available directory.
|
|
116
|
-
*
|
|
117
|
-
* Running `wrangler generate worker https://some-git-repo` in a directory
|
|
118
|
-
* with the structure:
|
|
119
|
-
* ```
|
|
120
|
-
* - workers
|
|
121
|
-
* |
|
|
122
|
-
* | - worker
|
|
123
|
-
* | | - wrangler.toml
|
|
124
|
-
* | | ...
|
|
125
|
-
* |
|
|
126
|
-
* | - worker-1
|
|
127
|
-
* | | - wrangler.toml
|
|
128
|
-
* | | ...
|
|
129
|
-
* ```
|
|
130
|
-
*
|
|
131
|
-
* will result in a new worker called `worker-2` being generated.
|
|
132
|
-
*
|
|
133
|
-
* @param workerName the name of the generated worker
|
|
134
|
-
* @returns an absolute path to the directory to generate the worker into
|
|
135
|
-
*/
|
|
136
|
-
function generateWorkerDirectoryName(workerName: string): string {
|
|
137
|
-
let workerDirectoryPath = path.resolve(process.cwd(), workerName);
|
|
138
|
-
let i = 1;
|
|
139
|
-
|
|
140
|
-
while (fs.existsSync(workerDirectoryPath)) {
|
|
141
|
-
workerDirectoryPath = path.resolve(process.cwd(), `${workerName}-${i}`);
|
|
142
|
-
i++;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return workerDirectoryPath;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Checks if an arg is a template, which can be useful if the order
|
|
150
|
-
* of template & worker name args is switched
|
|
151
|
-
*
|
|
152
|
-
* @param arg a template to generate from, or a folder to generate into
|
|
153
|
-
* @returns true if the given arg was remote (a template)
|
|
154
|
-
*/
|
|
155
|
-
function isRemote(arg: string) {
|
|
156
|
-
return /^(https?|ftps?|file|git|ssh):\/\//.test(arg) || arg.includes(":");
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* unreadable regex basically copied from degit. i put some named capture groups in,
|
|
161
|
-
* but uhh...there's not much to do short of using pomsky or some other tool.
|
|
162
|
-
*
|
|
163
|
-
* notably: this only supports `https://` and `git@` urls,
|
|
164
|
-
* and is missing support for:
|
|
165
|
-
* - `http`
|
|
166
|
-
* - `ftp(s)`
|
|
167
|
-
* - `file`
|
|
168
|
-
* - `ssh`
|
|
169
|
-
*/
|
|
170
|
-
const TEMPLATE_REGEX =
|
|
171
|
-
/^(?:(?:https:\/\/)?(?<httpsUrl>[^:/]+\.[^:/]+)\/|git@(?<gitUrl>[^:/]+)[:/]|(?<shorthandUrl>[^/]+):)?(?<user>[^/\s]+)\/(?<repository>[^/\s#]+)(?:(?<subdirectoryPath>(?:\/[^/\s#]+)+))?(?:\/)?(?:#(?<tag>.+))?/;
|
|
172
|
-
|
|
173
|
-
// there are a few URL formats we support:
|
|
174
|
-
// - `user/repo` -> assume github, use "https://github.com/user/repo.git"
|
|
175
|
-
// - `https://<httpsUrl>
|
|
176
|
-
// - `git@<gitUrl>`
|
|
177
|
-
// - `(bb|bitbucket|gh|github|gl|gitlab):user/repo` -> parse shorthand into https url
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* There's no URL, so assume a github repo
|
|
181
|
-
*/
|
|
182
|
-
type NoUrl = {
|
|
183
|
-
httpsUrl: undefined;
|
|
184
|
-
gitUrl: undefined;
|
|
185
|
-
shorthandUrl: undefined;
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* A https url (e.g. https://bitbucket.org/user/repo)
|
|
190
|
-
*/
|
|
191
|
-
type HttpsUrl = Omit<NoUrl, "httpsUrl"> & { httpsUrl: string };
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* A git url (e.g. git@gitlab.com:user/repo)
|
|
195
|
-
*/
|
|
196
|
-
type GitUrl = Omit<NoUrl, "gitUrl"> & { gitUrl: string };
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* A shorthand url (e.g. github:user/repo)
|
|
200
|
-
*/
|
|
201
|
-
type ShorthandUrl = Omit<NoUrl, "shorthandUrl"> & { shorthandUrl: string };
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Union of all possible URL groups. Exactly one will be present, the rest
|
|
205
|
-
* will be `undefined`.
|
|
206
|
-
*/
|
|
207
|
-
type TemplateRegexUrlGroup = NoUrl | HttpsUrl | GitUrl | ShorthandUrl;
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Possible matches of `TEMPLATE_REGEX` against a passed-in template arg
|
|
211
|
-
*/
|
|
212
|
-
type TemplateRegexGroups = {
|
|
213
|
-
/** The user the repo is under */
|
|
214
|
-
user: string;
|
|
215
|
-
|
|
216
|
-
/** The repo name */
|
|
217
|
-
repository: string;
|
|
218
|
-
|
|
219
|
-
/** Optional, path to subdirectory containing template. Begins with `/` */
|
|
220
|
-
subdirectoryPath?: string;
|
|
221
|
-
|
|
222
|
-
/** Optional tag (or branch, etc.) to clone */
|
|
223
|
-
tag?: string;
|
|
224
|
-
} & TemplateRegexUrlGroup;
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Parses a regex match on any of the URL groups into a URL base
|
|
228
|
-
*
|
|
229
|
-
* @param urlGroup a regex hit for a URL of any sort
|
|
230
|
-
* @returns the protocol and domain name of the url to clone from
|
|
231
|
-
*/
|
|
232
|
-
function toUrlBase({ httpsUrl, gitUrl, shorthandUrl }: TemplateRegexUrlGroup) {
|
|
233
|
-
if (httpsUrl !== undefined) {
|
|
234
|
-
return `https://${httpsUrl}`;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if (gitUrl !== undefined) {
|
|
238
|
-
return `git@${gitUrl}`;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
if (shorthandUrl !== undefined) {
|
|
242
|
-
switch (shorthandUrl) {
|
|
243
|
-
case "github":
|
|
244
|
-
case "gh":
|
|
245
|
-
return "https://github.com";
|
|
246
|
-
case "gitlab":
|
|
247
|
-
case "gl":
|
|
248
|
-
return "https://gitlab.com";
|
|
249
|
-
case "bitbucket":
|
|
250
|
-
case "bb":
|
|
251
|
-
return "https://bitbucket.org";
|
|
252
|
-
default:
|
|
253
|
-
throw new Error(
|
|
254
|
-
`Unable to parse shorthand ${shorthandUrl}. Supported options are "bitbucket" ("bb"), "github" ("gh"), and "gitlab" ("gl")`
|
|
255
|
-
);
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
return "https://github.com";
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* Parses a template string (e.g. "user/repo", "github:user/repo/path/to/subdirectory")
|
|
264
|
-
* into a remote URL to clone from and an optional subdirectory to filter for
|
|
265
|
-
*
|
|
266
|
-
* @param templatePath the template string to parse
|
|
267
|
-
* @returns an object containing the remote url and an optional subdirectory to clone
|
|
268
|
-
*/
|
|
269
|
-
function parseTemplatePath(templatePath: string): {
|
|
270
|
-
remote: string;
|
|
271
|
-
subdirectory?: string;
|
|
272
|
-
} {
|
|
273
|
-
if (!templatePath.includes("/")) {
|
|
274
|
-
// template is a cloudflare canonical template, it doesn't include a slash in the name
|
|
275
|
-
return {
|
|
276
|
-
remote: "https://github.com/cloudflare/templates.git",
|
|
277
|
-
subdirectory: templatePath,
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
const groups = TEMPLATE_REGEX.exec(templatePath)?.groups as unknown as
|
|
282
|
-
| TemplateRegexGroups
|
|
283
|
-
| undefined;
|
|
284
|
-
|
|
285
|
-
if (!groups) {
|
|
286
|
-
throw new Error(`Unable to parse ${templatePath} as a template`);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
const { user, repository, subdirectoryPath, tag, ...urlGroups } = groups;
|
|
290
|
-
|
|
291
|
-
const urlBase = toUrlBase(urlGroups);
|
|
292
|
-
const isHttp = urlBase.startsWith("http");
|
|
293
|
-
|
|
294
|
-
const remote = `${urlBase}${isHttp ? "/" : ":"}${user}/${repository}.git${
|
|
295
|
-
tag ? `#${tag}` : ""
|
|
296
|
-
}`;
|
|
297
|
-
|
|
298
|
-
// remove starting /
|
|
299
|
-
const subdirectory = subdirectoryPath?.slice(1);
|
|
300
|
-
|
|
301
|
-
return { remote, subdirectory };
|
|
302
|
-
}
|
|
9
|
+
import type { Argv, BuilderCallback } from "yargs";
|
|
303
10
|
|
|
304
11
|
export function buildOptions(yargs: Argv<CommonYargsOptions>) {
|
|
305
12
|
return yargs;
|
package/src/dev/dev.tsx
CHANGED
|
@@ -28,7 +28,7 @@ import type { Config } from "../config";
|
|
|
28
28
|
import type { Route } from "../config/environment";
|
|
29
29
|
import type { WorkerRegistry } from "../dev-registry";
|
|
30
30
|
import type { Entry } from "../entry";
|
|
31
|
-
import type { EnablePagesAssetsServiceBindingOptions } from "../miniflare-cli";
|
|
31
|
+
import type { EnablePagesAssetsServiceBindingOptions } from "../miniflare-cli/types";
|
|
32
32
|
import type { AssetPaths } from "../sites";
|
|
33
33
|
import type { CfWorkerInit } from "../worker";
|
|
34
34
|
|
|
@@ -441,7 +441,7 @@ function useCustomBuild(expectedEntry: Entry, build: Config["build"]): void {
|
|
|
441
441
|
}
|
|
442
442
|
|
|
443
443
|
return () => {
|
|
444
|
-
watcher?.close();
|
|
444
|
+
void watcher?.close();
|
|
445
445
|
};
|
|
446
446
|
}, [build, expectedEntry]);
|
|
447
447
|
}
|
|
File without changes
|
package/src/dev/local.tsx
CHANGED
|
@@ -8,11 +8,11 @@ import getPort from "get-port";
|
|
|
8
8
|
import { npxImport } from "npx-import";
|
|
9
9
|
import { useState, useEffect, useRef } from "react";
|
|
10
10
|
import onExit from "signal-exit";
|
|
11
|
+
import { fetch } from "undici";
|
|
11
12
|
import { performApiFetch } from "../cfetch/internal";
|
|
12
13
|
import { registerWorker } from "../dev-registry";
|
|
13
14
|
import useInspector from "../inspect";
|
|
14
15
|
import { logger } from "../logger";
|
|
15
|
-
import generateASSETSBinding from "../miniflare-cli/assets";
|
|
16
16
|
import {
|
|
17
17
|
DEFAULT_MODULE_RULES,
|
|
18
18
|
ModuleTypeToRuleType,
|
|
@@ -23,7 +23,7 @@ import { requireAuth } from "../user";
|
|
|
23
23
|
import type { Config } from "../config";
|
|
24
24
|
import type { WorkerRegistry } from "../dev-registry";
|
|
25
25
|
import type { LoggerLevel } from "../logger";
|
|
26
|
-
import type { EnablePagesAssetsServiceBindingOptions } from "../miniflare-cli";
|
|
26
|
+
import type { EnablePagesAssetsServiceBindingOptions } from "../miniflare-cli/types";
|
|
27
27
|
import type { AssetPaths } from "../sites";
|
|
28
28
|
import type {
|
|
29
29
|
CfWorkerInit,
|
|
@@ -256,7 +256,7 @@ function useLocalWorker({
|
|
|
256
256
|
experimentalLocalRef.current = mf;
|
|
257
257
|
removeExperimentalLocalSignalExitListener.current = onExit(() => {
|
|
258
258
|
logger.log("⎔ Shutting down experimental local server.");
|
|
259
|
-
mf.dispose();
|
|
259
|
+
void mf.dispose();
|
|
260
260
|
experimentalLocalRef.current = undefined;
|
|
261
261
|
});
|
|
262
262
|
await mf.ready;
|
|
@@ -313,13 +313,15 @@ function useLocalWorker({
|
|
|
313
313
|
});
|
|
314
314
|
logger.log("⎔ Starting a local server...");
|
|
315
315
|
|
|
316
|
+
const hasColourSupport =
|
|
317
|
+
chalk.supportsColor.hasBasic && process.env.FORCE_COLOR !== "0";
|
|
316
318
|
const child = (local.current = fork(miniflareCLIPath, forkOptions, {
|
|
317
319
|
cwd: path.dirname(scriptPath),
|
|
318
320
|
execArgv: nodeOptions,
|
|
319
321
|
stdio: "pipe",
|
|
320
322
|
env: {
|
|
321
323
|
...process.env,
|
|
322
|
-
FORCE_COLOR:
|
|
324
|
+
FORCE_COLOR: hasColourSupport ? "1" : undefined,
|
|
323
325
|
},
|
|
324
326
|
}));
|
|
325
327
|
|
|
@@ -851,6 +853,16 @@ export async function transformMf2OptionsToMf3Options({
|
|
|
851
853
|
};
|
|
852
854
|
|
|
853
855
|
if (enablePagesAssetsServiceBinding !== undefined) {
|
|
856
|
+
// `../miniflare-cli/assets` dynamically imports`@cloudflare/pages-shared/environment-polyfills`.
|
|
857
|
+
// `@cloudflare/pages-shared/environment-polyfills/types.ts` defines `global`
|
|
858
|
+
// augmentations that pollute the `import`-site's typing environment.
|
|
859
|
+
//
|
|
860
|
+
// We `require` instead of `import`ing here to avoid polluting the main
|
|
861
|
+
// `wrangler` TypeScript project with the `global` augmentations. This
|
|
862
|
+
// relies on the fact that `require` is untyped.
|
|
863
|
+
//
|
|
864
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
865
|
+
const generateASSETSBinding = require("../miniflare-cli/assets");
|
|
854
866
|
options.serviceBindings = {
|
|
855
867
|
...options.serviceBindings,
|
|
856
868
|
ASSETS: (await generateASSETSBinding({
|
package/src/dev/remote.tsx
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { Text } from "ink";
|
|
4
|
+
import SelectInput from "ink-select-input";
|
|
3
5
|
import React, { useState, useEffect, useRef } from "react";
|
|
4
6
|
import { useErrorHandler } from "react-error-boundary";
|
|
5
7
|
import { printBundleSize } from "../bundle-reporter";
|
|
@@ -12,7 +14,6 @@ import { logger } from "../logger";
|
|
|
12
14
|
import { startPreviewServer, usePreviewServer } from "../proxy";
|
|
13
15
|
import { syncAssets } from "../sites";
|
|
14
16
|
import {
|
|
15
|
-
ChooseAccount,
|
|
16
17
|
getAccountChoices,
|
|
17
18
|
requireApiToken,
|
|
18
19
|
saveAccountToCache,
|
|
@@ -601,3 +602,29 @@ function getWorkerAccountAndContext(props: {
|
|
|
601
602
|
|
|
602
603
|
return { workerAccount, workerContext };
|
|
603
604
|
}
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* A component that allows the user to select from a list of available accounts.
|
|
608
|
+
*/
|
|
609
|
+
function ChooseAccount(props: {
|
|
610
|
+
accounts: ChooseAccountItem[];
|
|
611
|
+
onSelect: (account: { name: string; id: string }) => void;
|
|
612
|
+
onError: (error: Error) => void;
|
|
613
|
+
}) {
|
|
614
|
+
return (
|
|
615
|
+
<>
|
|
616
|
+
<Text bold>Select an account from below:</Text>
|
|
617
|
+
<SelectInput
|
|
618
|
+
items={props.accounts.map((item) => ({
|
|
619
|
+
key: item.id,
|
|
620
|
+
label: item.name,
|
|
621
|
+
value: item,
|
|
622
|
+
}))}
|
|
623
|
+
onSelect={(item) => {
|
|
624
|
+
logger.log(`Using account: "${item.value.name} - ${item.value.id}"`);
|
|
625
|
+
props.onSelect({ id: item.value.id, name: item.value.name });
|
|
626
|
+
}}
|
|
627
|
+
/>
|
|
628
|
+
</>
|
|
629
|
+
);
|
|
630
|
+
}
|
package/src/dev/start-server.ts
CHANGED
|
@@ -39,6 +39,7 @@ import type { ChildProcess } from "node:child_process";
|
|
|
39
39
|
export async function startDevServer(
|
|
40
40
|
props: DevProps & {
|
|
41
41
|
local: boolean;
|
|
42
|
+
disableDevRegistry: boolean;
|
|
42
43
|
}
|
|
43
44
|
) {
|
|
44
45
|
try {
|
|
@@ -62,17 +63,24 @@ export async function startDevServer(
|
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
//start the worker registry
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
66
|
+
logger.log("disableDevRegistry: ", props.disableDevRegistry);
|
|
67
|
+
if (!props.disableDevRegistry) {
|
|
68
|
+
try {
|
|
69
|
+
await startWorkerRegistry();
|
|
70
|
+
if (props.local) {
|
|
71
|
+
const boundRegisteredWorkers = await getBoundRegisteredWorkers({
|
|
72
|
+
services: props.bindings.services,
|
|
73
|
+
durableObjects: props.bindings.durable_objects,
|
|
74
|
+
});
|
|
73
75
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
if (
|
|
77
|
+
!util.isDeepStrictEqual(boundRegisteredWorkers, workerDefinitions)
|
|
78
|
+
) {
|
|
79
|
+
workerDefinitions = boundRegisteredWorkers || {};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} catch (err) {
|
|
83
|
+
logger.error("failed to start worker registry", err);
|
|
76
84
|
}
|
|
77
85
|
}
|
|
78
86
|
|
|
@@ -419,7 +427,7 @@ export async function startLocalServer({
|
|
|
419
427
|
experimentalLocalRef = mf;
|
|
420
428
|
removeSignalExitListener = onExit((_code, _signal) => {
|
|
421
429
|
logger.log("⎔ Shutting down experimental local server.");
|
|
422
|
-
mf.dispose();
|
|
430
|
+
void mf.dispose();
|
|
423
431
|
experimentalLocalRef = undefined;
|
|
424
432
|
});
|
|
425
433
|
onReady?.(runtimeURL.hostname, parseInt(runtimeURL.port ?? 8787));
|