@bernierllc/publishing-rules
v1.0.5
Published
Publishing rule engine with conditional logic and platform-specific configurations
Readme
@bernierllc/publishing-rules
Publishing rule engine with conditional logic and platform-specific configurations for content management systems.
Installation
npm install @bernierllc/publishing-rulesUsage
Basic Setup
import { createRulesEngine, commonRules, ConditionType, ActionType } from '@bernierllc/publishing-rules';
// Create a rules engine
const engine = createRulesEngine({
maxRules: 100,
timeout: 5000,
continueOnError: true,
enableLogging: true
});
// Add a common rule
const businessHoursRule = commonRules.businessHours('09:00', '17:00');
engine.addRule(businessHoursRule);
// Evaluate content against rules
const context = {
content: {
id: 'post-123',
type: 'blog-post',
title: 'My Blog Post',
content: 'This is the content of my blog post...',
author: 'john-doe',
status: 'approved',
tags: ['tech', 'javascript'],
createdAt: new Date()
},
user: {
id: 'user-456',
roles: ['editor'],
permissions: ['publish']
}
};
const result = await engine.evaluateRules(context);
if (result.shouldProceed) {
console.log('Content can be published');
console.log('Actions to take:', result.actions);
} else {
console.log('Content publishing blocked');
console.log('Errors:', result.errors);
}Custom Rules
import { ConditionType, ConditionOperator, ActionType } from '@bernierllc/publishing-rules';
// Create a custom rule
const customRule = {
id: 'weekend-hold',
name: 'Weekend Publishing Hold',
description: 'Hold content publishing during weekends',
enabled: true,
priority: 300,
conditions: [
{
type: ConditionType.DAY_OF_WEEK,
field: 'current-time',
operator: ConditionOperator.IN,
value: [0, 6] // Sunday and Saturday
}
],
actions: [
{
type: ActionType.HOLD,
parameters: {
reason: 'Weekend publishing policy',
resumeOn: 'next-business-day'
}
},
{
type: ActionType.NOTIFY,
parameters: {
recipients: ['[email protected]'],
subject: 'Content held for weekend policy',
message: 'Content will be published on the next business day'
}
}
],
createdAt: new Date(),
updatedAt: new Date()
};
engine.addRule(customRule);Rule Templates
import { RuleTemplateLibrary, getBuiltinTemplates, createRuleFromTemplate } from '@bernierllc/publishing-rules';
// Use built-in templates
const templates = getBuiltinTemplates();
const approvalTemplate = templates.find(t => t.id === 'content-approval-required');
if (approvalTemplate) {
const approvalRule = createRuleFromTemplate(
approvalTemplate,
'my-approval-rule',
{
requiredStatus: 'approved',
notificationEmail: '[email protected]'
}
);
engine.addRule(approvalRule);
}
// Create custom template library
const library = new RuleTemplateLibrary();
const customTemplate = {
id: 'tag-based-scheduling',
name: 'Tag-Based Scheduling',
description: 'Schedule content based on tags',
category: 'SCHEDULING_RULES',
parameters: [
{
name: 'requiredTag',
type: 'string',
description: 'Tag that triggers scheduling',
required: true
},
{
name: 'scheduleDelay',
type: 'number',
description: 'Hours to delay publishing',
required: false,
defaultValue: 24
}
],
conditions: [
{
type: ConditionType.TAG_EXISTS,
field: 'tags',
operator: ConditionOperator.CONTAINS,
value: '{{requiredTag}}'
}
],
actions: [
{
type: ActionType.SCHEDULE,
parameters: {
delay: '{{scheduleDelay}}h'
}
}
],
examples: []
};
library.registerTemplate(customTemplate);Common Rules
The package provides several built-in common rules:
// Business hours only
const businessRule = commonRules.businessHours('08:00', '18:00');
// Content approval required
const approvalRule = commonRules.approvalRequired();
// Weekend delay
const weekendRule = commonRules.weekendDelay('09:00');
// Content length validation
const lengthRule = commonRules.contentLengthValidation(100, 5000);
// Rate limiting
const rateLimitRule = commonRules.rateLimit(10); // max 10 posts per hour
// Emergency stop
const emergencyRule = commonRules.emergencyStop(['[email protected]']);Advanced Features
Custom Condition Evaluators
const customRule = {
id: 'advanced-rule',
name: 'Advanced Rule',
description: 'Rule with custom evaluator',
enabled: true,
priority: 100,
conditions: [
{
type: ConditionType.CUSTOM_FIELD,
field: 'metadata.sentiment',
operator: ConditionOperator.EQUALS,
value: 'positive',
customEvaluator: async (context, condition) => {
// Custom sentiment analysis logic
const sentiment = await analyzeSentiment(context.content.content);
return {
passed: sentiment.score > 0.7,
details: `Sentiment score: ${sentiment.score}`
};
}
}
],
actions: [
{
type: ActionType.PUBLISH,
parameters: {}
}
],
createdAt: new Date(),
updatedAt: new Date()
};Event Handling
engine.on('rule-evaluated', (event) => {
console.log(`Rule ${event.ruleId} evaluated:`, event.result);
});
engine.on('action-executed', (event) => {
console.log(`Action ${event.actionType} executed:`, event.result);
});
engine.on('error', (event) => {
console.error('Rule engine error:', event.error);
});Statistics and Monitoring
// Get engine statistics
const stats = engine.getStatistics();
console.log('Total evaluations:', stats.totalEvaluations);
console.log('Rule executions:', stats.ruleExecutions);
console.log('Average evaluation time:', stats.averageEvaluationTime);
// Reset statistics
engine.resetStatistics();API Reference
PublishingRulesEngine
Main rule engine class for managing and evaluating publishing rules.
Constructor
new PublishingRulesEngine(config?: RuleEngineConfig)
Methods
addRule(rule: PublishingRule): voidremoveRule(id: string): booleanupdateRule(id: string, updates: Partial<PublishingRule>): PublishingRule | nullgetRule(id: string): PublishingRule | undefinedgetRules(): PublishingRule[]enableRule(id: string): voiddisableRule(id: string): voidclearAllRules(): voidevaluateRules(context: RuleEvaluationContext): Promise<RuleEvaluationResult>getStatistics(): RuleEngineStatisticsresetStatistics(): void
RuleTemplateLibrary
Template system for creating reusable rule patterns.
Methods
registerTemplate(template: RuleTemplate): voidgetTemplate(id: string): RuleTemplate | undefinedlistTemplates(): RuleTemplate[]getTemplatesByCategory(category: RuleCategory): RuleTemplate[]removeTemplate(id: string): booleanvalidateTemplate(template: RuleTemplate): string[]
Common Functions
createRulesEngine(config?: Partial<RuleEngineConfig>): PublishingRulesEnginegetBuiltinTemplates(): RuleTemplate[]createRuleFromTemplate(template: RuleTemplate, ruleId: string, parameters: Record<string, any>): PublishingRule
Configuration
interface RuleEngineConfig {
maxRules: number; // Maximum number of rules (default: 100)
timeout: number; // Rule evaluation timeout in ms (default: 5000)
continueOnError: boolean; // Continue evaluation on rule errors (default: true)
enableCaching: boolean; // Enable result caching (default: true)
cacheTTL: number; // Cache TTL in ms (default: 300000)
enableLogging: boolean; // Enable logging (default: true)
logLevel: LogLevel; // Log level (default: INFO)
parallelEvaluation: boolean; // Evaluate rules in parallel (default: true)
maxConcurrency: number; // Max parallel evaluations (default: 10)
}Condition Types
CONTENT_TYPE- Match content typeCONTENT_LENGTH- Validate content lengthWORD_COUNT- Validate word countTAG_EXISTS- Check for specific tagsTITLE_MATCHES- Match title patternsAUTHOR_IS- Match content authorCATEGORY_IS- Match content categorySTATUS_IS- Match content statusTIME_OF_DAY- Time-based conditionsDAY_OF_WEEK- Day-based conditionsDATE_RANGE- Date range conditionsCUSTOM_FIELD- Custom field evaluationUSER_ROLE- User role checksUSER_PERMISSION- User permission checksRATE_LIMIT- Publishing rate limits
Action Types
PUBLISH- Proceed with publishingHOLD- Hold content for reviewSCHEDULE- Schedule for later publishingNOTIFY- Send notificationsREJECT- Reject contentREQUIRE_APPROVAL- Require additional approvalADD_TAG- Add tags to contentREMOVE_TAG- Remove tags from contentUPDATE_METADATA- Update content metadata
Error Handling
try {
const result = await engine.evaluateRules(context);
if (result.errors.length > 0) {
console.warn('Rule evaluation warnings:', result.errors);
}
} catch (error) {
console.error('Rule engine failed:', error);
// Handle critical failure
}License
Copyright (c) 2025 Bernier LLC. All rights reserved.
