
Research
/Security News
Mini Shai-Hulud Campaign Hits Red Hat Cloud Services npm Packages
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.
@hazeljs/cron
Advanced tools
Scheduled tasks as decorators. No setInterval hacks.
@Cron('0 9 * * *') for daily at 9am. @Interval(60000) for every minute. Real cron expressions, timezone support, overlap prevention. Background jobs that actually run when you expect.
@Cron, @Interval, @Timeoutnpm install @hazeljs/cron
import { HazelModule } from '@hazeljs/core';
import { CronModule } from '@hazeljs/cron';
@HazelModule({
imports: [CronModule.forRoot()],
})
export class AppModule {}
import { Injectable } from '@hazeljs/core';
import { Cron, CronExpression } from '@hazeljs/cron';
@Injectable()
export class TasksService {
@Cron(CronExpression.EVERY_MINUTE)
handleEveryMinute() {
console.log('This runs every minute');
}
@Cron('0 0 * * *') // Every day at midnight
handleMidnight() {
console.log('This runs at midnight every day');
}
@Cron('0 9 * * 1-5') // Weekdays at 9 AM
handleWeekdayMorning() {
console.log('This runs Monday-Friday at 9 AM');
}
}
import { CronExpression } from '@hazeljs/cron';
@Cron(CronExpression.EVERY_SECOND) // Every second
@Cron(CronExpression.EVERY_5_SECONDS) // Every 5 seconds
@Cron(CronExpression.EVERY_10_SECONDS) // Every 10 seconds
@Cron(CronExpression.EVERY_30_SECONDS) // Every 30 seconds
@Cron(CronExpression.EVERY_MINUTE) // Every minute
@Cron(CronExpression.EVERY_5_MINUTES) // Every 5 minutes
@Cron(CronExpression.EVERY_10_MINUTES) // Every 10 minutes
@Cron(CronExpression.EVERY_30_MINUTES) // Every 30 minutes
@Cron(CronExpression.EVERY_HOUR) // Every hour
@Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT) // Daily at 00:00
@Cron(CronExpression.EVERY_DAY_AT_NOON) // Daily at 12:00
@Cron(CronExpression.EVERY_WEEK) // Every Sunday at 00:00
@Cron(CronExpression.EVERY_MONTH) // First day of month at 00:00
// Format: second minute hour day month weekday
// * * * * * *
@Cron('0 */15 * * * *') // Every 15 minutes
@Cron('0 0 12 * * *') // Every day at noon
@Cron('0 0 0 1 * *') // First day of every month
@Cron('0 0 9 * * 1-5') // Weekdays at 9 AM
@Cron('0 30 11 * * 1,3,5') // Mon, Wed, Fri at 11:30 AM
Schedule recurring tasks:
@Injectable()
export class TasksService {
@Cron('0 0 * * *', {
name: 'daily-cleanup',
timezone: 'America/New_York',
})
async dailyCleanup() {
console.log('Running daily cleanup');
await this.cleanupOldData();
}
}
Run tasks at fixed intervals:
@Injectable()
export class MonitoringService {
@Interval(5000) // Every 5 seconds
checkHealth() {
console.log('Health check');
}
@Interval(60000, { name: 'metrics-collector' })
collectMetrics() {
console.log('Collecting metrics');
}
}
Run tasks once after a delay:
@Injectable()
export class StartupService {
@Timeout(5000) // After 5 seconds
async warmupCache() {
console.log('Warming up cache');
await this.cacheService.warmup();
}
}
import { Injectable } from '@hazeljs/core';
import { CronService, SchedulerRegistry } from '@hazeljs/cron';
@Injectable()
export class JobManager {
constructor(
private schedulerRegistry: SchedulerRegistry,
private cronService: CronService
) {}
stopJob(name: string) {
const job = this.schedulerRegistry.getCronJob(name);
job.stop();
console.log(`Job ${name} stopped`);
}
startJob(name: string) {
const job = this.schedulerRegistry.getCronJob(name);
job.start();
console.log(`Job ${name} started`);
}
deleteJob(name: string) {
this.schedulerRegistry.deleteCronJob(name);
console.log(`Job ${name} deleted`);
}
getAllJobs() {
return this.schedulerRegistry.getCronJobs();
}
}
@Injectable()
export class DynamicJobService {
constructor(private schedulerRegistry: SchedulerRegistry) {}
addJob(name: string, cronExpression: string, callback: () => void) {
const job = new CronJob(cronExpression, callback);
this.schedulerRegistry.addCronJob(name, job);
job.start();
}
removeJob(name: string) {
this.schedulerRegistry.deleteCronJob(name);
}
}
CronModule.forRoot({
// Enable/disable all cron jobs
enabled: true,
// Default timezone for all jobs
timezone: 'UTC',
// Prevent overlapping executions
preventOverlap: true,
// Retry failed jobs
retry: {
attempts: 3,
delay: 1000,
},
// Logging
logging: {
enabled: true,
logSuccess: true,
logErrors: true,
},
});
@Cron('0 0 * * *', {
name: 'backup-job',
timezone: 'America/New_York',
runOnInit: false,
preventOverlap: true,
retryAttempts: 3,
retryDelay: 5000,
})
async backupDatabase() {
await this.databaseService.backup();
}
@Injectable()
export class TasksService {
@Cron('0 0 * * *', {
name: 'risky-job',
retryAttempts: 3,
retryDelay: 5000,
})
async riskyJob() {
try {
await this.performRiskyOperation();
} catch (error) {
console.error('Job failed:', error);
// Error will be retried automatically
throw error;
}
}
}
@Injectable()
export class DatabaseCleanupService {
@Cron('0 2 * * *') // Every day at 2 AM
async cleanupOldRecords() {
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
await this.db.logs.deleteMany({
where: { createdAt: { lt: thirtyDaysAgo } },
});
console.log('Old records cleaned up');
}
}
@Injectable()
export class ReportService {
@Cron('0 0 9 * * 1') // Every Monday at 9 AM
async generateWeeklyReport() {
const report = await this.analytics.generateWeeklyReport();
await this.email.send({
to: 'admin@example.com',
subject: 'Weekly Report',
body: report,
});
}
}
@Injectable()
export class CacheService {
@Cron('0 */30 * * * *') // Every 30 minutes
async warmupCache() {
const popularProducts = await this.db.products.findMany({
where: { popular: true },
});
for (const product of popularProducts) {
await this.cache.set(`product:${product.id}`, product, 3600);
}
}
}
@Injectable()
export class HealthMonitor {
@Interval(30000) // Every 30 seconds
async checkServices() {
const services = ['database', 'redis', 'api'];
for (const service of services) {
const isHealthy = await this.checkServiceHealth(service);
if (!isHealthy) {
await this.alertService.sendAlert(`${service} is down!`);
}
}
}
}
@Injectable()
export class SyncService {
@Cron('0 */5 * * * *') // Every 5 minutes
async syncData() {
const localData = await this.getLocalData();
const remoteData = await this.getRemoteData();
const diff = this.calculateDiff(localData, remoteData);
await this.applyChanges(diff);
}
}
preventOverlap for long-running jobs@Interval for fixed-interval tasks@Cron(expression: string, options?: CronOptions)
@Interval(milliseconds: number, options?: IntervalOptions)
@Timeout(milliseconds: number, options?: TimeoutOptions)
class CronService {
addCronJob(name: string, expression: string, callback: () => void): void;
getCronJob(name: string): CronJob;
deleteCronJob(name: string): void;
getCronJobs(): Map<string, CronJob>;
}
class SchedulerRegistry {
addCronJob(name: string, job: CronJob): void;
getCronJob(name: string): CronJob;
deleteCronJob(name: string): void;
getCronJobs(): Map<string, CronJob>;
addInterval(name: string, intervalId: NodeJS.Timeout): void;
deleteInterval(name: string): void;
addTimeout(name: string, timeoutId: NodeJS.Timeout): void;
deleteTimeout(name: string): void;
}
See the examples directory for complete working examples.
npm test
Contributions are welcome! Please read our Contributing Guide for details.
Apache 2.0 © HazelJS
FAQs
Cron job scheduling module for HazelJS framework
The npm package @hazeljs/cron receives a total of 55 weekly downloads. As such, @hazeljs/cron popularity was classified as not popular.
We found that @hazeljs/cron demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.

Research
/Security News
The North Korean malware loader hides in a Packagist-listed package and its GitHub branch to fetch and execute remote code in a likely Contagious Interview-style lure.

Security News
The Rust project is moving toward formal rules on LLM use in contributions after months of internal debate over maintainer burden, code quality, and contributor experience.