Skip to content

Commit

Permalink
Merge branch 'master' of github.com:SUI-Components/sui into typescrip…
Browse files Browse the repository at this point in the history
…t-support
  • Loading branch information
kikoruiz committed May 6, 2024
2 parents b35b308 + f309b08 commit 7952850
Show file tree
Hide file tree
Showing 14 changed files with 521 additions and 58 deletions.
11 changes: 11 additions & 0 deletions packages/eslint-plugin-sui/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# CHANGELOG

# 1.4.0 (2024-04-30)


### Features

* add basic decorators rules for UseCases ([86ef4a2](https://github.com/SUI-Components/sui/commit/86ef4a25ee642b6a1fe2cdb134958a342f13edcf))
* Add rule to mark any uso off commonjs syntax in our code ([f210c46](https://github.com/SUI-Components/sui/commit/f210c46717117b4132a3586a2e2fe2548a4a51d2))
* Allow require from ESM module ([ea666e0](https://github.com/SUI-Components/sui/commit/ea666e0495246e15d209aac2a8ad1acc477430a1))



# 1.3.0 (2024-03-21)


Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin-sui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "eslint-plugin-sui",
"version": "1.3.0",
"version": "1.4.0",
"access": "public",
"description": "Set of sui lint rules",
"keywords": [
Expand Down
6 changes: 5 additions & 1 deletion packages/eslint-plugin-sui/src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
const FactoryPattern = require('./rules/factory-pattern.js')
const SerializeDeserialize = require('./rules/serialize-deserialize.js')
const CommonJS = require('./rules/commonjs.js')
const Decorators = require('./rules/decorators.js')

// ------------------------------------------------------------------------------
// Plugin Definition
Expand All @@ -9,6 +11,8 @@ const SerializeDeserialize = require('./rules/serialize-deserialize.js')
module.exports = {
rules: {
'factory-pattern': FactoryPattern,
'serialize-deserialize': SerializeDeserialize
'serialize-deserialize': SerializeDeserialize,
commonjs: CommonJS,
decorators: Decorators
}
}
118 changes: 118 additions & 0 deletions packages/eslint-plugin-sui/src/rules/commonjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/**
* @fileoverview Ensure your code is not using CommonJS signatures like module.exports or moduel.exports.foo or require() or require.resolve()
*/
'use strict'

const dedent = require('string-dedent')

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
meta: {
type: 'problem',
docs: {
description: 'Ensure that your code is using ems over commonjs modules',
recommended: true,
url: 'https://github.mpi-internal.com/scmspain/es-td-agreements/blob/master/30-Frontend/00-agreements'
},
fixable: null,
schema: [],
messages: {
forbiddenExports: dedent`
Use module.* should be avoid.
`,
forbiddenRequires: dedent`
Use require function should be avoid.
`,
forbiddenModuleRequire: dedent`
Use module.require function should be avoid.
`,
forbiddenRequiresObjects: dedent`
Use require.cache or require.extensions or require.main should be avoid.
`,
forbiddenRequireResolve: dedent`
Use require.resolve function should be avoid.
`,
forbidden__filename: dedent`
__filename should be avoid
`,
forbidden__dirname: dedent`
__dirname should be avoid
`
}
},
create: function (context) {
return {
CallExpression(node) {
const isRequire = node.callee?.name === 'require'
const isResolve = node.callee?.object?.name === 'require' && node.callee?.property?.name === 'resolve'
const isModule = node.callee?.object?.name === 'module' && node.callee?.property?.name === 'require'

const isRequireFormCreateRequire = node.parent?.parent?.body
?.filter(node => node.type === 'ImportDeclaration')
?.some(
node =>
node.source?.value === 'module' && node.specifiers?.some(spec => spec.imported?.name === 'createRequire')
)

isRequire &&
!isRequireFormCreateRequire &&
context.report({
node,
messageId: 'forbiddenRequires'
})

isResolve &&
context.report({
node,
messageId: 'forbiddenRequireResolve'
})

isModule &&
context.report({
node,
messageId: 'forbiddenModuleRequire'
})
},
MemberExpression(node) {
const isModule =
node.object?.name === 'module' &&
['children', 'exports', 'filename', 'id', 'isPreloading', 'loaded', 'parent', 'path', 'paths'].some(
property => node.property?.name === property
)

const isRequire =
node.object?.name === 'require' &&
['cache', 'extensions', 'main'].some(property => node.property?.name === property)

isModule &&
context.report({
node,
messageId: 'forbiddenExports'
})

isRequire &&
context.report({
node,
messageId: 'forbiddenRequiresObjects'
})
},
Identifier(node) {
node.name === '__filename' &&
context.report({
node,
messageId: 'forbidden__filename'
})

node.name === '__dirname' &&
context.report({
node,
messageId: 'forbidden__dirname'
})
}
}
}
}
86 changes: 86 additions & 0 deletions packages/eslint-plugin-sui/src/rules/decorators.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/**
* @fileoverview Ensure that at least all your UseCases are using @inlineError and @tracer decorator from sui
*/
'use strict'

const dedent = require('string-dedent')

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
meta: {
type: 'problem',
docs: {
description: 'Ensure that at least all your UseCases are using @inlineError and @tracer decorator from sui',
recommended: true,
url: 'https://github.mpi-internal.com/scmspain/es-td-agreements/blob/master/30-Frontend/00-agreements'
},
fixable: 'code',
schema: [],
messages: {
missingInlineError: dedent`
All our UseCases must have an @inlineError decorator.
`,
missingTracer: dedent`
All our UseCases must have a @tracer() decorator.
`,
tracerMissCall: dedent`
Your tracer decorator should be call always with the name of your class
`,
inlineErrorMissplace: dedent`
the inlineError decorator should be always the first
`
}
},
create: function (context) {
return {
MethodDefinition(node) {
const className = node.parent?.parent?.id?.name
const shouldExtendFromUseCase = node.parent?.parent?.superClass?.name === 'UseCase'
const isExecute = node.key?.name === 'execute' && shouldExtendFromUseCase
const hasInlineError = node.decorators?.some(node => node.expression?.name === 'inlineError')
const tracerNode = node.decorators?.find(node => node.expression?.callee?.name === 'tracer')
const isTracerCalledWithClassName =
tracerNode?.expression?.callee?.name === 'tracer' &&
className + '#' + node.key?.name === tracerNode?.expression?.arguments[0]?.properties[0]?.value?.value &&
tracerNode?.expression?.arguments[0]?.properties[0]?.key?.name === 'metric'
const isInlineErrorTheFirst = node.decorators?.at(-1)?.expression?.name === 'inlineError'

isExecute &&
!hasInlineError &&
context.report({
node: node.key,
messageId: 'missingInlineError'
})

isExecute &&
hasInlineError &&
!isInlineErrorTheFirst &&
context.report({
node: node.key,
messageId: 'inlineErrorMissplace'
})

isExecute &&
!tracerNode &&
context.report({
node: node.key,
messageId: 'missingTracer'
})

tracerNode &&
!isTracerCalledWithClassName &&
context.report({
node: tracerNode,
messageId: 'tracerMissCall',
fix(fixer) {
return fixer.replaceText(tracerNode.expression, `tracer({metric: '${className}#${node.key?.name}'})`)
}
})
}
}
}
}
46 changes: 0 additions & 46 deletions packages/eslint-plugin-sui/src/rules/forbidden-require.js

This file was deleted.

Loading

0 comments on commit 7952850

Please sign in to comment.