Files
dss/packages/dss-rules/lib/index.js
DSS 44cea9443b
Some checks failed
DSS Project Analysis / dss-context-update (push) Has been cancelled
Revert "feat: Enterprise DSS architecture implementation"
This reverts commit 9dbd56271e.
2025-12-11 09:59:45 -03:00

199 lines
4.8 KiB
JavaScript

/**
* @dss/rules - Design System Rules Package
*
* Provides versioned rule definitions for enterprise design system enforcement.
* Pull-based distribution via npm for consistent rule versions across 60+ projects.
*/
const fs = require('fs');
const path = require('path');
// Rule categories
const CATEGORIES = ['colors', 'spacing', 'typography', 'components', 'accessibility'];
/**
* Load all rules from the rules directory
* @returns {Object} Rules organized by category
*/
function loadRules() {
const rules = {};
const rulesDir = path.join(__dirname, '..', 'rules');
for (const category of CATEGORIES) {
const rulePath = path.join(rulesDir, `${category}.json`);
if (fs.existsSync(rulePath)) {
try {
const content = fs.readFileSync(rulePath, 'utf-8');
rules[category] = JSON.parse(content);
} catch (error) {
console.error(`Failed to load rules for ${category}:`, error.message);
rules[category] = null;
}
}
}
return rules;
}
/**
* Get rules for a specific category
* @param {string} category - Rule category (colors, spacing, etc.)
* @returns {Object|null} Rule definitions or null if not found
*/
function getRulesByCategory(category) {
const rules = loadRules();
return rules[category] || null;
}
/**
* Get all rule IDs across all categories
* @returns {string[]} Array of rule IDs in format "category/rule-id"
*/
function getAllRuleIds() {
const rules = loadRules();
const ids = [];
for (const [category, ruleSet] of Object.entries(rules)) {
if (ruleSet && ruleSet.rules) {
for (const rule of ruleSet.rules) {
ids.push(`${category}/${rule.id}`);
}
}
}
return ids;
}
/**
* Get a specific rule by its full ID
* @param {string} ruleId - Full rule ID in format "category/rule-id"
* @returns {Object|null} Rule definition or null
*/
function getRule(ruleId) {
const [category, id] = ruleId.split('/');
const ruleSet = getRulesByCategory(category);
if (!ruleSet || !ruleSet.rules) return null;
return ruleSet.rules.find(r => r.id === id) || null;
}
/**
* Validate a value against rule patterns
* @param {string} ruleId - Full rule ID
* @param {string} value - Value to validate
* @returns {Object} Validation result {valid, violations}
*/
function validateValue(ruleId, value) {
const rule = getRule(ruleId);
if (!rule) {
return { valid: true, violations: [], error: `Rule not found: ${ruleId}` };
}
const violations = [];
// Check forbidden patterns
if (rule.patterns?.forbidden) {
for (const pattern of rule.patterns.forbidden) {
const regex = new RegExp(pattern, 'gi');
const matches = value.match(regex);
if (matches) {
violations.push({
rule: ruleId,
pattern,
matches,
severity: rule.severity || 'warning',
message: `Found forbidden pattern: ${matches.join(', ')}`
});
}
}
}
return {
valid: violations.length === 0,
violations
};
}
/**
* Get required tokens from all rule sets
* @returns {Object} Required tokens organized by category
*/
function getRequiredTokens() {
const rules = loadRules();
const required = {};
for (const [category, ruleSet] of Object.entries(rules)) {
if (ruleSet?.tokens?.required) {
required[category] = ruleSet.tokens.required;
}
}
return required;
}
/**
* Get severity level for a rule
* @param {string} ruleId - Full rule ID
* @returns {string} Severity level (error, warning, info)
*/
function getRuleSeverity(ruleId) {
const rule = getRule(ruleId);
if (!rule) return 'warning';
// Rule-specific severity overrides category default
if (rule.severity) return rule.severity;
// Fall back to category default
const [category] = ruleId.split('/');
const ruleSet = getRulesByCategory(category);
return ruleSet?.severity || 'warning';
}
/**
* Get package version
* @returns {string} Package version
*/
function getVersion() {
const packagePath = path.join(__dirname, '..', 'package.json');
const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf-8'));
return pkg.version;
}
/**
* Export configuration for CI/CD integration
* @returns {Object} Configuration object for CI pipelines
*/
function getCIConfig() {
return {
version: getVersion(),
categories: CATEGORIES,
errorSeverities: ['error'],
warningSeverities: ['warning'],
blockingRules: getAllRuleIds().filter(id => getRuleSeverity(id) === 'error'),
advisoryRules: getAllRuleIds().filter(id => getRuleSeverity(id) !== 'error')
};
}
module.exports = {
// Rule loading
loadRules,
getRulesByCategory,
getAllRuleIds,
getRule,
// Validation
validateValue,
getRuleSeverity,
// Token helpers
getRequiredTokens,
// Metadata
getVersion,
getCIConfig,
// Constants
CATEGORIES
};