@bernierllc/content-workflow-schedule-step
v1.2.2
Published
Scheduling workflow step for content publishing with immediate and scheduled execution support
Readme
@bernierllc/content-workflow-schedule-step
Scheduling workflow step for content publishing with immediate and scheduled execution support.
Features
- Immediate Publishing: Execute content publishing immediately
- Scheduled Publishing: Schedule content for future publishing
- Constraint Validation: Enforce minimum and maximum scheduling delays
- Multi-Platform Support: Schedule across multiple platforms
- Timezone Support: Handle timezone conversions
- Job Management: Cancel and reschedule jobs
Installation
npm install @bernierllc/content-workflow-schedule-stepUsage
Basic Setup
import { ScheduleStep } from '@bernierllc/content-workflow-schedule-step';
import { SchedulerService } from '@bernierllc/scheduler-service';
import { Logger } from '@bernierllc/logger';
// Initialize dependencies
const scheduler = new SchedulerService({
maxConcurrentJobs: 10,
defaultTimezone: 'UTC',
// ... other config
});
const logger = new Logger({ serviceName: 'workflow' });
// Create schedule step
const scheduleStep = new ScheduleStep(scheduler, logger);Immediate Publishing
import type { WorkflowStepConfig, WorkflowContext } from '@bernierllc/content-workflow-schedule-step';
const config: WorkflowStepConfig = {
id: 'schedule',
name: 'Schedule Step',
type: 'schedule',
scheduleConfig: {
allowImmediate: true
}
};
const context: WorkflowContext = {
content: {
id: 'article-123',
type: 'article',
title: 'My Article',
data: { body: 'Content here' }
},
variables: new Map(),
userId: 'user-123'
};
const result = await scheduleStep.execute(config, context);
if (result.success) {
console.log('Scheduled:', result.data);
// {
// scheduledFor: Date,
// jobId: 'job-123',
// immediate: true
// }
}Scheduled Publishing
const futureTime = new Date(Date.now() + 2 * 60 * 60 * 1000); // 2 hours from now
const config: WorkflowStepConfig = {
id: 'schedule',
name: 'Schedule Step',
type: 'schedule',
scheduleConfig: {
allowImmediate: false,
minDelayMinutes: 5,
maxDelayDays: 30,
timezone: 'America/New_York'
}
};
const context: WorkflowContext = {
content: {
id: 'article-123',
type: 'article',
data: { body: 'Content' }
},
variables: new Map([
['scheduledTime', futureTime],
['platforms', ['twitter', 'facebook']]
]),
userId: 'user-123'
};
const result = await scheduleStep.execute(config, context);
if (result.success) {
console.log('Scheduled for:', result.data?.scheduledFor);
console.log('Job ID:', result.data?.jobId);
console.log('Platforms:', result.data?.platforms);
}Multi-Platform Scheduling
const context: WorkflowContext = {
content: {
id: 'article-123',
type: 'article',
data: {}
},
variables: new Map([
['scheduledTime', new Date('2025-12-25T10:00:00Z')],
['platforms', ['twitter', 'facebook', 'linkedin']]
]),
userId: 'user-123'
};
const result = await scheduleStep.execute(config, context);
// Job will be created for all three platformsConfiguration Validation
const config: WorkflowStepConfig = {
id: 'schedule',
name: 'Schedule Step',
type: 'schedule',
scheduleConfig: {
minDelayMinutes: 30,
maxDelayDays: 7,
timezone: 'Europe/London'
}
};
const validation = scheduleStep.validate(config);
if (!validation.valid) {
console.error('Configuration errors:', validation.errors);
}Job Management
Cancel a Scheduled Job
const cancelled = await scheduleStep.cancelScheduledJob('job-123');
if (cancelled) {
console.log('Job cancelled successfully');
} else {
console.error('Failed to cancel job');
}Reschedule a Job
const newTime = new Date(Date.now() + 4 * 60 * 60 * 1000); // 4 hours from now
const result = await scheduleStep.rescheduleJob('job-123', newTime, {
minDelayMinutes: 5,
timezone: 'America/New_York'
});
if (result.success) {
console.log('New job ID:', result.data?.jobId);
console.log('New scheduled time:', result.data?.scheduledFor);
}API Reference
ScheduleStep
Main workflow step class for scheduling content.
Properties
id: string- Step identifier ('schedule-step')type: string- Step type ('schedule')
Methods
execute(config, context)
Execute the schedule step.
Parameters:
config: WorkflowStepConfig- Step configurationcontext: WorkflowContext- Workflow execution context
Returns: Promise<WorkflowStepExecutionResult>
validate(config)
Validate step configuration.
Parameters:
config: WorkflowStepConfig- Configuration to validate
Returns: ValidationResult
cancelScheduledJob(jobId)
Cancel a scheduled job.
Parameters:
jobId: string- Job identifier
Returns: Promise<boolean>
rescheduleJob(jobId, newScheduledTime, scheduleConfig)
Reschedule an existing job.
Parameters:
jobId: string- Job identifiernewScheduledTime: Date- New scheduled timescheduleConfig: ScheduleConfig- Schedule constraints
Returns: Promise<WorkflowStepExecutionResult>
Types
ScheduleConfig
interface ScheduleConfig {
allowImmediate?: boolean;
minDelayMinutes?: number;
maxDelayDays?: number;
timezone?: string;
}ScheduleResult
interface ScheduleResult {
scheduledFor: Date;
jobId: string;
immediate: boolean;
platforms?: string[];
}WorkflowContext
interface WorkflowContext {
content: WorkflowContentItem;
variables: Map<string, any>;
userId?: string;
metadata?: Record<string, any>;
}Validation Functions
validateScheduleConfig(config)
Validate schedule configuration.
import { validateScheduleConfig } from '@bernierllc/content-workflow-schedule-step';
const result = validateScheduleConfig({
id: 'schedule',
name: 'Schedule',
type: 'schedule',
scheduleConfig: {
minDelayMinutes: 5,
maxDelayDays: 30
}
});validateScheduledTime(scheduledTime, config)
Validate scheduled time against constraints.
import { validateScheduledTime } from '@bernierllc/content-workflow-schedule-step';
const futureTime = new Date(Date.now() + 60 * 60 * 1000);
const result = validateScheduledTime(futureTime, {
minDelayMinutes: 5,
maxDelayDays: 7
});convertToTimezone(date, timezone)
Convert date to specific timezone.
import { convertToTimezone } from '@bernierllc/content-workflow-schedule-step';
const date = new Date('2025-12-25T10:00:00Z');
const converted = convertToTimezone(date, 'America/New_York');Error Handling
The schedule step returns errors in a structured format:
const result = await scheduleStep.execute(config, context);
if (!result.success) {
console.error('Error:', result.error);
// Possible errors:
// - "Scheduled time is required when immediate publishing is not allowed"
// - "Scheduled time cannot be in the past"
// - "Scheduled time must be at least X minutes in the future"
// - "Scheduled time cannot be more than X days in the future"
}Integration with Scheduler Service
The schedule step integrates with @bernierllc/scheduler-service to create jobs:
- Job type:
CONTENT_PUBLISH - Schedule type:
ONCE - Retry policy: 3 attempts with 5 second delay
- Tags:
['content-publish', 'workflow']
Best Practices
- Always validate configuration before using in production
- Set reasonable constraints (min/max delays) based on your use case
- Handle timezone conversions explicitly for international audiences
- Monitor scheduled jobs using the scheduler service
- Cancel jobs when content is deleted or workflows are cancelled
Testing
npm test # Run all tests
npm run test:coverage # Run with coverage
npm run test:watch # Watch modeLicense
Copyright (c) 2025 Bernier LLC. See LICENSE for details.
