Skip to content

Commit

Permalink
fix: add back onComplete to callbacks signatures
Browse files Browse the repository at this point in the history
  • Loading branch information
sheerlox committed Oct 5, 2023
1 parent 8722d95 commit d6938d8
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 54 deletions.
92 changes: 54 additions & 38 deletions src/job.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,54 +5,58 @@ import {
CronCallback,
CronCommand,
CronContext,
CronJobParams
CronJobParams,
CronOnCompleteCallback,
CronOnCompleteCommand,
WithOnComplete
} from './types/cron.types';

export class CronJob<C = null> {
export class CronJob<OC extends CronOnCompleteCommand<C> | null, C = null> {
cronTime: CronTime;
running = false;
unrefTimeout = false;
lastExecution: Date | null = null;
runOnce = false;
context: CronContext<C>;
onComplete?: CronCallback<C>;
onComplete?: WithOnComplete<OC> extends true
? CronOnCompleteCallback<C>
: undefined;

private _timeout?: NodeJS.Timeout;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private _callbacks: ((...args: any) => void)[] = [];
private _callbacks: CronCallback<C, WithOnComplete<OC>>[] = [];

constructor(
cronTime: CronJobParams<C>['cronTime'],
onTick: CronJobParams<C>['onTick'],
onComplete?: CronJobParams<C>['onComplete'],
start?: CronJobParams<C>['start'],
timeZone?: CronJobParams<C>['timeZone'],
context?: CronJobParams<C>['context'],
runOnInit?: CronJobParams<C>['runOnInit'],
cronTime: CronJobParams<OC, C>['cronTime'],
onTick: CronJobParams<OC, C>['onTick'],
onComplete?: CronJobParams<OC, C>['onComplete'],
start?: CronJobParams<OC, C>['start'],
timeZone?: CronJobParams<OC, C>['timeZone'],
context?: CronJobParams<OC, C>['context'],
runOnInit?: CronJobParams<OC, C>['runOnInit'],
utcOffset?: null,
unrefTimeout?: CronJobParams<C>['unrefTimeout']
unrefTimeout?: CronJobParams<OC, C>['unrefTimeout']
);
constructor(
cronTime: CronJobParams<C>['cronTime'],
onTick: CronJobParams<C>['onTick'],
onComplete?: CronJobParams<C>['onComplete'],
start?: CronJobParams<C>['start'],
cronTime: CronJobParams<OC, C>['cronTime'],
onTick: CronJobParams<OC, C>['onTick'],
onComplete?: CronJobParams<OC, C>['onComplete'],
start?: CronJobParams<OC, C>['start'],
timeZone?: null,
context?: CronJobParams<C>['context'],
runOnInit?: CronJobParams<C>['runOnInit'],
utcOffset?: CronJobParams<C>['utcOffset'],
unrefTimeout?: CronJobParams<C>['unrefTimeout']
context?: CronJobParams<OC, C>['context'],
runOnInit?: CronJobParams<OC, C>['runOnInit'],
utcOffset?: CronJobParams<OC, C>['utcOffset'],
unrefTimeout?: CronJobParams<OC, C>['unrefTimeout']
);
constructor(
cronTime: CronJobParams<C>['cronTime'],
onTick: CronJobParams<C>['onTick'],
onComplete?: CronJobParams<C>['onComplete'],
start?: CronJobParams<C>['start'],
timeZone?: CronJobParams<C>['timeZone'],
context?: CronJobParams<C>['context'],
runOnInit?: CronJobParams<C>['runOnInit'],
utcOffset?: CronJobParams<C>['utcOffset'],
unrefTimeout?: CronJobParams<C>['unrefTimeout']
cronTime: CronJobParams<OC, C>['cronTime'],
onTick: CronJobParams<OC, C>['onTick'],
onComplete?: CronJobParams<OC, C>['onComplete'],
start?: CronJobParams<OC, C>['start'],
timeZone?: CronJobParams<OC, C>['timeZone'],
context?: CronJobParams<OC, C>['context'],
runOnInit?: CronJobParams<OC, C>['runOnInit'],
utcOffset?: CronJobParams<OC, C>['utcOffset'],
unrefTimeout?: CronJobParams<OC, C>['unrefTimeout']
) {
this.context = (context ?? this) as CronContext<C>;

Expand All @@ -74,7 +78,12 @@ export class CronJob<C = null> {
}

if (onComplete != null) {
this.onComplete = this._fnWrap(onComplete);
// casting to the correct type since we just made sure that WithOnComplete<OC> = true
this.onComplete = this._fnWrap(
onComplete
) as WithOnComplete<OC> extends true
? CronOnCompleteCallback<C>
: undefined;
}

if (this.cronTime.realDate) {
Expand All @@ -91,15 +100,17 @@ export class CronJob<C = null> {
if (start) this.start();
}

static from<C = null>(params: CronJobParams<C>) {
static from<C = null, OC extends CronOnCompleteCommand<C> | null = null>(
params: CronJobParams<OC, C>
) {
// runtime check for JS users
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (params.timeZone != null && params.utcOffset != null) {
throw new ExclusiveParametersError('timeZone', 'utcOffset');
}

if (params.timeZone != null) {
return new CronJob<C>(
return new CronJob<OC, C>(
params.cronTime,
params.onTick,
params.onComplete,
Expand All @@ -111,7 +122,7 @@ export class CronJob<C = null> {
params.unrefTimeout
);
} else if (params.utcOffset != null) {
return new CronJob<C>(
return new CronJob<OC, C>(
params.cronTime,
params.onTick,
params.onComplete,
Expand All @@ -123,7 +134,7 @@ export class CronJob<C = null> {
params.unrefTimeout
);
} else {
return new CronJob<C>(
return new CronJob<OC, C>(
params.cronTime,
params.onTick,
params.onComplete,
Expand All @@ -137,7 +148,7 @@ export class CronJob<C = null> {
}
}

private _fnWrap(cmd: CronCommand<C>) {
private _fnWrap(cmd: CronCommand<C, boolean>): CronCallback<C, boolean> {
switch (typeof cmd) {
case 'function': {
return cmd;
Expand All @@ -161,7 +172,7 @@ export class CronJob<C = null> {
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
addCallback(callback: (...args: any) => void) {
addCallback(callback: CronCallback<C, WithOnComplete<OC>>) {
if (typeof callback === 'function') {
this._callbacks.push(callback);
}
Expand All @@ -183,7 +194,12 @@ export class CronJob<C = null> {

fireOnTick() {
for (const callback of this._callbacks) {
callback.call(this.context, this.onComplete);
callback.call(
this.context,
this.onComplete as WithOnComplete<OC> extends true
? CronOnCompleteCallback<C>
: never
);
}
}

Expand Down
14 changes: 7 additions & 7 deletions src/time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,19 @@ export class CronTime {
private dayOfWeek: TimeUnitField<'dayOfWeek'> = {};

constructor(
source: CronJobParams['cronTime'],
timeZone?: CronJobParams['timeZone'],
source: CronJobParams<null>['cronTime'],
timeZone?: CronJobParams<null>['timeZone'],
utcOffset?: null
);
constructor(
source: CronJobParams['cronTime'],
source: CronJobParams<null>['cronTime'],
timeZone?: null,
utcOffset?: CronJobParams['utcOffset']
utcOffset?: CronJobParams<null>['utcOffset']
);
constructor(
source: CronJobParams['cronTime'],
timeZone?: CronJobParams['timeZone'],
utcOffset?: CronJobParams['utcOffset']
source: CronJobParams<null>['cronTime'],
timeZone?: CronJobParams<null>['timeZone'],
utcOffset?: CronJobParams<null>['utcOffset']
) {
// runtime check for JS users
if (timeZone != null && utcOffset != null) {
Expand Down
40 changes: 31 additions & 9 deletions src/types/cron.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,24 @@ import { CONSTRAINTS, TIME_UNITS_MAP } from '../constants';
import { CronJob } from '../job';
import { IntRange } from './utils';

interface BaseCronJobParams<C = null> {
interface BaseCronJobParams<
OC extends CronOnCompleteCommand<C> | null,
C = null
> {
cronTime: string | Date | DateTime;
onTick: CronCommand<C>;
onComplete?: CronCommand<C> | null;
onTick: CronCommand<C, WithOnComplete<OC>>;
onComplete?: OC;
start?: boolean | null;
context?: C;
runOnInit?: boolean | null;
unrefTimeout?: boolean | null;
}

export type CronJobParams<C = null> =
| BaseCronJobParams<C> &
export type CronJobParams<
OC extends CronOnCompleteCommand<C> | null,
C = null
> =
| BaseCronJobParams<OC, C> &
(
| {
timeZone?: string | null;
Expand All @@ -27,19 +33,35 @@ export type CronJobParams<C = null> =
}
);

export type CronContext<C = null> = C extends null ? CronJob : NonNullable<C>;
export type CronContext<C> = C extends null ? CronJob<null> : NonNullable<C>;

export type CronCallback<C = null> = (this: CronContext<C>) => void;
export type CronCallback<C, WithOnCompleteBool extends boolean = false> = (
this: CronContext<C>,
onComplete: WithOnCompleteBool extends true
? OmitThisParameter<CronOnCompleteCallback<C>>
: never
) => void;

export type CronCommand<C = null> =
| CronCallback<C>
export type CronOnCompleteCallback<C> = (this: CronContext<C>) => void;

export type CronSystemCommand =
| string
| {
command: string;
args?: readonly string[] | null;
options?: SpawnOptions | null;
};

export type CronCommand<C, WithOnCompleteBool extends boolean = false> =
| CronCallback<C, WithOnCompleteBool>
| CronSystemCommand;

export type CronOnCompleteCommand<C> =
| OmitThisParameter<CronOnCompleteCallback<C>>
| CronSystemCommand;

export type WithOnComplete<OC> = OC extends null ? false : true;

export type TimeUnit = (typeof TIME_UNITS_MAP)[keyof typeof TIME_UNITS_MAP];

export type TimeUnitField<T extends TimeUnit> = Partial<
Expand Down

0 comments on commit d6938d8

Please sign in to comment.