wrangler 0.0.0-e2a26a0 → 0.0.0-e3cab74
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/package.json +16 -7
- package/pages/functions/filepath-routing.test.ts +112 -36
- package/pages/functions/filepath-routing.ts +66 -119
- package/pages/functions/routes.ts +8 -17
- package/pages/functions/template-worker.ts +3 -9
- package/src/__tests__/configuration.test.ts +2185 -0
- package/src/__tests__/dev.test.tsx +48 -6
- package/src/__tests__/guess-worker-format.test.ts +66 -0
- package/src/__tests__/helpers/faye-websocket.d.ts +6 -0
- package/src/__tests__/helpers/mock-account-id.ts +6 -6
- package/src/__tests__/helpers/mock-bin.ts +4 -1
- package/src/__tests__/helpers/mock-cfetch.ts +2 -2
- package/src/__tests__/helpers/mock-console.ts +11 -5
- package/src/__tests__/helpers/mock-web-socket.ts +29 -0
- package/src/__tests__/helpers/run-wrangler.ts +5 -3
- package/src/__tests__/helpers/write-wrangler-toml.ts +17 -0
- package/src/__tests__/index.test.ts +343 -20
- package/src/__tests__/jest.setup.ts +21 -1
- package/src/__tests__/kv.test.ts +82 -80
- package/src/__tests__/package-manager.test.ts +2 -2
- package/src/__tests__/parse.test.ts +322 -0
- package/src/__tests__/publish.test.ts +1428 -244
- package/src/__tests__/r2.test.ts +198 -0
- package/src/__tests__/secret.test.ts +176 -60
- package/src/__tests__/sentry.test.ts +146 -0
- package/src/__tests__/tail.test.ts +564 -0
- package/src/api/form_data.ts +106 -23
- package/src/api/preview.ts +32 -13
- package/src/api/worker.ts +49 -18
- package/src/bundle.ts +133 -0
- package/src/cfetch/index.ts +8 -6
- package/src/cfetch/internal.ts +49 -17
- package/src/cli.ts +10 -0
- package/src/config/README.md +107 -0
- package/src/config/config.ts +265 -0
- package/src/config/diagnostics.ts +80 -0
- package/src/config/environment.ts +305 -0
- package/src/config/index.ts +52 -0
- package/src/config/validation-helpers.ts +370 -0
- package/src/config/validation.ts +1017 -0
- package/src/dev.tsx +338 -211
- package/src/entry.ts +57 -0
- package/src/environment-variables.ts +33 -0
- package/src/guess-worker-format.ts +68 -0
- package/src/index.tsx +860 -634
- package/src/inspect.ts +16 -3
- package/src/kv.tsx +20 -29
- package/src/module-collection.ts +141 -34
- package/src/open-in-browser.ts +13 -0
- package/src/package-manager.ts +21 -15
- package/src/pages.tsx +9 -10
- package/src/parse.ts +183 -0
- package/src/proxy.ts +11 -5
- package/src/publish.ts +272 -314
- package/src/r2.ts +50 -0
- package/src/reporting.ts +115 -0
- package/src/sites.tsx +16 -15
- package/src/tail/filters.ts +279 -0
- package/src/tail/index.ts +299 -0
- package/src/tail/printing.ts +62 -0
- package/src/user.tsx +74 -44
- package/templates/new-worker.js +1 -1
- package/templates/new-worker.ts +1 -1
- package/templates/tsconfig.json +105 -0
- package/wrangler-dist/cli.js +51308 -36440
- package/wrangler-dist/cli.js.map +3 -3
- package/src/config.ts +0 -641
- package/src/tail.tsx +0 -73
package/src/inspect.ts
CHANGED
|
@@ -367,7 +367,10 @@ export default function useInspector(props: InspectorProps) {
|
|
|
367
367
|
);
|
|
368
368
|
remoteWebSocket.send(event.data);
|
|
369
369
|
} catch (e) {
|
|
370
|
-
if (
|
|
370
|
+
if (
|
|
371
|
+
(e as Error).message !==
|
|
372
|
+
"WebSocket is not open: readyState 0 (CONNECTING)"
|
|
373
|
+
) {
|
|
371
374
|
/**
|
|
372
375
|
* ^ this just means we haven't opened a websocket yet
|
|
373
376
|
* usually happens until there's at least one request
|
|
@@ -587,8 +590,18 @@ function logConsoleMessage(evt: Protocol.Runtime.ConsoleAPICalledEvent): void {
|
|
|
587
590
|
const method = mapConsoleAPIMessageTypeToConsoleMethod[evt.type];
|
|
588
591
|
|
|
589
592
|
if (method in console) {
|
|
590
|
-
|
|
591
|
-
|
|
593
|
+
switch (method) {
|
|
594
|
+
case "dir":
|
|
595
|
+
console.dir(args);
|
|
596
|
+
break;
|
|
597
|
+
case "table":
|
|
598
|
+
console.table(args);
|
|
599
|
+
break;
|
|
600
|
+
default:
|
|
601
|
+
// eslint-disable-next-line prefer-spread
|
|
602
|
+
console[method].apply(console, args);
|
|
603
|
+
break;
|
|
604
|
+
}
|
|
592
605
|
} else {
|
|
593
606
|
console.warn(`Unsupported console method: ${method}`);
|
|
594
607
|
console.log("console event:", evt);
|
package/src/kv.tsx
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { URLSearchParams } from "node:url";
|
|
2
2
|
import { fetchListResult, fetchResult, fetchKVGetValue } from "./cfetch";
|
|
3
|
-
import type { Config } from "./config";
|
|
3
|
+
import type { Config, Environment } from "./config";
|
|
4
4
|
|
|
5
5
|
type KvArgs = {
|
|
6
6
|
binding?: string;
|
|
7
7
|
"namespace-id"?: string;
|
|
8
8
|
env?: string;
|
|
9
9
|
preview?: boolean;
|
|
10
|
-
config?: Config;
|
|
11
10
|
};
|
|
12
11
|
|
|
13
12
|
/**
|
|
@@ -153,13 +152,10 @@ export async function deleteBulkKeyValue(
|
|
|
153
152
|
);
|
|
154
153
|
}
|
|
155
154
|
|
|
156
|
-
export function getNamespaceId(
|
|
157
|
-
preview,
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
"namespace-id": namespaceId,
|
|
161
|
-
env,
|
|
162
|
-
}: KvArgs): string {
|
|
155
|
+
export function getNamespaceId(
|
|
156
|
+
{ preview, binding, "namespace-id": namespaceId, env }: KvArgs,
|
|
157
|
+
configOrEnv: Config | Environment | undefined
|
|
158
|
+
): string {
|
|
163
159
|
// nice
|
|
164
160
|
if (namespaceId) {
|
|
165
161
|
return namespaceId;
|
|
@@ -167,13 +163,13 @@ export function getNamespaceId({
|
|
|
167
163
|
|
|
168
164
|
// begin pre-flight checks
|
|
169
165
|
|
|
170
|
-
// `--binding` is only valid if there's a wrangler configuration
|
|
171
|
-
if (binding && !
|
|
166
|
+
// `--binding` is only valid if there's a wrangler configuration.
|
|
167
|
+
if (binding && !configOrEnv) {
|
|
172
168
|
throw new Error("--binding specified, but no config file was found.");
|
|
173
169
|
}
|
|
174
170
|
|
|
175
171
|
// there's no config. abort here
|
|
176
|
-
if (!
|
|
172
|
+
if (!configOrEnv) {
|
|
177
173
|
throw new Error(
|
|
178
174
|
"Failed to find a config file.\n" +
|
|
179
175
|
"Either use --namespace-id to upload directly or create a configuration file with a binding."
|
|
@@ -182,36 +178,31 @@ export function getNamespaceId({
|
|
|
182
178
|
|
|
183
179
|
// they want to use an environment, actually
|
|
184
180
|
if (env) {
|
|
185
|
-
if (!
|
|
181
|
+
if (!("env" in configOrEnv) || !configOrEnv.env[env]) {
|
|
186
182
|
throw new Error(
|
|
187
183
|
`Failed to find environment "${env}" in configuration file!`
|
|
188
184
|
);
|
|
189
185
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
env: undefined,
|
|
196
|
-
preview,
|
|
197
|
-
config: {
|
|
198
|
-
env: undefined,
|
|
199
|
-
build: undefined,
|
|
200
|
-
name: undefined,
|
|
201
|
-
account_id: undefined,
|
|
202
|
-
...config.env[env],
|
|
186
|
+
return getNamespaceId(
|
|
187
|
+
{
|
|
188
|
+
binding,
|
|
189
|
+
"namespace-id": namespaceId,
|
|
190
|
+
preview,
|
|
203
191
|
},
|
|
204
|
-
|
|
192
|
+
configOrEnv.env[env]
|
|
193
|
+
);
|
|
205
194
|
}
|
|
206
195
|
|
|
207
196
|
// there's no KV namespaces
|
|
208
|
-
if (!
|
|
197
|
+
if (!configOrEnv.kv_namespaces || configOrEnv.kv_namespaces.length === 0) {
|
|
209
198
|
throw new Error(
|
|
210
199
|
"No KV Namespaces configured! Either use --namespace-id to upload directly or add a KV namespace to your wrangler config file."
|
|
211
200
|
);
|
|
212
201
|
}
|
|
213
202
|
|
|
214
|
-
const namespace =
|
|
203
|
+
const namespace = configOrEnv.kv_namespaces.find(
|
|
204
|
+
(ns) => ns.binding === binding
|
|
205
|
+
);
|
|
215
206
|
|
|
216
207
|
// we couldn't find a namespace with that binding
|
|
217
208
|
if (!namespace) {
|
package/src/module-collection.ts
CHANGED
|
@@ -1,21 +1,86 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
2
|
import { readFile } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import
|
|
4
|
+
import globToRegExp from "glob-to-regexp";
|
|
5
|
+
import type { CfModule, CfModuleType, CfScriptFormat } from "./api/worker";
|
|
6
|
+
import type { Config, ConfigModuleRuleType } from "./config";
|
|
5
7
|
import type esbuild from "esbuild";
|
|
6
8
|
|
|
9
|
+
const RuleTypeToModuleType: Record<ConfigModuleRuleType, CfModuleType> = {
|
|
10
|
+
ESModule: "esm",
|
|
11
|
+
CommonJS: "commonjs",
|
|
12
|
+
CompiledWasm: "compiled-wasm",
|
|
13
|
+
Data: "buffer",
|
|
14
|
+
Text: "text",
|
|
15
|
+
};
|
|
16
|
+
|
|
7
17
|
// This is a combination of an esbuild plugin and a mutable array
|
|
8
18
|
// that we use to collect module references from source code.
|
|
9
19
|
// There will be modules that _shouldn't_ be inlined directly into
|
|
10
20
|
// the bundle. (eg. wasm modules, some text files, etc). We can include
|
|
11
|
-
// those files as modules in the multi part
|
|
21
|
+
// those files as modules in the multi part worker form upload. This
|
|
12
22
|
// plugin+array is used to collect references to these modules, reference
|
|
13
23
|
// them correctly in the bundle, and add them to the form upload.
|
|
14
24
|
|
|
15
|
-
export
|
|
25
|
+
export const DEFAULT_MODULE_RULES: Config["rules"] = [
|
|
26
|
+
{ type: "Text", globs: ["**/*.txt", "**/*.html"] },
|
|
27
|
+
{ type: "Data", globs: ["**/*.bin"] },
|
|
28
|
+
{ type: "CompiledWasm", globs: ["**/*.wasm"] },
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
export default function makeModuleCollector(props: {
|
|
32
|
+
format: CfScriptFormat;
|
|
33
|
+
rules?: Config["rules"];
|
|
34
|
+
}): {
|
|
16
35
|
modules: CfModule[];
|
|
17
36
|
plugin: esbuild.Plugin;
|
|
18
37
|
} {
|
|
38
|
+
const rules: Config["rules"] = [
|
|
39
|
+
...(props.rules || []),
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
41
|
+
...DEFAULT_MODULE_RULES!,
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
const completedRuleLocations: Record<string, number> = {};
|
|
45
|
+
let index = 0;
|
|
46
|
+
const rulesToRemove: Config["rules"] = [];
|
|
47
|
+
for (const rule of rules) {
|
|
48
|
+
if (rule.type in completedRuleLocations) {
|
|
49
|
+
if (rules[completedRuleLocations[rule.type]].fallthrough !== false) {
|
|
50
|
+
if (index < (props.rules || []).length) {
|
|
51
|
+
console.warn(
|
|
52
|
+
`The module rule at position ${index} (${JSON.stringify(
|
|
53
|
+
rule
|
|
54
|
+
)}) has the same type as a previous rule (at position ${
|
|
55
|
+
completedRuleLocations[rule.type]
|
|
56
|
+
}, ${JSON.stringify(
|
|
57
|
+
rules[completedRuleLocations[rule.type]]
|
|
58
|
+
)}). This rule will be ignored. To the previous rule, add \`fallthrough = true\` to allow this one to also be used, or \`fallthrough = false\` to silence this warning.`
|
|
59
|
+
);
|
|
60
|
+
} else {
|
|
61
|
+
console.warn(
|
|
62
|
+
`The default module rule ${JSON.stringify(
|
|
63
|
+
rule
|
|
64
|
+
)} has the same type as a previous rule (at position ${
|
|
65
|
+
completedRuleLocations[rule.type]
|
|
66
|
+
}, ${JSON.stringify(
|
|
67
|
+
rules[completedRuleLocations[rule.type]]
|
|
68
|
+
)}). This rule will be ignored. To the previous rule, add \`fallthrough = true\` to allow the default one to also be used, or \`fallthrough = false\` to silence this warning.`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
rulesToRemove.push(rule);
|
|
74
|
+
}
|
|
75
|
+
if (!(rule.type in completedRuleLocations) && rule.fallthrough !== true) {
|
|
76
|
+
completedRuleLocations[rule.type] = index;
|
|
77
|
+
}
|
|
78
|
+
index++;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
82
|
+
rulesToRemove.forEach((rule) => rules!.splice(rules!.indexOf(rule), 1));
|
|
83
|
+
|
|
19
84
|
const modules: CfModule[] = [];
|
|
20
85
|
return {
|
|
21
86
|
modules,
|
|
@@ -23,40 +88,82 @@ export default function makeModuleCollector(): {
|
|
|
23
88
|
name: "wrangler-module-collector",
|
|
24
89
|
setup(build) {
|
|
25
90
|
build.onStart(() => {
|
|
26
|
-
// reset the
|
|
91
|
+
// reset the module collection array
|
|
27
92
|
modules.splice(0);
|
|
28
93
|
});
|
|
29
94
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
95
|
+
rules?.forEach((rule) => {
|
|
96
|
+
if (rule.type === "ESModule" || rule.type === "CommonJS") return; // TODO: we should treat these as js files, and use the jsx loader
|
|
97
|
+
|
|
98
|
+
rule.globs.forEach((glob) => {
|
|
99
|
+
build.onResolve(
|
|
100
|
+
{ filter: globToRegExp(glob) },
|
|
101
|
+
async (args: esbuild.OnResolveArgs) => {
|
|
102
|
+
// take the file and massage it to a
|
|
103
|
+
// transportable/manageable format
|
|
104
|
+
|
|
105
|
+
const filePath = path.join(args.resolveDir, args.path);
|
|
106
|
+
const fileContent = await readFile(filePath);
|
|
107
|
+
const fileHash = crypto
|
|
108
|
+
.createHash("sha1")
|
|
109
|
+
.update(fileContent)
|
|
110
|
+
.digest("hex");
|
|
111
|
+
const fileName = `./${fileHash}-${path.basename(args.path)}`;
|
|
112
|
+
|
|
113
|
+
// add the module to the array
|
|
114
|
+
modules.push({
|
|
115
|
+
name: fileName,
|
|
116
|
+
content: fileContent,
|
|
117
|
+
type: RuleTypeToModuleType[rule.type],
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
path: fileName, // change the reference to the changed module
|
|
122
|
+
external: props.format === "modules", // mark it as external in the bundle
|
|
123
|
+
namespace: `wrangler-module-${rule.type}`, // just a tag, this isn't strictly necessary
|
|
124
|
+
watchFiles: [filePath], // we also add the file to esbuild's watch list
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
if (props.format === "service-worker") {
|
|
130
|
+
build.onLoad(
|
|
131
|
+
{ filter: globToRegExp(glob) },
|
|
132
|
+
async (args: esbuild.OnLoadArgs) => {
|
|
133
|
+
return {
|
|
134
|
+
// We replace the the module with an identifier
|
|
135
|
+
// that we'll separately add to the form upload
|
|
136
|
+
// as part of [wasm_modules]/[text_blobs]. This identifier has to be a valid
|
|
137
|
+
// JS identifier, so we replace all non alphanumeric characters
|
|
138
|
+
// with an underscore.
|
|
139
|
+
// TODO: what of "Data"?
|
|
140
|
+
contents: `export default ${args.path.replace(
|
|
141
|
+
/[^a-zA-Z0-9_$]/g,
|
|
142
|
+
"_"
|
|
143
|
+
)};`,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
rulesToRemove.forEach((rule) => {
|
|
152
|
+
rule.globs.forEach((glob) => {
|
|
153
|
+
build.onResolve(
|
|
154
|
+
{ filter: globToRegExp(glob) },
|
|
155
|
+
async (args: esbuild.OnResolveArgs) => {
|
|
156
|
+
throw new Error(
|
|
157
|
+
`The file ${
|
|
158
|
+
args.path
|
|
159
|
+
} matched a module rule in your configuration (${JSON.stringify(
|
|
160
|
+
rule
|
|
161
|
+
)}), but was ignored because a previous rule with the same type was not marked as \`fallthrough = true\`.`
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
60
167
|
},
|
|
61
168
|
},
|
|
62
169
|
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import open from "open";
|
|
2
|
+
/**
|
|
3
|
+
* An extremely simple wrapper around the open command.
|
|
4
|
+
* Specifically, it adds an 'error' event handler so that when this function
|
|
5
|
+
* is called in environments where we can't open the browser (e.g. github codespaces,
|
|
6
|
+
* stackblitz, remote servers), it doesn't just crash the process.
|
|
7
|
+
*/
|
|
8
|
+
export default async function openInBrowser(url: string): Promise<void> {
|
|
9
|
+
const childProcess = await open(url);
|
|
10
|
+
childProcess.on("error", () => {
|
|
11
|
+
console.warn(`Failed to open ${url} in a browser`);
|
|
12
|
+
});
|
|
13
|
+
}
|
package/src/package-manager.ts
CHANGED
|
@@ -3,49 +3,51 @@ import { join } from "node:path";
|
|
|
3
3
|
import { execa, execaCommandSync } from "execa";
|
|
4
4
|
|
|
5
5
|
export interface PackageManager {
|
|
6
|
+
cwd: string;
|
|
7
|
+
type: "npm" | "yarn";
|
|
6
8
|
addDevDeps(...packages: string[]): Promise<void>;
|
|
7
9
|
install(): Promise<void>;
|
|
8
10
|
}
|
|
9
11
|
|
|
10
|
-
export async function getPackageManager(
|
|
12
|
+
export async function getPackageManager(cwd: string): Promise<PackageManager> {
|
|
11
13
|
const [hasYarn, hasNpm] = await Promise.all([supportsYarn(), supportsNpm()]);
|
|
12
|
-
const hasYarnLock = existsSync(join(
|
|
13
|
-
const hasNpmLock = existsSync(join(
|
|
14
|
+
const hasYarnLock = existsSync(join(cwd, "yarn.lock"));
|
|
15
|
+
const hasNpmLock = existsSync(join(cwd, "package-lock.json"));
|
|
14
16
|
|
|
15
17
|
if (hasNpmLock) {
|
|
16
18
|
if (hasNpm) {
|
|
17
19
|
console.log(
|
|
18
20
|
"Using npm as package manager, as there is already a package-lock.json file."
|
|
19
21
|
);
|
|
20
|
-
return NpmPackageManager;
|
|
22
|
+
return { ...NpmPackageManager, cwd };
|
|
21
23
|
} else if (hasYarn) {
|
|
22
24
|
console.log("Using yarn as package manager.");
|
|
23
25
|
console.warn(
|
|
24
26
|
"There is already a package-lock.json file but could not find npm on the PATH."
|
|
25
27
|
);
|
|
26
|
-
return YarnPackageManager;
|
|
28
|
+
return { ...YarnPackageManager, cwd };
|
|
27
29
|
}
|
|
28
30
|
} else if (hasYarnLock) {
|
|
29
31
|
if (hasYarn) {
|
|
30
32
|
console.log(
|
|
31
33
|
"Using yarn as package manager, as there is already a yarn.lock file."
|
|
32
34
|
);
|
|
33
|
-
return YarnPackageManager;
|
|
35
|
+
return { ...YarnPackageManager, cwd };
|
|
34
36
|
} else if (hasNpm) {
|
|
35
37
|
console.log("Using npm as package manager.");
|
|
36
38
|
console.warn(
|
|
37
39
|
"There is already a yarn.lock file but could not find yarn on the PATH."
|
|
38
40
|
);
|
|
39
|
-
return NpmPackageManager;
|
|
41
|
+
return { ...NpmPackageManager, cwd };
|
|
40
42
|
}
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
if (hasNpm) {
|
|
44
46
|
console.log("Using npm as package manager.");
|
|
45
|
-
return NpmPackageManager;
|
|
47
|
+
return { ...NpmPackageManager, cwd };
|
|
46
48
|
} else if (hasYarn) {
|
|
47
49
|
console.log("Using yarn as package manager.");
|
|
48
|
-
return YarnPackageManager;
|
|
50
|
+
return { ...YarnPackageManager, cwd };
|
|
49
51
|
} else {
|
|
50
52
|
throw new Error(
|
|
51
53
|
"Unable to find a package manager. Supported managers are: npm and yarn."
|
|
@@ -56,22 +58,21 @@ export async function getPackageManager(root: string): Promise<PackageManager> {
|
|
|
56
58
|
/**
|
|
57
59
|
* Get the name of the given `packageManager`.
|
|
58
60
|
*/
|
|
59
|
-
export function getPackageManagerName(packageManager:
|
|
60
|
-
return packageManager
|
|
61
|
-
? "npm"
|
|
62
|
-
: packageManager === YarnPackageManager
|
|
63
|
-
? "yarn"
|
|
64
|
-
: "unknown";
|
|
61
|
+
export function getPackageManagerName(packageManager: PackageManager): string {
|
|
62
|
+
return packageManager.type ?? "unknown";
|
|
65
63
|
}
|
|
66
64
|
|
|
67
65
|
/**
|
|
68
66
|
* Manage packages using npm
|
|
69
67
|
*/
|
|
70
68
|
const NpmPackageManager: PackageManager = {
|
|
69
|
+
cwd: process.cwd(),
|
|
70
|
+
type: "npm",
|
|
71
71
|
/** Add and install a new devDependency into the local package.json. */
|
|
72
72
|
async addDevDeps(...packages: string[]): Promise<void> {
|
|
73
73
|
await execa("npm", ["install", ...packages, "--save-dev"], {
|
|
74
74
|
stdio: "inherit",
|
|
75
|
+
cwd: this.cwd,
|
|
75
76
|
});
|
|
76
77
|
},
|
|
77
78
|
|
|
@@ -79,6 +80,7 @@ const NpmPackageManager: PackageManager = {
|
|
|
79
80
|
async install(): Promise<void> {
|
|
80
81
|
await execa("npm", ["install"], {
|
|
81
82
|
stdio: "inherit",
|
|
83
|
+
cwd: this.cwd,
|
|
82
84
|
});
|
|
83
85
|
},
|
|
84
86
|
};
|
|
@@ -87,10 +89,13 @@ const NpmPackageManager: PackageManager = {
|
|
|
87
89
|
* Manage packages using yarn
|
|
88
90
|
*/
|
|
89
91
|
const YarnPackageManager: PackageManager = {
|
|
92
|
+
cwd: process.cwd(),
|
|
93
|
+
type: "yarn",
|
|
90
94
|
/** Add and install a new devDependency into the local package.json. */
|
|
91
95
|
async addDevDeps(...packages: string[]): Promise<void> {
|
|
92
96
|
await execa("yarn", ["add", ...packages, "--dev"], {
|
|
93
97
|
stdio: "inherit",
|
|
98
|
+
cwd: this.cwd,
|
|
94
99
|
});
|
|
95
100
|
},
|
|
96
101
|
|
|
@@ -98,6 +103,7 @@ const YarnPackageManager: PackageManager = {
|
|
|
98
103
|
async install(): Promise<void> {
|
|
99
104
|
await execa("yarn", ["install"], {
|
|
100
105
|
stdio: "inherit",
|
|
106
|
+
cwd: this.cwd,
|
|
101
107
|
});
|
|
102
108
|
},
|
|
103
109
|
};
|
package/src/pages.tsx
CHANGED
|
@@ -7,10 +7,10 @@ import { join } from "node:path";
|
|
|
7
7
|
import { URL } from "node:url";
|
|
8
8
|
import { watch } from "chokidar";
|
|
9
9
|
import { getType } from "mime";
|
|
10
|
-
import open from "open";
|
|
11
10
|
import { buildWorker } from "../pages/functions/buildWorker";
|
|
12
11
|
import { generateConfigFromFileTree } from "../pages/functions/filepath-routing";
|
|
13
12
|
import { writeRoutesModule } from "../pages/functions/routes";
|
|
13
|
+
import openInBrowser from "./open-in-browser";
|
|
14
14
|
import { toUrlPath } from "./paths";
|
|
15
15
|
import type { Config } from "../pages/functions/routes";
|
|
16
16
|
import type { Headers, Request, fetch } from "@miniflare/core";
|
|
@@ -771,7 +771,7 @@ export const pages: BuilderCallback<unknown, unknown> = (yargs) => {
|
|
|
771
771
|
kv: kvs = [],
|
|
772
772
|
do: durableObjects = [],
|
|
773
773
|
"live-reload": liveReload,
|
|
774
|
-
|
|
774
|
+
_: [_pages, _dev, ...remaining],
|
|
775
775
|
}) => {
|
|
776
776
|
if (!local) {
|
|
777
777
|
console.error("Only local mode is supported at the moment.");
|
|
@@ -795,8 +795,8 @@ export const pages: BuilderCallback<unknown, unknown> = (yargs) => {
|
|
|
795
795
|
|
|
796
796
|
let miniflareArgs: MiniflareOptions = {};
|
|
797
797
|
|
|
798
|
-
let scriptReadyResolve;
|
|
799
|
-
const scriptReadyPromise = new Promise(
|
|
798
|
+
let scriptReadyResolve: () => void;
|
|
799
|
+
const scriptReadyPromise = new Promise<void>(
|
|
800
800
|
(resolve) => (scriptReadyResolve = resolve)
|
|
801
801
|
);
|
|
802
802
|
|
|
@@ -830,7 +830,8 @@ export const pages: BuilderCallback<unknown, unknown> = (yargs) => {
|
|
|
830
830
|
scriptPath,
|
|
831
831
|
};
|
|
832
832
|
} else {
|
|
833
|
-
|
|
833
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
834
|
+
scriptReadyResolve!();
|
|
834
835
|
|
|
835
836
|
const scriptPath =
|
|
836
837
|
directory !== undefined
|
|
@@ -900,7 +901,7 @@ export const pages: BuilderCallback<unknown, unknown> = (yargs) => {
|
|
|
900
901
|
|
|
901
902
|
// env.ASSETS.fetch
|
|
902
903
|
serviceBindings: {
|
|
903
|
-
async ASSETS(request) {
|
|
904
|
+
async ASSETS(request: Request) {
|
|
904
905
|
if (proxyPort) {
|
|
905
906
|
try {
|
|
906
907
|
const url = new URL(request.url);
|
|
@@ -945,9 +946,7 @@ export const pages: BuilderCallback<unknown, unknown> = (yargs) => {
|
|
|
945
946
|
console.log(`Serving at http://localhost:${port}/`);
|
|
946
947
|
|
|
947
948
|
if (process.env.BROWSER !== "none") {
|
|
948
|
-
|
|
949
|
-
// fail silently if the open command doesn't work (e.g. in GitHub Codespaces)
|
|
950
|
-
childProcess.on("error", (_err) => {});
|
|
949
|
+
await openInBrowser(`http://localhost:${port}/`);
|
|
951
950
|
}
|
|
952
951
|
|
|
953
952
|
if (directory !== undefined && liveReload) {
|
|
@@ -964,7 +963,7 @@ export const pages: BuilderCallback<unknown, unknown> = (yargs) => {
|
|
|
964
963
|
miniflare.dispose().catch((err) => miniflare.log.error(err));
|
|
965
964
|
});
|
|
966
965
|
} catch (e) {
|
|
967
|
-
miniflare.log.error(e);
|
|
966
|
+
miniflare.log.error(e as Error);
|
|
968
967
|
EXIT("Could not start Miniflare.", 1);
|
|
969
968
|
}
|
|
970
969
|
}
|