wrangler 2.1.13 → 2.1.15
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/README.md +0 -4
- package/miniflare-dist/index.mjs +11 -7
- package/package.json +2 -1
- package/src/__tests__/delete.test.ts +114 -0
- package/src/__tests__/deployments.test.ts +91 -0
- package/src/__tests__/helpers/msw/handlers/deployments.ts +80 -0
- package/src/__tests__/helpers/msw/index.ts +4 -2
- package/src/__tests__/index.test.ts +4 -2
- package/src/__tests__/init.test.ts +1 -1
- package/src/__tests__/pages.test.ts +110 -0
- package/src/__tests__/tail.test.ts +2 -2
- package/src/__tests__/type-generation.test.ts +217 -0
- package/src/delete.ts +26 -1
- package/src/dev/local.tsx +5 -0
- package/src/entry.ts +1 -1
- package/src/index.tsx +88 -2
- package/src/init.ts +1 -1
- package/src/is-interactive.ts +4 -0
- package/src/logger.ts +2 -2
- package/src/miniflare-cli/index.ts +13 -8
- package/src/pages/constants.ts +2 -0
- package/src/pages/dev.tsx +4 -0
- package/src/pages/upload.tsx +23 -13
- package/src/sites.tsx +1 -1
- package/src/type-generation.ts +159 -0
- package/templates/__tests__/pages-dev-util.test.ts +128 -0
- package/templates/pages-dev-pipeline.ts +5 -12
- package/templates/pages-dev-util.ts +52 -0
- package/templates/pages-template-plugin.ts +4 -0
- package/templates/pages-template-worker.ts +21 -4
- package/templates/tsconfig.json +2 -1
- package/wrangler-dist/cli.js +7857 -6920
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as TOML from "@iarna/toml";
|
|
3
|
+
import { mockConsoleMethods } from "./helpers/mock-console";
|
|
4
|
+
import { runInTempDir } from "./helpers/run-in-tmp";
|
|
5
|
+
import { runWrangler } from "./helpers/run-wrangler";
|
|
6
|
+
import type { Config } from "../config";
|
|
7
|
+
import type { CfWorkerInit } from "../worker";
|
|
8
|
+
|
|
9
|
+
const bindingsConfigMock: CfWorkerInit["bindings"] & {
|
|
10
|
+
rules: Config["rules"];
|
|
11
|
+
} = {
|
|
12
|
+
kv_namespaces: [{ binding: "TEST_KV_NAMESPACE", id: "1234" }],
|
|
13
|
+
vars: {
|
|
14
|
+
SOMETHING: "asdasdfasdf",
|
|
15
|
+
ANOTHER: "thing",
|
|
16
|
+
OBJECT_VAR: {
|
|
17
|
+
enterprise: "1701-D",
|
|
18
|
+
activeDuty: true,
|
|
19
|
+
captian: "Picard",
|
|
20
|
+
}, // We can assume the objects will be stringified
|
|
21
|
+
},
|
|
22
|
+
durable_objects: {
|
|
23
|
+
bindings: [
|
|
24
|
+
{ name: "DURABLE_TEST1", class_name: "Durability1" },
|
|
25
|
+
{ name: "DURABLE_TEST2", class_name: "Durability2" },
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
r2_buckets: [
|
|
29
|
+
{
|
|
30
|
+
binding: "R2_BUCKET_BINDING",
|
|
31
|
+
bucket_name: "R2BUCKET_NAME_TEST",
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
d1_databases: [
|
|
35
|
+
{
|
|
36
|
+
// @ts-expect-error This type is resolved in the function that handles creating BETA string
|
|
37
|
+
binding: "D1_TESTING_SOMETHING",
|
|
38
|
+
database_name: "D1_BINDING",
|
|
39
|
+
database_id: "1234",
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
services: [{ binding: "SERVICE_BINDING", service: "SERVICE_NAME" }],
|
|
43
|
+
dispatch_namespaces: [
|
|
44
|
+
{ binding: "NAMESPACE_BINDING", namespace: "NAMESPACE_ID" },
|
|
45
|
+
],
|
|
46
|
+
logfwdr: {
|
|
47
|
+
schema: "LOGFWDER_SCHEMA",
|
|
48
|
+
bindings: [{ name: "LOGFWDR_BINDING", destination: "LOGFWDR_DESTINATION" }],
|
|
49
|
+
},
|
|
50
|
+
data_blobs: {
|
|
51
|
+
SOME_DATA_BLOB1: "SOME_DATA_BLOB1.bin",
|
|
52
|
+
SOME_DATA_BLOB2: "SOME_DATA_BLOB2.bin",
|
|
53
|
+
},
|
|
54
|
+
text_blobs: {
|
|
55
|
+
SOME_TEXT_BLOB1: "SOME_TEXT_BLOB1.txt",
|
|
56
|
+
SOME_TEXT_BLOB2: "SOME_TEXT_BLOB2.txt",
|
|
57
|
+
},
|
|
58
|
+
wasm_modules: { MODULE1: "module1.wasm", MODULE2: "module2.wasm" },
|
|
59
|
+
unsafe: [
|
|
60
|
+
{
|
|
61
|
+
// @ts-expect-error Unsafe bindings type is somewhat different in different places
|
|
62
|
+
bindings: [{ name: "testing_unsafe", type: "plain_text" }],
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
rules: [
|
|
66
|
+
{
|
|
67
|
+
type: "Text",
|
|
68
|
+
globs: ["**/*.txt"],
|
|
69
|
+
fallthrough: true,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
type: "Data",
|
|
73
|
+
globs: ["**/*.webp"],
|
|
74
|
+
fallthrough: true,
|
|
75
|
+
},
|
|
76
|
+
{ type: "CompiledWasm", globs: ["**/*.wasm"], fallthrough: true },
|
|
77
|
+
],
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
describe("generateTypes()", () => {
|
|
81
|
+
const std = mockConsoleMethods();
|
|
82
|
+
runInTempDir();
|
|
83
|
+
|
|
84
|
+
it("should log the interface type generated and declare modules", async () => {
|
|
85
|
+
fs.writeFileSync("./index.ts", "export default { async fetch () {} };");
|
|
86
|
+
fs.writeFileSync(
|
|
87
|
+
"./wrangler.toml",
|
|
88
|
+
TOML.stringify({
|
|
89
|
+
compatibility_date: "2022-01-12",
|
|
90
|
+
name: "test-name",
|
|
91
|
+
main: "./index.ts",
|
|
92
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
93
|
+
...(bindingsConfigMock as any),
|
|
94
|
+
unsafe: bindingsConfigMock.unsafe?.at(0) ?? {},
|
|
95
|
+
}),
|
|
96
|
+
"utf-8"
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
await runWrangler("types");
|
|
100
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
101
|
+
"interface Env {
|
|
102
|
+
TEST_KV_NAMESPACE: KVNamespace;
|
|
103
|
+
SOMETHING: asdasdfasdf;
|
|
104
|
+
ANOTHER: thing;
|
|
105
|
+
OBJECT_VAR: {\\"enterprise\\":\\"1701-D\\",\\"activeDuty\\":true,\\"captian\\":\\"Picard\\"};
|
|
106
|
+
DURABLE_TEST1: DurableObjectNamespace;
|
|
107
|
+
DURABLE_TEST2: DurableObjectNamespace;
|
|
108
|
+
R2_BUCKET_BINDING: R2Bucket;
|
|
109
|
+
D1_TESTING_SOMETHING: D1Database;
|
|
110
|
+
SERVICE_BINDING: Fetcher;
|
|
111
|
+
NAMESPACE_BINDING: any;
|
|
112
|
+
LOGFWDR_SCHEMA: any;
|
|
113
|
+
SOME_DATA_BLOB1: ArrayBuffer;
|
|
114
|
+
SOME_DATA_BLOB2: ArrayBuffer;
|
|
115
|
+
SOME_TEXT_BLOB1: string;
|
|
116
|
+
SOME_TEXT_BLOB2: string;
|
|
117
|
+
testing_unsafe: any;
|
|
118
|
+
}
|
|
119
|
+
declare module \\"*.txt\\" {
|
|
120
|
+
const value: string;
|
|
121
|
+
export default value;
|
|
122
|
+
}
|
|
123
|
+
declare module \\"*.webp\\" {
|
|
124
|
+
const value: ArrayBuffer;
|
|
125
|
+
export default value;
|
|
126
|
+
}
|
|
127
|
+
declare module \\"*.wasm\\" {
|
|
128
|
+
const value: WebAssembly.Module;
|
|
129
|
+
export default value;
|
|
130
|
+
}"
|
|
131
|
+
`);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("should create a DTS file at the location that the command is executed from", async () => {
|
|
135
|
+
fs.writeFileSync("./index.ts", "export default { async fetch () {} };");
|
|
136
|
+
fs.writeFileSync(
|
|
137
|
+
"./wrangler.toml",
|
|
138
|
+
TOML.stringify({
|
|
139
|
+
compatibility_date: "2022-01-12",
|
|
140
|
+
name: "test-name",
|
|
141
|
+
main: "./index.ts",
|
|
142
|
+
// @ts-expect-error This type is out of sync with the actual bindingsConfig type
|
|
143
|
+
vars: bindingsConfigMock.vars,
|
|
144
|
+
}),
|
|
145
|
+
"utf-8"
|
|
146
|
+
);
|
|
147
|
+
await runWrangler("types");
|
|
148
|
+
expect(fs.existsSync("./worker-configuration.d.ts")).toBe(true);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("should not create DTS file if there is nothing in the config to generate types from", async () => {
|
|
152
|
+
fs.writeFileSync("./index.ts", "export default { async fetch () {} };");
|
|
153
|
+
fs.writeFileSync(
|
|
154
|
+
"./wrangler.toml",
|
|
155
|
+
TOML.stringify({
|
|
156
|
+
compatibility_date: "2022-01-12",
|
|
157
|
+
name: "test-name",
|
|
158
|
+
main: "./index.ts",
|
|
159
|
+
}),
|
|
160
|
+
"utf-8"
|
|
161
|
+
);
|
|
162
|
+
await runWrangler("types");
|
|
163
|
+
expect(fs.existsSync("./worker-configuration.d.ts")).toBe(false);
|
|
164
|
+
expect(std.out).toMatchInlineSnapshot(`""`);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it("should create a DTS file at the location that the command is executed from", async () => {
|
|
168
|
+
fs.writeFileSync(
|
|
169
|
+
"./worker-configuration.d.ts",
|
|
170
|
+
"NOT THE CONTENTS OF THE GENERATED FILE"
|
|
171
|
+
);
|
|
172
|
+
fs.writeFileSync("./index.ts", "export default { async fetch () {} };");
|
|
173
|
+
fs.writeFileSync(
|
|
174
|
+
"./wrangler.toml",
|
|
175
|
+
TOML.stringify({
|
|
176
|
+
compatibility_date: "2022-01-12",
|
|
177
|
+
name: "test-name",
|
|
178
|
+
main: "./index.ts",
|
|
179
|
+
// @ts-expect-error This type is out of sync with the actual bindingsConfig type
|
|
180
|
+
vars: bindingsConfigMock.vars,
|
|
181
|
+
}),
|
|
182
|
+
"utf-8"
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
await expect(runWrangler("types")).rejects.toMatchInlineSnapshot(
|
|
186
|
+
`[Error: A non-wrangler worker-configuration.d.ts already exists, please rename and try again.]`
|
|
187
|
+
);
|
|
188
|
+
expect(fs.existsSync("./worker-configuration.d.ts")).toBe(true);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it("should log the declare global type generated and declare modules", async () => {
|
|
192
|
+
fs.writeFileSync(
|
|
193
|
+
"./index.ts",
|
|
194
|
+
`addEventListener('fetch', event => { event.respondWith(handleRequest(event.request));
|
|
195
|
+
}); async function handleRequest(request) { return new Response('Hello worker!', {headers: { 'content-type': 'text/plain' },});}`
|
|
196
|
+
);
|
|
197
|
+
fs.writeFileSync(
|
|
198
|
+
"./wrangler.toml",
|
|
199
|
+
TOML.stringify({
|
|
200
|
+
compatibility_date: "2022-01-12",
|
|
201
|
+
name: "test-name",
|
|
202
|
+
main: "./index.ts",
|
|
203
|
+
// @ts-expect-error This type is out of sync with the actual bindingsConfig type
|
|
204
|
+
unsafe: bindingsConfigMock.unsafe?.at(0) ?? {},
|
|
205
|
+
}),
|
|
206
|
+
"utf-8"
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
await runWrangler("types");
|
|
210
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
211
|
+
"declare global {
|
|
212
|
+
testing_unsafe: any;
|
|
213
|
+
}
|
|
214
|
+
"
|
|
215
|
+
`);
|
|
216
|
+
});
|
|
217
|
+
});
|
package/src/delete.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import assert from "assert";
|
|
1
2
|
import path from "path";
|
|
2
3
|
import { fetchResult } from "./cfetch";
|
|
3
4
|
import { findWranglerToml, readConfig } from "./config";
|
|
4
5
|
import { confirm } from "./dialogs";
|
|
5
6
|
import { CI } from "./is-ci";
|
|
6
7
|
import isInteractive from "./is-interactive";
|
|
8
|
+
import { deleteKVNamespace, listKVNamespaces } from "./kv/helpers";
|
|
7
9
|
import { logger } from "./logger";
|
|
8
10
|
import * as metrics from "./metrics";
|
|
9
11
|
import { requireAuth } from "./user";
|
|
@@ -60,11 +62,18 @@ export async function deleteHandler(args: ArgumentsCamelCase<DeleteArgs>) {
|
|
|
60
62
|
|
|
61
63
|
const scriptName = getScriptName(args, config);
|
|
62
64
|
|
|
65
|
+
assert(
|
|
66
|
+
scriptName,
|
|
67
|
+
"A worker name must be defined, either via --name, or in wrangler.toml"
|
|
68
|
+
);
|
|
69
|
+
|
|
63
70
|
if (args.dryRun) {
|
|
64
71
|
logger.log(`--dry-run: exiting now.`);
|
|
65
72
|
return;
|
|
66
73
|
}
|
|
67
74
|
|
|
75
|
+
assert(accountId, "Missing accountId");
|
|
76
|
+
|
|
68
77
|
let confirmed = true;
|
|
69
78
|
if (isInteractive() || !CI.isCI()) {
|
|
70
79
|
confirmed = await confirm(
|
|
@@ -79,8 +88,24 @@ export async function deleteHandler(args: ArgumentsCamelCase<DeleteArgs>) {
|
|
|
79
88
|
new URLSearchParams({ force: "true" })
|
|
80
89
|
);
|
|
81
90
|
|
|
91
|
+
await deleteSiteNamespaceIfExisting(scriptName, accountId);
|
|
92
|
+
|
|
82
93
|
logger.log("Successfully deleted", scriptName);
|
|
83
94
|
}
|
|
95
|
+
}
|
|
84
96
|
|
|
85
|
-
|
|
97
|
+
async function deleteSiteNamespaceIfExisting(
|
|
98
|
+
scriptName: string,
|
|
99
|
+
accountId: string
|
|
100
|
+
): Promise<void> {
|
|
101
|
+
const title = `__${scriptName}-workers_sites_assets`;
|
|
102
|
+
const previewTitle = `__${scriptName}-workers_sites_assets_preview`;
|
|
103
|
+
const allNamespaces = await listKVNamespaces(accountId);
|
|
104
|
+
const namespacesToDelete = allNamespaces.filter(
|
|
105
|
+
(ns) => ns.title === title || ns.title === previewTitle
|
|
106
|
+
);
|
|
107
|
+
for (const ns of namespacesToDelete) {
|
|
108
|
+
await deleteKVNamespace(accountId, ns.id);
|
|
109
|
+
logger.log(`🌀 Deleted asset namespace for Workers Site "${ns.title}"`);
|
|
110
|
+
}
|
|
86
111
|
}
|
package/src/dev/local.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import { fork } from "node:child_process";
|
|
|
3
3
|
import { realpathSync } from "node:fs";
|
|
4
4
|
import { readFile, writeFile } from "node:fs/promises";
|
|
5
5
|
import path from "node:path";
|
|
6
|
+
import chalk from "chalk";
|
|
6
7
|
import { npxImport } from "npx-import";
|
|
7
8
|
import { useState, useEffect, useRef } from "react";
|
|
8
9
|
import onExit from "signal-exit";
|
|
@@ -221,6 +222,10 @@ function useLocalWorker({
|
|
|
221
222
|
cwd: path.dirname(scriptPath),
|
|
222
223
|
execArgv: nodeOptions,
|
|
223
224
|
stdio: "pipe",
|
|
225
|
+
env: {
|
|
226
|
+
...process.env,
|
|
227
|
+
FORCE_COLOR: chalk.supportsColor.hasBasic ? "1" : undefined,
|
|
228
|
+
},
|
|
224
229
|
}));
|
|
225
230
|
|
|
226
231
|
child.on("message", async (messageString) => {
|
package/src/entry.ts
CHANGED
package/src/index.tsx
CHANGED
|
@@ -5,6 +5,7 @@ import supportsColor from "supports-color";
|
|
|
5
5
|
import { ProxyAgent, setGlobalDispatcher } from "undici";
|
|
6
6
|
import makeCLI from "yargs";
|
|
7
7
|
import { version as wranglerVersion } from "../package.json";
|
|
8
|
+
import { fetchResult } from "./cfetch";
|
|
8
9
|
import { readConfig } from "./config";
|
|
9
10
|
import { d1 } from "./d1";
|
|
10
11
|
import { deleteHandler, deleteOptions } from "./delete";
|
|
@@ -35,11 +36,22 @@ import { pubSubCommands } from "./pubsub/pubsub-commands";
|
|
|
35
36
|
import { r2 } from "./r2";
|
|
36
37
|
import { secret, secretBulkHandler, secretBulkOptions } from "./secret";
|
|
37
38
|
import { tailOptions, tailHandler } from "./tail";
|
|
39
|
+
import { generateTypes } from "./type-generation";
|
|
38
40
|
import { updateCheck } from "./update-check";
|
|
39
|
-
import {
|
|
41
|
+
import {
|
|
42
|
+
listScopes,
|
|
43
|
+
login,
|
|
44
|
+
logout,
|
|
45
|
+
requireAuth,
|
|
46
|
+
validateScopeKeys,
|
|
47
|
+
} from "./user";
|
|
40
48
|
import { whoami } from "./whoami";
|
|
41
49
|
|
|
50
|
+
import type { DeploymentListRes } from "./__tests__/helpers/msw/handlers/deployments";
|
|
42
51
|
import type { Config } from "./config";
|
|
52
|
+
import type { ServiceMetadataRes } from "./init";
|
|
53
|
+
import type { PartialConfigToDTS } from "./type-generation";
|
|
54
|
+
import type { ArgumentsCamelCase } from "yargs";
|
|
43
55
|
import type Yargs from "yargs";
|
|
44
56
|
|
|
45
57
|
export type ConfigPath = string | undefined;
|
|
@@ -262,7 +274,7 @@ export function createCLIParser(argv: string[]) {
|
|
|
262
274
|
// delete
|
|
263
275
|
wrangler.command(
|
|
264
276
|
"delete [script]",
|
|
265
|
-
"🗑
|
|
277
|
+
"🗑 Delete your Worker from Cloudflare.",
|
|
266
278
|
deleteOptions,
|
|
267
279
|
deleteHandler
|
|
268
280
|
);
|
|
@@ -467,6 +479,80 @@ export function createCLIParser(argv: string[]) {
|
|
|
467
479
|
}
|
|
468
480
|
);
|
|
469
481
|
|
|
482
|
+
// type generation
|
|
483
|
+
wrangler.command(
|
|
484
|
+
"types",
|
|
485
|
+
"📝 Generate types from bindings & module rules in config",
|
|
486
|
+
() => {},
|
|
487
|
+
async () => {
|
|
488
|
+
await printWranglerBanner();
|
|
489
|
+
const config = readConfig(undefined, {});
|
|
490
|
+
|
|
491
|
+
const configBindings: PartialConfigToDTS = {
|
|
492
|
+
kv_namespaces: config.kv_namespaces ?? [],
|
|
493
|
+
vars: { ...config.vars },
|
|
494
|
+
wasm_modules: config.wasm_modules,
|
|
495
|
+
text_blobs: {
|
|
496
|
+
...config.text_blobs,
|
|
497
|
+
},
|
|
498
|
+
data_blobs: config.data_blobs,
|
|
499
|
+
durable_objects: config.durable_objects,
|
|
500
|
+
r2_buckets: config.r2_buckets,
|
|
501
|
+
// @ts-expect-error - We don't want the type generated to inlcude the Beta prefix
|
|
502
|
+
d1_databases: config.d1_databases,
|
|
503
|
+
services: config.services,
|
|
504
|
+
dispatch_namespaces: config.dispatch_namespaces,
|
|
505
|
+
logfwdr: config.logfwdr,
|
|
506
|
+
unsafe: config.unsafe?.bindings,
|
|
507
|
+
rules: config.rules,
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
await generateTypes(configBindings, config);
|
|
511
|
+
}
|
|
512
|
+
);
|
|
513
|
+
|
|
514
|
+
wrangler.command(
|
|
515
|
+
"deployments",
|
|
516
|
+
false,
|
|
517
|
+
// "🚢 Logs the 10 most recent deployments with 'Version ID', 'Version number','Author email', 'Created on' and 'Latest deploy'",
|
|
518
|
+
(yargs) => {
|
|
519
|
+
yargs.option("name", {
|
|
520
|
+
describe: "The name of your worker",
|
|
521
|
+
type: "string",
|
|
522
|
+
});
|
|
523
|
+
},
|
|
524
|
+
async (deploymentsYargs: ArgumentsCamelCase<{ name: string }>) => {
|
|
525
|
+
await printWranglerBanner();
|
|
526
|
+
const config = readConfig(
|
|
527
|
+
deploymentsYargs.config as ConfigPath,
|
|
528
|
+
deploymentsYargs
|
|
529
|
+
);
|
|
530
|
+
const accountId = await requireAuth(config);
|
|
531
|
+
const scriptName = getScriptName(
|
|
532
|
+
{ name: deploymentsYargs.name, env: undefined },
|
|
533
|
+
config
|
|
534
|
+
);
|
|
535
|
+
const scriptMetadata = await fetchResult<ServiceMetadataRes>(
|
|
536
|
+
`/accounts/${accountId}/workers/services/${scriptName}`
|
|
537
|
+
);
|
|
538
|
+
|
|
539
|
+
const scriptTag = scriptMetadata.default_environment.script.tag;
|
|
540
|
+
const deployments = await fetchResult<DeploymentListRes>(
|
|
541
|
+
`/accounts/${accountId}/workers/versions/by-script/${scriptTag}`
|
|
542
|
+
);
|
|
543
|
+
|
|
544
|
+
const versionMessages = deployments.versions.map(
|
|
545
|
+
(versions, index) =>
|
|
546
|
+
`\nVersion ID: ${versions.version_id}\nVersion number: ${
|
|
547
|
+
versions.version_number
|
|
548
|
+
}\nCreated on: ${versions.metadata.created_on}\nAuthor email: ${
|
|
549
|
+
versions.metadata.author_email
|
|
550
|
+
}\nLatest deploy: ${index === 0}\n`
|
|
551
|
+
);
|
|
552
|
+
logger.log(...versionMessages);
|
|
553
|
+
}
|
|
554
|
+
);
|
|
555
|
+
|
|
470
556
|
// This set to false to allow overwrite of default behaviour
|
|
471
557
|
wrangler.version(false);
|
|
472
558
|
|
package/src/init.ts
CHANGED
|
@@ -16,8 +16,8 @@ import { parsePackageJSON, parseTOML, readFileSync } from "./parse";
|
|
|
16
16
|
import { getBasePath } from "./paths";
|
|
17
17
|
import { requireAuth } from "./user";
|
|
18
18
|
import { CommandLineArgsError, printWranglerBanner } from "./index";
|
|
19
|
-
import type { RawConfig } from "./config";
|
|
20
19
|
|
|
20
|
+
import type { RawConfig } from "./config";
|
|
21
21
|
import type { Route, SimpleRoute } from "./config/environment";
|
|
22
22
|
import type { WorkerMetadata } from "./create-worker-upload-form";
|
|
23
23
|
import type { ConfigPath } from "./index";
|
package/src/is-interactive.ts
CHANGED
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
* or you're piping values from / to another process, etc
|
|
5
5
|
*/
|
|
6
6
|
export default function isInteractive(): boolean {
|
|
7
|
+
if (process.env.CF_PAGES === "1") {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
|
|
7
11
|
try {
|
|
8
12
|
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
9
13
|
} catch {
|
package/src/logger.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { format } from "node:util";
|
|
|
2
2
|
import { formatMessagesSync } from "esbuild";
|
|
3
3
|
import { getEnvironmentVariableFactory } from "./environment-variables";
|
|
4
4
|
|
|
5
|
-
const LOGGER_LEVELS = {
|
|
5
|
+
export const LOGGER_LEVELS = {
|
|
6
6
|
none: -1,
|
|
7
7
|
error: 0,
|
|
8
8
|
warn: 1,
|
|
@@ -11,7 +11,7 @@ const LOGGER_LEVELS = {
|
|
|
11
11
|
debug: 4,
|
|
12
12
|
} as const;
|
|
13
13
|
|
|
14
|
-
type LoggerLevel = keyof typeof LOGGER_LEVELS;
|
|
14
|
+
export type LoggerLevel = keyof typeof LOGGER_LEVELS;
|
|
15
15
|
|
|
16
16
|
/** A map from LOGGER_LEVEL to the error `kind` needed by `formatMessagesSync()`. */
|
|
17
17
|
const LOGGER_LEVEL_FORMAT_TYPE_MAP = {
|
|
@@ -4,16 +4,18 @@ import {
|
|
|
4
4
|
DurableObjectStub,
|
|
5
5
|
} from "@miniflare/durable-objects";
|
|
6
6
|
import {
|
|
7
|
-
Log,
|
|
7
|
+
Log as MiniflareLog,
|
|
8
|
+
LogLevel as MiniflareLogLevel,
|
|
8
9
|
Miniflare,
|
|
9
|
-
Response as MiniflareResponse,
|
|
10
10
|
Request as MiniflareRequest,
|
|
11
|
+
Response as MiniflareResponse,
|
|
11
12
|
} from "miniflare";
|
|
12
13
|
import yargs from "yargs";
|
|
13
14
|
import { hideBin } from "yargs/helpers";
|
|
14
15
|
import { FatalError } from "../errors";
|
|
15
16
|
import generateASSETSBinding from "./assets";
|
|
16
17
|
import { getRequestContextCheckOptions } from "./request-context";
|
|
18
|
+
import type { LoggerLevel } from "../logger";
|
|
17
19
|
import type { Options } from "./assets";
|
|
18
20
|
import type { AddressInfo } from "net";
|
|
19
21
|
|
|
@@ -24,7 +26,7 @@ export interface EnablePagesAssetsServiceBindingOptions {
|
|
|
24
26
|
|
|
25
27
|
// miniflare defines this but importing it throws:
|
|
26
28
|
// Dynamic require of "path" is not supported
|
|
27
|
-
class
|
|
29
|
+
class MiniflareNoOpLog extends MiniflareLog {
|
|
28
30
|
log(): void {}
|
|
29
31
|
|
|
30
32
|
error(message: Error): void {
|
|
@@ -41,14 +43,17 @@ async function main() {
|
|
|
41
43
|
...JSON.parse((args._[0] as string) ?? "{}"),
|
|
42
44
|
...requestContextCheckOptions,
|
|
43
45
|
};
|
|
44
|
-
|
|
46
|
+
|
|
47
|
+
let logLevelString: Uppercase<LoggerLevel> = config.logLevel.toUpperCase();
|
|
48
|
+
if (logLevelString === "LOG") logLevelString = "INFO";
|
|
49
|
+
const logLevel = MiniflareLogLevel[logLevelString];
|
|
45
50
|
|
|
46
51
|
config.log =
|
|
47
|
-
|
|
48
|
-
? new
|
|
49
|
-
: new
|
|
52
|
+
logLevel === MiniflareLogLevel.NONE
|
|
53
|
+
? new MiniflareNoOpLog()
|
|
54
|
+
: new MiniflareLog(logLevel, config.logOptions);
|
|
50
55
|
|
|
51
|
-
if (logLevel ===
|
|
56
|
+
if (logLevel === MiniflareLogLevel.DEBUG) {
|
|
52
57
|
console.log("MINIFLARE OPTIONS:\n", JSON.stringify(config, null, 2));
|
|
53
58
|
}
|
|
54
59
|
|
package/src/pages/constants.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { version as wranglerVersion } from "../../package.json";
|
|
2
2
|
|
|
3
|
+
export const MAX_ASSET_COUNT = 20_000;
|
|
4
|
+
export const MAX_ASSET_SIZE = 25 * 1024 * 1024;
|
|
3
5
|
export const PAGES_CONFIG_CACHE_FILENAME = "pages.json";
|
|
4
6
|
export const MAX_BUCKET_SIZE = 50 * 1024 * 1024;
|
|
5
7
|
export const MAX_BUCKET_FILE_COUNT = 5000;
|
package/src/pages/dev.tsx
CHANGED
package/src/pages/upload.tsx
CHANGED
|
@@ -3,13 +3,17 @@ import { dirname, join, relative, resolve, sep } from "node:path";
|
|
|
3
3
|
import { render, Text } from "ink";
|
|
4
4
|
import Spinner from "ink-spinner";
|
|
5
5
|
import { getType } from "mime";
|
|
6
|
+
import { Minimatch } from "minimatch";
|
|
6
7
|
import PQueue from "p-queue";
|
|
7
8
|
import prettyBytes from "pretty-bytes";
|
|
8
9
|
import React from "react";
|
|
9
10
|
import { fetchResult } from "../cfetch";
|
|
10
11
|
import { FatalError } from "../errors";
|
|
12
|
+
import isInteractive from "../is-interactive";
|
|
11
13
|
import { logger } from "../logger";
|
|
12
14
|
import {
|
|
15
|
+
MAX_ASSET_COUNT,
|
|
16
|
+
MAX_ASSET_SIZE,
|
|
13
17
|
BULK_UPLOAD_CONCURRENCY,
|
|
14
18
|
MAX_BUCKET_FILE_COUNT,
|
|
15
19
|
MAX_BUCKET_SIZE,
|
|
@@ -96,10 +100,11 @@ export const upload = async (
|
|
|
96
100
|
"_redirects",
|
|
97
101
|
"_headers",
|
|
98
102
|
"_routes.json",
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
"
|
|
102
|
-
|
|
103
|
+
"functions",
|
|
104
|
+
"**/.DS_Store",
|
|
105
|
+
"**/node_modules",
|
|
106
|
+
"**/.git",
|
|
107
|
+
].map((pattern) => new Minimatch(pattern));
|
|
103
108
|
|
|
104
109
|
const directory = resolve(args.directory);
|
|
105
110
|
|
|
@@ -121,10 +126,13 @@ export const upload = async (
|
|
|
121
126
|
await Promise.all(
|
|
122
127
|
files.map(async (file) => {
|
|
123
128
|
const filepath = join(dir, file);
|
|
129
|
+
const relativeFilepath = relative(startingDir, filepath);
|
|
124
130
|
const filestat = await stat(filepath);
|
|
125
131
|
|
|
126
|
-
|
|
127
|
-
|
|
132
|
+
for (const minimatch of IGNORE_LIST) {
|
|
133
|
+
if (minimatch.match(relativeFilepath)) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
128
136
|
}
|
|
129
137
|
|
|
130
138
|
if (filestat.isSymbolicLink()) {
|
|
@@ -134,12 +142,12 @@ export const upload = async (
|
|
|
134
142
|
if (filestat.isDirectory()) {
|
|
135
143
|
fileMap = await walk(filepath, fileMap, startingDir);
|
|
136
144
|
} else {
|
|
137
|
-
const name =
|
|
145
|
+
const name = relativeFilepath.split(sep).join("/");
|
|
138
146
|
|
|
139
|
-
if (filestat.size >
|
|
147
|
+
if (filestat.size > MAX_ASSET_SIZE) {
|
|
140
148
|
throw new FatalError(
|
|
141
149
|
`Error: Pages only supports files up to ${prettyBytes(
|
|
142
|
-
|
|
150
|
+
MAX_ASSET_SIZE
|
|
143
151
|
)} in size\n${name} is ${prettyBytes(filestat.size)} in size`,
|
|
144
152
|
1
|
|
145
153
|
);
|
|
@@ -161,9 +169,9 @@ export const upload = async (
|
|
|
161
169
|
|
|
162
170
|
const fileMap = await walk(directory);
|
|
163
171
|
|
|
164
|
-
if (fileMap.size >
|
|
172
|
+
if (fileMap.size > MAX_ASSET_COUNT) {
|
|
165
173
|
throw new FatalError(
|
|
166
|
-
`Error: Pages only supports up to
|
|
174
|
+
`Error: Pages only supports up to ${MAX_ASSET_COUNT.toLocaleString()} files in a deployment. Ensure you have specified your build output directory correctly.`,
|
|
167
175
|
1
|
|
168
176
|
);
|
|
169
177
|
}
|
|
@@ -309,7 +317,9 @@ export const upload = async (
|
|
|
309
317
|
(error) => {
|
|
310
318
|
return Promise.reject(
|
|
311
319
|
new FatalError(
|
|
312
|
-
|
|
320
|
+
`Failed to upload files. Please try again. Error: ${JSON.stringify(
|
|
321
|
+
error
|
|
322
|
+
)})`,
|
|
313
323
|
error.code || 1
|
|
314
324
|
)
|
|
315
325
|
);
|
|
@@ -390,7 +400,7 @@ function Progress({ done, total }: { done: number; total: number }) {
|
|
|
390
400
|
return (
|
|
391
401
|
<>
|
|
392
402
|
<Text>
|
|
393
|
-
<Spinner type="earth" />
|
|
403
|
+
{isInteractive() ? <Spinner type="earth" /> : null}
|
|
394
404
|
{` Uploading... (${done}/${total})\n`}
|
|
395
405
|
</Text>
|
|
396
406
|
</>
|
package/src/sites.tsx
CHANGED
|
@@ -77,7 +77,7 @@ async function createKVNamespaceIfNotAlreadyExisting(
|
|
|
77
77
|
// check if it already exists
|
|
78
78
|
// TODO: this is super inefficient, should be made better
|
|
79
79
|
const namespaces = await listKVNamespaces(accountId);
|
|
80
|
-
const found = namespaces.find((
|
|
80
|
+
const found = namespaces.find((ns) => ns.title === title);
|
|
81
81
|
if (found) {
|
|
82
82
|
return { created: false, id: found.id };
|
|
83
83
|
}
|