@diia-inhouse/oxc-config 6.0.0 → 6.1.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../oxlint/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAsC,MAAM,QAAQ,CAAA;AAE9E,KAAK,MAAM,GAAG,YAAY,GAAG;IAAE,cAAc,EAAE,MAAM,EAAE,CAAA;CAAE,CAAA;AAujBzD,eAAO,MAAM,IAAI,EAAE,MAAuC,CAAA;AAE1D,eAAO,MAAM,UAAU,EAAE,MAKvB,CAAA;AAIF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY,GAAI,QAAQ,YAAY,KAAG,YAOnD,CAAA"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../oxlint/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAsC,MAAM,QAAQ,CAAA;AAE9E,KAAK,MAAM,GAAG,YAAY,GAAG;IAAE,cAAc,EAAE,MAAM,EAAE,CAAA;CAAE,CAAA;AAsjBzD,eAAO,MAAM,IAAI,EAAE,MAAuC,CAAA;AAE1D,eAAO,MAAM,UAAU,EAAE,MAKvB,CAAA;AAIF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY,GAAI,QAAQ,YAAY,KAAG,YAOnD,CAAA"}
@@ -9,7 +9,6 @@ const baseConfig = {
9
9
  resolve('eslint-plugin-security'),
10
10
  resolve('eslint-plugin-regexp'),
11
11
  { name: '@stylistic/js', specifier: resolve('@stylistic/eslint-plugin') },
12
- resolve('@diia-inhouse/eslint-plugin'),
13
12
  { name: '@diia-inhouse/package', specifier: resolveFile('./plugins/packageCheck.mjs') },
14
13
  { name: '@diia-inhouse/locale', specifier: resolveFile('./plugins/noHardcodedCyrillic.mjs') },
15
14
  { name: '@diia-inhouse/test', specifier: resolveFile('./plugins/testConventions.mjs') },
@@ -188,7 +187,6 @@ const baseConfig = {
188
187
  'security/detect-object-injection': 'off',
189
188
  'security/detect-non-literal-fs-filename': 'error',
190
189
  'security/detect-non-literal-regexp': 'error',
191
- '@diia-inhouse/logger-err-field': 'error',
192
190
  '@diia-inhouse/package/no-service-in-package-name': 'error',
193
191
  '@diia-inhouse/package/pinned-dependencies': 'error',
194
192
  '@diia-inhouse/package/unique-dependencies': 'error',
@@ -215,6 +213,7 @@ const baseConfig = {
215
213
  '@diia-inhouse/code/prefer-as-const-object': 'error',
216
214
  '@diia-inhouse/code/const-enum-naming': 'error',
217
215
  '@diia-inhouse/code/const-enum-type-name': 'error',
216
+ '@diia-inhouse/code/logger-err-field': 'error',
218
217
  '@diia-inhouse/mongoose/status-requires-history': 'error',
219
218
  // Context-specific rules — off by default, enable per service in oxlint.config.ts
220
219
  '@diia-inhouse/mongoose/schema-timestamps': 'off',
@@ -77,6 +77,83 @@ function isValidPlural(rawSingular, rawPlural) {
77
77
  return false
78
78
  }
79
79
 
80
+ const LOGGER_PROPERTY = 'logger'
81
+ const ERROR_FIELD = 'err'
82
+
83
+ function isNode(value) {
84
+ return value !== null && typeof value === 'object' && typeof value.type === 'string'
85
+ }
86
+
87
+ function collect(root, predicate) {
88
+ const found = []
89
+
90
+ const walk = (node) => {
91
+ if (predicate(node)) {
92
+ found.push(node)
93
+ }
94
+
95
+ for (const key of Object.keys(node)) {
96
+ if (key === 'parent') {
97
+ continue
98
+ }
99
+
100
+ const value = node[key]
101
+
102
+ if (Array.isArray(value)) {
103
+ for (const child of value) {
104
+ if (isNode(child)) {
105
+ walk(child)
106
+ }
107
+ }
108
+ } else if (isNode(value)) {
109
+ walk(value)
110
+ }
111
+ }
112
+ }
113
+
114
+ walk(root)
115
+
116
+ return found
117
+ }
118
+
119
+ function isThisLogger(node) {
120
+ return (
121
+ node.type === 'MemberExpression' &&
122
+ node.object.type === 'ThisExpression' &&
123
+ node.property.type === 'Identifier' &&
124
+ node.property.name === LOGGER_PROPERTY
125
+ )
126
+ }
127
+
128
+ // this.logger.error(...) and chains such as this.logger.child(...).warn(...)
129
+ function isLoggerCall(node) {
130
+ if (node.type !== 'CallExpression') {
131
+ return false
132
+ }
133
+
134
+ let callee = node.callee
135
+
136
+ while (callee.type === 'MemberExpression' || callee.type === 'CallExpression') {
137
+ if (isThisLogger(callee)) {
138
+ return true
139
+ }
140
+
141
+ callee = callee.type === 'MemberExpression' ? callee.object : callee.callee
142
+ }
143
+
144
+ return false
145
+ }
146
+
147
+ function isErrorUnderWrongField(node, errorName) {
148
+ return (
149
+ node.type === 'Property' &&
150
+ node.value.type === 'Identifier' &&
151
+ node.value.name === errorName &&
152
+ node.key.type === 'Identifier' &&
153
+ node.key.name !== ERROR_FIELD
154
+ )
155
+ }
156
+
80
157
  export default {
81
158
  meta: { name: '@diia-inhouse/oxlint-plugin-code' },
82
159
  rules: {
@@ -274,5 +351,47 @@ export default {
274
351
  }
275
352
  },
276
353
  },
354
+
355
+ 'logger-err-field': {
356
+ meta: {
357
+ type: 'problem',
358
+ messages: {
359
+ errField: 'Error must be logged only in the object with [err] field. For example: <{err: e}>',
360
+ },
361
+ },
362
+ create(context) {
363
+ return {
364
+ CatchClause(node) {
365
+ if (!node.param || node.param.type !== 'Identifier') {
366
+ return
367
+ }
368
+
369
+ const errorName = node.param.name
370
+ const report = (target) => context.report({ node: target, messageId: 'errField' })
371
+ const wrongFields = (root) => collect(root, (candidate) => isErrorUnderWrongField(candidate, errorName))
372
+
373
+ for (const call of collect(node.body, isLoggerCall)) {
374
+ for (const arg of call.arguments) {
375
+ if (arg.type === 'Identifier' && arg.name === errorName) {
376
+ report(arg)
377
+ } else if (arg.type === 'Identifier') {
378
+ const declarators = collect(
379
+ node.body,
380
+ (candidate) =>
381
+ candidate.type === 'VariableDeclarator' &&
382
+ candidate.id.type === 'Identifier' &&
383
+ candidate.id.name === arg.name,
384
+ )
385
+
386
+ declarators.flatMap(wrongFields).forEach(report)
387
+ } else if (arg.type === 'ObjectExpression') {
388
+ wrongFields(arg).forEach(report)
389
+ }
390
+ }
391
+ }
392
+ },
393
+ }
394
+ },
395
+ },
277
396
  },
278
397
  }
@@ -13,6 +13,7 @@ const LEGACY_PACKAGES = [
13
13
  'eslint-config-prettier',
14
14
  'eslint-plugin-prettier',
15
15
  '@diia-inhouse/eslint-config',
16
+ '@diia-inhouse/eslint-plugin',
16
17
  'prettier',
17
18
  'prettier-plugin-sort-imports',
18
19
  '@ianvs/prettier-plugin-sort-imports',
@@ -77,6 +77,83 @@ function isValidPlural(rawSingular, rawPlural) {
77
77
  return false
78
78
  }
79
79
 
80
+ const LOGGER_PROPERTY = 'logger'
81
+ const ERROR_FIELD = 'err'
82
+
83
+ function isNode(value) {
84
+ return value !== null && typeof value === 'object' && typeof value.type === 'string'
85
+ }
86
+
87
+ function collect(root, predicate) {
88
+ const found = []
89
+
90
+ const walk = (node) => {
91
+ if (predicate(node)) {
92
+ found.push(node)
93
+ }
94
+
95
+ for (const key of Object.keys(node)) {
96
+ if (key === 'parent') {
97
+ continue
98
+ }
99
+
100
+ const value = node[key]
101
+
102
+ if (Array.isArray(value)) {
103
+ for (const child of value) {
104
+ if (isNode(child)) {
105
+ walk(child)
106
+ }
107
+ }
108
+ } else if (isNode(value)) {
109
+ walk(value)
110
+ }
111
+ }
112
+ }
113
+
114
+ walk(root)
115
+
116
+ return found
117
+ }
118
+
119
+ function isThisLogger(node) {
120
+ return (
121
+ node.type === 'MemberExpression' &&
122
+ node.object.type === 'ThisExpression' &&
123
+ node.property.type === 'Identifier' &&
124
+ node.property.name === LOGGER_PROPERTY
125
+ )
126
+ }
127
+
128
+ // this.logger.error(...) and chains such as this.logger.child(...).warn(...)
129
+ function isLoggerCall(node) {
130
+ if (node.type !== 'CallExpression') {
131
+ return false
132
+ }
133
+
134
+ let callee = node.callee
135
+
136
+ while (callee.type === 'MemberExpression' || callee.type === 'CallExpression') {
137
+ if (isThisLogger(callee)) {
138
+ return true
139
+ }
140
+
141
+ callee = callee.type === 'MemberExpression' ? callee.object : callee.callee
142
+ }
143
+
144
+ return false
145
+ }
146
+
147
+ function isErrorUnderWrongField(node, errorName) {
148
+ return (
149
+ node.type === 'Property' &&
150
+ node.value.type === 'Identifier' &&
151
+ node.value.name === errorName &&
152
+ node.key.type === 'Identifier' &&
153
+ node.key.name !== ERROR_FIELD
154
+ )
155
+ }
156
+
80
157
  export default {
81
158
  meta: { name: '@diia-inhouse/oxlint-plugin-code' },
82
159
  rules: {
@@ -274,5 +351,47 @@ export default {
274
351
  }
275
352
  },
276
353
  },
354
+
355
+ 'logger-err-field': {
356
+ meta: {
357
+ type: 'problem',
358
+ messages: {
359
+ errField: 'Error must be logged only in the object with [err] field. For example: <{err: e}>',
360
+ },
361
+ },
362
+ create(context) {
363
+ return {
364
+ CatchClause(node) {
365
+ if (!node.param || node.param.type !== 'Identifier') {
366
+ return
367
+ }
368
+
369
+ const errorName = node.param.name
370
+ const report = (target) => context.report({ node: target, messageId: 'errField' })
371
+ const wrongFields = (root) => collect(root, (candidate) => isErrorUnderWrongField(candidate, errorName))
372
+
373
+ for (const call of collect(node.body, isLoggerCall)) {
374
+ for (const arg of call.arguments) {
375
+ if (arg.type === 'Identifier' && arg.name === errorName) {
376
+ report(arg)
377
+ } else if (arg.type === 'Identifier') {
378
+ const declarators = collect(
379
+ node.body,
380
+ (candidate) =>
381
+ candidate.type === 'VariableDeclarator' &&
382
+ candidate.id.type === 'Identifier' &&
383
+ candidate.id.name === arg.name,
384
+ )
385
+
386
+ declarators.flatMap(wrongFields).forEach(report)
387
+ } else if (arg.type === 'ObjectExpression') {
388
+ wrongFields(arg).forEach(report)
389
+ }
390
+ }
391
+ }
392
+ },
393
+ }
394
+ },
395
+ },
277
396
  },
278
397
  }
@@ -13,6 +13,7 @@ const LEGACY_PACKAGES = [
13
13
  'eslint-config-prettier',
14
14
  'eslint-plugin-prettier',
15
15
  '@diia-inhouse/eslint-config',
16
+ '@diia-inhouse/eslint-plugin',
16
17
  'prettier',
17
18
  'prettier-plugin-sort-imports',
18
19
  '@ianvs/prettier-plugin-sort-imports',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diia-inhouse/oxc-config",
3
- "version": "6.0.0",
3
+ "version": "6.1.0",
4
4
  "description": "OXC toolchain configs for Diia services: oxlint, oxfmt, oxc transformer",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "author": "diia-team",
@@ -30,7 +30,6 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "@boundaries/eslint-plugin": "7.2.1",
33
- "@diia-inhouse/eslint-plugin": "1.9.13",
34
33
  "@stylistic/eslint-plugin": "5.10.0",
35
34
  "eslint-import-resolver-oxc": "0.15.0",
36
35
  "eslint-plugin-regexp": "3.3.1",