@sap/eslint-plugin-cds
Version:
ESLint plugin including recommended SAP Cloud Application Programming model and environment rules
70 lines (63 loc) • 2.27 kB
JavaScript
const { RULE_CATEGORIES } = require('../../constants')
// used as a pre-check to ensure the checks using RegExps
// with greedy matchers are not susceptible to ReDoS attacks
const MAX_INPUT_STRING_LENGTH = 1_000
/**
* @param {string} importPath
* @param {RuleContext} context
* @param {Node} node
*/
function compareImportAndFilename (importPath, context, node) {
const currentFile = context.getFilename()
// ignore stdin
if (currentFile === '<input>') return
// ignore excessively long strings
if (importPath.length > MAX_INPUT_STRING_LENGTH || currentFile.length > MAX_INPUT_STRING_LENGTH) return
const [, typerModuleFq, typerModule] = /^#cds-models\/.*?((\w+)Service)$/.exec(importPath) ?? []
const [, fileNameFq, fileName] = /((\w+)-?[sS]ervice\.m?[jt]s)$/.exec(currentFile)
// typerModule === undefined -> not a service import (probably db-level-entity import)
if (typerModule && fileName && typerModule !== fileName) {
context.report({
node,
messageId: 'noCrossServiceImport',
data: {
from: typerModuleFq,
target: fileNameFq
}
})
}
}
module.exports = {
meta: {
type: 'problem',
docs: {
recommended: true,
category: RULE_CATEGORIES.javascript,
description: 'Warn about imports from another service.'
},
schema: [],
messages: {
noCrossServiceImport: 'You are importing service-level entities from another service "{{from}}" inside the definition of service "{{target}}". This is likely an accidental cross-service import.',
},
hasSuggestions: false
},
create: context => ({
CallExpression(node) {
// look for: require('#cds-models/...')
if (node.callee.type !== 'Identifier') return
if (node.callee.name !== 'require') return
if (node.arguments.length !== 1) return
if (node.arguments[0].type !== 'Literal') return
compareImportAndFilename(node.arguments[0].value, context, node)
},
ImportDeclaration(node) {
// import ... from '#cds-models/...'
compareImportAndFilename(node.source.value, context, node)
},
ImportExpression(node) {
// await import('#cds-models/...')
compareImportAndFilename(node.source.value, context, node)
}
})
}