Skip to content

Commit

Permalink
containerize fauna-client
Browse files Browse the repository at this point in the history
  • Loading branch information
ptpaterson committed Dec 17, 2024
1 parent 00b81f1 commit 4edb083
Show file tree
Hide file tree
Showing 18 changed files with 108 additions and 62 deletions.
3 changes: 2 additions & 1 deletion src/commands/database/create.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { container } from "../../cli.mjs";
import { validateDatabaseOrSecret } from "../../lib/command-helpers.mjs";
import { CommandError } from "../../lib/errors.mjs";
import { faunaToCommandError } from "../../lib/fauna.mjs";
import { getSecret, retryInvalidCredsOnce } from "../../lib/fauna-client.mjs";
import { colorize, Format } from "../../lib/formatting/colorize.mjs";

async function runCreateQuery(secret, argv) {
Expand All @@ -25,6 +24,8 @@ async function runCreateQuery(secret, argv) {
}

async function createDatabase(argv) {
const { getSecret, retryInvalidCredsOnce } = container.resolve("faunaClient");

const secret = await getSecret();
const logger = container.resolve("logger");

Expand Down
3 changes: 2 additions & 1 deletion src/commands/database/delete.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { container } from "../../cli.mjs";
import { validateDatabaseOrSecret } from "../../lib/command-helpers.mjs";
import { CommandError } from "../../lib/errors.mjs";
import { faunaToCommandError } from "../../lib/fauna.mjs";
import { getSecret, retryInvalidCredsOnce } from "../../lib/fauna-client.mjs";

async function runDeleteQuery(secret, argv) {
const { fql } = container.resolve("fauna");
Expand All @@ -19,6 +18,8 @@ async function runDeleteQuery(secret, argv) {
}

async function deleteDatabase(argv) {
const { getSecret, retryInvalidCredsOnce } = container.resolve("faunaClient");

const secret = await getSecret();
const logger = container.resolve("logger");

Expand Down
16 changes: 9 additions & 7 deletions src/commands/query.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@ import {
isUnknownError,
ValidationError,
} from "../lib/errors.mjs";
import {
formatError,
formatQueryResponse,
getSecret,
} from "../lib/fauna-client.mjs";
import { isTTY } from "../lib/misc.mjs";

function validate(argv) {
Expand Down Expand Up @@ -70,7 +65,14 @@ const resolveInput = (argv) => {
};

async function queryCommand(argv) {
const formatQueryInfo = container.resolve("formatQueryInfo");
const {
formatError,
formatQueryInfo,
formatQueryResponse,
getSecret,
runQueryFromString,
} = container.resolve("faunaClient");

const logger = container.resolve("logger");

// Run validation here instead of via check for more control over output
Expand Down Expand Up @@ -99,7 +101,7 @@ async function queryCommand(argv) {
// Using --json takes precedence over --format
const outputFormat = resolveFormat(argv);

const results = await container.resolve("runQueryFromString")(expression, {
const results = await runQueryFromString(expression, {
apiVersion,
secret,
url,
Expand Down
7 changes: 4 additions & 3 deletions src/commands/schema/abandon.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
import { container } from "../../cli.mjs";
import { yargsWithCommonQueryOptions } from "../../lib/command-helpers.mjs";
import { CommandError } from "../../lib/errors.mjs";
import { getSecret } from "../../lib/fauna-client.mjs";

async function doAbandon(argv) {
const makeFaunaRequest = container.resolve("makeFaunaRequest");
const logger = container.resolve("logger");
const confirm = container.resolve("confirm");
const { getSecret } = container.resolve("faunaClient");
const logger = container.resolve("logger");
const makeFaunaRequest = container.resolve("makeFaunaRequest");

const secret = await getSecret();

if (!argv.input) {
Expand Down
7 changes: 4 additions & 3 deletions src/commands/schema/commit.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
import { container } from "../../cli.mjs";
import { yargsWithCommonQueryOptions } from "../../lib/command-helpers.mjs";
import { CommandError } from "../../lib/errors.mjs";
import { getSecret } from "../../lib/fauna-client.mjs";

async function doCommit(argv) {
const makeFaunaRequest = container.resolve("makeFaunaRequest");
const logger = container.resolve("logger");
const confirm = container.resolve("confirm");
const { getSecret } = container.resolve("faunaClient");
const logger = container.resolve("logger");
const makeFaunaRequest = container.resolve("makeFaunaRequest");

const secret = await getSecret();

if (!argv.input) {
Expand Down
6 changes: 3 additions & 3 deletions src/commands/schema/diff.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import chalk from "chalk";
import { container } from "../../cli.mjs";
import { yargsWithCommonQueryOptions } from "../../lib/command-helpers.mjs";
import { ValidationError } from "../../lib/errors.mjs";
import { getSecret } from "../../lib/fauna-client.mjs";
import { reformatFSL } from "../../lib/schema.mjs";
import { localSchemaOptions } from "./schema.mjs";

Expand Down Expand Up @@ -57,11 +56,12 @@ function buildValidateParams(argv, version) {
}

async function doDiff(argv) {
const [source, target] = parseTarget(argv);

const { getSecret } = container.resolve("faunaClient");
const gatherFSL = container.resolve("gatherFSL");
const logger = container.resolve("logger");
const makeFaunaRequest = container.resolve("makeFaunaRequest");

const [source, target] = parseTarget(argv);
const secret = await getSecret();
const files = reformatFSL(await gatherFSL(argv.dir));

Expand Down
5 changes: 3 additions & 2 deletions src/commands/schema/pull.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import { container } from "../../cli.mjs";
import { yargsWithCommonQueryOptions } from "../../lib/command-helpers.mjs";
import { getSecret } from "../../lib/fauna-client.mjs";
import { localSchemaOptions } from "./schema.mjs";

async function determineFileState(argv, filenames) {
Expand Down Expand Up @@ -50,9 +49,11 @@ function logDiff({ argv, adds, overwrites, deletes, source }) {
}

async function doPull(argv) {
const logger = container.resolve("logger");
const confirm = container.resolve("confirm");
const { getSecret } = container.resolve("faunaClient");
const logger = container.resolve("logger");
const makeFaunaRequest = container.resolve("makeFaunaRequest");

const secret = await getSecret();

// Get the staged schema status
Expand Down
4 changes: 2 additions & 2 deletions src/commands/schema/push.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import path from "path";
import { container } from "../../cli.mjs";
import { yargsWithCommonQueryOptions } from "../../lib/command-helpers.mjs";
import { ValidationError } from "../../lib/errors.mjs";
import { getSecret } from "../../lib/fauna-client.mjs";
import { reformatFSL } from "../../lib/schema.mjs";
import { localSchemaOptions } from "./schema.mjs";

Expand All @@ -14,9 +13,10 @@ import { localSchemaOptions } from "./schema.mjs";
* @param {import("yargs").Argv & {dir: string, active: boolean, input: boolean}} argv
*/
export async function pushSchema(argv) {
const { getSecret } = container.resolve("faunaClient");
const gatherFSL = container.resolve("gatherFSL");
const logger = container.resolve("logger");
const makeFaunaRequest = container.resolve("makeFaunaRequest");
const gatherFSL = container.resolve("gatherFSL");

const isStagedPush = !argv.active;
const secret = await getSecret();
Expand Down
4 changes: 2 additions & 2 deletions src/commands/schema/status.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ import path from "path";
import { container } from "../../cli.mjs";
import { yargsWithCommonQueryOptions } from "../../lib/command-helpers.mjs";
import { CommandError } from "../../lib/errors.mjs";
import { getSecret } from "../../lib/fauna-client.mjs";
import { reformatFSL } from "../../lib/schema.mjs";
import { localSchemaOptions } from "./schema.mjs";

async function doStatus(argv) {
const { getSecret } = container.resolve("faunaClient");
const gatherFSL = container.resolve("gatherFSL");
const logger = container.resolve("logger");
const makeFaunaRequest = container.resolve("makeFaunaRequest");

const secret = await getSecret();
const absoluteDirPath = path.resolve(argv.dir);
const gatherFSL = container.resolve("gatherFSL");
const fslFiles = await gatherFSL(argv.dir);
const hasLocalSchema = fslFiles.length > 0;
const fsl = reformatFSL(fslFiles);
Expand Down
13 changes: 8 additions & 5 deletions src/commands/shell.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,15 @@ import {
validateDatabaseOrSecret,
yargsWithCommonConfigurableQueryOptions,
} from "../lib/command-helpers.mjs";
import { formatQueryResponse, getSecret } from "../lib/fauna-client.mjs";
import { clearHistoryStorage, initHistoryStorage } from "../lib/file-util.mjs";

async function shellCommand(argv) {
const { getSecret, isQueryable } = container.resolve("faunaClient");
const { query: v4Query } = container.resolve("faunadb");

validateDatabaseOrSecret(argv);

// Fast fail if the database is not queryable
const isQueryable = container.resolve("isQueryable");
await isQueryable({ ...argv, secret: await getSecret() });

const logger = container.resolve("logger");
Expand Down Expand Up @@ -146,9 +145,13 @@ const getArgvOrCtx = (key, argv, ctx) => {

// caches the logger, client, and performQuery for subsequent shell calls
async function buildCustomEval(argv) {
const formatError = container.resolve("formatError");
const formatQueryInfo = container.resolve("formatQueryInfo");
const runQueryFromString = container.resolve("runQueryFromString");
const {
formatError,
getSecret,
formatQueryInfo,
formatQueryResponse,
runQueryFromString,
} = container.resolve("faunaClient");

return async (cmd, ctx, _filename, cb) => {
try {
Expand Down
12 changes: 2 additions & 10 deletions src/config/setup-container.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,7 @@ import { Credentials } from "../lib/auth/credentials.mjs";
import OAuthClient from "../lib/auth/oauth-client.mjs";
import { makeRetryableFaunaRequest } from "../lib/db.mjs";
import * as faunaV10 from "../lib/fauna.mjs";
import {
formatError,
formatQueryInfo,
isQueryable,
runQueryFromString,
} from "../lib/fauna-client.mjs";
import * as faunaClient from "../lib/fauna-client.mjs";
import * as faunaV4 from "../lib/faunadb.mjs";
import fetchWrapper from "../lib/fetch-wrapper.mjs";
import { codeToAnsi } from "../lib/formatting/codeToAnsi.mjs";
Expand Down Expand Up @@ -97,12 +92,9 @@ export const injectables = {
lifetime: Lifetime.SINGLETON,
}),
// utilities for interacting with Fauna
runQueryFromString: awilix.asValue(runQueryFromString),
formatError: awilix.asValue(formatError),
formatQueryInfo: awilix.asValue(formatQueryInfo),
faunaClient: awilix.asValue(faunaClient),
faunaClientV10: awilix.asValue(faunaV10),
faunaClientV4: awilix.asValue(faunaV4),
isQueryable: awilix.asValue(isQueryable),

// feature-specific lib (homemade utilities)
gatherFSL: awilix.asValue(gatherFSL),
Expand Down
12 changes: 7 additions & 5 deletions src/config/setup-test-container.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { f, InMemoryWritableStream } from "../../test/helpers.mjs";
import { parseYargs } from "../cli.mjs";
import { makeRetryableFaunaRequest } from "../lib/db.mjs";
import * as faunaClientV10 from "../lib/fauna.mjs";
import { formatQueryInfo } from "../lib/fauna-client.mjs";
import * as faunaClient from "../lib/fauna-client.mjs";
import * as faunaClientV4 from "../lib/faunadb.mjs";
import buildLogger from "../lib/logger.mjs";
import { injectables, setupCommonContainer } from "./setup-container.mjs";
Expand Down Expand Up @@ -104,10 +104,12 @@ export function setupTestContainer() {
gatherFSL: awilix.asValue(stub().resolves([])),
makeFaunaRequest: awilix.asValue(spy(makeRetryableFaunaRequest)),
makeAccountRequest: awilix.asValue(stub()),
runQueryFromString: awilix.asValue(stub().resolves({})),
isQueryable: awilix.asValue(stub().resolves()),
formatError: awilix.asValue(stub()),
formatQueryInfo: awilix.asValue(spy(formatQueryInfo)),
faunaClient: awilix.asValue({
...faunaClient,
formatQueryInfo: spy(faunaClient.formatQueryInfo),
runQueryFromString: stub().resolves({}),
isQueryable: stub().resolves(),
}),
faunaClientV10: awilix.asValue({
getClient: stub(),
runQuery: stub(),
Expand Down
3 changes: 2 additions & 1 deletion src/lib/db.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
CommandError,
NETWORK_ERROR_MESSAGE,
} from "./errors.mjs";
import { retryInvalidCredsOnce } from "./fauna-client.mjs";

function buildParamsString({ argv, params, path }) {
const routesWithColor = ["/schema/1/staged/status", "/schema/1/diff"];
Expand Down Expand Up @@ -96,6 +95,8 @@ export async function makeFaunaRequest({
* @returns {Promise<Object>}
*/
export function makeRetryableFaunaRequest(opts) {
const { retryInvalidCredsOnce } = container.resolve("faunaClient");

return retryInvalidCredsOnce(opts.secret, (secret) =>
makeFaunaRequest({ ...opts, secret }),
);
Expand Down
4 changes: 3 additions & 1 deletion src/lib/fauna-client.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ export const formatError = (err, { apiVersion, color }) => {
* @param {*} argv
*/
export const isQueryable = async (argv) => {
const runQueryFromString = container.resolve("runQueryFromString");
// resolve runQueryFromString at runtime, not necessarily from this module.
const runQueryFromString =
container.resolve("faunaClient").runQueryFromString;
try {
await runQueryFromString("1+1", argv);
} catch (err) {
Expand Down
3 changes: 2 additions & 1 deletion src/lib/schema.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import * as path from "path";

import { container } from "../cli.mjs";
import { makeFaunaRequest } from "../lib/db.mjs";
import { getSecret } from "./fauna-client.mjs";
import { dirExists, dirIsWriteable } from "./file-util.mjs";

/**
Expand Down Expand Up @@ -178,6 +177,8 @@ export async function getAllSchemaFileContents(
version,
argv,
) {
const { getSecret } = container.resolve("faunaClient");

const promises = [];
/** @type Record<string, string> */
const fileContentCollection = {};
Expand Down
6 changes: 3 additions & 3 deletions test/credentials.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -275,9 +275,9 @@ describe("credentials", function () {
// We need to use the original implementation of runQueryFromString to ensure it hits
// faunaClientV10.runQueryFromString which is where we force the 401 and test the refresh
// logic.
container.register({
runQueryFromString: awilix.asValue(originalRunQueryFromString),
});
const faunaClient = container.resolve("faunaClient");
faunaClient.runQueryFromString = originalRunQueryFromString;

v10runQueryFromString =
container.resolve("faunaClientV10").runQueryFromString;
});
Expand Down
43 changes: 40 additions & 3 deletions test/query.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ import {
} from "./helpers.mjs";

describe("query", function () {
let container, logger, runQueryFromString;
let container, formatQueryInfo, logger, runQueryFromString;

beforeEach(() => {
container = setupContainer();
logger = container.resolve("logger");
runQueryFromString = container.resolve("runQueryFromString");

const faunaClient = container.resolve("faunaClient");
runQueryFromString = faunaClient.runQueryFromString;
formatQueryInfo = faunaClient.formatQueryInfo;

// Set a default empty response for all queries
runQueryFromString.resolves({ data: "test" });
Expand Down Expand Up @@ -321,7 +324,41 @@ describe("query", function () {
);
});

describe("query info", function () {
describe("--include usage", function () {
it("can set the include option to '[summary]' by default", async function () {
await run(`query "foo" --secret=foo`, container);

expect(formatQueryInfo.getCall(0).args[1].include).to.deep.equal([
"summary",
]);
});

it("can set the include option to an array", async function () {
await run(
`query "foo" --secret=foo --include summary stats`,
container,
);

expect(formatQueryInfo.getCall(0).args[1].include).to.deep.equal([
"summary",
"stats",
]);
});

it("can specify '--include all' to set all include options", async function () {
await run(`query "foo" --secret=foo --include all`, container);

expect(formatQueryInfo.getCall(0).args[1].include).to.deep.equal(
QUERY_INFO_CHOICES,
);
});

it("can specify '--include none' to set no include options", async function () {
await run(`query "foo" --secret=foo --include none`, container);

expect(formatQueryInfo).to.not.be.called;
});

it("displays summary by default", async function () {
runQueryFromString.resolves({
summary: "info at *query*:1: hello world",
Expand Down
Loading

0 comments on commit 4edb083

Please sign in to comment.