@mimik/eslint-plugin-logger 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -147
- package/index.js +31 -44
- package/package.json +12 -10
package/README.md
CHANGED
|
@@ -81,166 +81,41 @@ logger.info('User logged in', { userId: 123 }, correlationId, { type: 'audit' })
|
|
|
81
81
|
- The rule only applies to **default imports** (e.g. `import logger from '...'`)
|
|
82
82
|
- Named imports (`import { logger } from '...'`) are ignored
|
|
83
83
|
- Supports dot notation (`logger.info`), bracket notation with a string literal (`logger['info']`), and bracket notation with a variable (`logger[level]`)
|
|
84
|
-
- For bracket notation with a string literal, the value must be a
|
|
84
|
+
- For bracket notation with a string literal, the value must be a recognized log level
|
|
85
85
|
- For bracket notation with a variable, the call is always validated (the variable is assumed to hold a valid level)
|
|
86
86
|
- Minimum 2 arguments, maximum 4
|
|
87
87
|
- `message` must be a string (when passed as a literal)
|
|
88
88
|
- `correlationId` must be a string (when passed as a literal)
|
|
89
89
|
- `options` object must contain a `type` property with a string value
|
|
90
|
-
- When 2 arguments are passed and the 2nd is an object literal, it is treated as `(message, meta)` with a missing `correlationId`
|
|
90
|
+
- When 2 arguments are passed and the 2nd is an object or array literal, it is treated as `(message, meta)` with a missing `correlationId`
|
|
91
91
|
- When 3 arguments are passed, the 2nd argument type determines the signature:
|
|
92
92
|
- Object literal → `(message, meta, correlationId)`
|
|
93
93
|
- Otherwise → `(message, correlationId, options)`
|
|
94
94
|
|
|
95
95
|
## API Reference
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
<dl>
|
|
100
|
-
<dt><a href="#plugin">plugin</a> : <code>Object</code></dt>
|
|
101
|
-
<dd><p>ESLint plugin for validating logger call arguments.</p>
|
|
102
|
-
</dd>
|
|
103
|
-
</dl>
|
|
104
|
-
|
|
105
|
-
## Functions
|
|
106
|
-
|
|
107
|
-
<dl>
|
|
108
|
-
<dt><a href="#isNonStringLiteral">isNonStringLiteral(node)</a> ⇒ <code>boolean</code></dt>
|
|
109
|
-
<dd><p>Check whether an AST node is a non-string literal (number, boolean, null).</p>
|
|
110
|
-
</dd>
|
|
111
|
-
<dt><a href="#isObjectNode">isObjectNode(node)</a> ⇒ <code>boolean</code></dt>
|
|
112
|
-
<dd><p>Check whether an AST node is an object expression.</p>
|
|
113
|
-
</dd>
|
|
114
|
-
<dt><a href="#isTypeKey">isTypeKey(prop)</a> ⇒ <code>boolean</code></dt>
|
|
115
|
-
<dd><p>Check whether a property node has the key <code>type</code> (identifier or string literal).</p>
|
|
116
|
-
</dd>
|
|
117
|
-
<dt><a href="#findTypeProperty">findTypeProperty(node)</a> ⇒ <code>Object</code> | <code>undefined</code></dt>
|
|
118
|
-
<dd><p>Find the <code>type</code> property node inside an ObjectExpression.
|
|
119
|
-
Handles both identifier keys (<code>{ type: ... }</code>) and string-literal keys (<code>{ "type": ... }</code>).</p>
|
|
120
|
-
</dd>
|
|
121
|
-
<dt><a href="#validateOptions">validateOptions(context, optionsArg, level)</a></dt>
|
|
122
|
-
<dd><p>Validate the options argument of a logger call.
|
|
123
|
-
Reports an error when the options object is missing a <code>type</code> property or when the
|
|
124
|
-
<code>type</code> value is a non-string literal. Variable references (e.g. <code>{ type: someVar }</code>)
|
|
125
|
-
are allowed because their runtime type cannot be determined statically.</p>
|
|
126
|
-
</dd>
|
|
127
|
-
<dt><a href="#resolveLevel">resolveLevel(callee)</a> ⇒ <code>string</code> | <code>null</code></dt>
|
|
128
|
-
<dd><p>Resolve the log level from a MemberExpression callee.
|
|
129
|
-
Supports dot notation (<code>logger.info</code>), bracket notation with a string literal
|
|
130
|
-
(<code>logger['info']</code>), and bracket notation with a variable (<code>logger[level]</code>).
|
|
131
|
-
For string literals the value must be a recognised level; variables are assumed
|
|
132
|
-
to hold a valid level and the variable name is returned for error messages.</p>
|
|
133
|
-
</dd>
|
|
134
|
-
<dt><a href="#validateStringArg">validateStringArg(context, argNode, level, messageId)</a></dt>
|
|
135
|
-
<dd><p>Validate that a logger argument is a string when it is a literal.
|
|
136
|
-
Non-literal nodes (identifiers, call expressions) are skipped because their
|
|
137
|
-
runtime type cannot be determined statically.</p>
|
|
138
|
-
</dd>
|
|
139
|
-
</dl>
|
|
140
|
-
|
|
141
|
-
<a name="plugin"></a>
|
|
142
|
-
|
|
143
|
-
## plugin : <code>Object</code>
|
|
144
|
-
ESLint plugin for validating logger call arguments.
|
|
145
|
-
|
|
146
|
-
**Kind**: global constant
|
|
147
|
-
<a name="isNonStringLiteral"></a>
|
|
148
|
-
|
|
149
|
-
## isNonStringLiteral(node) ⇒ <code>boolean</code>
|
|
150
|
-
Check whether an AST node is a non-string literal (number, boolean, null).
|
|
151
|
-
|
|
152
|
-
**Kind**: global function
|
|
153
|
-
**Returns**: <code>boolean</code> - True when the node is a literal whose value is not a string.
|
|
154
|
-
|
|
155
|
-
| Param | Type | Description |
|
|
156
|
-
| --- | --- | --- |
|
|
157
|
-
| node | <code>Object</code> | The AST node to check. |
|
|
158
|
-
|
|
159
|
-
<a name="isObjectNode"></a>
|
|
160
|
-
|
|
161
|
-
## isObjectNode(node) ⇒ <code>boolean</code>
|
|
162
|
-
Check whether an AST node is an object expression.
|
|
163
|
-
|
|
164
|
-
**Kind**: global function
|
|
165
|
-
**Returns**: <code>boolean</code> - True when the node is an ObjectExpression.
|
|
166
|
-
|
|
167
|
-
| Param | Type | Description |
|
|
168
|
-
| --- | --- | --- |
|
|
169
|
-
| node | <code>Object</code> | The AST node to check. |
|
|
170
|
-
|
|
171
|
-
<a name="isTypeKey"></a>
|
|
172
|
-
|
|
173
|
-
## isTypeKey(prop) ⇒ <code>boolean</code>
|
|
174
|
-
Check whether a property node has the key `type` (identifier or string literal).
|
|
175
|
-
|
|
176
|
-
**Kind**: global function
|
|
177
|
-
**Returns**: <code>boolean</code> - True when the key is `type`.
|
|
178
|
-
|
|
179
|
-
| Param | Type | Description |
|
|
180
|
-
| --- | --- | --- |
|
|
181
|
-
| prop | <code>Object</code> | The property node. |
|
|
182
|
-
|
|
183
|
-
<a name="findTypeProperty"></a>
|
|
184
|
-
|
|
185
|
-
## findTypeProperty(node) ⇒ <code>Object</code> \| <code>undefined</code>
|
|
186
|
-
Find the `type` property node inside an ObjectExpression.
|
|
187
|
-
Handles both identifier keys (`{ type: ... }`) and string-literal keys (`{ "type": ... }`).
|
|
188
|
-
|
|
189
|
-
**Kind**: global function
|
|
190
|
-
**Returns**: <code>Object</code> \| <code>undefined</code> - The property node, or undefined if not found.
|
|
191
|
-
|
|
192
|
-
| Param | Type | Description |
|
|
193
|
-
| --- | --- | --- |
|
|
194
|
-
| node | <code>Object</code> | The object expression node. |
|
|
195
|
-
|
|
196
|
-
<a name="validateOptions"></a>
|
|
197
|
-
|
|
198
|
-
## validateOptions(context, optionsArg, level)
|
|
199
|
-
Validate the options argument of a logger call.
|
|
200
|
-
Reports an error when the options object is missing a `type` property or when the
|
|
201
|
-
`type` value is a non-string literal. Variable references (e.g. `{ type: someVar }`)
|
|
202
|
-
are allowed because their runtime type cannot be determined statically.
|
|
203
|
-
|
|
204
|
-
**Kind**: global function
|
|
205
|
-
|
|
206
|
-
| Param | Type | Description |
|
|
207
|
-
| --- | --- | --- |
|
|
208
|
-
| context | <code>Object</code> | The ESLint rule context. |
|
|
209
|
-
| optionsArg | <code>Object</code> | The options argument AST node. |
|
|
210
|
-
| level | <code>string</code> | The logger level (e.g. 'info', 'error'). |
|
|
211
|
-
|
|
212
|
-
<a name="resolveLevel"></a>
|
|
213
|
-
|
|
214
|
-
## resolveLevel(callee) ⇒ <code>string</code> \| <code>null</code>
|
|
215
|
-
Resolve the log level from a MemberExpression callee.
|
|
216
|
-
Supports dot notation (`logger.info`), bracket notation with a string literal
|
|
217
|
-
(`logger['info']`), and bracket notation with a variable (`logger[level]`).
|
|
218
|
-
For string literals the value must be a recognised level; variables are assumed
|
|
219
|
-
to hold a valid level and the variable name is returned for error messages.
|
|
97
|
+
The plugin exports a single object with the following shape:
|
|
220
98
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
<a name="validateStringArg"></a>
|
|
229
|
-
|
|
230
|
-
## validateStringArg(context, argNode, level, messageId)
|
|
231
|
-
Validate that a logger argument is a string when it is a literal.
|
|
232
|
-
Non-literal nodes (identifiers, call expressions) are skipped because their
|
|
233
|
-
runtime type cannot be determined statically.
|
|
234
|
-
|
|
235
|
-
**Kind**: global function
|
|
236
|
-
|
|
237
|
-
| Param | Type | Description |
|
|
238
|
-
| --- | --- | --- |
|
|
239
|
-
| context | <code>Object</code> | The ESLint rule context. |
|
|
240
|
-
| argNode | <code>Object</code> | The argument AST node. |
|
|
241
|
-
| level | <code>string</code> | The logger level (e.g. 'info', 'error'). |
|
|
242
|
-
| messageId | <code>string</code> | The ESLint message ID to report on failure. |
|
|
99
|
+
```js
|
|
100
|
+
{
|
|
101
|
+
rules: {
|
|
102
|
+
'validate-logger-args': { meta, create(context) }
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
243
106
|
|
|
107
|
+
### Error Messages
|
|
108
|
+
|
|
109
|
+
| Message ID | Description |
|
|
110
|
+
|---|---|
|
|
111
|
+
| `tooFewArguments` | Fewer than 2 arguments passed |
|
|
112
|
+
| `tooManyArguments` | More than 4 arguments passed |
|
|
113
|
+
| `messageNotString` | First argument is a non-string literal |
|
|
114
|
+
| `correlationIdNotString` | correlationId argument is a non-string literal |
|
|
115
|
+
| `missingCorrelationId` | 2nd argument is an object or array — correlationId is missing |
|
|
116
|
+
| `optionsNotObject` | Options argument is a literal instead of an object |
|
|
117
|
+
| `optionsMissingType` | Options object does not contain a `type` property |
|
|
118
|
+
| `optionsTypeNotString` | Options `type` property is a non-string literal |
|
|
244
119
|
|
|
245
120
|
## License
|
|
246
121
|
|
package/index.js
CHANGED
|
@@ -3,49 +3,39 @@ const MIN_ARGS = 2;
|
|
|
3
3
|
const THREE_ARGS = 3;
|
|
4
4
|
const MAX_ARGS = 4;
|
|
5
5
|
|
|
6
|
-
/**
|
|
7
|
-
* Check whether an AST node is a non-string literal (number, boolean, null).
|
|
8
|
-
* @param {Object} node - The AST node to check.
|
|
9
|
-
* @returns {boolean} True when the node is a literal whose value is not a string.
|
|
10
|
-
*/
|
|
6
|
+
/** @private True when node is a literal whose value is not a string. */
|
|
11
7
|
const isNonStringLiteral = node => node.type === 'Literal' && typeof node.value !== 'string';
|
|
12
8
|
|
|
13
|
-
/**
|
|
14
|
-
* Check whether an AST node is an object expression.
|
|
15
|
-
* @param {Object} node - The AST node to check.
|
|
16
|
-
* @returns {boolean} True when the node is an ObjectExpression.
|
|
17
|
-
*/
|
|
9
|
+
/** @private True when node is an ObjectExpression. */
|
|
18
10
|
const isObjectNode = node => node.type === 'ObjectExpression';
|
|
19
11
|
|
|
20
|
-
/**
|
|
21
|
-
* Check whether a property node has the key `type` (identifier or string literal).
|
|
22
|
-
* @param {Object} prop - The property node.
|
|
23
|
-
* @returns {boolean} True when the key is `type`.
|
|
24
|
-
*/
|
|
12
|
+
/** @private True when the property key is `type` (identifier or string literal). */
|
|
25
13
|
const isTypeKey = prop => prop.type === 'Property'
|
|
26
14
|
&& !prop.computed
|
|
27
15
|
&& ((prop.key.type === 'Identifier' && prop.key.name === 'type')
|
|
28
16
|
|| (prop.key.type === 'Literal' && prop.key.value === 'type'));
|
|
29
17
|
|
|
30
|
-
/**
|
|
31
|
-
* Find the `type` property node inside an ObjectExpression.
|
|
32
|
-
* Handles both identifier keys (`{ type: ... }`) and string-literal keys (`{ "type": ... }`).
|
|
33
|
-
* @param {Object} node - The object expression node.
|
|
34
|
-
* @returns {Object|undefined} The property node, or undefined if not found.
|
|
35
|
-
*/
|
|
18
|
+
/** @private Find the `type` property inside an ObjectExpression. */
|
|
36
19
|
const findTypeProperty = node => node.properties.find(isTypeKey);
|
|
37
20
|
|
|
38
21
|
/**
|
|
39
22
|
* Validate the options argument of a logger call.
|
|
40
|
-
* Reports
|
|
41
|
-
* `type`
|
|
42
|
-
*
|
|
43
|
-
* @
|
|
44
|
-
* @param {Object} optionsArg - The options argument AST node.
|
|
45
|
-
* @param {string} level - The logger level (e.g. 'info', 'error').
|
|
23
|
+
* Reports when options is any literal (not an object), when the object is missing
|
|
24
|
+
* a `type` property, or when `type` is a non-string literal.
|
|
25
|
+
* Identifiers and other expressions are skipped (runtime type unknown).
|
|
26
|
+
* @private
|
|
46
27
|
*/
|
|
47
28
|
const validateOptions = (context, optionsArg, level) => {
|
|
48
|
-
if (!isObjectNode(optionsArg))
|
|
29
|
+
if (!isObjectNode(optionsArg)) {
|
|
30
|
+
if (optionsArg.type === 'Literal') {
|
|
31
|
+
context.report({
|
|
32
|
+
node: optionsArg,
|
|
33
|
+
messageId: 'optionsNotObject',
|
|
34
|
+
data: { level, actualType: typeof optionsArg.value },
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
49
39
|
const typeProp = findTypeProperty(optionsArg);
|
|
50
40
|
if (!typeProp) {
|
|
51
41
|
context.report({
|
|
@@ -65,12 +55,8 @@ const validateOptions = (context, optionsArg, level) => {
|
|
|
65
55
|
|
|
66
56
|
/**
|
|
67
57
|
* Resolve the log level from a MemberExpression callee.
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* For string literals the value must be a recognised level; variables are assumed
|
|
71
|
-
* to hold a valid level and the variable name is returned for error messages.
|
|
72
|
-
* @param {Object} callee - The MemberExpression callee node.
|
|
73
|
-
* @returns {string|null} The resolved level name, or null when the call should be skipped.
|
|
58
|
+
* Returns the level name for dot/bracket notation, or null to skip.
|
|
59
|
+
* @private
|
|
74
60
|
*/
|
|
75
61
|
const resolveLevel = (callee) => {
|
|
76
62
|
if (!callee.computed) {
|
|
@@ -89,13 +75,9 @@ const resolveLevel = (callee) => {
|
|
|
89
75
|
};
|
|
90
76
|
|
|
91
77
|
/**
|
|
92
|
-
*
|
|
93
|
-
* Non-literal nodes
|
|
94
|
-
*
|
|
95
|
-
* @param {Object} context - The ESLint rule context.
|
|
96
|
-
* @param {Object} argNode - The argument AST node.
|
|
97
|
-
* @param {string} level - The logger level (e.g. 'info', 'error').
|
|
98
|
-
* @param {string} messageId - The ESLint message ID to report on failure.
|
|
78
|
+
* Report when a literal argument is not a string.
|
|
79
|
+
* Non-literal nodes are skipped (runtime type unknown).
|
|
80
|
+
* @private
|
|
99
81
|
*/
|
|
100
82
|
const validateStringArg = (context, argNode, level, messageId) => {
|
|
101
83
|
if (isNonStringLiteral(argNode)) {
|
|
@@ -108,10 +90,14 @@ const validateStringArg = (context, argNode, level, messageId) => {
|
|
|
108
90
|
};
|
|
109
91
|
|
|
110
92
|
/**
|
|
111
|
-
* ESLint plugin
|
|
112
|
-
*
|
|
93
|
+
* ESLint plugin that validates logger call argument signatures.
|
|
94
|
+
* Only tracks default imports (`import logger from '...'`).
|
|
113
95
|
*/
|
|
114
96
|
const plugin = {
|
|
97
|
+
meta: {
|
|
98
|
+
name: '@mimik/eslint-plugin-logger',
|
|
99
|
+
version: '2.0.8',
|
|
100
|
+
},
|
|
115
101
|
rules: {
|
|
116
102
|
'validate-logger-args': {
|
|
117
103
|
meta: {
|
|
@@ -126,7 +112,8 @@ const plugin = {
|
|
|
126
112
|
tooManyArguments: 'logger.{{ level }}() accepts at most 4 arguments: (message, meta, correlationId, options). Found {{ count }}.',
|
|
127
113
|
messageNotString: 'logger.{{ level }}() message (1st argument) must be a string. Found {{ actualType }}.',
|
|
128
114
|
correlationIdNotString: 'logger.{{ level }}() correlationId must be a string. Found {{ actualType }}.',
|
|
129
|
-
missingCorrelationId: 'logger.{{ level }}()
|
|
115
|
+
missingCorrelationId: 'logger.{{ level }}() 2nd argument is an object or array — missing required correlationId. Expected (message, meta, correlationId).',
|
|
116
|
+
optionsNotObject: 'logger.{{ level }}() options argument must be an object. Found {{ actualType }}.',
|
|
130
117
|
optionsMissingType: 'logger.{{ level }}() options object must contain a "type" property.',
|
|
131
118
|
optionsTypeNotString: 'logger.{{ level }}() options "type" property must be a string.',
|
|
132
119
|
},
|
package/package.json
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mimik/eslint-plugin-logger",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "Validation of logger call parameters for mimik services",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"exports": "./index.js",
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": ">=24.0.0"
|
|
10
|
+
},
|
|
7
11
|
"scripts": {
|
|
8
|
-
"lint": "eslint . --no-error-on-unmatched-pattern",
|
|
9
12
|
"docs": "jsdoc2md --template docs/README.hbs index.js > README.md",
|
|
10
|
-
"
|
|
13
|
+
"lint": "eslint . --no-error-on-unmatched-pattern",
|
|
14
|
+
"test": "mocha --reporter mochawesome --bail --exit --check-leaks test/",
|
|
11
15
|
"test-ci": "c8 --reporter=lcov --reporter=text npm test",
|
|
12
16
|
"prepublishOnly": "npm run docs && npm run lint && npm run test-ci",
|
|
13
17
|
"commit-ready": "npm run docs && npm run lint && npm run test-ci"
|
|
@@ -17,22 +21,20 @@
|
|
|
17
21
|
"eslint",
|
|
18
22
|
"eslint-plugin",
|
|
19
23
|
"eslintplugin",
|
|
20
|
-
"logger"
|
|
24
|
+
"logger",
|
|
25
|
+
"@mimik/sumologic-winston-logger"
|
|
21
26
|
],
|
|
22
27
|
"author": "mimik technology inc <support@mimik.com> (https://developer.mimik.com/)",
|
|
23
28
|
"license": "MIT",
|
|
24
|
-
"engines": {
|
|
25
|
-
"node": ">=24"
|
|
26
|
-
},
|
|
27
29
|
"repository": {
|
|
28
30
|
"type": "git",
|
|
29
31
|
"url": "git+https://bitbucket.org/mimiktech/eslint-plugin-logger.git"
|
|
30
32
|
},
|
|
31
33
|
"devDependencies": {
|
|
32
|
-
"@eslint/js": "9.39.
|
|
34
|
+
"@eslint/js": "9.39.4",
|
|
33
35
|
"@stylistic/eslint-plugin": "5.10.0",
|
|
34
36
|
"c8": "11.0.0",
|
|
35
|
-
"eslint": "9.39.
|
|
37
|
+
"eslint": "9.39.4",
|
|
36
38
|
"eslint-plugin-import": "2.32.0",
|
|
37
39
|
"globals": "17.4.0",
|
|
38
40
|
"husky": "9.1.7",
|