@sap/eslint-plugin-cds
Version:
ESLint plugin including recommended SAP Cloud Application Programming model and environment rules
78 lines (69 loc) • 2.06 kB
JavaScript
'use strict'
const cds = requireMtx()
const { dirname } = require('node:path')
const rule = module.exports = {
meta: {
docs: {
description: 'Extensions must not violate restrictions set by the extended SaaS app.',
category: 'Model Validation',
recommended: true,
url: 'https://cap.cloud.sap/docs/tools/cds-lint/rules/extension-restrictions',
},
hasSuggestions: false,
type: 'problem',
model: 'parsed'
},
mtxApi: () => {
if (!cds) return // no mtxs lib installed
if (!cds.xt?.linter) return // too old mtxs
return cds.xt.linter
},
create (context) {
if (!rule.mtxApi()) return // no mtxs lib installed
return () => {
const extModel = context.getModel()
if (!extModel) return
const base = baseModel(context)
if (!base) return
const file = context.getFilename()
const findings = rule.mtxApi().lint(extModel, base.model, base.env)
for (const finding of findings) {
context.report({
message: finding.message,
node: context.getNode(finding.element),
file
})
}
}
}
}
/**
* @param {CDSRuleContext} context
*/
function baseModel (context) {
let dir = context.getFilename()
do {
dir = dirname(dir)
const projEnv = cds.env.for('cds', dir)
if (!projEnv.extends) continue
const files = cds.resolve(projEnv.extends, { root: dir }) // resolve local base model
if (files?.length) {
const model = cds.load(files, { sync: true })
// env of SaaS app is needed for extension rules
const env = cds.env.for('cds', dirname(files[0]))
return { env, model }
}
} while (dir && dir !== cds.root && dir.length > 1)
}
/** @returns { import('@sap/cds/apis/cds') } */
function requireMtx () {
const cds = require('@sap/cds')
try {
// eslint-disable-next-line
const pkg = require.resolve('@sap/cds-mtxs', { paths: [cds.root, __dirname] })
return require(pkg)
} catch (e) {
if (e.code !== 'MODULE_NOT_FOUND')
throw e
}
}