Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FE-6254 Setting schema on 'fauna local --database Foo' #533

Merged
merged 13 commits into from
Dec 17, 2024
52 changes: 52 additions & 0 deletions src/commands/local.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { AbortError } from "fauna";

import { container } from "../cli.mjs";
import { pushSchema } from "../commands/schema/push.mjs";
import { ensureContainerRunning } from "../lib/docker-containers.mjs";
import { CommandError, ValidationError } from "../lib/errors.mjs";
import { colorize, Format } from "../lib/formatting/colorize.mjs";
Expand All @@ -28,6 +29,34 @@
if (argv.database) {
await createDatabase(argv);
}
if (argv.directory) {
await createDatabaseSchema(argv);
}
}

async function createDatabaseSchema(argv) {
const logger = container.resolve("logger");
logger.stderr(
colorize(
`[CreateDatabaseSchema] Creating schema for database '${argv.database}' from directory '${argv.directory}'...`,
{
format: Format.LOG,
color: argv.color,
},
),
);
// hack to let us push schema to the local database
argv.secret = `secret:${argv.database}:admin`;
await pushSchema(argv);
logger.stderr(
colorize(
`[CreateDatabaseSchema] Schema for database '${argv.database}' created from directory '${argv.directory}'.`,
{
format: Format.LOG,
color: argv.color,
},
),
);
}

async function createDatabase(argv) {
Expand Down Expand Up @@ -152,8 +181,26 @@
description:
"User-defined priority for the database. Valid only if --database is set.",
},
"project-directory": {
type: "string",
alias: ["dir", "directory"],
description:
"Path to a local directory containing `.fsl` files for the database. Valid only if --database is set.",
},
active: {
description:
"Immediately applies the local schema to the database's active schema, skipping staging the schema. To disable this, use `--no-active` or `--active=false`.",
type: "boolean",
default: true,
},
input: {
description:
"Prompt for schema input, such as confirmation. To disable prompts, use `--no-input` or `--input=false`. Disabled prompts are useful for scripts, CI/CD, and automation workflows.",
default: true,
type: "boolean",
},
})
.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("--max-attempts must be greater than 0.");
}
Expand All @@ -177,6 +224,11 @@
"--priority can only be set if --database is set.",
);
}
if (argv.directory && !argv.database) {
throw new ValidationError(
"--directory,--dir can only be set if --database is set.",
);
}
return true;
});
}
Expand Down
9 changes: 7 additions & 2 deletions src/commands/schema/push.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import { getSecret } from "../../lib/fauna-client.mjs";
import { reformatFSL } from "../../lib/schema.mjs";
import { localSchemaOptions } from "./schema.mjs";

async function doPush(argv) {
/**
* Pushes a schema (FSL) based on argv.
* @param {import("yargs").Argv & {dir: string, active: boolean, input: boolean}} argv
*/
export async function pushSchema(argv) {
const logger = container.resolve("logger");
const makeFaunaRequest = container.resolve("makeFaunaRequest");
const gatherFSL = container.resolve("gatherFSL");
Expand Down Expand Up @@ -66,6 +70,7 @@ async function doPush(argv) {
? "Stage the file contents anyway?"
: "Push the file contents anyway?";
}

const confirm = container.resolve("confirm");
const confirmed = await confirm({
message,
Expand Down Expand Up @@ -133,5 +138,5 @@ export default {
command: "push",
description: "Push local .fsl schema files to Fauna.",
builder: buildPushCommand,
handler: doPush,
handler: pushSchema,
};
9 changes: 5 additions & 4 deletions src/lib/auth/credentials.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@
import { container } from "../../cli.mjs";
import { ValidationError } from "../errors.mjs";
import { FaunaAccountClient } from "../fauna-account-client.mjs";
import { isLocal } from "../middleware.mjs";
import { AccountKeys } from "./accountKeys.mjs";
import { DatabaseKeys } from "./databaseKeys.mjs";

const validateCredentialArgs = (argv) => {
const logger = container.resolve("logger");
const illegalArgCombos = [
["accountKey", "secret", "local"],
["secret", "database", "local"],
["secret", "role", "local"],
["accountKey", "secret", isLocal],
["secret", "database", isLocal],
["secret", "role", isLocal],
];
for (const [first, second, conditional] of illegalArgCombos) {
if (argv[first] && argv[second] && !argv[conditional]) {
if (argv[first] && argv[second] && !conditional(argv)) {
throw new ValidationError(
`Cannot use both the '--${first}' and '--${second}' options together. Please specify only one.`,
);
Expand Down Expand Up @@ -63,7 +64,7 @@
this.accountKeys.keyStore.save({
accountKey,
refreshToken,
// TODO: set expiration

Check warning on line 67 in src/lib/auth/credentials.mjs

View workflow job for this annotation

GitHub Actions / lint

Unexpected 'todo' comment: 'TODO: set expiration'
});
this.accountKeys.key = accountKey;
}
Expand Down
15 changes: 12 additions & 3 deletions src/lib/middleware.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import { fixPath } from "../lib/file-util.mjs";
import { redactedStringify } from "./formatting/redact.mjs";

const LOCAL_URL = "http://localhost:8443";
const LOCAL_URL = "http://0.0.0.0:8443";
const LOCAL_SECRET = "secret";
const DEFAULT_URL = "https://db.fauna.com";

Expand Down Expand Up @@ -43,7 +43,7 @@
}

export function checkForUpdates(argv) {
// TODO: figure out upgrade path for SEA installations

Check warning on line 46 in src/lib/middleware.mjs

View workflow job for this annotation

GitHub Actions / lint

Unexpected 'todo' comment: 'TODO: figure out upgrade path for SEA...'
if (isSea()) return argv;

const __filename = fileURLToPath(import.meta.url);
Expand Down Expand Up @@ -79,6 +79,15 @@
applyLocalToSecret(argv);
}

/**
* @param {import('yargs').Arguments} argv
* @returns {boolean} true if this command acts on a local
* container, false otherwise.
*/
export function isLocal(argv) {
return argv.local || argv._[0] === "local";
}

/**
* Mutates argv.url appropriately for local Fauna usage
* (i.e. local container usage). If --local is provided
Expand All @@ -89,7 +98,7 @@
function applyLocalToUrl(argv) {
const logger = container.resolve("logger");
if (!argv.url) {
if (argv.local) {
if (isLocal(argv)) {
argv.url = LOCAL_URL;
logger.debug(
`Set url to '${LOCAL_URL}' as --local was given and --url was not`,
Expand Down Expand Up @@ -120,7 +129,7 @@
*/
function applyLocalToSecret(argv) {
const logger = container.resolve("logger");
if (!argv.secret && argv.local) {
if (!argv.secret && isLocal(argv)) {
if (argv.role && argv.database) {
argv.secret = `${LOCAL_SECRET}:${argv.database}:${argv.role}`;
} else if (argv.role) {
Expand Down
8 changes: 4 additions & 4 deletions test/config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -177,13 +177,13 @@ describe("configuration file", function () {
});
});

it("--local arg sets the argv.url to http://localhost:8443 if no --url is given", async function () {
it("--local arg sets the argv.url to http://0.0.0.0:8443 if no --url is given", async function () {
fs.readdirSync.withArgs(process.cwd()).returns([]);
await runArgvTest({
cmd: `argv --secret "no-config" --local`,
argvMatcher: sinon.match({
secret: "no-config",
url: "http://localhost:8443",
url: "http://0.0.0.0:8443",
}),
});
});
Expand All @@ -205,7 +205,7 @@ describe("configuration file", function () {
cmd: `argv --local`,
argvMatcher: sinon.match({
secret: "secret",
url: "http://localhost:8443",
url: "http://0.0.0.0:8443",
}),
});
});
Expand All @@ -216,7 +216,7 @@ describe("configuration file", function () {
cmd: `argv --local --secret "sauce"`,
argvMatcher: sinon.match({
secret: "sauce",
url: "http://localhost:8443",
url: "http://0.0.0.0:8443",
}),
});
});
Expand Down
6 changes: 3 additions & 3 deletions test/database/list.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,22 @@ describe("database list", () => {
[
{
args: "--local",
expected: { secret: "secret", url: "http://localhost:8443" },
expected: { secret: "secret", url: "http://0.0.0.0:8443" },
},
{
args: "--local --url http://yo_dog:8443",
expected: { secret: "secret", url: "http://yo_dog:8443" },
},
{
args: "--local --secret taco",
expected: { secret: "taco", url: "http://localhost:8443" },
expected: { secret: "taco", url: "http://0.0.0.0:8443" },
},
{
args: "--local --pageSize 10",
expected: {
secret: "secret",
pageSize: 10,
url: "http://localhost:8443",
url: "http://0.0.0.0:8443",
},
},
].forEach(({ args, expected }) => {
Expand Down
6 changes: 3 additions & 3 deletions test/lib/middleware.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ describe("middlewares", function () {
setupTestContainer();
});

it("should set url to localhost:8443 when --local is true and no url provided", function () {
it("should set url to 0.0.0.0:8443 when --local is true and no url provided", function () {
const argv = { ...baseArgv, local: true };
applyLocalArg(argv);
expect(argv.url).to.equal("http://localhost:8443");
expect(argv.url).to.equal("http://0.0.0.0:8443");
expect(argv.secret).to.equal("secret");
});

Expand All @@ -38,7 +38,7 @@ describe("middlewares", function () {
it("should not modify secret if already provided", function () {
const argv = { ...baseArgv, local: true, secret: "custom-secret" };
applyLocalArg(argv);
expect(argv.url).to.equal("http://localhost:8443");
expect(argv.url).to.equal("http://0.0.0.0:8443");
expect(argv.secret).to.equal("custom-secret");
});

Expand Down
Loading
Loading