Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor cron module and add daily.runAt() and monthly.runAt().on() methods #6

Merged
merged 3 commits into from
Mar 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/witty-rockets-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@aulidev/cron": minor
---

added daily.runAt() and monthly.runAt().on() methods to execute daily and monthly cron jobs
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@aulidev/cron",
"version": "1.0.0",
"description": "A simple cron wrapper for nodejs",
"description": "An easy-to-use interface for setting up cron jobs to execute tasks at a specific time using node-cron.",
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
Expand Down
229 changes: 225 additions & 4 deletions src/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { describe, expect, it } from 'vitest'

import cron from '@/index'
import { i } from 'vitest/dist/reporters-MmQN-57K'

describe('Cron Scheudle Test ', () => {
describe('Should be defined', () => {
describe('Should be defined (cron.every)', () => {
it('Should be defined cron value', () => {
expect(cron).toBeDefined()
})
Expand All @@ -31,7 +30,28 @@ describe('Cron Scheudle Test ', () => {
})
})

describe('Should be able to schedule', () => {
describe('Should be define (cron.daily.runAt.on)', () => {
it('Should be defined cron value', () => {
expect(cron.daily).toBeDefined()
})
it('Should have runAt method', () => {
expect(cron.daily.runAt).toBeDefined()
})
})

describe('Should be define (cron.weekly.runAt.on)', () => {
it('Should be defined cron value', () => {
expect(cron.weekly).toBeDefined()
})
it('Should have runAt method', () => {
expect(cron.weekly.runAt).toBeDefined()
})
it('Should have on method', () => {
expect(cron.weekly.runAt('12:00').on).toBeDefined()
})
})

describe('Should be able to schedule (cron.every(n))', () => {
it('Should be able to schedule every second', () => {
const task = cron.every(1).second.do(() => {})
expect(task).toBeDefined()
Expand Down Expand Up @@ -62,7 +82,7 @@ describe('Cron Scheudle Test ', () => {
})
})

describe('Should be able to schedule with options', () => {
describe('Should be able to schedule with options (cron.every(n))', () => {
it('Should be able to schedule every second with options', () => {
const task = cron
.every(1)
Expand Down Expand Up @@ -106,4 +126,205 @@ describe('Cron Scheudle Test ', () => {
expect(task).toBeDefined()
})
})

describe('Should be able to schedule with options (cron.daily.runAt("12:00"))', () => {
it('Should be able to schedule daily at 12:00', () => {
const task = cron.daily.runAt('12:00').do(() => {})
expect(task).toBeDefined()
})
it('Should be able to schedule daily at 12:00 with options', () => {
const task = cron.daily.runAt('12:00').do(() => {}, {
timezone: 'America/New_York',
})
expect(task).toBeDefined()
})
})

describe('Should be able to schedule with options (cron.daily.runAt("12:00 PM"))', () => {
it('Should be able to schedule daily at 12:00 PM', () => {
const task = cron.daily.runAt('12:00 PM').do(() => {})
expect(task).toBeDefined()
})
it('Should be able to schedule daily at 12:00 PM with options', () => {
const task = cron.daily.runAt('12:00 PM').do(() => {}, {
timezone: 'America/New_York',
})
expect(task).toBeDefined()
})
})

describe('Should be able to schedule with options (cron.daily.runAt("12:00 AM"))', () => {
it('Should be able to schedule daily at 12:00 AM', () => {
const task = cron.daily.runAt('12:00 AM').do(() => {})
expect(task).toBeDefined()
})
it('Should be able to schedule daily at 12:00 AM with options', () => {
const task = cron.daily.runAt('12:00 AM').do(() => {}, {
timezone: 'America/New_York',
})
expect(task).toBeDefined()
})
})

describe('Should be able to schedule with options (cron.daily.runAt("12:00:00"))', () => {
it('Should be able to schedule daily at 12:00:00', () => {
const task = cron.daily.runAt('12:00:00').do(() => {})
expect(task).toBeDefined()
})
it('Should be able to schedule daily at 12:00:00 with options', () => {
const task = cron.daily.runAt('12:00:00').do(() => {}, {
timezone: 'America/New_York',
})
expect(task).toBeDefined()
})
})

describe('Should be able to schedule with options (cron.daily.runAt("12:00:00 PM"))', () => {
it('Should be able to schedule daily at 12:00:00 PM', () => {
const task = cron.daily.runAt('12:00:00 PM').do(() => {})
expect(task).toBeDefined()
})
it('Should be able to schedule daily at 12:00:00 PM with options', () => {
const task = cron.daily.runAt('12:00:00 PM').do(() => {}, {
timezone: 'America/New_York',
})
expect(task).toBeDefined()
})
})

describe('Should be able to schedule with options (cron.daily.runAt("12:00:00 AM"))', () => {
it('Should be able to schedule daily at 12:00:00 AM', () => {
const task = cron.daily.runAt('12:00:00 AM').do(() => {})
expect(task).toBeDefined()
})
it('Should be able to schedule daily at 12:00:00 AM with options', () => {
const task = cron.daily.runAt('12:00:00 AM').do(() => {}, {
timezone: 'America/New_York',
})
expect(task).toBeDefined()
})
})

describe('Should be able to schedule with options (cron.weekly.runAt("12:00").on("monday"))', () => {
it('Should be able to schedule weekly at 12:00 on monday', () => {
const task = cron.weekly
.runAt('12:00')
.on('monday')
.do(() => {})
expect(task).toBeDefined()
})
it('Should be able to schedule weekly at 12:00 on monday with options', () => {
const task = cron.weekly
.runAt('12:00')
.on('monday')
.do(() => {}, {
timezone: 'America/New_York',
})
expect(task).toBeDefined()
})
// wrong day to get error
it('Should get and error while schedule with options (cron.weekly.runAt("12:00").on("mondays"))', () => {
expect(() => {
cron.weekly
.runAt('12:00')
.on('mondays')
.do(() => {})
}).toThrowError('Invalid day: mondays')
})
})

describe('Should be able to schedule with options (cron.weekly.runAt("12:00 PM").on("monday"))', () => {
it('Should be able to schedule weekly at 12:00 PM on monday', () => {
const task = cron.weekly
.runAt('12:00 PM')
.on('monday')
.do(() => {})
expect(task).toBeDefined()
})
it('Should be able to schedule weekly at 12:00 PM on monday with options', () => {
const task = cron.weekly
.runAt('12:00 PM')
.on('monday')
.do(() => {}, {
timezone: 'America/New_York',
})
expect(task).toBeDefined()
})
})

describe('Should be able to schedule with options (cron.weekly.runAt("12:00 AM").on("monday"))', () => {
it('Should be able to schedule weekly at 12:00 AM on monday', () => {
const task = cron.weekly
.runAt('12:00 AM')
.on('monday')
.do(() => {})
expect(task).toBeDefined()
})
it('Should be able to schedule weekly at 12:00 AM on monday with options', () => {
const task = cron.weekly
.runAt('12:00 AM')
.on('monday')
.do(() => {}, {
timezone: 'America/New_York',
})
expect(task).toBeDefined()
})
})

describe('Should be able to schedule with options (cron.weekly.runAt("12:00:00").on("monday"))', () => {
it('Should be able to schedule weekly at 12:00:00 on monday', () => {
const task = cron.weekly
.runAt('12:00:00')
.on('monday')
.do(() => {})
expect(task).toBeDefined()
})
it('Should be able to schedule weekly at 12:00:00 on monday with options', () => {
const task = cron.weekly
.runAt('12:00:00')
.on('monday')
.do(() => {}, {
timezone: 'America/New_York',
})
expect(task).toBeDefined()
})
})

describe('Should be able to schedule with options (cron.weekly.runAt("12:00:00 PM").on("monday"))', () => {
it('Should be able to schedule weekly at 12:00:00 PM on monday', () => {
const task = cron.weekly
.runAt('12:00:00 PM')
.on('monday')
.do(() => {})
expect(task).toBeDefined()
})
it('Should be able to schedule weekly at 12:00:00 PM on monday with options', () => {
const task = cron.weekly
.runAt('12:00:00 PM')
.on('monday')
.do(() => {}, {
timezone: 'America/New_York',
})
expect(task).toBeDefined()
})
})

describe('Should be able to schedule with options (cron.weekly.runAt("12:00:00 AM").on("monday"))', () => {
it('Should be able to schedule weekly at 12:00:00 AM on monday', () => {
const task = cron.weekly
.runAt('12:00:00 AM')
.on('monday')
.do(() => {})
expect(task).toBeDefined()
})
it('Should be able to schedule weekly at 12:00:00 AM on monday with options', () => {
const task = cron.weekly
.runAt('12:00:00 AM')
.on('monday')
.do(() => {}, {
timezone: 'America/New_York',
})
expect(task).toBeDefined()
})
})
})
85 changes: 67 additions & 18 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,82 @@
import Timer from '@/timer'
import { CronFunction, CronOptions, CronTask, CronUnit } from '@/lib'
import {
CronFunction,
CronOptions,
CronTask,
CronUnit,
cronSchedular,
} from '@/lib'
import { generateEveryMethod } from '@/lib/every'
import { convertDayToNumber, getHoursMinutesSeconds } from '@/lib/time'

interface Cron {
/**
* Represents a cron job configuration.
*/
type Cron = {
every: (interval: number) => {
[unit in CronUnit]: {
do: (callback: CronFunction, option?: CronOptions) => CronTask
}
}
daily: {
runAt: (time: string) => {
do: (callback: CronFunction, option?: CronOptions) => CronTask
}
}
weekly: {
runAt: (time: string) => {
on: (day: string) => {
do: (callback: CronFunction, option?: CronOptions) => CronTask
}
}
}
}

/**
Returns an object with methods to generate intervals for different time units.
@param interval - The interval value for the time units.
@returns An object with methods to generate intervals for different time units.
*/

const cron: Cron = {
every: (interval: number) => ({
second: generateMethod('second', interval),
minute: generateMethod('minute', interval),
hour: generateMethod('hour', interval),
day: generateMethod('day', interval),
week: generateMethod('week', interval),
month: generateMethod('month', interval),
year: generateMethod('year', interval),
second: generateEveryMethod('second', interval),
minute: generateEveryMethod('minute', interval),
hour: generateEveryMethod('hour', interval),
day: generateEveryMethod('day', interval),
week: generateEveryMethod('week', interval),
month: generateEveryMethod('month', interval),
year: generateEveryMethod('year', interval),
}),
}

function generateMethod(unit: CronUnit, interval: number) {
const methodName = `everyN${unit.charAt(0).toUpperCase() + unit.slice(1)}s`
return {
do(callback: CronFunction, option?: CronOptions): CronTask {
return (Timer as any)[methodName](interval, callback, option)
daily: {
runAt(time: string) {
return {
do(callback: CronFunction, option?: CronOptions): CronTask {
const { hour, minute, second } = getHoursMinutesSeconds(time)
const cronString = `${second === 0 ? '0' : second} ${minute === 0 ? '0' : minute} ${hour === 0 ? '*' : `*/${hour}`} * * *`
return cronSchedular(cronString, callback, option)
},
}
},
}
},
weekly: {
runAt(time: string) {
return {
on(day: string) {
return {
do(callback: CronFunction, option?: CronOptions): CronTask {
const { hour, minute, second } = getHoursMinutesSeconds(time)
const dayOfWeek = convertDayToNumber(day)
return cronSchedular(
`${second === 0 ? '0' : second} ${minute === 0 ? '0' : minute} ${hour === 0 ? '*' : `*/${hour}`} * * ${dayOfWeek}`,
callback,
option,
)
},
}
},
}
},
},
}

export default cron
24 changes: 24 additions & 0 deletions src/lib/every.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { CronFunction, CronOptions, CronTask, CronUnit } from '@/lib'
import Timer from '@/timer'

/**
Generates a method for executing a callback function at regular intervals.
@param unit - The unit of time for the interval (e.g. 'second', 'minute', 'hour').
@param interval - The interval duration in milliseconds.
@returns An object with a 'do' method for executing the callback function.
*/

export function generateEveryMethod(unit: CronUnit, interval: number) {
const methodName = `everyN${unit.charAt(0).toUpperCase() + unit.slice(1)}s`
return {
/**
* Executes the provided callback function at regular intervals.
* @param callback - The function to be executed.
* @param option - Optional configuration options for the cron task.
* @returns A cron task object.
*/
do(callback: CronFunction, option?: CronOptions): CronTask {
return Timer[methodName](interval, callback, option)
},
}
}
Loading
Loading