Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/v3' into v3_schemaLocal
Browse files Browse the repository at this point in the history
  • Loading branch information
ecooper committed Dec 16, 2024
2 parents 18aa4f8 + d04a487 commit 389bdac
Show file tree
Hide file tree
Showing 11 changed files with 118 additions and 105 deletions.
4 changes: 2 additions & 2 deletions src/cli.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,9 @@ function buildYargs(argvInput) {
default: false,
group: "Output:",
},
verboseComponent: {
"verbose-component": {
description:
"Components to emit diagnostic logs for. Takes precedence over the `--verbosity` flag. Pass components as a space-separated list, such as `--verboseComponent fetch error`, or as separate flags, such as `--verboseComponent fetch --verboseComponent error`.",
"Components to emit diagnostic logs for. Takes precedence over the `--verbosity` flag. Pass components as a space-separated list, such as `--verbose-component fetch error`, or as separate flags, such as `--verbose-component fetch --verbose-component error`.",
type: "array",
default: [],
choices: ["fetch", "error", "config", "argv", "creds", "completion"],
Expand Down
2 changes: 1 addition & 1 deletion src/commands/database/create.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ function buildCreateCommand(yargs) {
description: "Name of the child database to create.",
},
typechecked: {
type: "string",
type: "boolean",
description:
"Enable typechecking for the database. Defaults to the typechecking setting of the parent database.",
},
Expand Down
55 changes: 23 additions & 32 deletions src/commands/database/list.mjs
Original file line number Diff line number Diff line change
@@ -1,82 +1,73 @@
//@ts-check
import chalk from "chalk";

import { container } from "../../cli.mjs";
import { faunaToCommandError } from "../../lib/fauna.mjs";
import { FaunaAccountClient } from "../../lib/fauna-account-client.mjs";
import { colorize, Format } from "../../lib/formatting/colorize.mjs";

// Narrow the output fields based on the provided flags.
const getOutputFields = (argv) => {
if (!argv.secret && !argv.database) {
// If we are listing top level databases the region group
// needs to be included as database names can be re-used across
// regions.
return ["name", "region_group"];
}
return ["name"];
};

function pickOutputFields(databases, argv) {
return databases.map((d) =>
getOutputFields(argv).reduce((acc, field) => {
acc[field] = d[field];
return acc;
}, {}),
);
}

async function listDatabasesWithAccountAPI(argv) {
const { pageSize, database } = argv;
const accountClient = new FaunaAccountClient();
const response = await accountClient.listDatabases({
pageSize,
path: database,
});
return pickOutputFields(response.results, argv);

return response.results.map(({ path, name }) => ({ path, name }));
}

async function listDatabasesWithSecret(argv) {
const { url, secret, pageSize } = argv;
const { runQueryFromString } = container.resolve("faunaClientV10");

try {
return await runQueryFromString({
const res = await runQueryFromString({
url,
secret,
// This gives us back an array of database names. If we want to
// provide the after token at some point this query will need to be updated.
expression: `Database.all().paginate(${pageSize}).data { ${getOutputFields(argv)} }`,
expression: `Database.all().paginate(${pageSize}).data { name }`,
});
return res.data;
} catch (e) {
return faunaToCommandError(e);
}
}

export async function listDatabases(argv) {
let databases;
if (argv.secret) {
databases = await listDatabasesWithSecret(argv);
return await listDatabasesWithSecret(argv);
} else {
databases = await listDatabasesWithAccountAPI(argv);
return await listDatabasesWithAccountAPI(argv);
}
return databases;
}

async function doListDatabases(argv) {
const logger = container.resolve("logger");
const { formatQueryResponse } = container.resolve("faunaClientV10");
const res = await listDatabases(argv);

if (argv.secret) {
logger.stdout(formatQueryResponse(res, argv));
} else {
logger.stderr(
chalk.yellow(
"Warning: Full database paths are not available when using --secret. Use --database if a full path, including the Region Group identified and hierarchy, is needed.",
),
);
}

if (argv.json) {
logger.stdout(colorize(res, { format: Format.JSON, color: argv.color }));
} else {
res.forEach(({ path, name }) => {
logger.stdout(path ?? name);
});
}
}

function buildListCommand(yargs) {
return yargs
.options({
pageSize: {
"page-size": {
type: "number",
description: "Maximum number of databases to return.",
default: 1000,
Expand All @@ -97,7 +88,7 @@ function buildListCommand(yargs) {
"List all top-level databases and output as JSON.",
],
[
"$0 database list --pageSize 10",
"$0 database list --page-size 10",
"List the first 10 top-level databases.",
],
]);
Expand Down
10 changes: 5 additions & 5 deletions src/commands/local.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -123,18 +123,18 @@ ${chalk.red("Please use choose a different name using --name or align the --type
function buildLocalCommand(yargs) {
return yargs
.options({
containerPort: {
"container-port": {
describe: "The port inside the container Fauna listens on.",
type: "number",
default: 8443,
},
hostPort: {
"host-port": {
describe:
"The port on the host machine mapped to the container's port. This is the port you'll connect to Fauna on.",
type: "number",
default: 8443,
},
hostIp: {
"host-ip": {
describe: `The IP address to bind the container's exposed port on the host.`,
type: "string",
default: "0.0.0.0",
Expand All @@ -145,7 +145,7 @@ function buildLocalCommand(yargs) {
type: "number",
default: 10000,
},
maxAttempts: {
"max-attempts": {
describe:
"The maximum number of health check attempts before declaring the start Fauna continer process as failed.",
type: "number",
Expand Down Expand Up @@ -202,7 +202,7 @@ function buildLocalCommand(yargs) {
})
.check((argv) => {

Check warning on line 203 in src/commands/local.mjs

View workflow job for this annotation

GitHub Actions / lint

Arrow function has a complexity of 11. Maximum allowed is 10
if (argv.maxAttempts < 1) {
throw new ValidationError("--maxAttempts must be greater than 0.");
throw new ValidationError("--max-attempts must be greater than 0.");
}
if (argv.interval < 0) {
throw new ValidationError(
Expand Down
2 changes: 1 addition & 1 deletion src/lib/auth/DEV-README.md → src/lib/auth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ If no account key is provided, the CLI will prompt a login via the dashboard whe

### The CLI will look for account keys in this order:

- `--accountKey` flag
- `--account-key` flag
- `FAUNA_ACCOUNT_KEY` environment variable
- `--config` file `accountKey` value
- `~/.fauna/credentials/access_keys`
Expand Down
10 changes: 5 additions & 5 deletions src/lib/command-helpers.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ import { Format } from "./formatting/colorize.mjs";

const COMMON_OPTIONS = {
// hidden
accountUrl: {
"account-url": {
type: "string",
description: "the Fauna account URL to query",
default: "https://account.fauna.com",
hidden: true,
},
clientId: {
"client-id": {
type: "string",
description: "the client id to use when calling Fauna",
required: false,
hidden: true,
},
clientSecret: {
"client-secret": {
type: "string",
description: "the client secret to use when calling Fauna",
required: false,
Expand Down Expand Up @@ -56,7 +56,7 @@ const COMMON_QUERY_OPTIONS = {
required: false,
group: "API:",
},
accountKey: {
"account-key": {
type: "string",
description:
"Fauna account key used for authentication. Negates the need for a user login. The key is used to generate short-lived database secrets for the CLI. Mutually exclusive with `--user` and `--secret`.",
Expand Down Expand Up @@ -90,7 +90,7 @@ export const QUERY_INFO_CHOICES = [
// used for queries customers can configure
const COMMON_CONFIGURABLE_QUERY_OPTIONS = {
...COMMON_QUERY_OPTIONS,
apiVersion: {
"api-version": {
description: "FQL version to use.",
type: "string",
alias: "v",
Expand Down
4 changes: 2 additions & 2 deletions src/lib/docker-containers.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ async function createContainer({
if (occupied) {
throw new CommandError(
`[StartContainer] The hostPort '${hostPort}' on IP '${hostIp}' is already occupied. \
Please pass a --hostPort other than '${hostPort}'.`,
Please pass a --host-port other than '${hostPort}'.`,
);
}
const dockerContainer = await docker.createContainer({
Expand Down Expand Up @@ -390,7 +390,7 @@ async function waitForHealthCheck({
`[HealthCheck] Max attempts reached. Service at ${url} did not respond.`,
);
throw new CommandError(
`[HealthCheck] Fauna at ${url} is not ready after ${maxAttempts} attempts. Consider increasing --interval or --maxAttempts.`,
`[HealthCheck] Fauna at ${url} is not ready after ${maxAttempts} attempts. Consider increasing --interval or --max-attempts.`,
);
}

Expand Down
23 changes: 23 additions & 0 deletions test/database/create.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,29 @@ describe("database create", () => {
});
});

[
{
flag: "--typechecked",
value: "imastring",
},
{
flag: "--protected",
value: "imastring",
},
].forEach(({ flag, value }) => {
it(`handles invalid option types: ${flag} ${value}`, async () => {
try {
await run(
`database create --name 'testdb' --secret 'secret' ${flag} ${value}`,
container,
);
} catch (e) {}
// Make sure we bail before calling fauna
expect(runQuery).to.not.have.been.called;
expect(logger.stderr).to.have.been.called;
});
});

[
{
error: new ServiceError({
Expand Down
Loading

0 comments on commit 389bdac

Please sign in to comment.