Skip to content

Commit 9adbd50

Browse files
knickishknickish
andauthored
add mysql options to hyperdrive (#8258)
Co-authored-by: knickish <[email protected]>
1 parent 5ae12a9 commit 9adbd50

File tree

8 files changed

+153
-32
lines changed

8 files changed

+153
-32
lines changed

.changeset/cold-baths-dance.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"miniflare": patch
3+
"wrangler": patch
4+
---
5+
6+
Enable the creation of MySQL Hypedrive configs via the Wrangler CLI.

packages/miniflare/src/plugins/hyperdrive/index.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,14 @@ function hasPostgresProtocol(url: URL) {
99
return url.protocol === "postgresql:" || url.protocol === "postgres:";
1010
}
1111

12+
function hasMysqlProtocol(url: URL) {
13+
return url.protocol === "mysql:";
14+
}
15+
1216
function getPort(url: URL) {
1317
if (url.port !== "") return url.port;
1418
if (hasPostgresProtocol(url)) return "5432";
19+
if (hasMysqlProtocol(url)) return "3306";
1520
// Validated in `HyperdriveSchema`
1621
assert.fail(`Expected known protocol, got ${url.protocol}`);
1722
}
@@ -23,13 +28,14 @@ export const HyperdriveSchema = z
2328
if (url.protocol === "") {
2429
ctx.addIssue({
2530
code: z.ZodIssueCode.custom,
26-
message: "You must specify the database protocol - e.g. 'postgresql'.",
31+
message:
32+
"You must specify the database protocol - e.g. 'postgresql'/'mysql'.",
2733
});
28-
} else if (!hasPostgresProtocol(url)) {
34+
} else if (!hasPostgresProtocol(url) && !hasMysqlProtocol(url)) {
2935
ctx.addIssue({
3036
code: z.ZodIssueCode.custom,
3137
message:
32-
"Only PostgreSQL or PostgreSQL compatible databases are currently supported.",
38+
"Only PostgreSQL-compatible or MySQL-compatible databases are currently supported.",
3339
});
3440
}
3541
if (url.host === "") {

packages/miniflare/test/plugins/hyperdrive/index.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ test("validates config", async (t) => {
7474
}),
7575
{
7676
message:
77-
/Only PostgreSQL or PostgreSQL compatible databases are currently supported/,
77+
/Only PostgreSQL-compatible or MySQL-compatible databases are currently supported./,
7878
}
7979
);
8080

packages/wrangler/src/__tests__/hyperdrive.test.ts

Lines changed: 106 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ describe("hyperdrive commands", () => {
120120

121121
expect(std.out).toMatchInlineSnapshot(`
122122
"🚧 Creating 'test123'
123-
✅ Created new Hyperdrive config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
123+
✅ Created new Hyperdrive PostgreSQL config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
124124
📋 To start using your config from a Worker, add the following binding configuration to your Wrangler configuration file:
125125
126126
{
@@ -157,7 +157,7 @@ describe("hyperdrive commands", () => {
157157

158158
expect(std.out).toMatchInlineSnapshot(`
159159
"🚧 Creating 'test123'
160-
✅ Created new Hyperdrive config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
160+
✅ Created new Hyperdrive PostgreSQL config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
161161
📋 To start using your config from a Worker, add the following binding configuration to your wrangler.toml file:
162162
163163
[[hyperdrive]]
@@ -188,7 +188,42 @@ describe("hyperdrive commands", () => {
188188
`);
189189
expect(std.out).toMatchInlineSnapshot(`
190190
"🚧 Creating 'test123'
191-
✅ Created new Hyperdrive config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
191+
✅ Created new Hyperdrive PostgreSQL config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
192+
📋 To start using your config from a Worker, add the following binding configuration to your Wrangler configuration file:
193+
194+
{
195+
\\"hyperdrive\\": [
196+
{
197+
\\"binding\\": \\"HYPERDRIVE\\",
198+
\\"id\\": \\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\\"
199+
}
200+
]
201+
}"
202+
`);
203+
});
204+
205+
it("should handle creating a hyperdrive config for postgres without a port specified", async () => {
206+
const reqProm = mockHyperdriveCreate();
207+
await runWrangler(
208+
"hyperdrive create test123 --connection-string='mysql://test:[email protected]/neondb'"
209+
);
210+
211+
await expect(reqProm).resolves.toMatchInlineSnapshot(`
212+
Object {
213+
"name": "test123",
214+
"origin": Object {
215+
"database": "neondb",
216+
"host": "example.com",
217+
"password": "password",
218+
"port": 3306,
219+
"scheme": "mysql",
220+
"user": "test",
221+
},
222+
}
223+
`);
224+
expect(std.out).toMatchInlineSnapshot(`
225+
"🚧 Creating 'test123'
226+
✅ Created new Hyperdrive MySQL config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
192227
📋 To start using your config from a Worker, add the following binding configuration to your Wrangler configuration file:
193228
194229
{
@@ -227,7 +262,7 @@ describe("hyperdrive commands", () => {
227262
`);
228263
expect(std.out).toMatchInlineSnapshot(`
229264
"🚧 Creating 'test123'
230-
✅ Created new Hyperdrive config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
265+
✅ Created new Hyperdrive PostgreSQL config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
231266
📋 To start using your config from a Worker, add the following binding configuration to your Wrangler configuration file:
232267
233268
{
@@ -262,7 +297,7 @@ describe("hyperdrive commands", () => {
262297
`);
263298
expect(std.out).toMatchInlineSnapshot(`
264299
"🚧 Creating 'test123'
265-
✅ Created new Hyperdrive config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
300+
✅ Created new Hyperdrive PostgreSQL config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
266301
📋 To start using your config from a Worker, add the following binding configuration to your Wrangler configuration file:
267302
268303
{
@@ -297,7 +332,7 @@ describe("hyperdrive commands", () => {
297332
`);
298333
expect(std.out).toMatchInlineSnapshot(`
299334
"🚧 Creating 'test123'
300-
✅ Created new Hyperdrive config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
335+
✅ Created new Hyperdrive PostgreSQL config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
301336
📋 To start using your config from a Worker, add the following binding configuration to your Wrangler configuration file:
302337
303338
{
@@ -332,7 +367,7 @@ describe("hyperdrive commands", () => {
332367
`);
333368
expect(std.out).toMatchInlineSnapshot(`
334369
"🚧 Creating 'test123'
335-
✅ Created new Hyperdrive config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
370+
✅ Created new Hyperdrive PostgreSQL config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
336371
📋 To start using your config from a Worker, add the following binding configuration to your Wrangler configuration file:
337372
338373
{
@@ -367,7 +402,7 @@ describe("hyperdrive commands", () => {
367402
`);
368403
expect(std.out).toMatchInlineSnapshot(`
369404
"🚧 Creating 'test123'
370-
✅ Created new Hyperdrive config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
405+
✅ Created new Hyperdrive PostgreSQL config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
371406
📋 To start using your config from a Worker, add the following binding configuration to your Wrangler configuration file:
372407
373408
{
@@ -402,7 +437,42 @@ describe("hyperdrive commands", () => {
402437
`);
403438
expect(std.out).toMatchInlineSnapshot(`
404439
"🚧 Creating 'test123'
405-
✅ Created new Hyperdrive config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
440+
✅ Created new Hyperdrive PostgreSQL config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
441+
📋 To start using your config from a Worker, add the following binding configuration to your Wrangler configuration file:
442+
443+
{
444+
\\"hyperdrive\\": [
445+
{
446+
\\"binding\\": \\"HYPERDRIVE\\",
447+
\\"id\\": \\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\\"
448+
}
449+
]
450+
}"
451+
`);
452+
});
453+
454+
it("should create a hyperdrive config given individual params instead of a connection string", async () => {
455+
const reqProm = mockHyperdriveCreate();
456+
await runWrangler(
457+
"hyperdrive create test123 --host=example.com --database=neondb --user=test --password=password --port=1234 --origin-scheme=mysql"
458+
);
459+
460+
await expect(reqProm).resolves.toMatchInlineSnapshot(`
461+
Object {
462+
"name": "test123",
463+
"origin": Object {
464+
"database": "neondb",
465+
"host": "example.com",
466+
"password": "password",
467+
"port": 1234,
468+
"scheme": "mysql",
469+
"user": "test",
470+
},
471+
}
472+
`);
473+
expect(std.out).toMatchInlineSnapshot(`
474+
"🚧 Creating 'test123'
475+
✅ Created new Hyperdrive MySQL config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
406476
📋 To start using your config from a Worker, add the following binding configuration to your Wrangler configuration file:
407477
408478
{
@@ -429,6 +499,21 @@ describe("hyperdrive commands", () => {
429499
`);
430500
});
431501

502+
it("should reject a create hyperdrive command if an unexpected origin-scheme is provided", async () => {
503+
await expect(() =>
504+
runWrangler(
505+
"hyperdrive create test123 --host=example.com --port=5432 --database=foo --user=test --password=foo --origin-scheme=mongodb"
506+
)
507+
).rejects.toThrow();
508+
expect(std.err).toMatchInlineSnapshot(`
509+
"X [ERROR] Invalid values:
510+
511+
Argument: origin-scheme, Given: \\"mongodb\\", Choices: \\"postgres\\", \\"postgresql\\", \\"mysql\\"
512+
513+
"
514+
`);
515+
});
516+
432517
it("should reject a create hyperdrive command if both connection string and individual origin params are provided", async () => {
433518
await expect(() =>
434519
runWrangler(
@@ -463,7 +548,7 @@ describe("hyperdrive commands", () => {
463548
`);
464549
expect(std.out).toMatchInlineSnapshot(`
465550
"🚧 Creating 'test123'
466-
✅ Created new Hyperdrive config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
551+
✅ Created new Hyperdrive PostgreSQL config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
467552
📋 To start using your config from a Worker, add the following binding configuration to your Wrangler configuration file:
468553
469554
{
@@ -498,7 +583,7 @@ describe("hyperdrive commands", () => {
498583
`);
499584
expect(std.out).toMatchInlineSnapshot(`
500585
"🚧 Creating 'test123'
501-
✅ Created new Hyperdrive config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
586+
✅ Created new Hyperdrive PostgreSQL config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
502587
📋 To start using your config from a Worker, add the following binding configuration to your Wrangler configuration file:
503588
504589
{
@@ -564,7 +649,7 @@ describe("hyperdrive commands", () => {
564649
`);
565650
expect(std.out).toMatchInlineSnapshot(`
566651
"🚧 Creating 'test123'
567-
✅ Created new Hyperdrive config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
652+
✅ Created new Hyperdrive PostgreSQL config: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
568653
📋 To start using your config from a Worker, add the following binding configuration to your Wrangler configuration file:
569654
570655
{
@@ -583,15 +668,15 @@ describe("hyperdrive commands", () => {
583668
await runWrangler("hyperdrive list");
584669
expect(std.out).toMatchInlineSnapshot(`
585670
"📋 Listing Hyperdrive configs
586-
┌──────────────────────────────────────┬─────────────┬─────────┬────────────────┬──────┬───────────┬───────────────────┬───────────────────────────────────────────────────────────────┐
587-
│ id │ name │ user │ host │ port │ database │ caching │ mtls │
588-
├──────────────────────────────────────┼─────────────┼─────────┼────────────────┼──────┼───────────┼───────────────────┼───────────────────────────────────────────────────────────────┤
589-
│ xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx │ test123 │ test │ example.com │ 5432 │ neondb │ │ │
590-
├──────────────────────────────────────┼─────────────┼─────────┼────────────────┼──────┼───────────┼───────────────────┼───────────────────────────────────────────────────────────────┤
591-
│ yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy │ new-db │ dbuser │ www.google.com │ 3211 │ mydb │ {\\"disabled\\":true} │ │
592-
├──────────────────────────────────────┼─────────────┼─────────┼────────────────┼──────┼───────────┼───────────────────┼───────────────────────────────────────────────────────────────┤
593-
│ zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz │ new-db-mtls │ pg-mtls │ www.mtls.com │ 3212 │ mydb-mtls │ │ {\\"ca_certificate_uuid\\":\\"1234\\",\\"mtls_certificate_uuid\\":\\"1234\\"} │
594-
└──────────────────────────────────────┴─────────────┴─────────┴────────────────┴──────┴───────────┴───────────────────┴───────────────────────────────────────────────────────────────┘"
671+
┌──────────────────────────────────────┬─────────────┬─────────┬────────────────┬──────┬────────────┬───────────┬───────────────────┬───────────────────────────────────────────────────────────────┐
672+
│ id │ name │ user │ host │ port │ scheme │ database │ caching │ mtls │
673+
├──────────────────────────────────────┼─────────────┼─────────┼────────────────┼──────┼────────────┼───────────┼───────────────────┼───────────────────────────────────────────────────────────────┤
674+
│ xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx │ test123 │ test │ example.com │ 5432 │ PostgreSQL │ neondb │ │ │
675+
├──────────────────────────────────────┼─────────────┼─────────┼────────────────┼──────┼────────────┼───────────┼───────────────────┼───────────────────────────────────────────────────────────────┤
676+
│ yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy │ new-db │ dbuser │ www.google.com │ 3211 │ PostgreSQL │ mydb │ {\\"disabled\\":true} │ │
677+
├──────────────────────────────────────┼─────────────┼─────────┼────────────────┼──────┼────────────┼───────────┼───────────────────┼───────────────────────────────────────────────────────────────┤
678+
│ zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz │ new-db-mtls │ pg-mtls │ www.mtls.com │ 3212 │ mydb-mtls │ │ {\\"ca_certificate_uuid\\":\\"1234\\",\\"mtls_certificate_uuid\\":\\"1234\\"} │
679+
└──────────────────────────────────────┴─────────────┴─────────┴────────────────┴──────┴────────────┴───────────┴───────────────────┴───────────────────────────────────────────────────────────────┘"
595680
`);
596681
});
597682

packages/wrangler/src/hyperdrive/create.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { configFileName, formatConfigSnippet, readConfig } from "../config";
22
import { logger } from "../logger";
33
import { createConfig } from "./client";
4+
import { capitalizeScheme } from "./shared";
45
import {
56
getCacheOptionsFromArgs,
67
getMtlsFromArgs,
@@ -39,7 +40,9 @@ export async function handler(
3940
caching: getCacheOptionsFromArgs(args),
4041
mtls: getMtlsFromArgs(args),
4142
});
42-
logger.log(`✅ Created new Hyperdrive config: ${database.id}`);
43+
logger.log(
44+
`✅ Created new Hyperdrive ${capitalizeScheme(database.origin.scheme)} config: ${database.id}`
45+
);
4346
logger.log(
4447
`📋 To start using your config from a Worker, add the following binding configuration to your ${configFileName(config.configPath)} file:\n`
4548
);

packages/wrangler/src/hyperdrive/index.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export function upsertOptions<T>(yargs: Argv<T>) {
7070
"origin-scheme": {
7171
alias: "scheme",
7272
type: "string",
73-
choices: ["postgres", "postgresql"],
73+
choices: ["postgres", "postgresql", "mysql"],
7474
describe: "The scheme used to connect to the origin database",
7575
},
7676
database: {
@@ -165,20 +165,28 @@ export function getOriginFromArgs<
165165
): PartialUpdate extends true ? OriginConfig | undefined : OriginConfig {
166166
if (args.connectionString) {
167167
const url = new URL(args.connectionString);
168+
url.protocol = url.protocol.toLowerCase();
169+
168170
if (
169171
url.port === "" &&
170172
(url.protocol == "postgresql:" || url.protocol == "postgres:")
171173
) {
172174
url.port = "5432";
175+
} else if (url.port === "" && url.protocol == "mysql:") {
176+
url.port = "3306";
173177
}
174178

175179
if (url.protocol === "") {
176180
throw new UserError(
177-
"You must specify the database protocol - e.g. 'postgresql'."
181+
"You must specify the database protocol - e.g. 'postgresql'/'mysql'."
178182
);
179-
} else if (url.protocol !== "postgresql:" && url.protocol !== "postgres:") {
183+
} else if (
184+
!url.protocol.startsWith("postgresql") &&
185+
!url.protocol.startsWith("postgres") &&
186+
!url.protocol.startsWith("mysql")
187+
) {
180188
throw new UserError(
181-
"Only PostgreSQL or PostgreSQL compatible databases are currently supported."
189+
"Only PostgreSQL-compatible or MySQL-compatible databases are currently supported."
182190
);
183191
} else if (url.host === "") {
184192
throw new UserError(
@@ -188,9 +196,9 @@ export function getOriginFromArgs<
188196
throw new UserError(
189197
"You must provide a port number - e.g. 'user:[email protected]:port/databasename"
190198
);
191-
} else if (url.pathname === "") {
199+
} else if (!url.pathname) {
192200
throw new UserError(
193-
"You must provide a database name as the path component - e.g. example.com:port/postgres"
201+
"You must provide a database name as the path component - e.g. example.com:port/databasename"
194202
);
195203
} else if (url.username === "") {
196204
throw new UserError(

0 commit comments

Comments
 (0)