UNPKG

bpmnlint

Version:

Validate your BPMN diagrams based on configurable lint rules

172 lines (122 loc) 3.93 kB
const path = require('path'); const { isString } = require('min-dash'); const Linter = require('../linter'); const NodeResolver = require('../resolver/node-resolver'); /** * Compile the bpmnlint configuration to a JavaScript file that exports * a { config, resolver } bundle, resolving all enabled rules. * * @param {Object} config the parsed bpmnlint configuration * @param {NodeResolver} [resolver] * @return {Promise<String>} the configuration compiled to a JS file */ async function compileConfig(config, resolver) { resolver = resolver || new NodeResolver(); const linter = new Linter({ resolver }); const resolvedRules = await linter.resolveConfiguredRules(config); // only process and serialize enabled rules const rules = Object.keys(resolvedRules).reduce(function(rules, key) { const value = resolvedRules[key]; const { category } = linter.parseRuleValue(value); if (category === 'off') { rules[key] = 0; } else { rules[key] = value; } return rules; }, {}); const serializedRules = JSON.stringify(rules, null, ' '); const preambleCode = ` const cache = {}; /** * A resolver that caches rules and configuration as part of the bundle, * making them accessible in the browser. * * @param {Object} cache */ function Resolver() {} Resolver.prototype.resolveRule = function(pkg, ruleName) { const rule = cache[pkg + '/' + ruleName]; if (!rule) { throw new Error('cannot resolve rule <' + pkg + '/' + ruleName + '>: not bundled'); } return rule; }; Resolver.prototype.resolveConfig = function(pkg, configName) { throw new Error( 'cannot resolve config <' + configName + '> in <' + pkg +'>: not bundled' ); }; const resolver = new Resolver(); const rules = ${serializedRules}; const config = { rules: rules }; const bundle = { resolver: resolver, config: config }; export { resolver, config }; export default bundle; `; const importCode = Object.entries(rules).map(([ key, value ], idx) => { if (!value) { return null; } const { pkg, ruleName } = linter.parseRuleName(key); return createImportStatement(pkg, ruleName, idx, resolver); }).filter(e => e).join('\n'); return `${preambleCode}${importCode}`; } module.exports = compileConfig; function requirePkg(resolver, pkg) { try { return resolver.require(pkg); } catch (err) { return null; } } function createImportStatement(pkg, ruleName, idx, resolver) { const originalPkg = pkg; pkg = resolver.normalizePkg(pkg); const pkgExport = requirePkg(resolver, pkg); // (1) try resolving rule via $PKG.rules[$NAME] if (pkgExport && pkgExport.rules) { const rules = pkgExport.rules; if (ruleName in rules) { const rule = rules[ruleName]; if (!isString(rule)) { throw new Error( `failed to bundle rule <${ruleName}> from <${ pkg }>: illegal rule export (expected path reference)` ); } const rulePath = computeRuleImport(resolver, pkg, originalPkg, rule); return ` import rule_${ idx } from '${rulePath}'; cache['${ originalPkg }/${ ruleName }'] = rule_${ idx };`; } } // (2) resolve rule via $PKG/rules/$NAME return ` import rule_${ idx } from '${ pkg }/rules/${ ruleName }'; cache['${ originalPkg }/${ ruleName }'] = rule_${ idx };`; } function computeRuleImport(resolver, pkg, originalPkg, rule) { // local reference, resolved relative to pkg location if (rule.startsWith('.')) { const pkgJsonPath = resolver.require.resolve(`${ pkg }/package.json`); const pkgMainPath = resolver.require.resolve(pkg); const relativePkgMainPath = path.relative( path.dirname(pkgJsonPath), path.dirname(pkgMainPath) ); return path.posix.normalize(`${ originalPkg }/${ relativePkgMainPath }/${ rule }`); } else { // absolute reference return path.posix.normalize(rule); } }