Skip to content

Commit

Permalink
refactor hyperdrive commands
Browse files Browse the repository at this point in the history
  • Loading branch information
RamIdeas committed Sep 9, 2024
1 parent 7adc7a2 commit ce7f96e
Show file tree
Hide file tree
Showing 9 changed files with 409 additions and 408 deletions.
1 change: 1 addition & 0 deletions packages/wrangler/src/commands.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import "./auth/commands";
import "./kv/index";
import "./ai/commands";
import "./hyperdrive/commands";
16 changes: 16 additions & 0 deletions packages/wrangler/src/hyperdrive/commands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { defineNamespace } from "../core";
import "./create";
import "./delete";
import "./get";
import "./list";
import "./update";

defineNamespace({
command: "wrangler hyperdrive",

metadata: {
description: "🚀 Manage Hyperdrive databases",
status: "stable",
owner: "Product: Hyperdrive",
},
});
335 changes: 169 additions & 166 deletions packages/wrangler/src/hyperdrive/create.ts
Original file line number Diff line number Diff line change
@@ -1,181 +1,184 @@
import { readConfig } from "../config";
import { defineCommand } from "../core";
import { UserError } from "../errors";
import { logger } from "../logger";
import { createConfig } from "./client";
import type {
CommonYargsArgv,
StrictYargsOptionsToInterface,
} from "../yargs-types";

export function options(yargs: CommonYargsArgv) {
return yargs
.positional("name", {
defineCommand({
command: "wrangler hyperdrive create",

metadata: {
description: "Create a Hyperdrive config",
status: "stable",
owner: "Product: Hyperdrive",
},

args: {
name: {
type: "string",
demandOption: true,
description: "The name of the Hyperdrive config",
})
.options({
"connection-string": {
type: "string",
describe:
"The connection string for the database you want Hyperdrive to connect to - ex: protocol://user:password@host:port/database",
},
host: {
type: "string",
describe: "The host of the origin database",
conflicts: "connection-string",
},
port: {
type: "number",
describe: "The port number of the origin database",
conflicts: [
"connection-string",
"access-client-id",
"access-client-secret",
],
},
scheme: {
type: "string",
describe:
"The scheme used to connect to the origin database - e.g. postgresql or postgres",
default: "postgresql",
},
database: {
type: "string",
describe: "The name of the database within the origin database",
conflicts: "connection-string",
},
user: {
type: "string",
describe: "The username used to connect to the origin database",
conflicts: "connection-string",
},
password: {
type: "string",
describe: "The password used to connect to the origin database",
conflicts: "connection-string",
},
"access-client-id": {
type: "string",
describe:
"The Client ID of the Access token to use when connecting to the origin database, must be set with a Client Access Secret",
conflicts: ["connection-string", "port"],
implies: ["access-client-secret"],
},
"access-client-secret": {
type: "string",
describe:
"The Client Secret of the Access token to use when connecting to the origin database, must be set with a Client Access ID",
conflicts: ["connection-string", "port"],
implies: ["access-client-id"],
},
"caching-disabled": {
type: "boolean",
describe: "Disables the caching of SQL responses",
default: false,
},
"max-age": {
type: "number",
describe:
"Specifies max duration for which items should persist in the cache, cannot be set when caching is disabled",
},
swr: {
type: "number",
describe:
"Indicates the number of seconds cache may serve the response after it becomes stale, cannot be set when caching is disabled",
},
});
}
describe: "The name of the Hyperdrive config",
},
"connection-string": {
type: "string",
describe:
"The connection string for the database you want Hyperdrive to connect to - ex: protocol://user:password@host:port/database",
},
host: {
type: "string",
describe: "The host of the origin database",
conflicts: "connection-string",
},
port: {
type: "number",
describe: "The port number of the origin database",
conflicts: [
"connection-string",
"access-client-id",
"access-client-secret",
],
},
scheme: {
type: "string",
describe:
"The scheme used to connect to the origin database - e.g. postgresql or postgres",
default: "postgresql",
},
database: {
type: "string",
describe: "The name of the database within the origin database",
conflicts: "connection-string",
},
user: {
type: "string",
describe: "The username used to connect to the origin database",
conflicts: "connection-string",
},
password: {
type: "string",
describe: "The password used to connect to the origin database",
conflicts: "connection-string",
},
"access-client-id": {
type: "string",
describe:
"The Client ID of the Access token to use when connecting to the origin database, must be set with a Client Access Secret",
conflicts: ["connection-string", "port"],
implies: ["access-client-secret"],
},
"access-client-secret": {
type: "string",
describe:
"The Client Secret of the Access token to use when connecting to the origin database, must be set with a Client Access ID",
conflicts: ["connection-string", "port"],
implies: ["access-client-id"],
},
"caching-disabled": {
type: "boolean",
describe: "Disables the caching of SQL responses",
default: false,
},
"max-age": {
type: "number",
describe:
"Specifies max duration for which items should persist in the cache, cannot be set when caching is disabled",
},
swr: {
type: "number",
describe:
"Indicates the number of seconds cache may serve the response after it becomes stale, cannot be set when caching is disabled",
},
},
positionalArgs: ["name"],

export async function handler(
args: StrictYargsOptionsToInterface<typeof options>
) {
const config = readConfig(args.config, args);
async handler(args) {
const config = readConfig(args.config, args);

const url = args.connectionString
? new URL(args.connectionString)
: buildURLFromParts(
args.host,
args.port,
args.scheme,
args.database,
args.user,
args.password
);
const url = args.connectionString
? new URL(args.connectionString)
: buildURLFromParts(
args.host,
args.port,
args.scheme,
args.database,
args.user,
args.password
);

if (
url.port === "" &&
(url.protocol == "postgresql:" || url.protocol == "postgres:")
) {
url.port = "5432";
}
if (
url.port === "" &&
(url.protocol == "postgresql:" || url.protocol == "postgres:")
) {
url.port = "5432";
}

if (url.protocol === "") {
throw new UserError(
"You must specify the database protocol - e.g. 'postgresql'."
);
} else if (url.protocol !== "postgresql:" && url.protocol !== "postgres:") {
throw new UserError(
"Only PostgreSQL or PostgreSQL compatible databases are currently supported."
);
} else if (url.host === "") {
throw new UserError(
"You must provide a hostname or IP address in your connection string - e.g. 'user:[email protected]:5432/databasename"
);
} else if (url.port === "") {
throw new UserError(
"You must provide a port number - e.g. 'user:[email protected]:port/databasename"
);
} else if (url.pathname === "") {
throw new UserError(
"You must provide a database name as the path component - e.g. /postgres"
);
} else if (url.username === "") {
throw new UserError(
"You must provide a username - e.g. 'user:[email protected]:port/databasename'"
);
} else if (url.password === "") {
throw new UserError(
"You must provide a password - e.g. 'user:[email protected]:port/databasename' "
);
} else {
logger.log(`🚧 Creating '${args.name}'`);
if (url.protocol === "") {
throw new UserError(
"You must specify the database protocol - e.g. 'postgresql'."
);
} else if (url.protocol !== "postgresql:" && url.protocol !== "postgres:") {
throw new UserError(
"Only PostgreSQL or PostgreSQL compatible databases are currently supported."
);
} else if (url.host === "") {
throw new UserError(
"You must provide a hostname or IP address in your connection string - e.g. 'user:[email protected]:5432/databasename"
);
} else if (url.port === "") {
throw new UserError(
"You must provide a port number - e.g. 'user:[email protected]:port/databasename"
);
} else if (url.pathname === "") {
throw new UserError(
"You must provide a database name as the path component - e.g. /postgres"
);
} else if (url.username === "") {
throw new UserError(
"You must provide a username - e.g. 'user:[email protected]:port/databasename'"
);
} else if (url.password === "") {
throw new UserError(
"You must provide a password - e.g. 'user:[email protected]:port/databasename' "
);
} else {
logger.log(`🚧 Creating '${args.name}'`);

// if access client ID and client secret supplied in args, use them to construct origin without a port
const origin =
args.accessClientId && args.accessClientSecret
? {
host: url.hostname,
scheme: url.protocol.replace(":", ""),
database: decodeURIComponent(url.pathname.replace("/", "")),
user: decodeURIComponent(url.username),
password: decodeURIComponent(url.password),
access_client_id: args.accessClientId,
access_client_secret: args.accessClientSecret,
}
: {
host: url.hostname,
port: parseInt(url.port),
scheme: url.protocol.replace(":", ""),
database: decodeURIComponent(url.pathname.replace("/", "")),
user: decodeURIComponent(url.username),
password: decodeURIComponent(url.password),
};
const database = await createConfig(config, {
name: args.name,
origin,
caching: {
disabled: args.cachingDisabled,
max_age: args.maxAge,
stale_while_revalidate: args.swr,
},
});
logger.log(
`✅ Created new Hyperdrive config\n`,
JSON.stringify(database, null, 2)
);
}
}
// if access client ID and client secret supplied in args, use them to construct origin without a port
const origin =
args.accessClientId && args.accessClientSecret
? {
host: url.hostname,
scheme: url.protocol.replace(":", ""),
database: decodeURIComponent(url.pathname.replace("/", "")),
user: decodeURIComponent(url.username),
password: decodeURIComponent(url.password),
access_client_id: args.accessClientId,
access_client_secret: args.accessClientSecret,
}
: {
host: url.hostname,
port: parseInt(url.port),
scheme: url.protocol.replace(":", ""),
database: decodeURIComponent(url.pathname.replace("/", "")),
user: decodeURIComponent(url.username),
password: decodeURIComponent(url.password),
};
const database = await createConfig(config, {
name: args.name,
origin,
caching: {
disabled: args.cachingDisabled,
max_age: args.maxAge,
stale_while_revalidate: args.swr,
},
});
logger.log(
`✅ Created new Hyperdrive config\n`,
JSON.stringify(database, null, 2)
);
}
},
});

function buildURLFromParts(
host: string | undefined,
Expand Down
Loading

0 comments on commit ce7f96e

Please sign in to comment.