Skip to content

Commit

Permalink
infer types via JSDoc through IoC container (#377)
Browse files Browse the repository at this point in the history
  • Loading branch information
echo-bravo-yahoo authored Oct 7, 2024
1 parent 36bcb33 commit 8ae0a0b
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 1,128 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
{
"name": "fauna-shell",
"description": "faunadb shell",
"version": "2.0.2",
"version": "3.0.0-beta",
"author": "Fauna",
"bin": {
"fauna": "./yargs-entrypoint.mjs"
},
"bugs": "https://github.com/fauna/fauna-shell/issues",
"dependencies": {
"@babel/core": "^7.25.7",
"@inquirer/prompts": "^3.1.1",
"@oclif/core": "^4.0.12",
"@oclif/plugin-help": "^5.2.14",
Expand Down Expand Up @@ -45,6 +46,7 @@
"@types/node": "^20.6.0",
"@types/sinon": "^17.0.3",
"@types/supports-color": "^8.1.3",
"@types/yargs": "^17.0.33",
"@typescript-eslint/parser": "6.7.3",
"c8": "^8.0.1",
"chai": "^5.1.1",
Expand All @@ -54,7 +56,6 @@
"eslint-plugin-prettier": "^3.4.0",
"globals": "^15.10.0",
"husky": "^7.0.4",
"jest": "^29.7.0",
"mocha": "^10.7.3",
"mocha-junit-reporter": "^2.2.1",
"mock-require": "^3.0.3",
Expand Down
18 changes: 17 additions & 1 deletion src/cli.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// @ts-check

import yargs from "yargs";
import chalk from "chalk";

Expand All @@ -6,9 +8,18 @@ import loginCommand from "./yargs-commands/login.mjs";
import schemaCommand from "./yargs-commands/schema/schema.mjs";
import { logArgv } from "./lib/middleware.mjs";

/** @typedef {import('awilix').AwilixContainer<import('./config/setup-container.mjs').modifiedInjectables>} cliContainer */

/** @type {cliContainer} */
export let container;
/** @type {yargs.Argv} */
export let builtYargs;

/**
* @function run
* @param {string} argvInput - The command string provided by the user or test. Parsed by yargs into an argv object.
* @param {cliContainer} _container - A built and ready for use awilix container with registered injectables.
*/
export async function run(argvInput, _container) {
container = _container;
const logger = container.resolve("logger");
Expand All @@ -34,6 +45,11 @@ export async function parseYargs(builtYargs) {
return builtYargs.parseAsync();
}

/**
* @function buildYargs
* @param {string} argvInput
* @returns {yargs.Argv<any>}
*/
function buildYargs(argvInput) {
return (
yargs(argvInput)
Expand Down Expand Up @@ -78,7 +94,7 @@ function buildYargs(argvInput) {
choices: ["fetch", "error", "argv"],
},
})
.wrap(yargs.terminalWidth)
.wrap(yargs.terminalWidth())
.help("help", "show help")
.fail(false)
.exitProcess(false)
Expand Down
9 changes: 8 additions & 1 deletion src/config/setup-container.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { exit } from "node:process";

import * as awilix from "awilix/lib/awilix.module.mjs";
import awilix from "awilix";

import { performQuery } from "../yargs-commands/eval.mjs";
import logger from "../lib/logger.mjs";
Expand Down Expand Up @@ -40,6 +40,12 @@ export function setupCommonContainer() {
return container;
}

/**
* @template T
* @typedef {{ [P in keyof T[P]]: ReturnType<T[P]['resolve']> }} Resolvers<T>
*/

/** @typedef {Resolvers<injectables>} modifiedInjectables */
export const injectables = {
// node libraries
exit: awilix.asValue(exit),
Expand Down Expand Up @@ -74,6 +80,7 @@ export const injectables = {
};

export function setupRealContainer() {
/** @type {awilix.AwilixContainer<injectables>} */
const container = setupCommonContainer();

container.register(injectables);
Expand Down
3 changes: 2 additions & 1 deletion src/lib/fetch-wrapper.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { container } from "../cli.mjs";

// this wrapper exists for only one reason: logging
// in the future, it could also be extended for error-handling
// in the future, it could also be extended for error-handling,
// analytics, or metrics collection.
export default async function fetchWrapper(url, options) {
const logger = container.resolve("logger");
const method = options?.method || "GET";
Expand Down
83 changes: 72 additions & 11 deletions src/lib/logger.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,31 @@ import chalk from "chalk";
import yargs from "yargs";
import { hideBin } from "yargs/helpers";

/**
* @typedef argv
* @type {object}
* @property {Array.<string>} verboseComponent - An array of components to always log information about, regardless of the current verbosity level.
* @property {number} verbosity - The highest (least critical) log line to emit, ranging from 4 (debug) to 1 (fatal). Logs above the verbosity level are not emitted.
*/

/**
* Runs the function in the context of a database connection.
*
* @function
* @param {Object} args
* @param {string} args.text - The text to log.
* @param {number} args.verbosity - The verbosity level for the log line, ranging from 4 (debug) to 1 (fatal). Used to determine the color of the logged text as well as whether or not to emit the log line (and if so, to which stream).
* @param {function} args.stream - A function that handles a log line. Typically `console.log` or `console.error`, but could be any function that takes string input.
* @param {string} [args.component] - A string that identifies what "component" of the application this is. Included in the log line as a prefix and also used for formatting with verboseComponents
* @param {function} [args.formatter] - A function that takes a string and decorates it. Usually used to provide color for the log line.
* @param {argv} [args.argv] - The parsed yargs argv. Used to determine the current verbosity and if any components are included in verboseComponents.
*/
export function log({
text,
verbosity,
stream,
component = "unknown",
formatter,
formatter = (text) => text,
argv,
}) {
// stringified errors come with this prefix; since we're going to add a component
Expand All @@ -18,16 +37,18 @@ export function log({
if (!argv) {
// we give yargs _just_ enough information that we can use it to parse
// out the verbosity flags needed by the logger
argv = yargs(hideBin(process.argv)).options({
verboseComponent: {
type: "array",
default: [],
},
verbosity: {
type: "number",
default: 0,
},
}).argv;
argv = yargs(hideBin(process.argv))
.options({
verboseComponent: {
type: "array",
default: [],
},
verbosity: {
type: "number",
default: 0,
},
})
.version(false).argv;
}

if (
Expand All @@ -41,6 +62,14 @@ export function log({
return false;
}

/**
* Log text at a debug log level (verbosity 5).
*
* @function
* @param {string} text - The text to log.
* @param {string} [component] - A string that identifies what "component" of the application this is. Included in the log line as a prefix and also used for formatting with verboseComponents
* @param {argv} [argv] - The parsed yargs argv. Used to determine the current verbosity and if any components are included in verboseComponents.
*/
function debug(text, component, argv) {
log({
text,
Expand All @@ -52,6 +81,14 @@ function debug(text, component, argv) {
});
}

/**
* Log text at a info log level (verbosity 4).
*
* @function
* @param {string} text - The text to log.
* @param {string} [component] - A string that identifies what "component" of the application this is. Included in the log line as a prefix and also used for formatting with verboseComponents
* @param {argv} [argv] - The parsed yargs argv. Used to determine the current verbosity and if any components are included in verboseComponents.
*/
function info(text, component, argv) {
log({
text,
Expand All @@ -63,6 +100,14 @@ function info(text, component, argv) {
});
}

/**
* Log text at a warn log level (verbosity 3).
*
* @function
* @param {string} text - The text to log.
* @param {string} [component] - A string that identifies what "component" of the application this is. Included in the log line as a prefix and also used for formatting with verboseComponents
* @param {argv} [argv] - The parsed yargs argv. Used to determine the current verbosity and if any components are included in verboseComponents.
*/
function warn(text, component, argv) {
log({
text,
Expand All @@ -74,6 +119,14 @@ function warn(text, component, argv) {
});
}

/**
* Log text at a error log level (verbosity 2).
*
* @function
* @param {string} text - The text to log.
* @param {string} [component] - A string that identifies what "component" of the application this is. Included in the log line as a prefix and also used for formatting with verboseComponents
* @param {argv} [argv] - The parsed yargs argv. Used to determine the current verbosity and if any components are included in verboseComponents.
*/
function error(text, component, argv) {
log({
text,
Expand All @@ -85,6 +138,14 @@ function error(text, component, argv) {
});
}

/**
* Log text at a fatal log level (verbosity 1).
*
* @function
* @param {string} text - The text to log.
* @param {string} [component] - A string that identifies what "component" of the application this is. Included in the log line as a prefix and also used for formatting with verboseComponents
* @param {argv} [argv] - The parsed yargs argv. Used to determine the current verbosity and if any components are included in verboseComponents.
*/
function fatal(text, component, argv) {
log({
text,
Expand Down
1 change: 1 addition & 0 deletions src/yargs-commands/schema/schema.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ export default {
command: "schema",
describe: "Manipulate Fauna schema state",
builder: buildSchema,
handler: () => {},
};
Loading

0 comments on commit 8ae0a0b

Please sign in to comment.