wrangler 2.12.2 → 2.13.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.
Files changed (53) hide show
  1. package/package.json +4 -3
  2. package/src/__tests__/configuration.test.ts +14 -12
  3. package/src/__tests__/d1/execute.test.ts +2 -0
  4. package/src/__tests__/d1/migrate.test.ts +2 -0
  5. package/src/__tests__/delete.test.ts +6 -0
  6. package/src/__tests__/deployments.test.ts +335 -95
  7. package/src/__tests__/dev.test.tsx +71 -56
  8. package/src/__tests__/helpers/mock-console.ts +6 -0
  9. package/src/__tests__/helpers/msw/handlers/deployments.ts +70 -3
  10. package/src/__tests__/helpers/msw/index.ts +4 -2
  11. package/src/__tests__/helpers/worker-scripts/parent-worker.js +4 -1
  12. package/src/__tests__/index.test.ts +10 -4
  13. package/src/__tests__/init.test.ts +127 -96
  14. package/src/__tests__/jest.setup.ts +4 -0
  15. package/src/__tests__/kv.test.ts +9 -9
  16. package/src/__tests__/middleware.scheduled.test.ts +2 -2
  17. package/src/__tests__/middleware.test.ts +2 -2
  18. package/src/__tests__/mtls-certificates.test.ts +5 -2
  19. package/src/__tests__/pages/deployment-list.test.ts +2 -0
  20. package/src/__tests__/pages/project-list.test.ts +2 -0
  21. package/src/__tests__/pages/project-upload.test.ts +43 -24
  22. package/src/__tests__/pages/publish.test.ts +69 -69
  23. package/src/__tests__/publish.test.ts +275 -155
  24. package/src/__tests__/pubsub.test.ts +3 -0
  25. package/src/__tests__/queues.test.ts +5 -2
  26. package/src/__tests__/tsconfig.tsbuildinfo +1 -1
  27. package/src/__tests__/worker-namespace.test.ts +1 -0
  28. package/src/bundle.ts +10 -0
  29. package/src/config/environment.ts +3 -0
  30. package/src/config/validation.ts +3 -1
  31. package/src/create-worker-upload-form.ts +1 -1
  32. package/src/d1/backups.tsx +15 -11
  33. package/src/d1/create.tsx +20 -16
  34. package/src/d1/execute.tsx +21 -18
  35. package/src/d1/list.tsx +2 -2
  36. package/src/d1/migrations/apply.tsx +35 -29
  37. package/src/d1/migrations/create.tsx +15 -12
  38. package/src/d1/migrations/list.tsx +10 -7
  39. package/src/deployments.ts +260 -8
  40. package/src/index.ts +75 -22
  41. package/src/init.ts +144 -135
  42. package/src/metrics/send-event.ts +2 -1
  43. package/src/pages/deployments.tsx +3 -5
  44. package/src/pages/functions/tsconfig.tsbuildinfo +1 -1
  45. package/src/pages/projects.tsx +2 -5
  46. package/src/pages/upload.tsx +29 -9
  47. package/src/publish/publish.ts +7 -18
  48. package/src/queues/cli/commands/consumer/add.ts +6 -0
  49. package/src/queues/client.ts +1 -0
  50. package/src/utils/render.ts +93 -0
  51. package/templates/d1-beta-facade.js +3 -0
  52. package/wrangler-dist/cli.d.ts +2 -0
  53. package/wrangler-dist/cli.js +8174 -7873
@@ -27,6 +27,7 @@ describe("dispatch-namespace", () => {
27
27
  Object {
28
28
  "debug": "",
29
29
  "err": "",
30
+ "info": "",
30
31
  "out": "wrangler dispatch-namespace
31
32
 
32
33
  📦 Interact with a dispatch namespace
package/src/bundle.ts CHANGED
@@ -94,6 +94,15 @@ const nodejsCompatPlugin: esbuild.Plugin = {
94
94
  },
95
95
  };
96
96
 
97
+ const cloudflareJsPlugin: esbuild.Plugin = {
98
+ name: "cloudflare javascript Plugin",
99
+ setup(pluginBuild) {
100
+ pluginBuild.onResolve({ filter: /^cloudflare:.*/ }, () => {
101
+ return { external: true };
102
+ });
103
+ },
104
+ };
105
+
97
106
  /**
98
107
  * Generate a bundle for the worker identified by the arguments passed in.
99
108
  */
@@ -379,6 +388,7 @@ export async function bundleWorker(
379
388
  ? [NodeGlobalsPolyfills({ buffer: true }), NodeModulesPolyfills()]
380
389
  : []),
381
390
  ...(nodejsCompat ? [nodejsCompatPlugin] : []),
391
+ ...[cloudflareJsPlugin],
382
392
  ...(plugins || []),
383
393
  ],
384
394
  ...(jsxFactory && { jsxFactory }),
@@ -374,6 +374,9 @@ interface EnvironmentNonInheritable {
374
374
 
375
375
  /** The queue to send messages that failed to be consumed. */
376
376
  dead_letter_queue?: string;
377
+
378
+ /** The maximum number of concurrent consumer Worker invocations. Leaving this unset will allow your consumer to scale to the maximum concurrency needed to keep up with the message backlog. */
379
+ max_concurrency?: number | null;
377
380
  }[];
378
381
  };
379
382
 
@@ -2215,6 +2215,7 @@ const validateConsumer: ValidatorFn = (diagnostics, field, value, _config) => {
2215
2215
  "max_batch_timeout",
2216
2216
  "max_retries",
2217
2217
  "dead_letter_queue",
2218
+ "max_concurrency",
2218
2219
  ])
2219
2220
  ) {
2220
2221
  isValid = false;
@@ -2230,12 +2231,13 @@ const validateConsumer: ValidatorFn = (diagnostics, field, value, _config) => {
2230
2231
 
2231
2232
  const options: {
2232
2233
  key: string;
2233
- type: "number" | "string";
2234
+ type: "number" | "string" | "boolean";
2234
2235
  }[] = [
2235
2236
  { key: "max_batch_size", type: "number" },
2236
2237
  { key: "max_batch_timeout", type: "number" },
2237
2238
  { key: "max_retries", type: "number" },
2238
2239
  { key: "dead_letter_queue", type: "string" },
2240
+ { key: "max_concurrency", type: "number" },
2239
2241
  ];
2240
2242
  for (const optionalOpt of options) {
2241
2243
  if (!isOptionalProperty(value, optionalOpt.key, optionalOpt.type)) {
@@ -23,7 +23,7 @@ export function toMimeType(type: CfModuleType): string {
23
23
  }
24
24
  }
25
25
 
26
- type WorkerMetadataBinding =
26
+ export type WorkerMetadataBinding =
27
27
  // If you add any new binding types here, also add it to safeBindings
28
28
  // under validateUnsafeBinding in config/validation.ts
29
29
  | { type: "plain_text"; name: string; text: string }
@@ -1,6 +1,5 @@
1
1
  import fs from "node:fs/promises";
2
2
  import * as path from "path";
3
- import { render } from "ink";
4
3
  import Table from "ink-table";
5
4
  import React from "react";
6
5
  import { fetchResult } from "../cfetch";
@@ -8,6 +7,7 @@ import { performApiFetch } from "../cfetch/internal";
8
7
  import { withConfig } from "../config";
9
8
  import { logger } from "../logger";
10
9
  import { requireAuth } from "../user";
10
+ import { renderToString } from "../utils/render";
11
11
  import { formatBytes, formatTimeAgo } from "./formatTimeAgo";
12
12
  import { Name } from "./options";
13
13
  import { d1BetaWarning, getDatabaseByNameOrBinding } from "./utils";
@@ -33,11 +33,13 @@ export const ListHandler = withConfig<ListHandlerOptions>(
33
33
  );
34
34
 
35
35
  const backups: Backup[] = await listBackups(accountId, db.uuid);
36
- render(
37
- <Table
38
- data={backups}
39
- columns={["created_at", "id", "num_tables", "size"]}
40
- ></Table>
36
+ logger.log(
37
+ renderToString(
38
+ <Table
39
+ data={backups}
40
+ columns={["created_at", "id", "num_tables", "size"]}
41
+ ></Table>
42
+ )
41
43
  );
42
44
  }
43
45
  );
@@ -94,11 +96,13 @@ export const CreateHandler = withConfig<CreateHandlerOptions>(
94
96
  );
95
97
 
96
98
  const backup: Backup = await createBackup(accountId, db.uuid);
97
- render(
98
- <Table
99
- data={[backup]}
100
- columns={["created_at", "id", "num_tables", "size", "state"]}
101
- ></Table>
99
+ logger.log(
100
+ renderToString(
101
+ <Table
102
+ data={[backup]}
103
+ columns={["created_at", "id", "num_tables", "size", "state"]}
104
+ ></Table>
105
+ )
102
106
  );
103
107
  }
104
108
  );
package/src/d1/create.tsx CHANGED
@@ -1,8 +1,9 @@
1
- import { render, Text, Box } from "ink";
1
+ import { Text, Box } from "ink";
2
2
  import React from "react";
3
3
  import { fetchResult } from "../cfetch";
4
4
  import { logger } from "../logger";
5
5
  import { requireAuth } from "../user";
6
+ import { renderToString } from "../utils/render";
6
7
  import { d1BetaWarning } from "./utils";
7
8
  import type {
8
9
  CommonYargsArgv,
@@ -45,20 +46,23 @@ export async function Handler({
45
46
  throw e;
46
47
  }
47
48
 
48
- render(
49
- <Box flexDirection="column">
50
- <Text>✅ Successfully created DB &apos;{db.name}&apos;!</Text>
51
- <Text>&nbsp;</Text>
52
- <Text>
53
- Add the following to your wrangler.toml to connect to it from a Worker:
54
- </Text>
55
- <Text>&nbsp;</Text>
56
- <Text>[[ d1_databases ]]</Text>
57
- <Text>
58
- binding = &quot;DB&quot; # i.e. available in your Worker on env.DB
59
- </Text>
60
- <Text>database_name = &quot;{db.name}&quot;</Text>
61
- <Text>database_id = &quot;{db.uuid}&quot;</Text>
62
- </Box>
49
+ logger.log(
50
+ renderToString(
51
+ <Box flexDirection="column">
52
+ <Text>✅ Successfully created DB &apos;{db.name}&apos;!</Text>
53
+ <Text>&nbsp;</Text>
54
+ <Text>
55
+ Add the following to your wrangler.toml to connect to it from a
56
+ Worker:
57
+ </Text>
58
+ <Text>&nbsp;</Text>
59
+ <Text>[[ d1_databases ]]</Text>
60
+ <Text>
61
+ binding = &quot;DB&quot; # i.e. available in your Worker on env.DB
62
+ </Text>
63
+ <Text>database_name = &quot;{db.name}&quot;</Text>
64
+ <Text>database_id = &quot;{db.uuid}&quot;</Text>
65
+ </Box>
66
+ )
63
67
  );
64
68
  }
@@ -2,7 +2,7 @@ import { existsSync } from "node:fs";
2
2
  import { mkdir } from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import chalk from "chalk";
5
- import { render, Static, Text } from "ink";
5
+ import { Static, Text } from "ink";
6
6
  import Table from "ink-table";
7
7
  import { npxImport } from "npx-import";
8
8
  import React from "react";
@@ -14,6 +14,7 @@ import { logger } from "../logger";
14
14
  import { readFileSync } from "../parse";
15
15
  import { readableRelative } from "../paths";
16
16
  import { requireAuth } from "../user";
17
+ import { renderToString } from "../utils/render";
17
18
  import * as options from "./options";
18
19
  import splitSqlQuery from "./splitter";
19
20
  import {
@@ -110,25 +111,27 @@ export const Handler = async (args: HandlerOptions): Promise<void> => {
110
111
 
111
112
  if (isInteractive && !json) {
112
113
  // Render table if single result
113
- render(
114
- <Static items={response}>
115
- {(result) => {
116
- // batch results
117
- if (!Array.isArray(result)) {
118
- const { results, query } = result;
114
+ logger.log(
115
+ renderToString(
116
+ <Static items={response}>
117
+ {(result) => {
118
+ // batch results
119
+ if (!Array.isArray(result)) {
120
+ const { results, query } = result;
119
121
 
120
- if (Array.isArray(results) && results.length > 0) {
121
- const shortQuery = shorten(query, 48);
122
- return (
123
- <>
124
- {shortQuery ? <Text dimColor>{shortQuery}</Text> : null}
125
- <Table data={results}></Table>
126
- </>
127
- );
122
+ if (Array.isArray(results) && results.length > 0) {
123
+ const shortQuery = shorten(query, 48);
124
+ return (
125
+ <>
126
+ {shortQuery ? <Text dimColor>{shortQuery}</Text> : null}
127
+ <Table data={results}></Table>
128
+ </>
129
+ );
130
+ }
128
131
  }
129
- }
130
- }}
131
- </Static>
132
+ }}
133
+ </Static>
134
+ )
132
135
  );
133
136
  } else {
134
137
  // set loggerLevel back to what it was before to actually output the JSON in stdout
package/src/d1/list.tsx CHANGED
@@ -1,9 +1,9 @@
1
- import { render } from "ink";
2
1
  import Table from "ink-table";
3
2
  import React from "react";
4
3
  import { fetchResult } from "../cfetch";
5
4
  import { logger } from "../logger";
6
5
  import { requireAuth } from "../user";
6
+ import { renderToString } from "../utils/render";
7
7
  import { d1BetaWarning } from "./utils";
8
8
  import type {
9
9
  CommonYargsArgv,
@@ -31,7 +31,7 @@ export async function Handler({
31
31
  logger.log(JSON.stringify(dbs, null, 2));
32
32
  } else {
33
33
  logger.log(d1BetaWarning);
34
- render(<Table data={dbs}></Table>);
34
+ logger.log(renderToString(<Table data={dbs}></Table>));
35
35
  }
36
36
  }
37
37
 
@@ -1,7 +1,7 @@
1
1
  import assert from "node:assert";
2
2
  import fs from "node:fs";
3
3
  import path from "path";
4
- import { Box, render, Text } from "ink";
4
+ import { Box, Text } from "ink";
5
5
  import Table from "ink-table";
6
6
  import React from "react";
7
7
  import { withConfig } from "../../config";
@@ -10,6 +10,7 @@ import { CI } from "../../is-ci";
10
10
  import isInteractive from "../../is-interactive";
11
11
  import { logger } from "../../logger";
12
12
  import { requireAuth } from "../../user";
13
+ import { renderToString } from "../../utils/render";
13
14
  import { createBackup } from "../backups";
14
15
  import { DEFAULT_MIGRATION_PATH, DEFAULT_MIGRATION_TABLE } from "../constants";
15
16
  import { executeSql } from "../execute";
@@ -97,14 +98,16 @@ export const ApplyHandler = withConfig<ApplyHandlerOptions>(
97
98
  });
98
99
 
99
100
  if (unappliedMigrations.length === 0) {
100
- render(<Text>✅ No migrations to apply!</Text>);
101
+ logger.log(renderToString(<Text>✅ No migrations to apply!</Text>));
101
102
  return;
102
103
  }
103
- render(
104
- <Box flexDirection="column">
105
- <Text>Migrations to be applied:</Text>
106
- <Table data={unappliedMigrations} columns={["Name"]}></Table>
107
- </Box>
104
+ logger.log(
105
+ renderToString(
106
+ <Box flexDirection="column">
107
+ <Text>Migrations to be applied:</Text>
108
+ <Table data={unappliedMigrations} columns={["Name"]}></Table>
109
+ </Box>
110
+ )
108
111
  );
109
112
  const ok = await confirm(
110
113
  `About to apply ${unappliedMigrations.length} migration(s)
@@ -118,7 +121,7 @@ Your database may not be available to serve requests during the migration, conti
118
121
  databaseInfo,
119
122
  "In non-local mode `databaseInfo` should be defined."
120
123
  );
121
- render(<Text>🕒 Creating backup...</Text>);
124
+ logger.log(renderToString(<Text>🕒 Creating backup...</Text>));
122
125
  const accountId = await requireAuth({});
123
126
  await createBackup(accountId, databaseInfo.uuid);
124
127
  }
@@ -169,35 +172,38 @@ Your database may not be available to serve requests during the migration, conti
169
172
  }
170
173
  } catch (e) {
171
174
  const err = e as ParseError;
175
+ const maybeCause = (err.cause ?? err) as Error;
172
176
 
173
177
  success = false;
174
178
  errorNotes = err.notes?.map((msg) => msg.text) ?? [
175
- err.message ?? err.toString(),
179
+ maybeCause?.message ?? maybeCause.toString(),
176
180
  ];
177
181
  }
178
182
 
179
183
  migration.Status = success ? "✅" : "❌";
180
184
 
181
- render(
182
- <Box flexDirection="column">
183
- <Table
184
- data={unappliedMigrations}
185
- columns={["Name", "Status"]}
186
- ></Table>
187
- {errorNotes.length > 0 && (
188
- <Box flexDirection="column">
189
- <Text>&nbsp;</Text>
190
- <Text>
191
- ❌ Migration {migration.Name} failed with following Errors
192
- </Text>
193
- <Table
194
- data={errorNotes.map((err) => {
195
- return { Error: err };
196
- })}
197
- ></Table>
198
- </Box>
199
- )}
200
- </Box>
185
+ logger.log(
186
+ renderToString(
187
+ <Box flexDirection="column">
188
+ <Table
189
+ data={unappliedMigrations}
190
+ columns={["Name", "Status"]}
191
+ ></Table>
192
+ {errorNotes.length > 0 && (
193
+ <Box flexDirection="column">
194
+ <Text>&nbsp;</Text>
195
+ <Text>
196
+ ❌ Migration {migration.Name} failed with following Errors
197
+ </Text>
198
+ <Table
199
+ data={errorNotes.map((err) => {
200
+ return { Error: err };
201
+ })}
202
+ ></Table>
203
+ </Box>
204
+ )}
205
+ </Box>
206
+ )
201
207
  );
202
208
 
203
209
  if (errorNotes.length > 0) return;
@@ -1,9 +1,10 @@
1
1
  import fs from "node:fs";
2
2
  import path from "path";
3
- import { Box, render, Text } from "ink";
3
+ import { Box, Text } from "ink";
4
4
  import React from "react";
5
5
  import { withConfig } from "../../config";
6
6
  import { logger } from "../../logger";
7
+ import { renderToString } from "../../utils/render";
7
8
  import { DEFAULT_MIGRATION_PATH } from "../constants";
8
9
  import { Database } from "../options";
9
10
  import { d1BetaWarning, getDatabaseInfoFromConfig } from "../utils";
@@ -54,17 +55,19 @@ export const CreateHandler = withConfig<CreateHandlerOptions>(
54
55
  `-- Migration number: ${nextMigrationNumber} \t ${new Date().toISOString()}\n`
55
56
  );
56
57
 
57
- render(
58
- <Box flexDirection="column">
59
- <Text>
60
- ✅ Successfully created Migration &apos;{newMigrationName}&apos;!
61
- </Text>
62
- <Text>&nbsp;</Text>
63
- <Text>The migration is available for editing here</Text>
64
- <Text>
65
- {migrationsPath}/{newMigrationName}
66
- </Text>
67
- </Box>
58
+ logger.log(
59
+ renderToString(
60
+ <Box flexDirection="column">
61
+ <Text>
62
+ ✅ Successfully created Migration &apos;{newMigrationName}&apos;!
63
+ </Text>
64
+ <Text>&nbsp;</Text>
65
+ <Text>The migration is available for editing here</Text>
66
+ <Text>
67
+ {migrationsPath}/{newMigrationName}
68
+ </Text>
69
+ </Box>
70
+ )
68
71
  );
69
72
  }
70
73
  );
@@ -1,10 +1,11 @@
1
1
  import path from "path";
2
- import { Box, render, Text } from "ink";
2
+ import { Box, Text } from "ink";
3
3
  import Table from "ink-table";
4
4
  import React from "react";
5
5
  import { withConfig } from "../../config";
6
6
  import { logger } from "../../logger";
7
7
  import { requireAuth } from "../../user";
8
+ import { renderToString } from "../../utils/render";
8
9
  import { DEFAULT_MIGRATION_PATH, DEFAULT_MIGRATION_TABLE } from "../constants";
9
10
  import { d1BetaWarning, getDatabaseInfoFromConfig } from "../utils";
10
11
  import {
@@ -78,15 +79,17 @@ export const ListHandler = withConfig<ListHandlerOptions>(
78
79
  });
79
80
 
80
81
  if (unappliedMigrations.length === 0) {
81
- render(<Text>✅ No migrations to apply!</Text>);
82
+ logger.log(renderToString(<Text>✅ No migrations to apply!</Text>));
82
83
  return;
83
84
  }
84
85
 
85
- render(
86
- <Box flexDirection="column">
87
- <Text>Migrations to be applied:</Text>
88
- <Table data={unappliedMigrations} columns={["Name"]}></Table>
89
- </Box>
86
+ logger.log(
87
+ renderToString(
88
+ <Box flexDirection="column">
89
+ <Text>Migrations to be applied:</Text>
90
+ <Table data={unappliedMigrations} columns={["Name"]}></Table>
91
+ </Box>
92
+ )
90
93
  );
91
94
  }
92
95
  );