@dawans/promptshield
Version:
Secure your LLM stack with enterprise-grade RulePacks for AI safety scanning
156 lines (155 loc) • 4.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RulePack = void 0;
const Rule_1 = require("./Rule");
/**
* Represents a collection of rules
*/
class RulePack {
constructor(name, description, rules, version = '1.0.0', lastUpdated = new Date()) {
this.name = name;
this.description = description;
this.rules = rules;
this.version = version;
this.lastUpdated = lastUpdated;
this.validate();
}
/**
* Validates the rulepack configuration
*/
validate() {
if (!this.name || this.name.trim() === '') {
throw new Error('RulePack name is required');
}
if (!this.description || this.description.trim() === '') {
throw new Error('RulePack description is required');
}
if (this.rules.length === 0) {
throw new Error('RulePack must have at least one rule');
}
// Check for duplicate rule IDs
const ruleIds = new Set();
this.rules.forEach((rule) => {
if (ruleIds.has(rule.id)) {
throw new Error(`Duplicate rule ID: ${rule.id}`);
}
ruleIds.add(rule.id);
});
}
/**
* Gets enabled rules only
*/
getEnabledRules() {
return this.rules.filter((rule) => rule.enabled);
}
/**
* Gets rules by category
*/
getRulesByCategory(category) {
return this.rules.filter((rule) => rule.category === category);
}
/**
* Gets rules by severity
*/
getRulesBySeverity(severity) {
return this.rules.filter((rule) => rule.severity === severity);
}
/**
* Gets rules by multiple categories
*/
getRulesByCategories(categories) {
if (categories.length === 0)
return this.rules;
return this.rules.filter((rule) => categories.includes(rule.category));
}
/**
* Gets rules by multiple severities
*/
getRulesBySeverities(severities) {
if (severities.length === 0)
return this.rules;
return this.rules.filter((rule) => severities.includes(rule.severity));
}
/**
* Finds a rule by ID
*/
findRuleById(id) {
return this.rules.find((rule) => rule.id === id);
}
/**
* Gets all categories present in this rulepack
*/
getCategories() {
const categories = new Set(this.rules.map((rule) => rule.category));
return Array.from(categories);
}
/**
* Gets all severities present in this rulepack
*/
getSeverities() {
const severities = new Set(this.rules.map((rule) => rule.severity));
return Array.from(severities);
}
/**
* Gets rule count by category
*/
getRuleCountByCategory() {
const counts = {};
this.rules.forEach((rule) => {
counts[rule.category] = (counts[rule.category] || 0) + 1;
});
return counts;
}
/**
* Gets rule count by severity
*/
getRuleCountBySeverity() {
const counts = {};
this.rules.forEach((rule) => {
counts[rule.severity] = (counts[rule.severity] || 0) + 1;
});
return counts;
}
/**
* Creates a rulepack from YAML data
*/
static fromYaml(data) {
// Type guard to ensure data has required properties
if (!data || typeof data !== 'object') {
throw new Error('Invalid rulepack data: must be an object');
}
const rulePackData = data;
if (typeof rulePackData.name !== 'string') {
throw new Error('Invalid rulepack data: name must be a string');
}
if (typeof rulePackData.description !== 'string') {
throw new Error('Invalid rulepack data: description must be a string');
}
if (!Array.isArray(rulePackData.rules)) {
throw new Error('Invalid rulepack data: rules must be an array');
}
const rules = rulePackData.rules.map((ruleData) => Rule_1.Rule.fromYaml(ruleData));
return new RulePack(rulePackData.name, rulePackData.description, rules, typeof rulePackData.version === 'string' ? rulePackData.version : '1.0.0', typeof rulePackData.last_updated === 'string'
? new Date(rulePackData.last_updated)
: new Date());
}
/**
* Converts rulepack to YAML format
*/
toYaml() {
return {
version: this.version,
last_updated: this.lastUpdated.toISOString().split('T')[0],
name: this.name,
description: this.description,
rules: this.rules.map((rule) => rule.toYaml()),
};
}
/**
* Creates an empty rulepack
*/
static empty() {
return new RulePack('Empty RulePack', 'No rules defined', []);
}
}
exports.RulePack = RulePack;