Skip to content

Commit

Permalink
CLI and Logging improvements (#4353)
Browse files Browse the repository at this point in the history
  • Loading branch information
ardatan authored Aug 23, 2022
1 parent 2889115 commit f23e14e
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 13 deletions.
14 changes: 14 additions & 0 deletions .changeset/friendly-bears-walk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
"@graphql-mesh/cli": minor
"@graphql-mesh/utils": minor
---

Now CLI reports critical errors with stack traces even if DEBUG isn't enabled, and error messages are no longer trimmed.

```diff
Schema couldn't be generated because of the following errors:
- - Foo bar is n...
+ - Foo bar is not valid
+ at /somepath/somejsfile.js:123:2
+ at /someotherpath/someotherjs.file:232:4
```
6 changes: 6 additions & 0 deletions .changeset/young-clouds-burn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@graphql-mesh/cli": minor
"@graphql-mesh/config": minor
---

New flag for `mesh build`. You can set `mesh build --throwOnInvalidConfig=true` to make the CLI throw an exception if the configuration file is invalid per Mesh's configuration schema
15 changes: 14 additions & 1 deletion packages/cli/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,31 @@ import { defaultImportFn, loadYaml, DefaultLogger } from '@graphql-mesh/utils';
import Ajv from 'ajv';
import { cosmiconfig, defaultLoaders } from 'cosmiconfig';
import { path, process } from '@graphql-mesh/cross-helpers';
import { AggregateError } from '@graphql-tools/utils';

export function validateConfig(
config: any,
filepath: string,
initialLoggerPrefix: string
initialLoggerPrefix: string,
throwOnInvalidConfig = false
): asserts config is YamlConfig.Config {
const ajv = new Ajv({
strict: false,
} as any);
jsonSchema.$schema = undefined;
const isValid = ajv.validate(jsonSchema, config);
if (!isValid) {
if (throwOnInvalidConfig) {
const aggregateError = new AggregateError(
ajv.errors.map(e => {
const error = new Error(e.message);
error.stack += `\n at ${filepath}:0:0`;
return error;
}),
'Configuration file is not valid'
);
throw aggregateError;
}
const logger = new DefaultLogger(initialLoggerPrefix).child('config');
logger.warn('Configuration file is not valid!');
logger.warn("This is just a warning! It doesn't have any effects on runtime.");
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/handleFatalError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Logger } from '@graphql-mesh/types';
import { process } from '@graphql-mesh/cross-helpers';

export function handleFatalError(e: Error, logger: Logger): any {
logger.error(e.stack || e.message);
logger.error(e);
if (process.env.JEST == null) {
process.exit(1);
}
Expand Down
7 changes: 6 additions & 1 deletion packages/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ export async function graphqlMesh(
}
}
)
.command<{ fileType: 'json' | 'ts' | 'js' }>(
.command<{ fileType: 'json' | 'ts' | 'js'; throwOnInvalidConfig: boolean }>(
cliParams.buildArtifactsCommand,
'Builds artifacts',
builder => {
Expand All @@ -318,6 +318,10 @@ export async function graphqlMesh(
choices: ['json', 'ts', 'js'],
default: 'ts',
});
builder.option('throwOnInvalidConfig', {
type: 'boolean',
default: false,
});
},
async args => {
try {
Expand Down Expand Up @@ -373,6 +377,7 @@ export async function graphqlMesh(
additionalPackagePrefixes: cliParams.additionalPackagePrefixes,
generateCode: true,
initialLoggerPrefix: cliParams.initialLoggerPrefix,
throwOnInvalidConfig: args.throwOnInvalidConfig,
});
logger = meshConfig.logger;

Expand Down
1 change: 1 addition & 0 deletions packages/config/src/process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export type ConfigProcessOptions = {
additionalPackagePrefixes?: string[];
generateCode?: boolean;
initialLoggerPrefix?: string;
throwOnInvalidConfig?: boolean;
};

type EnvelopPlugins = Parameters<typeof envelop>[0]['plugins'];
Expand Down
34 changes: 24 additions & 10 deletions packages/utils/src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ export const titleBold: MessageTransformer = msg => ANSI_CODES.bold + msg + ANSI
export class DefaultLogger implements Logger {
constructor(public name?: string) {}

private getLoggerMessage(...args: any[]) {
private getLoggerMessage({ args = [], trim = this.isDebug }: { args: any[]; trim?: boolean }) {
return args
.flat(Infinity)
.map(arg => {
if (typeof arg === 'string') {
if (arg.length > 100 && !this.isDebug) {
return arg.slice(0, 100) + '...';
if (trim && arg.length > 100) {
return arg.slice(0, 100) + '...' + '<Error message is too long. Enable DEBUG=1 to see the full message.>';
}
return arg;
} else if (typeof arg === 'object' && arg?.stack != null) {
Expand All @@ -43,14 +43,17 @@ export class DefaultLogger implements Logger {
.join(` `);
}

private handleLazyMessage(...lazyArgs: LazyLoggerMessage[]) {
private handleLazyMessage({ lazyArgs, trim }: { lazyArgs: LazyLoggerMessage[]; trim?: boolean }) {
const flattenedArgs = lazyArgs.flat(Infinity).flatMap(arg => {
if (typeof arg === 'function') {
return arg();
}
return arg;
});
return this.getLoggerMessage(flattenedArgs);
return this.getLoggerMessage({
args: flattenedArgs,
trim,
});
}

private get isDebug() {
Expand All @@ -66,12 +69,16 @@ export class DefaultLogger implements Logger {
}

log(...args: any[]) {
const message = this.getLoggerMessage(...args);
const message = this.getLoggerMessage({
args,
});
return console.log(`${this.prefix} ${message}`);
}

warn(...args: any[]) {
const message = this.getLoggerMessage(...args);
const message = this.getLoggerMessage({
args,
});
const fullMessage = `⚠️ ${this.prefix} ${warnColor(message)}`;
if (console.warn) {
console.warn(fullMessage);
Expand All @@ -81,7 +88,9 @@ export class DefaultLogger implements Logger {
}

info(...args: any[]) {
const message = this.getLoggerMessage(...args);
const message = this.getLoggerMessage({
args,
});
const fullMessage = `💡 ${this.prefix} ${infoColor(message)}`;
if (console.info) {
console.info(fullMessage);
Expand All @@ -91,14 +100,19 @@ export class DefaultLogger implements Logger {
}

error(...args: any[]) {
const message = this.getLoggerMessage(...args);
const message = this.getLoggerMessage({
args,
trim: false,
});
const fullMessage = `💥 ${this.prefix} ${errorColor(message)}`;
console.log(fullMessage);
}

debug(...lazyArgs: LazyLoggerMessage[]) {
if (this.isDebug) {
const message = this.handleLazyMessage(lazyArgs);
const message = this.handleLazyMessage({
lazyArgs,
});
const fullMessage = `🐛 ${this.prefix} ${debugColor(message)}`;
if (console.debug) {
console.debug(fullMessage);
Expand Down

1 comment on commit f23e14e

@vercel
Copy link

@vercel vercel bot commented on f23e14e Aug 23, 2022

Choose a reason for hiding this comment

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

Please sign in to comment.