Skip to content

Commit 07ca043

Browse files
committed
Support for the loggerFunctions option
1 parent eeb1d39 commit 07ca043

File tree

7 files changed

+64
-12
lines changed

7 files changed

+64
-12
lines changed

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
dist/
22
node_modules/
33
package-lock.json
4+
*.md

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,12 @@ You can customize the logger functions that are used to log errors in your proje
6060
{
6161
"settings": {
6262
"handle-errors": {
63-
"loggerFunctions": ["console.error", "console.warn", "Sentry.captureException", "logError"]
63+
"loggerFunctions": [
64+
"console.error",
65+
"console.warn",
66+
"Sentry.captureException",
67+
"logError"
68+
]
6469
}
6570
}
6671
}

src/rules/log-error-in-promises.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,11 @@ runRuleTester('log-error-in-promises', logErrorInPromises, {
136136
`,
137137
},
138138
{
139+
settings: {
140+
handleErrors: {
141+
loggerFunctions: ['logError'],
142+
},
143+
},
139144
code: dedent`
140145
a.then(callback).catch(logError)
141146
`,

src/rules/log-error-in-promises.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import { createRule } from '../utils/createRule';
22
import { createLoggerCallTracker, createCallExpression, createMemberExpression } from '../utils/loggerCallTracker';
3-
4-
// TODO: add option to specify custom loggers
5-
const loggers = ['console.error', 'console.warn', 'Sentry.captureException'] as const;
3+
import { parseSettings } from '../utils/settings';
64

75
export const logErrorInPromises = createRule({
86
meta: {
@@ -21,7 +19,8 @@ export const logErrorInPromises = createRule({
2119
schema: [],
2220
},
2321
create(context) {
24-
const tracker = createLoggerCallTracker(node =>
22+
const settings = parseSettings(context.settings);
23+
const tracker = createLoggerCallTracker(settings, node =>
2524
context.report({
2625
node,
2726
messageId: 'error-not-handled',
@@ -42,7 +41,7 @@ export const logErrorInPromises = createRule({
4241
[`${catchCall}[arguments.length=1] > :function BlockStatement ThrowStatement`]:
4342
tracker.onErrorProccessingInBlock,
4443

45-
...loggers.reduce((acc, logger) => {
44+
...settings.loggerFunctions.reduce((acc, logger) => {
4645
Object.assign(acc, {
4746
[`CallExpression[callee.property.name="catch"][arguments.length=1] > :function > BlockStatement > ExpressionStatement > ${createCallExpression(logger)}`]:
4847
tracker.onErrorProccessingInRoot,

src/rules/log-error-in-trycatch.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import { createRule } from '../utils/createRule';
22
import { createLoggerCallTracker, createCallExpression } from '../utils/loggerCallTracker';
3-
4-
// TODO: add option to specify custom loggers
5-
const loggers = ['console.error', 'console.warn', 'Sentry.captureException'] as const;
3+
import { parseSettings } from '../utils/settings';
64

75
export const logErrorInTrycatch = createRule({
86
meta: {
@@ -21,7 +19,8 @@ export const logErrorInTrycatch = createRule({
2119
schema: [],
2220
},
2321
create(context) {
24-
const tracker = createLoggerCallTracker(node => {
22+
const settings = parseSettings(context.settings);
23+
const tracker = createLoggerCallTracker(settings, node => {
2524
context.report({
2625
node,
2726
messageId: 'error-not-handled',
@@ -40,7 +39,7 @@ export const logErrorInTrycatch = createRule({
4039
'CatchClause > BlockStatement > ThrowStatement': tracker.onErrorProccessingInRoot,
4140
'CatchClause BlockStatement ThrowStatement': tracker.onErrorProccessingInBlock,
4241

43-
...loggers.reduce((acc, logger) => {
42+
...settings.loggerFunctions.reduce((acc, logger) => {
4443
Object.assign(acc, {
4544
[`CatchClause > BlockStatement > ExpressionStatement > ${createCallExpression(logger)}`]:
4645
tracker.onErrorProccessingInRoot,

src/utils/loggerCallTracker.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Rule } from 'eslint';
22
import { BlockStatement, ReturnStatement, ThrowStatement } from 'estree';
33
import t from '@babel/types';
4+
import { Settings } from './settings';
45

56
interface ScopeStackEntry {
67
isErrorHandled: boolean;
@@ -13,7 +14,7 @@ interface BlockStackEntry {
1314
isErrorHandled: boolean;
1415
}
1516

16-
export function createLoggerCallTracker(report: (node: Rule.Node) => void) {
17+
export function createLoggerCallTracker(settings: Settings, report: (node: Rule.Node) => void) {
1718
const scopesStack: ScopeStackEntry[] = [];
1819
const blocksStack: BlockStackEntry[] = [];
1920

src/utils/settings.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
export interface Settings {
2+
readonly loggerFunctions: readonly string[];
3+
}
4+
5+
const defaultLoggerFunctions = ['console.warn', 'console.error'] as const;
6+
7+
const defaultSettings: Settings = {
8+
loggerFunctions: defaultLoggerFunctions,
9+
};
10+
11+
export function parseSettings(settings: unknown): Settings {
12+
if (!isObject(settings)) return defaultSettings;
13+
if (!isObject(settings.handleErrors)) return defaultSettings;
14+
15+
return parsePluginSettings(settings.handleErrors);
16+
}
17+
18+
function parsePluginSettings(settings: Record<PropertyKey, unknown>): Settings {
19+
const { loggerFunctions = defaultLoggerFunctions } = settings;
20+
21+
if (!isArrayOfString(loggerFunctions)) {
22+
throw new Error(
23+
`Invalid configuration value for settings.handleErrors.loggerFunctions. The value must be array of strings. Got: ${loggerFunctions}`
24+
);
25+
}
26+
27+
return {
28+
loggerFunctions,
29+
};
30+
}
31+
32+
function isObject(settings: unknown): settings is Record<PropertyKey, unknown> {
33+
return settings !== null && typeof settings === 'object';
34+
}
35+
36+
function isString(value: unknown): value is string {
37+
return typeof value === 'string';
38+
}
39+
40+
function isArrayOfString(value: unknown): value is string[] {
41+
return Array.isArray(value) && value.every(isString);
42+
}

0 commit comments

Comments
 (0)