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

Clean up lint warnings #547

Merged
merged 6 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/cli.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ function buildYargs(argvInput) {
.filter((key) => previousWord === key)
.pop();

// TODO: this doesn't handle aliasing, and it needs to
// This doesn't handle aliasing, and it needs to
if (
currentWord === "--profile" ||
currentWordFlag === "profile" ||
Expand Down
56 changes: 28 additions & 28 deletions src/commands/local.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,32 @@ ${chalk.red("Please use choose a different name using --name or align the --type
}
}

function validateContainerArgv(argv) {
if (argv.maxAttempts < 1) {
throw new ValidationError("--max-attempts must be greater than 0.");
}
if (argv.interval < 0) {
throw new ValidationError("--interval must be greater than or equal to 0.");
}
}

function validateDatabaseArgv(argv) {
const dbOnlyArgs = {
typechecked: "--typechecked",
protected: "--protected",
priority: "--priority",
directory: "--fsl-directory",
};

for (const [arg, name] of Object.entries(dbOnlyArgs)) {
if (argv[arg] !== undefined && !argv.database) {
throw new ValidationError(
`${name} can only be set if --database is set.`,
);
}
}
}

/**
* Builds the yargs command for the local command
* @param {import('yargs').Argv} yargs The yargs instance
Expand Down Expand Up @@ -198,34 +224,8 @@ function buildLocalCommand(yargs) {
},
})
.check((argv) => {
if (argv.maxAttempts < 1) {
throw new ValidationError("--max-attempts must be greater than 0.");
}
if (argv.interval < 0) {
throw new ValidationError(
"--interval must be greater than or equal to 0.",
);
}
if (argv.typechecked !== undefined && !argv.database) {
throw new ValidationError(
"--typechecked can only be set if --database is set.",
);
}
if (argv.protected && !argv.database) {
throw new ValidationError(
"--protected can only be set if --database is set.",
);
}
if (argv.priority && !argv.database) {
throw new ValidationError(
"--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.",
);
}
validateContainerArgv(argv);
validateDatabaseArgv(argv);
return true;
})
.example([
Expand Down
1 change: 0 additions & 1 deletion src/commands/shell.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ async function shellCommand(argv) {
prompt: `${argv.database || ""}> `,
ignoreUndefined: true,
preview: argv.apiVersion !== "10",
// TODO: integrate with fql-analyzer for completions
completer: argv.apiVersion === "10" ? () => [] : undefined,
output: container.resolve("stdoutStream"),
input: container.resolve("stdinStream"),
Expand Down
2 changes: 1 addition & 1 deletion src/lib/auth/accountKeys.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export class AccountKeys {
async getOrRefreshKey() {
if (this.keySource === "credentials-file") {
const key = this.keyStore.get();
// TODO: track ttl for account and refresh keys

if (!key) {
this.logger.debug(
"Found account key, but it is expired. Refreshing...",
Expand Down
1 change: 0 additions & 1 deletion src/lib/auth/credentials.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ export class Credentials {
this.accountKeys.keyStore.save({
accountKey,
refreshToken,
// TODO: set expiration
});
this.accountKeys.key = accountKey;
}
Expand Down
108 changes: 63 additions & 45 deletions src/lib/auth/oauth-client.mjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import { createHash, randomBytes } from "crypto";
import http from "http";
import url from "url";
import util from "util";

import { container } from "../../cli.mjs";
import SuccessPage from "./successPage.mjs";

const ALLOWED_ORIGINS = [
"http://localhost:3005",
"http://127.0.0.1:3005",
"http://dashboard.fauna.com",
"http://dashboard.fauna-dev.com",
"http://dashboard.fauna-preview.com",
];

// Default to prod client id and secret
const CLIENT_ID = process.env.FAUNA_CLIENT_ID ?? "Aq4_G0mOtm_F1fK3PuzE0k-i9F0";
// Native public clients are not confidential. The client secret is not used beyond
Expand Down Expand Up @@ -52,64 +61,73 @@ class OAuthClient {
return Buffer.from(randomBytes(20)).toString("base64url");
}

_handleRedirect({ pathname, res }) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefix with # instead to make it private?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd need to update the shared eslint configuration and that's outside the scope of this PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, bummer.

if (pathname === "/success") {
res.writeHead(200, { "Content-Type": "text/html" });
res.write(SuccessPage);
res.end();
this.closeServer();
} else if (pathname !== "/") {
throw new Error("Invalid redirect uri");
}
}

_handleCode({ authCode, state, res }) {
if (!authCode || typeof authCode !== "string") {
throw new Error("Invalid authorization code received");
} else {
this.authCode = authCode;
if (state !== this.state) {
throw new Error("Invalid state received");
}
res.writeHead(302, { Location: "/success" });
res.end();
this.server.emit("auth_code_received");
}
}

// req: IncomingMessage, res: ServerResponse
_handleRequest(req, res) {
const logger = container.resolve("logger");
const allowedOrigins = [
"http://localhost:3005",
"http://127.0.0.1:3005",
"http://dashboard.fauna.com",
"http://dashboard.fauna-dev.com",
"http://dashboard.fauna-preview.com",
];
const origin = req.headers.origin || "";

if (allowedOrigins.includes(origin)) {
if (ALLOWED_ORIGINS.includes(origin)) {
res.setHeader("Access-Control-Allow-Origin", origin);
res.setHeader("Access-Control-Allow-Methods", "GET");
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
}

let errorMessage = "";

if (req.method === "GET") {
const parsedUrl = url.parse(req.url || "", true);
if (parsedUrl.pathname === "/success") {
res.writeHead(200, { "Content-Type": "text/html" });
res.write(SuccessPage);
res.end();
this.closeServer();
} else if (parsedUrl.pathname !== "/") {
errorMessage = "Invalid redirect uri";
this.closeServer();
}
const query = parsedUrl.query;
if (query.error) {
errorMessage = `${query.error.toString()} - ${query.error_description}`;
this.closeServer();
}
if (query.code) {
const authCode = query.code;
if (!authCode || typeof authCode !== "string") {
errorMessage = "Invalid authorization code received";
this.server.close();
} else {
this.authCode = authCode;
if (query.state !== this.state) {
errorMessage = "Invalid state received";
this.closeServer();
}
res.writeHead(302, { Location: "/success" });
res.end();
this.server.emit("auth_code_received");
try {
// We only expect GET requests
if (req.method === "GET") {
const { pathname, query } = url.parse(req.url || "", true);

// If the pathname is not "/", we're handling a redirect
if (pathname !== "/") {
this._handleRedirect({ pathname, res });
}

// If the query contains an error, we're handling an error
if (query.error) {
throw new Error(
`${query.error.toString()} - ${query.error_description}`,
);
}

// If the query contains an auth code, we're handling a successful auth
if (query.code) {
this._handleCode({ authCode: query.code, state: query.state, res });
}
} else {
throw new Error("Invalid request method");
}
} else {
errorMessage = "Invalid request method";
} catch (e) {
this.closeServer();
}
if (errorMessage) {
logger.stderr(`Error during authentication: ${errorMessage}`);
logger.debug(
`Authentication error: ${util.inspect(e, true, 2, false)}`,
"creds",
);
logger.stderr(`Error during authentication: ${e.message}`);
}
}

Expand Down
3 changes: 0 additions & 3 deletions src/lib/fauna-account-client.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,6 @@ export class FaunaAccountClient {
* @returns {Promise<{accountKey: string, refreshToken: string}>} - The session information.
* @throws {Error} - Throws an error if there is an issue during session retrieval.
*/

// TODO: get/set expiration details
static async getSession(accessToken) {
const makeAccountRequest = container.resolve("makeAccountRequest");
try {
Expand All @@ -149,7 +147,6 @@ export class FaunaAccountClient {
}
}

// TODO: get/set expiration details
/**
* Uses refreshToken to get a new accountKey and refreshToken.
* @param {*} refreshToken
Expand Down
43 changes: 23 additions & 20 deletions src/lib/fauna-client.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -187,26 +187,29 @@ export const formatQuerySummary = (summary) => {
}
};

/**
* Selects a subset of query info fields from a v10 query response.
* @param {import("fauna").QueryInfo} response - The query response
* @param {string[]} include - The query info fields to include
* @returns {object} An object with the selected query info fields
*/
const pickAndCamelCaseQueryInfo = (response, include) => {
const queryInfo = {};

if (include.includes("txnTs") && response.txn_ts)
queryInfo.txnTs = response.txn_ts;
if (include.includes("schemaVersion") && response.schema_version)
queryInfo.schemaVersion = response.schema_version.toString();
if (include.includes("summary") && response.summary)
queryInfo.summary = response.summary;
if (include.includes("queryTags") && response.query_tags)
queryInfo.queryTags = response.query_tags;
if (include.includes("stats") && response.stats)
queryInfo.stats = response.stats;
const getQueryInfoValue = (response, field) => {
switch (field) {
case "txnTs":
return response.txn_ts;
case "schemaVersion":
return response.schema_version?.toString();
case "summary":
return response.summary;
case "queryTags":
return response.query_tags;
case "stats":
return response.stats;
default:
return undefined;
}
};

const getIncludedQueryInfo = (response, include) => {
const queryInfo = {};
include.forEach((field) => {
const value = getQueryInfoValue(response, field);
if (value) queryInfo[field] = value;
});
return queryInfo;
};

Expand All @@ -230,7 +233,7 @@ export const formatQueryInfo = (response, { apiVersion, color, include }) => {

return `${colorized}\n`;
} else if (apiVersion === "10") {
const queryInfoToDisplay = pickAndCamelCaseQueryInfo(response, include);
const queryInfoToDisplay = getIncludedQueryInfo(response, include);

if (Object.keys(queryInfoToDisplay).length === 0) return "";

Expand Down
1 change: 0 additions & 1 deletion src/lib/middleware.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ export function fixPaths(argv) {
}

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

const __filename = fileURLToPath(import.meta.url);
Expand Down
1 change: 0 additions & 1 deletion test/schema/commit.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ describe("schema commit", function () {
});

it("errors if the schema is not in a ready state", async function () {
// TODO: what are the valid statuses? !none, !ready results in this case
fetch.onCall(0).resolves(f({ status: "building", diff: diff }));

const [error] = await tryToCatch(() =>
Expand Down
Loading