backend v4 half

This commit is contained in:
2025-07-18 09:20:40 +02:00
parent aba7a506ad
commit 725516ad6c
4183 changed files with 217684 additions and 75056 deletions
+7
View File
@@ -0,0 +1,7 @@
## ISC License
Copyright (c) 2016, Lucas Merencia \<lucas.merencia@gmail.com\>
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+117
View File
@@ -0,0 +1,117 @@
# Node Cron
[![npm](https://img.shields.io/npm/l/node-cron.svg)](https://github.com/merencia/node-cron/blob/master/LICENSE.md)
[![npm](https://img.shields.io/npm/v/node-cron.svg)](https://img.shields.io/npm/v/node-cron.svg)
![NPM Downloads](https://img.shields.io/npm/dm/node-cron)
[![Coverage Status](https://coveralls.io/repos/github/node-cron/node-cron/badge.svg?branch=main)](https://coveralls.io/github/node-cron/node-cron?branch=main)
The node-cron module is tiny task scheduler in pure JavaScript for node.js based on [GNU crontab](https://www.gnu.org/software/mcron/manual/html_node/Crontab-file.html). This module allows you to schedule task in node.js using full crontab syntax.
### [Node-Cron Documentation](http://nodecron.com)
## Getting Started
Install node-cron using npm:
```console
npm install --save node-cron
```
Import node-cron and schedule a task:
- commonjs
```javascript
const cron = require('node-cron');
cron.schedule('* * * * *', () => {
console.log('running a task every minute');
});
```
- es6 (module)
```javascript
import cron from 'node-cron';
cron.schedule('* * * * *', () => {
console.log('running a task every minute');
});
```
## Cron Syntax
This is a quick reference to cron syntax and also shows the options supported by node-cron.
### Allowed fields
```
# ┌────────────── second (optional)
# │ ┌──────────── minute
# │ │ ┌────────── hour
# │ │ │ ┌──────── day of month
# │ │ │ │ ┌────── month
# │ │ │ │ │ ┌──── day of week
# │ │ │ │ │ │
# │ │ │ │ │ │
# * * * * * *
```
### Allowed values
| field | value |
| ------------ | --------------------------------- |
| second | 0-59 |
| minute | 0-59 |
| hour | 0-23 |
| day of month | 1-31 |
| month | 1-12 (or names) |
| day of week | 0-7 (or names, 0 or 7 are sunday) |
## Issues
Feel free to submit issues and enhancement requests [here](https://github.com/merencia/node-cron/issues).
## Contributing
In general, we follow the "fork-and-pull" Git workflow.
- Fork the repo on GitHub;
- Commit changes to a branch in your fork;
- Pull request "upstream" with your changes;
NOTE: Be sure to merge the latest from "upstream" before making a pull request!
Please do not contribute code you did not write yourself, unless you are certain you have the legal ability to do so. Also ensure all contributed code can be distributed under the ISC License.
## Contributors
This project exists thanks to all the people who contribute.
<a href="https://github.com/node-cron/node-cron/graphs/contributors"><img src="https://opencollective.com/node-cron/contributors.svg?width=890&button=false" /></a>
## Backers
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/node-cron#backer)]
<a href="https://opencollective.com/node-cron#backers" target="_blank"><img src="https://opencollective.com/node-cron/backers.svg?width=890"></a>
## Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/node-cron#sponsor)]
<a href="https://opencollective.com/node-cron/sponsor/0/website" target="_blank"><img src="https://opencollective.com/node-cron/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/node-cron/sponsor/1/website" target="_blank"><img src="https://opencollective.com/node-cron/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/node-cron/sponsor/2/website" target="_blank"><img src="https://opencollective.com/node-cron/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/node-cron/sponsor/3/website" target="_blank"><img src="https://opencollective.com/node-cron/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/node-cron/sponsor/4/website" target="_blank"><img src="https://opencollective.com/node-cron/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/node-cron/sponsor/5/website" target="_blank"><img src="https://opencollective.com/node-cron/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/node-cron/sponsor/6/website" target="_blank"><img src="https://opencollective.com/node-cron/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/node-cron/sponsor/7/website" target="_blank"><img src="https://opencollective.com/node-cron/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/node-cron/sponsor/8/website" target="_blank"><img src="https://opencollective.com/node-cron/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/node-cron/sponsor/9/website" target="_blank"><img src="https://opencollective.com/node-cron/sponsor/9/avatar.svg"></a>
## License
node-cron is under [ISC License](https://github.com/merencia/node-cron/blob/master/LICENSE.md).
+1
View File
@@ -0,0 +1 @@
export declare function createID(prefix?: string, length?: number): string;
+14
View File
@@ -0,0 +1,14 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createID = createID;
const node_crypto_1 = __importDefault(require("node:crypto"));
function createID(prefix = '', length = 16) {
const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const values = node_crypto_1.default.randomBytes(length);
const id = Array.from(values, v => charset[v % charset.length]).join('');
return prefix ? `${prefix}-${id}` : id;
}
//# sourceMappingURL=create-id.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"create-id.js","sourceRoot":"","sources":["../../src/create-id.ts"],"names":[],"mappings":";;;;;AAEA,4BAKC;AAPD,8DAAiC;AAEjC,SAAgB,QAAQ,CAAC,SAAiB,EAAE,EAAE,SAAiB,EAAE;IAC/D,MAAM,OAAO,GAAG,gEAAgE,CAAC;IACjF,MAAM,MAAM,GAAG,qBAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzE,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACzC,CAAC"}
+7
View File
@@ -0,0 +1,7 @@
declare const logger: {
info(message: string): void;
warn(message: string): void;
error(message: string | Error, err?: Error): void;
debug(message: string | Error, err?: Error): void;
};
export default logger;
+57
View File
@@ -0,0 +1,57 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const levelColors = {
INFO: '\x1b[36m',
WARN: '\x1b[33m',
ERROR: '\x1b[31m',
DEBUG: '\x1b[35m',
};
const GREEN = '\x1b[32m';
const RESET = '\x1b[0m';
function log(level, message, extra) {
const timestamp = new Date().toISOString();
const color = levelColors[level] ?? '';
const prefix = `[${timestamp}] [PID: ${process.pid}] ${GREEN}[NODE-CRON]${GREEN} ${color}[${level}]${RESET}`;
const output = `${prefix} ${message}`;
switch (level) {
case 'ERROR':
console.error(output, extra ?? '');
break;
case 'DEBUG':
console.debug(output, extra ?? '');
break;
case 'WARN':
console.warn(output);
break;
case 'INFO':
default:
console.info(output);
break;
}
}
const logger = {
info(message) {
log('INFO', message);
},
warn(message) {
log('WARN', message);
},
error(message, err) {
if (message instanceof Error) {
log('ERROR', message.message, message);
}
else {
log('ERROR', message, err);
}
},
debug(message, err) {
if (message instanceof Error) {
log('DEBUG', message.message, message);
}
else {
log('DEBUG', message, err);
}
},
};
exports.default = logger;
//# sourceMappingURL=logger.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/logger.ts"],"names":[],"mappings":";;AAEA,MAAM,WAAW,GAA6B;IAC5C,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,UAAU;IACjB,KAAK,EAAE,UAAU;CAClB,CAAC;AAEF,MAAM,KAAK,GAAG,UAAU,CAAC;AACzB,MAAM,KAAK,GAAG,SAAS,CAAC;AAExB,SAAS,GAAG,CAAC,KAAe,EAAE,OAAe,EAAE,KAAW;IACxD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,SAAS,WAAW,OAAO,CAAC,GAAG,KAAK,KAAK,cAAc,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,EAAE,CAAC;IAC7G,MAAM,MAAM,GAAG,GAAG,MAAM,IAAI,OAAO,EAAE,CAAC;IAEtC,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,OAAO;YACV,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YACnC,MAAM;QACR,KAAK,OAAO;YACR,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YACnC,MAAM;QACV,KAAK,MAAM;YACT,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrB,MAAM;QACR,KAAK,MAAM,CAAC;QACZ;YACE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrB,MAAM;IACV,CAAC;AACH,CAAC;AAED,MAAM,MAAM,GAAG;IACb,IAAI,CAAC,OAAe;QAClB,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvB,CAAC;IACD,IAAI,CAAC,OAAe;QAClB,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvB,CAAC;IACD,KAAK,CAAC,OAAuB,EAAE,GAAW;QACxC,IAAI,OAAO,YAAY,KAAK,EAAE,CAAC;YAC7B,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,KAAK,CAAC,OAAuB,EAAE,GAAW;QACxC,IAAI,OAAO,YAAY,KAAK,EAAE,CAAC;YAC7B,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;CACF,CAAC;AAEF,kBAAe,MAAM,CAAC"}
+18
View File
@@ -0,0 +1,18 @@
import { ScheduledTask, TaskFn, TaskOptions } from "./tasks/scheduled-task";
export declare function schedule(expression: string, func: TaskFn | string, options?: TaskOptions): ScheduledTask;
export declare function createTask(expression: string, func: TaskFn | string, options?: TaskOptions): ScheduledTask;
export declare function solvePath(filePath: string): string;
export declare function validate(expression: string): boolean;
export declare const getTasks: () => Map<string, ScheduledTask>;
export declare const getTask: (taskId: string) => ScheduledTask | undefined;
export { ScheduledTask } from './tasks/scheduled-task';
export type { TaskFn, TaskContext, TaskOptions } from './tasks/scheduled-task';
export interface NodeCron {
schedule: typeof schedule;
createTask: typeof createTask;
validate: typeof validate;
getTasks: typeof getTasks;
getTask: typeof getTask;
}
export declare const nodeCron: NodeCron;
export default nodeCron;
+71
View File
@@ -0,0 +1,71 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.nodeCron = exports.getTask = exports.getTasks = void 0;
exports.schedule = schedule;
exports.createTask = createTask;
exports.solvePath = solvePath;
exports.validate = validate;
const inline_scheduled_task_1 = require("./tasks/inline-scheduled-task");
const task_registry_1 = require("./task-registry");
const pattern_validation_1 = __importDefault(require("./pattern/validation/pattern-validation"));
const background_scheduled_task_1 = __importDefault(require("./tasks/background-scheduled-task/background-scheduled-task"));
const path_1 = __importDefault(require("path"));
const url_1 = require("url");
const registry = new task_registry_1.TaskRegistry();
function schedule(expression, func, options) {
const task = createTask(expression, func, options);
task.start();
return task;
}
function createTask(expression, func, options) {
let task;
if (func instanceof Function) {
task = new inline_scheduled_task_1.InlineScheduledTask(expression, func, options);
}
else {
const taskPath = solvePath(func);
task = new background_scheduled_task_1.default(expression, taskPath, options);
}
registry.add(task);
return task;
}
function solvePath(filePath) {
if (path_1.default.isAbsolute(filePath))
return (0, url_1.pathToFileURL)(filePath).href;
if (filePath.startsWith('file://'))
return filePath;
const stackLines = new Error().stack?.split('\n');
if (stackLines) {
stackLines?.shift();
const callerLine = stackLines?.find((line) => { return line.indexOf(__filename) === -1; });
const match = callerLine?.match(/(file:\/\/)?(((\/?)(\w:))?([/\\].+)):\d+:\d+/);
if (match) {
const dir = `${match[5] ?? ""}${path_1.default.dirname(match[6])}`;
return (0, url_1.pathToFileURL)(path_1.default.resolve(dir, filePath)).href;
}
}
throw new Error(`Could not locate task file ${filePath}`);
}
function validate(expression) {
try {
(0, pattern_validation_1.default)(expression);
return true;
}
catch (e) {
return false;
}
}
exports.getTasks = registry.all;
exports.getTask = registry.get;
exports.nodeCron = {
schedule,
createTask,
validate,
getTasks: exports.getTasks,
getTask: exports.getTask,
};
exports.default = exports.nodeCron;
//# sourceMappingURL=node-cron.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"node-cron.js","sourceRoot":"","sources":["../../src/node-cron.ts"],"names":[],"mappings":";;;;;;AA2CA,4BAIC;AAWD,gCAWC;AAUD,8BAoBC;AAQD,4BASC;AA1GD,yEAAoE;AAEpE,mDAA+C;AAE/C,iGAAiE;AACjE,4HAAkG;AAElG,gDAAwB;AACxB,6BAAoC;AAMpC,MAAM,QAAQ,GAAG,IAAI,4BAAY,EAAE,CAAC;AAmBpC,SAAgB,QAAQ,CAAC,UAAiB,EAAE,IAAqB,EAAE,OAAqB;IACpF,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACnD,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,OAAO,IAAI,CAAC;AAChB,CAAC;AAWD,SAAgB,UAAU,CAAC,UAAkB,EAAE,IAAqB,EAAE,OAAqB;IACvF,IAAI,IAAmB,CAAC;IACxB,IAAG,IAAI,YAAY,QAAQ,EAAC,CAAC;QAC3B,IAAI,GAAG,IAAI,2CAAmB,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC5D,CAAC;SAAM,CAAC;QACN,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,GAAG,IAAI,mCAAuB,CAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACpE,CAAC;IAED,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnB,OAAO,IAAI,CAAC;AAChB,CAAC;AAUD,SAAgB,SAAS,CAAC,QAAgB;IAExC,IAAG,cAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAA,mBAAa,EAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;IAGlE,IAAI,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,QAAQ,CAAC;IAEpD,MAAM,UAAU,GAAG,IAAI,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAClD,IAAG,UAAU,EAAC,CAAC;QACb,UAAU,EAAE,KAAK,EAAE,CAAC;QACpB,MAAM,UAAU,GAAG,UAAU,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3F,MAAM,KAAK,GAAG,UAAU,EAAE,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAEhF,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,cAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACzD,OAAO,IAAA,mBAAa,EAAC,cAAI,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;QACzD,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,EAAE,CAAC,CAAC;AAC5D,CAAC;AAQD,SAAgB,QAAQ,CAAC,UAAkB;IACzC,IAAI,CAAC;QACD,IAAA,4BAAU,EAAC,UAAU,CAAC,CAAC;QAEvB,OAAO,IAAI,CAAC;IAEhB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACT,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAOY,QAAA,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC;AAQxB,QAAA,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC;AAavB,QAAA,QAAQ,GAAa;IAChC,QAAQ;IACR,UAAU;IACV,QAAQ;IACR,QAAQ,EAAR,gBAAQ;IACR,OAAO,EAAP,eAAO;CACR,CAAC;AAKF,kBAAe,gBAAQ,CAAC"}
@@ -0,0 +1,2 @@
declare const _default: (expressions: any) => any;
export default _default;
@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = (() => {
function convertAsterisk(expression, replecement) {
if (expression.indexOf('*') !== -1) {
return expression.replace('*', replecement);
}
return expression;
}
function convertAsterisksToRanges(expressions) {
expressions[0] = convertAsterisk(expressions[0], '0-59');
expressions[1] = convertAsterisk(expressions[1], '0-59');
expressions[2] = convertAsterisk(expressions[2], '0-23');
expressions[3] = convertAsterisk(expressions[3], '1-31');
expressions[4] = convertAsterisk(expressions[4], '1-12');
expressions[5] = convertAsterisk(expressions[5], '0-6');
return expressions;
}
return convertAsterisksToRanges;
})();
//# sourceMappingURL=asterisk-to-range-conversion.js.map
@@ -0,0 +1 @@
{"version":3,"file":"asterisk-to-range-conversion.js","sourceRoot":"","sources":["../../../../src/pattern/convertion/asterisk-to-range-conversion.ts"],"names":[],"mappings":";;AACA,kBAAe,CAAC,GAAG,EAAE;IACjB,SAAS,eAAe,CAAC,UAAU,EAAE,WAAW;QAC5C,IAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAC,CAAC;YAC/B,OAAO,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,SAAS,wBAAwB,CAAC,WAAW;QACzC,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACxD,OAAO,WAAW,CAAC;IACvB,CAAC;IAED,OAAO,wBAAwB,CAAC;AACpC,CAAC,CAAC,EAAE,CAAC"}
@@ -0,0 +1,2 @@
declare const _default: (expression: any) => any;
export default _default;
@@ -0,0 +1,42 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const month_names_conversion_1 = __importDefault(require("./month-names-conversion"));
const week_day_names_conversion_1 = __importDefault(require("./week-day-names-conversion"));
const asterisk_to_range_conversion_1 = __importDefault(require("./asterisk-to-range-conversion"));
const range_conversion_1 = __importDefault(require("./range-conversion"));
exports.default = (() => {
function appendSeccondExpression(expressions) {
if (expressions.length === 5) {
return ['0'].concat(expressions);
}
return expressions;
}
function removeSpaces(str) {
return str.replace(/\s{2,}/g, ' ').trim();
}
function normalizeIntegers(expressions) {
for (let i = 0; i < expressions.length; i++) {
const numbers = expressions[i].split(',');
for (let j = 0; j < numbers.length; j++) {
numbers[j] = parseInt(numbers[j]);
}
expressions[i] = numbers;
}
return expressions;
}
function interprete(expression) {
let expressions = removeSpaces(`${expression}`).split(' ');
expressions = appendSeccondExpression(expressions);
expressions[4] = (0, month_names_conversion_1.default)(expressions[4]);
expressions[5] = (0, week_day_names_conversion_1.default)(expressions[5]);
expressions = (0, asterisk_to_range_conversion_1.default)(expressions);
expressions = (0, range_conversion_1.default)(expressions);
expressions = normalizeIntegers(expressions);
return expressions;
}
return interprete;
})();
//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/pattern/convertion/index.ts"],"names":[],"mappings":";;;;;AAAA,sFAA4D;AAC5D,4FAAiE;AACjE,kGAAsE;AACtE,0EAA+C;AAE/C,kBAAe,CAAC,GAAG,EAAE;IAEjB,SAAS,uBAAuB,CAAC,WAAW;QACxC,IAAG,WAAW,CAAC,MAAM,KAAK,CAAC,EAAC,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,WAAW,CAAC;IACvB,CAAC;IAED,SAAS,YAAY,CAAC,GAAG;QACrB,OAAO,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,CAAC;IAGD,SAAS,iBAAiB,CAAC,WAAW;QAClC,KAAK,IAAI,CAAC,GAAC,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC,CAAC;YACvC,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC1C,KAAK,IAAI,CAAC,GAAC,CAAC,EAAE,CAAC,GAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC,CAAC;gBACjC,OAAO,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;YACtC,CAAC;YACD,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;QAC7B,CAAC;QACD,OAAO,WAAW,CAAC;IACvB,CAAC;IAmBD,SAAS,UAAU,CAAC,UAAU;QAC1B,IAAI,WAAW,GAAG,YAAY,CAAC,GAAG,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3D,WAAW,GAAG,uBAAuB,CAAC,WAAW,CAAC,CAAC;QACnD,WAAW,CAAC,CAAC,CAAC,GAAG,IAAA,gCAAoB,EAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QACtD,WAAW,CAAC,CAAC,CAAC,GAAG,IAAA,mCAAsB,EAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,WAAW,GAAG,IAAA,sCAAwB,EAAC,WAAW,CAAC,CAAC;QACpD,WAAW,GAAG,IAAA,0BAAa,EAAC,WAAW,CAAC,CAAC;QAEzC,WAAW,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;QAE7C,OAAO,WAAW,CAAC;IACvB,CAAC;IAED,OAAO,UAAU,CAAC;AACtB,CAAC,CAAC,EAAE,CAAC"}
@@ -0,0 +1,2 @@
declare const _default: (monthExpression: any) => any;
export default _default;
@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = (() => {
const months = ['january', 'february', 'march', 'april', 'may', 'june', 'july',
'august', 'september', 'october', 'november', 'december'];
const shortMonths = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug',
'sep', 'oct', 'nov', 'dec'];
function convertMonthName(expression, items) {
for (let i = 0; i < items.length; i++) {
expression = expression.replace(new RegExp(items[i], 'gi'), i + 1);
}
return expression;
}
function interprete(monthExpression) {
monthExpression = convertMonthName(monthExpression, months);
monthExpression = convertMonthName(monthExpression, shortMonths);
return monthExpression;
}
return interprete;
})();
//# sourceMappingURL=month-names-conversion.js.map
@@ -0,0 +1 @@
{"version":3,"file":"month-names-conversion.js","sourceRoot":"","sources":["../../../../src/pattern/convertion/month-names-conversion.ts"],"names":[],"mappings":";;AAAA,kBAAe,CAAC,GAAG,EAAE;IACjB,MAAM,MAAM,GAAG,CAAC,SAAS,EAAC,UAAU,EAAC,OAAO,EAAC,OAAO,EAAC,KAAK,EAAC,MAAM,EAAC,MAAM;QACpE,QAAQ,EAAC,WAAW,EAAC,SAAS,EAAC,UAAU,EAAC,UAAU,CAAC,CAAC;IAC1D,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;QACvE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAEhC,SAAS,gBAAgB,CAAC,UAAU,EAAE,KAAK;QACvC,KAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC,CAAC;YAClC,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,SAAS,UAAU,CAAC,eAAe;QAC/B,eAAe,GAAG,gBAAgB,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;QAC5D,eAAe,GAAG,gBAAgB,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC;QACjE,OAAO,eAAe,CAAC;IAC3B,CAAC;IAED,OAAO,UAAU,CAAC;AACtB,CAAC,CAAC,EAAE,CAAC"}
@@ -0,0 +1,2 @@
declare const _default: (expressions: any) => any;
export default _default;
@@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = (() => {
function replaceWithRange(expression, text, init, end, stepTxt) {
const step = parseInt(stepTxt);
const numbers = [];
let last = parseInt(end);
let first = parseInt(init);
if (first > last) {
last = parseInt(init);
first = parseInt(end);
}
for (let i = first; i <= last; i += step) {
numbers.push(i);
}
return expression.replace(new RegExp(text, 'i'), numbers.join());
}
function convertRange(expression) {
const rangeRegEx = /(\d+)-(\d+)(\/(\d+)|)/;
let match = rangeRegEx.exec(expression);
while (match !== null && match.length > 0) {
expression = replaceWithRange(expression, match[0], match[1], match[2], match[4] || '1');
match = rangeRegEx.exec(expression);
}
return expression;
}
function convertAllRanges(expressions) {
for (let i = 0; i < expressions.length; i++) {
expressions[i] = convertRange(expressions[i]);
}
return expressions;
}
return convertAllRanges;
})();
//# sourceMappingURL=range-conversion.js.map
@@ -0,0 +1 @@
{"version":3,"file":"range-conversion.js","sourceRoot":"","sources":["../../../../src/pattern/convertion/range-conversion.ts"],"names":[],"mappings":";;AAAA,kBAAe,CAAE,GAAG,EAAE;IAClB,SAAS,gBAAgB,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO;QAC1D,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/B,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,IAAI,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAE3B,IAAG,KAAK,GAAG,IAAI,EAAC,CAAC;YACb,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YACtB,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;QAED,KAAI,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;YACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;QAED,OAAO,UAAU,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,SAAS,YAAY,CAAC,UAAU;QAC5B,MAAM,UAAU,GAAG,uBAAuB,CAAC;QAC3C,IAAI,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACxC,OAAM,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAC,CAAC;YACtC,UAAU,GAAG,gBAAgB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;YACzF,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,SAAS,gBAAgB,CAAC,WAAW;QACjC,KAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC,CAAC;YACxC,WAAW,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,WAAW,CAAC;IACvB,CAAC;IAED,OAAO,gBAAgB,CAAC;AAC5B,CAAC,CAAC,EAAE,CAAC"}
@@ -0,0 +1,2 @@
declare const _default: (expression: any) => any;
export default _default;
@@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = (() => {
const weekDays = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday',
'friday', 'saturday'];
const shortWeekDays = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
function convertWeekDayName(expression, items) {
for (let i = 0; i < items.length; i++) {
expression = expression.replace(new RegExp(items[i], 'gi'), i);
}
return expression;
}
function convertWeekDays(expression) {
expression = expression.replace('7', '0');
expression = convertWeekDayName(expression, weekDays);
return convertWeekDayName(expression, shortWeekDays);
}
return convertWeekDays;
})();
//# sourceMappingURL=week-day-names-conversion.js.map
@@ -0,0 +1 @@
{"version":3,"file":"week-day-names-conversion.js","sourceRoot":"","sources":["../../../../src/pattern/convertion/week-day-names-conversion.ts"],"names":[],"mappings":";;AAAA,kBAAe,CAAC,GAAG,EAAE;IACjB,MAAM,QAAQ,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU;QACpE,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC1B,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAExE,SAAS,kBAAkB,CAAC,UAAU,EAAE,KAAK;QACzC,KAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC,CAAC;YAClC,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,SAAS,eAAe,CAAC,UAAU;QAC/B,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC1C,UAAU,GAAG,kBAAkB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACtD,OAAO,kBAAkB,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,eAAe,CAAC;AAC3B,CAAC,CAAC,EAAE,CAAC"}
@@ -0,0 +1,2 @@
declare function validate(pattern: any): void;
export default validate;
@@ -0,0 +1,61 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const index_1 = __importDefault(require("../convertion/index"));
const validationRegex = /^(?:\d+|\*|\*\/\d+)$/;
function isValidExpression(expression, min, max) {
const options = expression;
for (const option of options) {
const optionAsInt = parseInt(option, 10);
if ((!Number.isNaN(optionAsInt) &&
(optionAsInt < min || optionAsInt > max)) ||
!validationRegex.test(option))
return false;
}
return true;
}
function isInvalidSecond(expression) {
return !isValidExpression(expression, 0, 59);
}
function isInvalidMinute(expression) {
return !isValidExpression(expression, 0, 59);
}
function isInvalidHour(expression) {
return !isValidExpression(expression, 0, 23);
}
function isInvalidDayOfMonth(expression) {
return !isValidExpression(expression, 1, 31);
}
function isInvalidMonth(expression) {
return !isValidExpression(expression, 1, 12);
}
function isInvalidWeekDay(expression) {
return !isValidExpression(expression, 0, 7);
}
function validateFields(patterns, executablePatterns) {
if (isInvalidSecond(executablePatterns[0]))
throw new Error(`${patterns[0]} is a invalid expression for second`);
if (isInvalidMinute(executablePatterns[1]))
throw new Error(`${patterns[1]} is a invalid expression for minute`);
if (isInvalidHour(executablePatterns[2]))
throw new Error(`${patterns[2]} is a invalid expression for hour`);
if (isInvalidDayOfMonth(executablePatterns[3]))
throw new Error(`${patterns[3]} is a invalid expression for day of month`);
if (isInvalidMonth(executablePatterns[4]))
throw new Error(`${patterns[4]} is a invalid expression for month`);
if (isInvalidWeekDay(executablePatterns[5]))
throw new Error(`${patterns[5]} is a invalid expression for week day`);
}
function validate(pattern) {
if (typeof pattern !== 'string')
throw new TypeError('pattern must be a string!');
const patterns = pattern.split(' ');
const executablePatterns = (0, index_1.default)(pattern);
if (patterns.length === 5)
patterns.unshift('0');
validateFields(patterns, executablePatterns);
}
exports.default = validate;
//# sourceMappingURL=pattern-validation.js.map
@@ -0,0 +1 @@
{"version":3,"file":"pattern-validation.js","sourceRoot":"","sources":["../../../../src/pattern/validation/pattern-validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
type PromiseState = 'pending' | 'fulfilled' | 'rejected';
export declare class TrackedPromise<T> {
promise: Promise<T>;
error: any;
state: PromiseState;
value?: T;
constructor(executor: (resolve: (value: T) => void, reject: (reason?: any) => void) => void);
getPromise(): Promise<T>;
getState(): PromiseState;
isPending(): boolean;
isFulfilled(): boolean;
isRejected(): boolean;
getValue(): T | undefined;
getError(): any;
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
finally(onfinally?: (() => void) | undefined | null): Promise<T>;
}
export {};
@@ -0,0 +1,55 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TrackedPromise = void 0;
class TrackedPromise {
promise;
error;
state;
value;
constructor(executor) {
this.state = 'pending';
this.promise = new Promise((resolve, reject) => {
executor((value) => {
this.state = 'fulfilled';
this.value = value;
resolve(value);
}, (error) => {
this.state = 'rejected';
this.error = error;
reject(error);
});
});
}
getPromise() {
return this.promise;
}
getState() {
return this.state;
}
isPending() {
return this.state === 'pending';
}
isFulfilled() {
return this.state === 'fulfilled';
}
isRejected() {
return this.state === 'rejected';
}
getValue() {
return this.value;
}
getError() {
return this.error;
}
then(onfulfilled, onrejected) {
return this.promise.then(onfulfilled, onrejected);
}
catch(onrejected) {
return this.promise.catch(onrejected);
}
finally(onfinally) {
return this.promise.finally(onfinally);
}
}
exports.TrackedPromise = TrackedPromise;
//# sourceMappingURL=tracked-promise.js.map
@@ -0,0 +1 @@
{"version":3,"file":"tracked-promise.js","sourceRoot":"","sources":["../../../src/promise/tracked-promise.ts"],"names":[],"mappings":";;;AAEA,MAAa,cAAc;IACzB,OAAO,CAAa;IACpB,KAAK,CAAM;IACX,KAAK,CAAe;IACpB,KAAK,CAAK;IAEV,YAAY,QAA+E;QACzF,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QAEvB,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAChD,QAAQ,CACN,CAAC,KAAK,EAAE,EAAE;gBACR,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC;gBACzB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;gBACnB,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC,EACD,CAAC,KAAK,EAAE,EAAE;gBACR,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC;gBACxB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;gBACnB,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC;IAClC,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,KAAK,KAAK,WAAW,CAAC;IACpC,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,KAAK,KAAK,UAAU,CAAC;IACnC,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,IAAI,CACF,WAAiF,EACjF,UAAmF;QAEnF,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CACH,UAAiF;QAEjF,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,CAAC,SAA2C;QACjD,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACzC,CAAC;CACF;AArED,wCAqEC"}
@@ -0,0 +1,42 @@
import { Execution } from "../tasks/scheduled-task";
import { TimeMatcher } from "../time/time-matcher";
type OnFn = (date: Date) => void | Promise<void>;
type OnErrorHookFn = (date: Date, error: Error, execution: Execution) => void | Promise<void>;
type OnHookFn = (date: Date, execution: Execution) => boolean | Promise<boolean>;
type OnMatch = (date: Date, execution: Execution) => any | Promise<any>;
export type RunnerOptions = {
noOverlap?: boolean;
timezone?: string;
maxExecutions?: number;
maxRandomDelay?: number;
onMissedExecution?: OnFn;
onOverlap?: OnFn;
onError?: OnErrorHookFn;
onFinished?: OnHookFn;
beforeRun?: OnHookFn;
onMaxExecutions?: OnFn;
};
export declare class Runner {
timeMatcher: TimeMatcher;
onMatch: OnMatch;
noOverlap: boolean;
maxExecutions?: number;
maxRandomDelay: number;
runCount: number;
running: boolean;
heartBeatTimeout?: NodeJS.Timeout;
onMissedExecution: OnFn;
onOverlap: OnFn;
onError: OnErrorHookFn;
beforeRun: OnHookFn;
onFinished: OnHookFn;
onMaxExecutions: OnFn;
constructor(timeMatcher: TimeMatcher, onMatch: OnMatch, options?: RunnerOptions);
start(): void;
nextRun(): Date;
stop(): void;
isStarted(): boolean;
isStopped(): boolean;
execute(): Promise<void>;
}
export {};
+192
View File
@@ -0,0 +1,192 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Runner = void 0;
const create_id_1 = require("../create-id");
const logger_1 = __importDefault(require("../logger"));
const tracked_promise_1 = require("../promise/tracked-promise");
function emptyOnFn() { }
;
function emptyHookFn() { return true; }
;
function defaultOnError(date, error) {
logger_1.default.error('Task failed with error!', error);
}
class Runner {
timeMatcher;
onMatch;
noOverlap;
maxExecutions;
maxRandomDelay;
runCount;
running;
heartBeatTimeout;
onMissedExecution;
onOverlap;
onError;
beforeRun;
onFinished;
onMaxExecutions;
constructor(timeMatcher, onMatch, options) {
this.timeMatcher = timeMatcher;
this.onMatch = onMatch;
this.noOverlap = options == undefined || options.noOverlap === undefined ? false : options.noOverlap;
this.maxExecutions = options?.maxExecutions;
this.maxRandomDelay = options?.maxRandomDelay || 0;
this.onMissedExecution = options?.onMissedExecution || emptyOnFn;
this.onOverlap = options?.onOverlap || emptyOnFn;
this.onError = options?.onError || defaultOnError;
this.onFinished = options?.onFinished || emptyHookFn;
this.beforeRun = options?.beforeRun || emptyHookFn;
this.onMaxExecutions = options?.onMaxExecutions || emptyOnFn;
this.runCount = 0;
this.running = false;
}
start() {
this.running = true;
let lastExecution;
let expectedNextExecution;
const scheduleNextHeartBeat = (currentDate) => {
if (this.running) {
clearTimeout(this.heartBeatTimeout);
this.heartBeatTimeout = setTimeout(heartBeat, getDelay(this.timeMatcher, currentDate));
}
};
const runTask = (date) => {
return new Promise(async (resolve) => {
const execution = {
id: (0, create_id_1.createID)('exec'),
reason: 'scheduled'
};
const shouldExecute = await this.beforeRun(date, execution);
const randomDelay = Math.floor(Math.random() * this.maxRandomDelay);
if (shouldExecute) {
setTimeout(async () => {
try {
this.runCount++;
execution.startedAt = new Date();
const result = await this.onMatch(date, execution);
execution.finishedAt = new Date();
execution.result = result;
this.onFinished(date, execution);
if (this.maxExecutions && this.runCount >= this.maxExecutions) {
this.onMaxExecutions(date);
this.stop();
}
}
catch (error) {
execution.finishedAt = new Date();
execution.error = error;
this.onError(date, error, execution);
}
resolve(true);
}, randomDelay);
}
});
};
const checkAndRun = (date) => {
return new tracked_promise_1.TrackedPromise(async (resolve, reject) => {
try {
if (this.timeMatcher.match(date)) {
await runTask(date);
}
resolve(true);
}
catch (err) {
reject(err);
}
});
};
const heartBeat = async () => {
const currentDate = nowWithoutMs();
if (expectedNextExecution && expectedNextExecution.getTime() < currentDate.getTime()) {
while (expectedNextExecution.getTime() < currentDate.getTime()) {
logger_1.default.warn(`missed execution at ${expectedNextExecution}! Possible blocking IO or high CPU user at the same process used by node-cron.`);
expectedNextExecution = this.timeMatcher.getNextMatch(expectedNextExecution);
runAsync(this.onMissedExecution, expectedNextExecution, defaultOnError);
}
}
if (lastExecution && lastExecution.getState() === 'pending') {
runAsync(this.onOverlap, currentDate, defaultOnError);
if (this.noOverlap) {
logger_1.default.warn('task still running, new execution blocked by overlap prevention!');
expectedNextExecution = this.timeMatcher.getNextMatch(currentDate);
scheduleNextHeartBeat(currentDate);
return;
}
}
lastExecution = checkAndRun(currentDate);
expectedNextExecution = this.timeMatcher.getNextMatch(currentDate);
scheduleNextHeartBeat(currentDate);
};
this.heartBeatTimeout = setTimeout(() => {
heartBeat();
}, getDelay(this.timeMatcher, nowWithoutMs()));
}
nextRun() {
return this.timeMatcher.getNextMatch(new Date());
}
stop() {
this.running = false;
if (this.heartBeatTimeout) {
clearTimeout(this.heartBeatTimeout);
this.heartBeatTimeout = undefined;
}
}
isStarted() {
return !!this.heartBeatTimeout && this.running;
}
isStopped() {
return !this.isStarted();
}
async execute() {
const date = new Date();
const execution = {
id: (0, create_id_1.createID)('exec'),
reason: 'invoked'
};
try {
const shouldExecute = await this.beforeRun(date, execution);
if (shouldExecute) {
this.runCount++;
execution.startedAt = new Date();
const result = await this.onMatch(date, execution);
execution.finishedAt = new Date();
execution.result = result;
this.onFinished(date, execution);
}
}
catch (error) {
execution.finishedAt = new Date();
execution.error = error;
this.onError(date, error, execution);
}
}
}
exports.Runner = Runner;
async function runAsync(fn, date, onError) {
try {
await fn(date);
}
catch (error) {
onError(date, error);
}
}
function getDelay(timeMatcher, currentDate) {
const maxDelay = 86400000;
const nextRun = timeMatcher.getNextMatch(currentDate);
const now = new Date();
const delay = nextRun.getTime() - now.getTime();
if (delay > maxDelay) {
return maxDelay;
}
return Math.max(0, delay);
}
function nowWithoutMs() {
const date = new Date();
date.setMilliseconds(0);
return date;
}
//# sourceMappingURL=runner.js.map
File diff suppressed because one or more lines are too long
+11
View File
@@ -0,0 +1,11 @@
import { ScheduledTask } from "./tasks/scheduled-task";
declare const tasks: Map<string, ScheduledTask>;
export declare class TaskRegistry {
add(task: ScheduledTask): void;
get(taskId: string): ScheduledTask | undefined;
remove(task: ScheduledTask): void;
all(): typeof tasks;
has(taskId: string): boolean;
killAll(): void;
}
export {};
+35
View File
@@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TaskRegistry = void 0;
const tasks = new Map();
class TaskRegistry {
add(task) {
if (this.has(task.id)) {
throw Error(`task ${task.id} already registred!`);
}
tasks.set(task.id, task);
task.on('task:destroyed', () => {
this.remove(task);
});
}
get(taskId) {
return tasks.get(taskId);
}
remove(task) {
if (this.has(task.id)) {
task?.destroy();
tasks.delete(task.id);
}
}
all() {
return tasks;
}
has(taskId) {
return tasks.has(taskId);
}
killAll() {
tasks.forEach(id => this.remove(id));
}
}
exports.TaskRegistry = TaskRegistry;
//# sourceMappingURL=task-registry.js.map
@@ -0,0 +1 @@
{"version":3,"file":"task-registry.js","sourceRoot":"","sources":["../../src/task-registry.ts"],"names":[],"mappings":";;;AAEA,MAAM,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;AAEhD,MAAa,YAAY;IACvB,GAAG,CAAC,IAAmB;QACrB,IAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAC,CAAC;YACpB,MAAM,KAAK,CAAC,QAAQ,IAAI,CAAC,EAAE,qBAAqB,CAAC,CAAA;QACnD,CAAC;QAED,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAEzB,IAAI,CAAC,EAAE,CAAC,gBAAgB,EAAE,GAAG,EAAE;YAC7B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,GAAG,CAAC,MAAc;QAChB,OAAO,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,IAAmB;QACxB,IAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAC,CAAC;YACpB,IAAI,EAAE,OAAO,EAAE,CAAC;YAChB,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,GAAG;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,GAAG,CAAC,MAAc;QAChB,OAAO,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO;QACN,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IACtC,CAAC;CACF;AAnCD,oCAmCC"}
@@ -0,0 +1,28 @@
import { ChildProcess } from 'child_process';
import { ScheduledTask, TaskContext, TaskEvent, TaskOptions } from '../scheduled-task';
import { EventEmitter } from 'stream';
import { StateMachine } from '../state-machine';
declare class TaskEmitter extends EventEmitter {
}
declare class BackgroundScheduledTask implements ScheduledTask {
emitter: TaskEmitter;
id: string;
name: string;
cronExpression: any;
taskPath: any;
options?: any;
forkProcess?: ChildProcess;
stateMachine: StateMachine;
constructor(cronExpression: string, taskPath: string, options?: TaskOptions);
getNextRun(): Date | null;
start(): Promise<void>;
stop(): Promise<void>;
getStatus(): string;
destroy(): Promise<void>;
execute(): Promise<any>;
on(event: TaskEvent, fun: (context: TaskContext) => Promise<void> | void): void;
off(event: TaskEvent, fun: (context: TaskContext) => Promise<void> | void): void;
once(event: TaskEvent, fun: (context: TaskContext) => Promise<void> | void): void;
private createContext;
}
export default BackgroundScheduledTask;
@@ -0,0 +1,220 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = require("path");
const child_process_1 = require("child_process");
const create_id_1 = require("../../create-id");
const stream_1 = require("stream");
const state_machine_1 = require("../state-machine");
const localized_time_1 = require("../../time/localized-time");
const logger_1 = __importDefault(require("../../logger"));
const time_matcher_1 = require("../../time/time-matcher");
const daemonPath = (0, path_1.resolve)(__dirname, 'daemon.js');
class TaskEmitter extends stream_1.EventEmitter {
}
class BackgroundScheduledTask {
emitter;
id;
name;
cronExpression;
taskPath;
options;
forkProcess;
stateMachine;
constructor(cronExpression, taskPath, options) {
this.cronExpression = cronExpression;
this.taskPath = taskPath;
this.options = options;
this.id = (0, create_id_1.createID)('task');
this.name = options?.name || this.id;
this.emitter = new TaskEmitter();
this.stateMachine = new state_machine_1.StateMachine('stopped');
this.on('task:stopped', () => {
this.forkProcess?.kill();
this.forkProcess = undefined;
this.stateMachine.changeState('stopped');
});
this.on('task:destroyed', () => {
this.forkProcess?.kill();
this.forkProcess = undefined;
this.stateMachine.changeState('destroyed');
});
}
getNextRun() {
if (this.stateMachine.state !== 'stopped') {
const timeMatcher = new time_matcher_1.TimeMatcher(this.cronExpression, this.options?.timezone);
return timeMatcher.getNextMatch(new Date());
}
return null;
}
start() {
return new Promise((resolve, reject) => {
if (this.forkProcess) {
return resolve(undefined);
}
const timeout = setTimeout(() => {
reject(new Error('Start operation timed out'));
}, 5000);
try {
this.forkProcess = (0, child_process_1.fork)(daemonPath);
this.forkProcess.on('error', (err) => {
clearTimeout(timeout);
reject(new Error(`Error on daemon: ${err.message}`));
});
this.forkProcess.on('exit', (code, signal) => {
if (code !== 0 && signal !== 'SIGTERM') {
const erro = new Error(`node-cron daemon exited with code ${code || signal}`);
logger_1.default.error(erro);
clearTimeout(timeout);
reject(erro);
}
});
this.forkProcess.on('message', (message) => {
if (message.jsonError) {
if (message.context?.execution) {
message.context.execution.error = deserializeError(message.jsonError);
delete message.jsonError;
}
}
if (message.context?.task?.state) {
this.stateMachine.changeState(message.context?.task?.state);
}
if (message.context) {
const execution = message.context?.execution;
delete execution?.hasError;
const context = this.createContext(new Date(message.context.date), execution);
this.emitter.emit(message.event, context);
}
});
this.once('task:started', () => {
this.stateMachine.changeState('idle');
clearTimeout(timeout);
resolve(undefined);
});
this.forkProcess.send({
command: 'task:start',
path: this.taskPath,
cron: this.cronExpression,
options: this.options
});
}
catch (error) {
reject(error);
}
});
}
stop() {
return new Promise((resolve, reject) => {
if (!this.forkProcess) {
return resolve(undefined);
}
const timeoutId = setTimeout(() => {
clearTimeout(timeoutId);
reject(new Error('Stop operation timed out'));
}, 5000);
const cleanupAndResolve = () => {
clearTimeout(timeoutId);
this.off('task:stopped', onStopped);
this.forkProcess = undefined;
resolve(undefined);
};
const onStopped = () => {
cleanupAndResolve();
};
this.once('task:stopped', onStopped);
this.forkProcess.send({
command: 'task:stop'
});
});
}
getStatus() {
return this.stateMachine.state;
}
destroy() {
return new Promise((resolve, reject) => {
if (!this.forkProcess) {
return resolve(undefined);
}
const timeoutId = setTimeout(() => {
clearTimeout(timeoutId);
reject(new Error('Destroy operation timed out'));
}, 5000);
const onDestroy = () => {
clearTimeout(timeoutId);
this.off('task:destroyed', onDestroy);
resolve(undefined);
};
this.once('task:destroyed', onDestroy);
this.forkProcess.send({
command: 'task:destroy'
});
});
}
execute() {
return new Promise((resolve, reject) => {
if (!this.forkProcess) {
return reject(new Error('Cannot execute background task because it hasn\'t been started yet. Please initialize the task using the start() method before attempting to execute it.'));
}
const timeoutId = setTimeout(() => {
cleanupListeners();
reject(new Error('Execution timeout exceeded'));
}, 5000);
const cleanupListeners = () => {
clearTimeout(timeoutId);
this.off('execution:finished', onFinished);
this.off('execution:failed', onFail);
};
const onFinished = (context) => {
cleanupListeners();
resolve(context.execution?.result);
};
const onFail = (context) => {
cleanupListeners();
reject(context.execution?.error || new Error('Execution failed without specific error'));
};
this.once('execution:finished', onFinished);
this.once('execution:failed', onFail);
this.forkProcess.send({
command: 'task:execute'
});
});
}
on(event, fun) {
this.emitter.on(event, fun);
}
off(event, fun) {
this.emitter.off(event, fun);
}
once(event, fun) {
this.emitter.once(event, fun);
}
createContext(executionDate, execution) {
const localTime = new localized_time_1.LocalizedTime(executionDate, this.options?.timezone);
const ctx = {
date: localTime.toDate(),
dateLocalIso: localTime.toISO(),
triggeredAt: new Date(),
task: this,
execution: execution
};
return ctx;
}
}
function deserializeError(str) {
const data = JSON.parse(str);
const Err = globalThis[data.name] || Error;
const err = new Err(data.message);
if (data.stack) {
err.stack = data.stack;
}
Object.keys(data).forEach(key => {
if (!['name', 'message', 'stack'].includes(key)) {
err[key] = data[key];
}
});
return err;
}
exports.default = BackgroundScheduledTask;
//# sourceMappingURL=background-scheduled-task.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
import { ScheduledTask } from "../scheduled-task";
export declare function startDaemon(message: any): Promise<ScheduledTask>;
export declare function bind(): void;
@@ -0,0 +1,142 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.startDaemon = startDaemon;
exports.bind = bind;
const url_1 = require("url");
const logger_1 = __importDefault(require("../../logger"));
const inline_scheduled_task_1 = require("../inline-scheduled-task");
async function startDaemon(message) {
let script;
try {
script = await Promise.resolve(`${message.path}`).then(s => __importStar(require(s)));
}
catch {
script = await Promise.resolve(`${(0, url_1.fileURLToPath)(message.path)}`).then(s => __importStar(require(s)));
}
const task = new inline_scheduled_task_1.InlineScheduledTask(message.cron, script.task, message.options);
task.on('task:started', (context => sendEvent('task:started', context)));
task.on('task:stopped', (context => sendEvent('task:stopped', context)));
task.on('task:destroyed', (context => sendEvent('task:destroyed', context)));
task.on('execution:started', (context => sendEvent('execution:started', context)));
task.on('execution:finished', (context => sendEvent('execution:finished', context)));
task.on('execution:failed', (context => sendEvent('execution:failed', context)));
task.on('execution:missed', (context => sendEvent('execution:missed', context)));
task.on('execution:overlap', (context => sendEvent('execution:overlap', context)));
task.on('execution:maxReached', (context => sendEvent('execution:maxReached', context)));
if (process.send)
process.send({ event: 'daemon:started' });
task.start();
return task;
}
function sendEvent(event, context) {
const message = { event: event, context: safelySerializeContext(context) };
if (context.execution?.error) {
message.jsonError = serializeError(context.execution?.error);
}
if (process.send)
process.send(message);
}
function serializeError(err) {
const plain = {
name: err.name,
message: err.message,
stack: err.stack,
...Object.getOwnPropertyNames(err)
.filter(k => !['name', 'message', 'stack'].includes(k))
.reduce((acc, k) => {
acc[k] = err[k];
return acc;
}, {})
};
return JSON.stringify(plain);
}
function safelySerializeContext(context) {
const safeContext = {
date: context.date,
dateLocalIso: context.dateLocalIso,
triggeredAt: context.triggeredAt
};
if (context.task) {
safeContext.task = {
id: context.task.id,
name: context.task.name,
status: context.task.getStatus()
};
}
if (context.execution) {
safeContext.execution = {
id: context.execution.id,
reason: context.execution.reason,
startedAt: context.execution.startedAt,
finishedAt: context.execution.finishedAt,
hasError: !!context.execution.error,
result: context.execution.result
};
}
return safeContext;
}
function bind() {
let task;
process.on('message', async (message) => {
switch (message.command) {
case 'task:start':
task = await startDaemon(message);
return task;
case 'task:stop':
if (task)
task.stop();
return task;
case 'task:destroy':
if (task)
task.destroy();
return task;
case 'task:execute':
try {
if (task)
await task.execute();
}
catch (error) {
logger_1.default.debug('Daemon task:execute falied:', error);
}
return task;
}
});
}
bind();
//# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../../../src/tasks/background-scheduled-task/daemon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
"use strict";
//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/tasks/background-scheduled-task/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,30 @@
import EventEmitter from "events";
import { ScheduledTask, TaskContext, TaskEvent, TaskFn, TaskOptions } from "./scheduled-task";
import { Runner } from "../scheduler/runner";
import { TimeMatcher } from "../time/time-matcher";
import { StateMachine } from "./state-machine";
declare class TaskEmitter extends EventEmitter {
}
export declare class InlineScheduledTask implements ScheduledTask {
emitter: TaskEmitter;
cronExpression: string;
timeMatcher: TimeMatcher;
runner: Runner;
id: string;
name: string;
stateMachine: StateMachine;
timezone?: string;
constructor(cronExpression: string, taskFn: TaskFn, options?: TaskOptions);
getNextRun(): Date | null;
private changeState;
start(): void;
stop(): void;
getStatus(): string;
destroy(): void;
execute(): Promise<any>;
on(event: TaskEvent, fun: (context: TaskContext) => Promise<void> | void): void;
off(event: TaskEvent, fun: (context: TaskContext) => Promise<void> | void): void;
once(event: TaskEvent, fun: (context: TaskContext) => Promise<void> | void): void;
private createContext;
}
export {};
@@ -0,0 +1,144 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.InlineScheduledTask = void 0;
const events_1 = __importDefault(require("events"));
const runner_1 = require("../scheduler/runner");
const time_matcher_1 = require("../time/time-matcher");
const create_id_1 = require("../create-id");
const state_machine_1 = require("./state-machine");
const logger_1 = __importDefault(require("../logger"));
const localized_time_1 = require("../time/localized-time");
class TaskEmitter extends events_1.default {
}
class InlineScheduledTask {
emitter;
cronExpression;
timeMatcher;
runner;
id;
name;
stateMachine;
timezone;
constructor(cronExpression, taskFn, options) {
this.emitter = new TaskEmitter();
this.cronExpression = cronExpression;
this.id = (0, create_id_1.createID)('task', 12);
this.name = options?.name || this.id;
this.timezone = options?.timezone;
this.timeMatcher = new time_matcher_1.TimeMatcher(cronExpression, options?.timezone);
this.stateMachine = new state_machine_1.StateMachine();
const runnerOptions = {
timezone: options?.timezone,
noOverlap: options?.noOverlap,
maxExecutions: options?.maxExecutions,
maxRandomDelay: options?.maxRandomDelay,
beforeRun: (date, execution) => {
if (execution.reason === 'scheduled') {
this.changeState('running');
}
this.emitter.emit('execution:started', this.createContext(date, execution));
return true;
},
onFinished: (date, execution) => {
if (execution.reason === 'scheduled') {
this.changeState('idle');
}
this.emitter.emit('execution:finished', this.createContext(date, execution));
return true;
},
onError: (date, error, execution) => {
logger_1.default.error(error);
this.emitter.emit('execution:failed', this.createContext(date, execution));
this.changeState('idle');
},
onOverlap: (date) => {
this.emitter.emit('execution:overlap', this.createContext(date));
},
onMissedExecution: (date) => {
this.emitter.emit('execution:missed', this.createContext(date));
},
onMaxExecutions: (date) => {
this.emitter.emit('execution:maxReached', this.createContext(date));
this.destroy();
}
};
this.runner = new runner_1.Runner(this.timeMatcher, (date, execution) => {
return taskFn(this.createContext(date, execution));
}, runnerOptions);
}
getNextRun() {
if (this.stateMachine.state !== 'stopped') {
return this.runner.nextRun();
}
return null;
}
changeState(state) {
if (this.runner.isStarted()) {
this.stateMachine.changeState(state);
}
}
start() {
if (this.runner.isStopped()) {
this.runner.start();
this.stateMachine.changeState('idle');
this.emitter.emit('task:started', this.createContext(new Date()));
}
}
stop() {
if (this.runner.isStarted()) {
this.runner.stop();
this.stateMachine.changeState('stopped');
this.emitter.emit('task:stopped', this.createContext(new Date()));
}
}
getStatus() {
return this.stateMachine.state;
}
destroy() {
if (this.stateMachine.state === 'destroyed')
return;
this.stop();
this.stateMachine.changeState('destroyed');
this.emitter.emit('task:destroyed', this.createContext(new Date()));
}
execute() {
return new Promise((resolve, reject) => {
const onFail = (context) => {
this.off('execution:finished', onFail);
reject(context.execution?.error);
};
const onFinished = (context) => {
this.off('execution:failed', onFail);
resolve(context.execution?.result);
};
this.once('execution:finished', onFinished);
this.once('execution:failed', onFail);
this.runner.execute();
});
}
on(event, fun) {
this.emitter.on(event, fun);
}
off(event, fun) {
this.emitter.off(event, fun);
}
once(event, fun) {
this.emitter.once(event, fun);
}
createContext(executionDate, execution) {
const localTime = new localized_time_1.LocalizedTime(executionDate, this.timezone);
const ctx = {
date: localTime.toDate(),
dateLocalIso: localTime.toISO(),
triggeredAt: new Date(),
task: this,
execution: execution
};
return ctx;
}
}
exports.InlineScheduledTask = InlineScheduledTask;
//# sourceMappingURL=inline-scheduled-task.js.map
@@ -0,0 +1 @@
{"version":3,"file":"inline-scheduled-task.js","sourceRoot":"","sources":["../../../src/tasks/inline-scheduled-task.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
export type TaskContext = {
date: Date;
dateLocalIso: string;
task?: ScheduledTask;
execution?: Execution;
triggeredAt: Date;
};
export type TaskEvent = 'task:started' | 'task:stopped' | 'task:destroyed' | 'execution:started' | 'execution:finished' | 'execution:failed' | 'execution:missed' | 'execution:overlap' | 'execution:maxReached';
export type TaskOptions = {
timezone?: string;
name?: string;
noOverlap?: boolean;
maxExecutions?: number;
maxRandomDelay?: number;
};
export type Execution = {
id: string;
reason: 'invoked' | 'scheduled';
startedAt?: Date;
finishedAt?: Date;
error?: Error;
result?: any;
};
export type TaskFn = (context: TaskContext) => any | Promise<any>;
export interface ScheduledTask {
id: string;
name?: string;
start(): void | Promise<void>;
stop(): void | Promise<void>;
getStatus(): string | Promise<string>;
destroy(): void | Promise<void>;
execute(): Promise<any>;
getNextRun(): Date | null;
on(event: TaskEvent, fun: (context: TaskContext) => Promise<void> | void): void;
off(event: TaskEvent, fun: (context: TaskContext) => Promise<void> | void): void;
once(event: TaskEvent, fun: (context: TaskContext) => Promise<void> | void): void;
}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=scheduled-task.js.map
@@ -0,0 +1 @@
{"version":3,"file":"scheduled-task.js","sourceRoot":"","sources":["../../../src/tasks/scheduled-task.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
export type TaskState = 'stopped' | 'idle' | 'running' | 'destroyed';
export declare class StateMachine {
state: TaskState;
constructor(initial?: TaskState);
changeState(state: TaskState): void;
}
@@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.StateMachine = void 0;
const allowedTransitions = {
'stopped': ['stopped', 'idle', 'destroyed'],
'idle': ['idle', 'running', 'stopped', 'destroyed'],
'running': ['running', 'idle', 'stopped', 'destroyed'],
'destroyed': ['destroyed']
};
class StateMachine {
state;
constructor(initial = 'stopped') {
this.state = initial;
}
changeState(state) {
if (allowedTransitions[this.state].includes(state)) {
this.state = state;
}
else {
throw new Error(`invalid transition from ${this.state} to ${state}`);
}
}
}
exports.StateMachine = StateMachine;
//# sourceMappingURL=state-machine.js.map
@@ -0,0 +1 @@
{"version":3,"file":"state-machine.js","sourceRoot":"","sources":["../../../src/tasks/state-machine.ts"],"names":[],"mappings":";;;AAEA,MAAM,kBAAkB,GAAmC;IACzD,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC;IAC3C,MAAM,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,CAAC;IACnD,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC;IACtD,WAAW,EAAE,CAAC,WAAW,CAAC;CAC3B,CAAA;AAED,MAAa,YAAY;IACvB,KAAK,CAAY;IAEjB,YAAY,UAAqB,SAAS;QACxC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC;IACvB,CAAC;IAED,WAAW,CAAC,KAAgB;QAC1B,IAAG,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAC,CAAC;YACjD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,CAAC,KAAK,OAAO,KAAK,EAAE,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;CAEF;AAfD,oCAeC"}
@@ -0,0 +1,22 @@
type DateParts = {
day: number;
month: number;
year: number;
hour: number;
minute: number;
second: number;
milisecond: number;
weekday: string;
gmt: string;
};
export declare class LocalizedTime {
timestamp: number;
parts: DateParts;
timezone?: string | undefined;
constructor(date: Date, timezone?: string);
toDate(): Date;
toISO(): string;
getParts(): DateParts;
set(field: string, value: number): void;
}
export {};
@@ -0,0 +1,81 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LocalizedTime = void 0;
class LocalizedTime {
timestamp;
parts;
timezone;
constructor(date, timezone) {
this.timestamp = date.getTime();
this.timezone = timezone;
this.parts = buildDateParts(date, timezone);
}
toDate() {
return new Date(this.timestamp);
}
toISO() {
const gmt = this.parts.gmt.replace(/^GMT/, '');
const offset = gmt ? gmt : 'Z';
const pad = (n) => String(n).padStart(2, '0');
return `${this.parts.year}-${pad(this.parts.month)}-${pad(this.parts.day)}`
+ `T${pad(this.parts.hour)}:${pad(this.parts.minute)}:${pad(this.parts.second)}`
+ `.${String(this.parts.milisecond).padStart(3, '0')}`
+ offset;
}
getParts() {
return this.parts;
}
set(field, value) {
this.parts[field] = value;
const newDate = new Date(this.toISO());
this.timestamp = newDate.getTime();
this.parts = buildDateParts(newDate, this.timezone);
}
}
exports.LocalizedTime = LocalizedTime;
function buildDateParts(date, timezone) {
const dftOptions = {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
weekday: 'short',
hour12: false
};
if (timezone) {
dftOptions.timeZone = timezone;
}
const dateFormat = new Intl.DateTimeFormat('en-US', dftOptions);
const parts = dateFormat.formatToParts(date).filter(part => {
return part.type !== 'literal';
}).reduce((acc, part) => {
acc[part.type] = part.value;
return acc;
}, {});
return {
day: parseInt(parts.day),
month: parseInt(parts.month),
year: parseInt(parts.year),
hour: parts.hour === '24' ? 0 : parseInt(parts.hour),
minute: parseInt(parts.minute),
second: parseInt(parts.second),
milisecond: date.getMilliseconds(),
weekday: parts.weekday,
gmt: getTimezoneGMT(date, timezone)
};
}
function getTimezoneGMT(date, timezone) {
const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' }));
const tzDate = new Date(date.toLocaleString('en-US', { timeZone: timezone }));
let offsetInMinutes = (utcDate.getTime() - tzDate.getTime()) / 60000;
const sign = offsetInMinutes <= 0 ? '+' : '-';
offsetInMinutes = Math.abs(offsetInMinutes);
if (offsetInMinutes === 0)
return 'Z';
const hours = Math.floor(offsetInMinutes / 60).toString().padStart(2, '0');
const minutes = Math.floor(offsetInMinutes % 60).toString().padStart(2, '0');
return `GMT${sign}${hours}:${minutes}`;
}
//# sourceMappingURL=localized-time.js.map
@@ -0,0 +1 @@
{"version":3,"file":"localized-time.js","sourceRoot":"","sources":["../../../src/time/localized-time.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
import { LocalizedTime } from './localized-time';
import { TimeMatcher } from './time-matcher';
export declare class MatcherWalker {
cronExpression: string;
baseDate: Date;
pattern: any;
expressions: number[][];
timeMatcher: TimeMatcher;
timezone?: string;
constructor(cronExpression: string, baseDate: Date, timezone?: string);
isMatching(): boolean;
matchNext(): LocalizedTime;
}
@@ -0,0 +1,100 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MatcherWalker = void 0;
const convertion_1 = __importDefault(require("../pattern/convertion"));
const localized_time_1 = require("./localized-time");
const time_matcher_1 = require("./time-matcher");
const week_day_names_conversion_1 = __importDefault(require("../pattern/convertion/week-day-names-conversion"));
class MatcherWalker {
cronExpression;
baseDate;
pattern;
expressions;
timeMatcher;
timezone;
constructor(cronExpression, baseDate, timezone) {
this.cronExpression = cronExpression;
this.baseDate = baseDate;
this.timeMatcher = new time_matcher_1.TimeMatcher(cronExpression, timezone);
this.timezone = timezone;
this.expressions = (0, convertion_1.default)(cronExpression);
}
isMatching() {
return this.timeMatcher.match(this.baseDate);
}
matchNext() {
const findNextDateIgnoringWeekday = () => {
const baseDate = new Date(this.baseDate.getTime());
baseDate.setMilliseconds(0);
const localTime = new localized_time_1.LocalizedTime(baseDate, this.timezone);
const dateParts = localTime.getParts();
const date = new localized_time_1.LocalizedTime(localTime.toDate(), this.timezone);
const seconds = this.expressions[0];
const nextSecond = availableValue(seconds, dateParts.second);
if (nextSecond) {
date.set('second', nextSecond);
if (this.timeMatcher.match(date.toDate())) {
return date;
}
}
date.set('second', seconds[0]);
const minutes = this.expressions[1];
const nextMinute = availableValue(minutes, dateParts.minute);
if (nextMinute) {
date.set('minute', nextMinute);
if (this.timeMatcher.match(date.toDate())) {
return date;
}
}
date.set('minute', minutes[0]);
const hours = this.expressions[2];
const nextHour = availableValue(hours, dateParts.hour);
if (nextHour) {
date.set('hour', nextHour);
if (this.timeMatcher.match(date.toDate())) {
return date;
}
}
date.set('hour', hours[0]);
const days = this.expressions[3];
const nextDay = availableValue(days, dateParts.day);
if (nextDay) {
date.set('day', nextDay);
if (this.timeMatcher.match(date.toDate())) {
return date;
}
}
date.set('day', days[0]);
const months = this.expressions[4];
const nextMonth = availableValue(months, dateParts.month);
if (nextMonth) {
date.set('month', nextMonth);
if (this.timeMatcher.match(date.toDate())) {
return date;
}
}
date.set('year', date.getParts().year + 1);
date.set('month', months[0]);
return date;
};
const date = findNextDateIgnoringWeekday();
const weekdays = this.expressions[5];
let currentWeekday = parseInt((0, week_day_names_conversion_1.default)(date.getParts().weekday));
while (!(weekdays.indexOf(currentWeekday) > -1)) {
date.set('year', date.getParts().year + 1);
currentWeekday = parseInt((0, week_day_names_conversion_1.default)(date.getParts().weekday));
}
return date;
}
}
exports.MatcherWalker = MatcherWalker;
function availableValue(values, currentValue) {
const availableValues = values.sort((a, b) => a - b).filter(s => s > currentValue);
if (availableValues.length > 0)
return availableValues[0];
return false;
}
//# sourceMappingURL=matcher-walker.js.map
@@ -0,0 +1 @@
{"version":3,"file":"matcher-walker.js","sourceRoot":"","sources":["../../../src/time/matcher-walker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
export declare class TimeMatcher {
timezone?: string;
pattern: string;
expressions: any[];
constructor(pattern: string, timezone?: string);
match(date: Date): boolean;
getNextMatch(date: Date): Date;
}
@@ -0,0 +1,41 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TimeMatcher = void 0;
const index_1 = __importDefault(require("../pattern/convertion/index"));
const week_day_names_conversion_1 = __importDefault(require("../pattern/convertion/week-day-names-conversion"));
const localized_time_1 = require("./localized-time");
const matcher_walker_1 = require("./matcher-walker");
function matchValue(allowedValues, value) {
return allowedValues.indexOf(value) !== -1;
}
class TimeMatcher {
timezone;
pattern;
expressions;
constructor(pattern, timezone) {
this.timezone = timezone;
this.pattern = pattern;
this.expressions = (0, index_1.default)(pattern);
}
match(date) {
const localizedTime = new localized_time_1.LocalizedTime(date, this.timezone);
const parts = localizedTime.getParts();
const runOnSecond = matchValue(this.expressions[0], parts.second);
const runOnMinute = matchValue(this.expressions[1], parts.minute);
const runOnHour = matchValue(this.expressions[2], parts.hour);
const runOnDay = matchValue(this.expressions[3], parts.day);
const runOnMonth = matchValue(this.expressions[4], parts.month);
const runOnWeekDay = matchValue(this.expressions[5], parseInt((0, week_day_names_conversion_1.default)(parts.weekday)));
return runOnSecond && runOnMinute && runOnHour && runOnDay && runOnMonth && runOnWeekDay;
}
getNextMatch(date) {
const walker = new matcher_walker_1.MatcherWalker(this.pattern, date, this.timezone);
const next = walker.matchNext();
return next.toDate();
}
}
exports.TimeMatcher = TimeMatcher;
//# sourceMappingURL=time-matcher.js.map
@@ -0,0 +1 @@
{"version":3,"file":"time-matcher.js","sourceRoot":"","sources":["../../../src/time/time-matcher.ts"],"names":[],"mappings":";;;;;;AACA,wEAA4D;AAC5D,gHAAqF;AACrF,qDAAiD;AACjD,qDAAiD;AAEjD,SAAS,UAAU,CAAC,aAAuB,EAAE,KAAa;IACxD,OAAO,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,MAAa,WAAW;IACpB,QAAQ,CAAU;IAClB,OAAO,CAAS;IAChB,WAAW,CAAQ;IAEnB,YAAY,OAAc,EAAE,QAAgB;QACxC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,WAAW,GAAG,IAAA,eAAiB,EAAC,OAAO,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,IAAU;QACZ,MAAM,aAAa,GAAG,IAAI,8BAAa,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QAC5D,MAAM,KAAK,GAAG,aAAa,CAAC,QAAQ,EAAE,CAAC;QACvC,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QAClE,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QAClE,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5D,MAAM,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAChE,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,IAAA,mCAAsB,EAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAEtG,OAAO,WAAW,IAAI,WAAW,IAAI,SAAS,IAAI,QAAQ,IAAI,UAAU,IAAI,YAAY,CAAC;IAC7F,CAAC;IAED,YAAY,CAAC,IAAU;QACrB,MAAM,MAAM,GAAG,IAAI,8BAAa,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpE,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;IACvB,CAAC;CACJ;AA7BD,kCA6BC"}
+1
View File
@@ -0,0 +1 @@
export declare function createID(prefix?: string, length?: number): string;
+14
View File
@@ -0,0 +1,14 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createID = createID;
const node_crypto_1 = __importDefault(require("node:crypto"));
function createID(prefix = '', length = 16) {
const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const values = node_crypto_1.default.randomBytes(length);
const id = Array.from(values, v => charset[v % charset.length]).join('');
return prefix ? `${prefix}-${id}` : id;
}
//# sourceMappingURL=create-id.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"create-id.js","sourceRoot":"","sources":["../../src/create-id.ts"],"names":[],"mappings":";;;;;AAEA,4BAKC;AAPD,8DAAiC;AAEjC,SAAgB,QAAQ,CAAC,SAAiB,EAAE,EAAE,SAAiB,EAAE;IAC/D,MAAM,OAAO,GAAG,gEAAgE,CAAC;IACjF,MAAM,MAAM,GAAG,qBAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzE,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACzC,CAAC"}
+7
View File
@@ -0,0 +1,7 @@
declare const logger: {
info(message: string): void;
warn(message: string): void;
error(message: string | Error, err?: Error): void;
debug(message: string | Error, err?: Error): void;
};
export default logger;
+57
View File
@@ -0,0 +1,57 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const levelColors = {
INFO: '\x1b[36m',
WARN: '\x1b[33m',
ERROR: '\x1b[31m',
DEBUG: '\x1b[35m',
};
const GREEN = '\x1b[32m';
const RESET = '\x1b[0m';
function log(level, message, extra) {
const timestamp = new Date().toISOString();
const color = levelColors[level] ?? '';
const prefix = `[${timestamp}] [PID: ${process.pid}] ${GREEN}[NODE-CRON]${GREEN} ${color}[${level}]${RESET}`;
const output = `${prefix} ${message}`;
switch (level) {
case 'ERROR':
console.error(output, extra ?? '');
break;
case 'DEBUG':
console.debug(output, extra ?? '');
break;
case 'WARN':
console.warn(output);
break;
case 'INFO':
default:
console.info(output);
break;
}
}
const logger = {
info(message) {
log('INFO', message);
},
warn(message) {
log('WARN', message);
},
error(message, err) {
if (message instanceof Error) {
log('ERROR', message.message, message);
}
else {
log('ERROR', message, err);
}
},
debug(message, err) {
if (message instanceof Error) {
log('DEBUG', message.message, message);
}
else {
log('DEBUG', message, err);
}
},
};
exports.default = logger;
//# sourceMappingURL=logger.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/logger.ts"],"names":[],"mappings":";;AAEA,MAAM,WAAW,GAA6B;IAC5C,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,UAAU;IACjB,KAAK,EAAE,UAAU;CAClB,CAAC;AAEF,MAAM,KAAK,GAAG,UAAU,CAAC;AACzB,MAAM,KAAK,GAAG,SAAS,CAAC;AAExB,SAAS,GAAG,CAAC,KAAe,EAAE,OAAe,EAAE,KAAW;IACxD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,SAAS,WAAW,OAAO,CAAC,GAAG,KAAK,KAAK,cAAc,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,EAAE,CAAC;IAC7G,MAAM,MAAM,GAAG,GAAG,MAAM,IAAI,OAAO,EAAE,CAAC;IAEtC,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,OAAO;YACV,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YACnC,MAAM;QACR,KAAK,OAAO;YACR,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YACnC,MAAM;QACV,KAAK,MAAM;YACT,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrB,MAAM;QACR,KAAK,MAAM,CAAC;QACZ;YACE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrB,MAAM;IACV,CAAC;AACH,CAAC;AAED,MAAM,MAAM,GAAG;IACb,IAAI,CAAC,OAAe;QAClB,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvB,CAAC;IACD,IAAI,CAAC,OAAe;QAClB,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvB,CAAC;IACD,KAAK,CAAC,OAAuB,EAAE,GAAW;QACxC,IAAI,OAAO,YAAY,KAAK,EAAE,CAAC;YAC7B,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,KAAK,CAAC,OAAuB,EAAE,GAAW;QACxC,IAAI,OAAO,YAAY,KAAK,EAAE,CAAC;YAC7B,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;CACF,CAAC;AAEF,kBAAe,MAAM,CAAC"}
+18
View File
@@ -0,0 +1,18 @@
import { ScheduledTask, TaskFn, TaskOptions } from "./tasks/scheduled-task";
export declare function schedule(expression: string, func: TaskFn | string, options?: TaskOptions): ScheduledTask;
export declare function createTask(expression: string, func: TaskFn | string, options?: TaskOptions): ScheduledTask;
export declare function solvePath(filePath: string): string;
export declare function validate(expression: string): boolean;
export declare const getTasks: () => Map<string, ScheduledTask>;
export declare const getTask: (taskId: string) => ScheduledTask | undefined;
export { ScheduledTask } from './tasks/scheduled-task';
export type { TaskFn, TaskContext, TaskOptions } from './tasks/scheduled-task';
export interface NodeCron {
schedule: typeof schedule;
createTask: typeof createTask;
validate: typeof validate;
getTasks: typeof getTasks;
getTask: typeof getTask;
}
export declare const nodeCron: NodeCron;
export default nodeCron;
+71
View File
@@ -0,0 +1,71 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.nodeCron = exports.getTask = exports.getTasks = void 0;
exports.schedule = schedule;
exports.createTask = createTask;
exports.solvePath = solvePath;
exports.validate = validate;
const inline_scheduled_task_1 = require("./tasks/inline-scheduled-task");
const task_registry_1 = require("./task-registry");
const pattern_validation_1 = __importDefault(require("./pattern/validation/pattern-validation"));
const background_scheduled_task_1 = __importDefault(require("./tasks/background-scheduled-task/background-scheduled-task"));
const path_1 = __importDefault(require("path"));
const url_1 = require("url");
const registry = new task_registry_1.TaskRegistry();
function schedule(expression, func, options) {
const task = createTask(expression, func, options);
task.start();
return task;
}
function createTask(expression, func, options) {
let task;
if (func instanceof Function) {
task = new inline_scheduled_task_1.InlineScheduledTask(expression, func, options);
}
else {
const taskPath = solvePath(func);
task = new background_scheduled_task_1.default(expression, taskPath, options);
}
registry.add(task);
return task;
}
function solvePath(filePath) {
if (path_1.default.isAbsolute(filePath))
return (0, url_1.pathToFileURL)(filePath).href;
if (filePath.startsWith('file://'))
return filePath;
const stackLines = new Error().stack?.split('\n');
if (stackLines) {
stackLines?.shift();
const callerLine = stackLines?.find((line) => { return line.indexOf(__filename) === -1; });
const match = callerLine?.match(/(file:\/\/)?(((\/?)(\w:))?([/\\].+)):\d+:\d+/);
if (match) {
const dir = `${match[5] ?? ""}${path_1.default.dirname(match[6])}`;
return (0, url_1.pathToFileURL)(path_1.default.resolve(dir, filePath)).href;
}
}
throw new Error(`Could not locate task file ${filePath}`);
}
function validate(expression) {
try {
(0, pattern_validation_1.default)(expression);
return true;
}
catch (e) {
return false;
}
}
exports.getTasks = registry.all;
exports.getTask = registry.get;
exports.nodeCron = {
schedule,
createTask,
validate,
getTasks: exports.getTasks,
getTask: exports.getTask,
};
exports.default = exports.nodeCron;
//# sourceMappingURL=node-cron.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"node-cron.js","sourceRoot":"","sources":["../../src/node-cron.ts"],"names":[],"mappings":";;;;;;AA2CA,4BAIC;AAWD,gCAWC;AAUD,8BAoBC;AAQD,4BASC;AA1GD,yEAAoE;AAEpE,mDAA+C;AAE/C,iGAAiE;AACjE,4HAAkG;AAElG,gDAAwB;AACxB,6BAAoC;AAMpC,MAAM,QAAQ,GAAG,IAAI,4BAAY,EAAE,CAAC;AAmBpC,SAAgB,QAAQ,CAAC,UAAiB,EAAE,IAAqB,EAAE,OAAqB;IACpF,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACnD,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,OAAO,IAAI,CAAC;AAChB,CAAC;AAWD,SAAgB,UAAU,CAAC,UAAkB,EAAE,IAAqB,EAAE,OAAqB;IACvF,IAAI,IAAmB,CAAC;IACxB,IAAG,IAAI,YAAY,QAAQ,EAAC,CAAC;QAC3B,IAAI,GAAG,IAAI,2CAAmB,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC5D,CAAC;SAAM,CAAC;QACN,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,GAAG,IAAI,mCAAuB,CAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACpE,CAAC;IAED,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnB,OAAO,IAAI,CAAC;AAChB,CAAC;AAUD,SAAgB,SAAS,CAAC,QAAgB;IAExC,IAAG,cAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAA,mBAAa,EAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;IAGlE,IAAI,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,QAAQ,CAAC;IAEpD,MAAM,UAAU,GAAG,IAAI,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAClD,IAAG,UAAU,EAAC,CAAC;QACb,UAAU,EAAE,KAAK,EAAE,CAAC;QACpB,MAAM,UAAU,GAAG,UAAU,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3F,MAAM,KAAK,GAAG,UAAU,EAAE,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAEhF,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,cAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACzD,OAAO,IAAA,mBAAa,EAAC,cAAI,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;QACzD,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,EAAE,CAAC,CAAC;AAC5D,CAAC;AAQD,SAAgB,QAAQ,CAAC,UAAkB;IACzC,IAAI,CAAC;QACD,IAAA,4BAAU,EAAC,UAAU,CAAC,CAAC;QAEvB,OAAO,IAAI,CAAC;IAEhB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACT,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAOY,QAAA,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC;AAQxB,QAAA,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC;AAavB,QAAA,QAAQ,GAAa;IAChC,QAAQ;IACR,UAAU;IACV,QAAQ;IACR,QAAQ,EAAR,gBAAQ;IACR,OAAO,EAAP,eAAO;CACR,CAAC;AAKF,kBAAe,gBAAQ,CAAC"}
@@ -0,0 +1,2 @@
declare const _default: (expressions: any) => any;
export default _default;
@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = (() => {
function convertAsterisk(expression, replecement) {
if (expression.indexOf('*') !== -1) {
return expression.replace('*', replecement);
}
return expression;
}
function convertAsterisksToRanges(expressions) {
expressions[0] = convertAsterisk(expressions[0], '0-59');
expressions[1] = convertAsterisk(expressions[1], '0-59');
expressions[2] = convertAsterisk(expressions[2], '0-23');
expressions[3] = convertAsterisk(expressions[3], '1-31');
expressions[4] = convertAsterisk(expressions[4], '1-12');
expressions[5] = convertAsterisk(expressions[5], '0-6');
return expressions;
}
return convertAsterisksToRanges;
})();
//# sourceMappingURL=asterisk-to-range-conversion.js.map
@@ -0,0 +1 @@
{"version":3,"file":"asterisk-to-range-conversion.js","sourceRoot":"","sources":["../../../../src/pattern/convertion/asterisk-to-range-conversion.ts"],"names":[],"mappings":";;AACA,kBAAe,CAAC,GAAG,EAAE;IACjB,SAAS,eAAe,CAAC,UAAU,EAAE,WAAW;QAC5C,IAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAC,CAAC;YAC/B,OAAO,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,SAAS,wBAAwB,CAAC,WAAW;QACzC,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACxD,OAAO,WAAW,CAAC;IACvB,CAAC;IAED,OAAO,wBAAwB,CAAC;AACpC,CAAC,CAAC,EAAE,CAAC"}
@@ -0,0 +1,2 @@
declare const _default: (expression: any) => any;
export default _default;
@@ -0,0 +1,42 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const month_names_conversion_1 = __importDefault(require("./month-names-conversion"));
const week_day_names_conversion_1 = __importDefault(require("./week-day-names-conversion"));
const asterisk_to_range_conversion_1 = __importDefault(require("./asterisk-to-range-conversion"));
const range_conversion_1 = __importDefault(require("./range-conversion"));
exports.default = (() => {
function appendSeccondExpression(expressions) {
if (expressions.length === 5) {
return ['0'].concat(expressions);
}
return expressions;
}
function removeSpaces(str) {
return str.replace(/\s{2,}/g, ' ').trim();
}
function normalizeIntegers(expressions) {
for (let i = 0; i < expressions.length; i++) {
const numbers = expressions[i].split(',');
for (let j = 0; j < numbers.length; j++) {
numbers[j] = parseInt(numbers[j]);
}
expressions[i] = numbers;
}
return expressions;
}
function interprete(expression) {
let expressions = removeSpaces(`${expression}`).split(' ');
expressions = appendSeccondExpression(expressions);
expressions[4] = (0, month_names_conversion_1.default)(expressions[4]);
expressions[5] = (0, week_day_names_conversion_1.default)(expressions[5]);
expressions = (0, asterisk_to_range_conversion_1.default)(expressions);
expressions = (0, range_conversion_1.default)(expressions);
expressions = normalizeIntegers(expressions);
return expressions;
}
return interprete;
})();
//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/pattern/convertion/index.ts"],"names":[],"mappings":";;;;;AAAA,sFAA4D;AAC5D,4FAAiE;AACjE,kGAAsE;AACtE,0EAA+C;AAE/C,kBAAe,CAAC,GAAG,EAAE;IAEjB,SAAS,uBAAuB,CAAC,WAAW;QACxC,IAAG,WAAW,CAAC,MAAM,KAAK,CAAC,EAAC,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,WAAW,CAAC;IACvB,CAAC;IAED,SAAS,YAAY,CAAC,GAAG;QACrB,OAAO,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,CAAC;IAGD,SAAS,iBAAiB,CAAC,WAAW;QAClC,KAAK,IAAI,CAAC,GAAC,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC,CAAC;YACvC,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC1C,KAAK,IAAI,CAAC,GAAC,CAAC,EAAE,CAAC,GAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC,CAAC;gBACjC,OAAO,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;YACtC,CAAC;YACD,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;QAC7B,CAAC;QACD,OAAO,WAAW,CAAC;IACvB,CAAC;IAmBD,SAAS,UAAU,CAAC,UAAU;QAC1B,IAAI,WAAW,GAAG,YAAY,CAAC,GAAG,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3D,WAAW,GAAG,uBAAuB,CAAC,WAAW,CAAC,CAAC;QACnD,WAAW,CAAC,CAAC,CAAC,GAAG,IAAA,gCAAoB,EAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QACtD,WAAW,CAAC,CAAC,CAAC,GAAG,IAAA,mCAAsB,EAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,WAAW,GAAG,IAAA,sCAAwB,EAAC,WAAW,CAAC,CAAC;QACpD,WAAW,GAAG,IAAA,0BAAa,EAAC,WAAW,CAAC,CAAC;QAEzC,WAAW,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;QAE7C,OAAO,WAAW,CAAC;IACvB,CAAC;IAED,OAAO,UAAU,CAAC;AACtB,CAAC,CAAC,EAAE,CAAC"}
@@ -0,0 +1,2 @@
declare const _default: (monthExpression: any) => any;
export default _default;
@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = (() => {
const months = ['january', 'february', 'march', 'april', 'may', 'june', 'july',
'august', 'september', 'october', 'november', 'december'];
const shortMonths = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug',
'sep', 'oct', 'nov', 'dec'];
function convertMonthName(expression, items) {
for (let i = 0; i < items.length; i++) {
expression = expression.replace(new RegExp(items[i], 'gi'), i + 1);
}
return expression;
}
function interprete(monthExpression) {
monthExpression = convertMonthName(monthExpression, months);
monthExpression = convertMonthName(monthExpression, shortMonths);
return monthExpression;
}
return interprete;
})();
//# sourceMappingURL=month-names-conversion.js.map
@@ -0,0 +1 @@
{"version":3,"file":"month-names-conversion.js","sourceRoot":"","sources":["../../../../src/pattern/convertion/month-names-conversion.ts"],"names":[],"mappings":";;AAAA,kBAAe,CAAC,GAAG,EAAE;IACjB,MAAM,MAAM,GAAG,CAAC,SAAS,EAAC,UAAU,EAAC,OAAO,EAAC,OAAO,EAAC,KAAK,EAAC,MAAM,EAAC,MAAM;QACpE,QAAQ,EAAC,WAAW,EAAC,SAAS,EAAC,UAAU,EAAC,UAAU,CAAC,CAAC;IAC1D,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;QACvE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAEhC,SAAS,gBAAgB,CAAC,UAAU,EAAE,KAAK;QACvC,KAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC,CAAC;YAClC,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,SAAS,UAAU,CAAC,eAAe;QAC/B,eAAe,GAAG,gBAAgB,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;QAC5D,eAAe,GAAG,gBAAgB,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC;QACjE,OAAO,eAAe,CAAC;IAC3B,CAAC;IAED,OAAO,UAAU,CAAC;AACtB,CAAC,CAAC,EAAE,CAAC"}
@@ -0,0 +1,2 @@
declare const _default: (expressions: any) => any;
export default _default;
@@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = (() => {
function replaceWithRange(expression, text, init, end, stepTxt) {
const step = parseInt(stepTxt);
const numbers = [];
let last = parseInt(end);
let first = parseInt(init);
if (first > last) {
last = parseInt(init);
first = parseInt(end);
}
for (let i = first; i <= last; i += step) {
numbers.push(i);
}
return expression.replace(new RegExp(text, 'i'), numbers.join());
}
function convertRange(expression) {
const rangeRegEx = /(\d+)-(\d+)(\/(\d+)|)/;
let match = rangeRegEx.exec(expression);
while (match !== null && match.length > 0) {
expression = replaceWithRange(expression, match[0], match[1], match[2], match[4] || '1');
match = rangeRegEx.exec(expression);
}
return expression;
}
function convertAllRanges(expressions) {
for (let i = 0; i < expressions.length; i++) {
expressions[i] = convertRange(expressions[i]);
}
return expressions;
}
return convertAllRanges;
})();
//# sourceMappingURL=range-conversion.js.map
@@ -0,0 +1 @@
{"version":3,"file":"range-conversion.js","sourceRoot":"","sources":["../../../../src/pattern/convertion/range-conversion.ts"],"names":[],"mappings":";;AAAA,kBAAe,CAAE,GAAG,EAAE;IAClB,SAAS,gBAAgB,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO;QAC1D,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/B,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,IAAI,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAE3B,IAAG,KAAK,GAAG,IAAI,EAAC,CAAC;YACb,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YACtB,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;QAED,KAAI,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;YACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;QAED,OAAO,UAAU,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,SAAS,YAAY,CAAC,UAAU;QAC5B,MAAM,UAAU,GAAG,uBAAuB,CAAC;QAC3C,IAAI,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACxC,OAAM,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAC,CAAC;YACtC,UAAU,GAAG,gBAAgB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;YACzF,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,SAAS,gBAAgB,CAAC,WAAW;QACjC,KAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC,CAAC;YACxC,WAAW,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,WAAW,CAAC;IACvB,CAAC;IAED,OAAO,gBAAgB,CAAC;AAC5B,CAAC,CAAC,EAAE,CAAC"}
@@ -0,0 +1,2 @@
declare const _default: (expression: any) => any;
export default _default;
@@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = (() => {
const weekDays = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday',
'friday', 'saturday'];
const shortWeekDays = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
function convertWeekDayName(expression, items) {
for (let i = 0; i < items.length; i++) {
expression = expression.replace(new RegExp(items[i], 'gi'), i);
}
return expression;
}
function convertWeekDays(expression) {
expression = expression.replace('7', '0');
expression = convertWeekDayName(expression, weekDays);
return convertWeekDayName(expression, shortWeekDays);
}
return convertWeekDays;
})();
//# sourceMappingURL=week-day-names-conversion.js.map
@@ -0,0 +1 @@
{"version":3,"file":"week-day-names-conversion.js","sourceRoot":"","sources":["../../../../src/pattern/convertion/week-day-names-conversion.ts"],"names":[],"mappings":";;AAAA,kBAAe,CAAC,GAAG,EAAE;IACjB,MAAM,QAAQ,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU;QACpE,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC1B,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAExE,SAAS,kBAAkB,CAAC,UAAU,EAAE,KAAK;QACzC,KAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC,CAAC;YAClC,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,SAAS,eAAe,CAAC,UAAU;QAC/B,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC1C,UAAU,GAAG,kBAAkB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACtD,OAAO,kBAAkB,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,eAAe,CAAC;AAC3B,CAAC,CAAC,EAAE,CAAC"}
@@ -0,0 +1,2 @@
declare function validate(pattern: any): void;
export default validate;
@@ -0,0 +1,61 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const index_1 = __importDefault(require("../convertion/index"));
const validationRegex = /^(?:\d+|\*|\*\/\d+)$/;
function isValidExpression(expression, min, max) {
const options = expression;
for (const option of options) {
const optionAsInt = parseInt(option, 10);
if ((!Number.isNaN(optionAsInt) &&
(optionAsInt < min || optionAsInt > max)) ||
!validationRegex.test(option))
return false;
}
return true;
}
function isInvalidSecond(expression) {
return !isValidExpression(expression, 0, 59);
}
function isInvalidMinute(expression) {
return !isValidExpression(expression, 0, 59);
}
function isInvalidHour(expression) {
return !isValidExpression(expression, 0, 23);
}
function isInvalidDayOfMonth(expression) {
return !isValidExpression(expression, 1, 31);
}
function isInvalidMonth(expression) {
return !isValidExpression(expression, 1, 12);
}
function isInvalidWeekDay(expression) {
return !isValidExpression(expression, 0, 7);
}
function validateFields(patterns, executablePatterns) {
if (isInvalidSecond(executablePatterns[0]))
throw new Error(`${patterns[0]} is a invalid expression for second`);
if (isInvalidMinute(executablePatterns[1]))
throw new Error(`${patterns[1]} is a invalid expression for minute`);
if (isInvalidHour(executablePatterns[2]))
throw new Error(`${patterns[2]} is a invalid expression for hour`);
if (isInvalidDayOfMonth(executablePatterns[3]))
throw new Error(`${patterns[3]} is a invalid expression for day of month`);
if (isInvalidMonth(executablePatterns[4]))
throw new Error(`${patterns[4]} is a invalid expression for month`);
if (isInvalidWeekDay(executablePatterns[5]))
throw new Error(`${patterns[5]} is a invalid expression for week day`);
}
function validate(pattern) {
if (typeof pattern !== 'string')
throw new TypeError('pattern must be a string!');
const patterns = pattern.split(' ');
const executablePatterns = (0, index_1.default)(pattern);
if (patterns.length === 5)
patterns.unshift('0');
validateFields(patterns, executablePatterns);
}
exports.default = validate;
//# sourceMappingURL=pattern-validation.js.map
@@ -0,0 +1 @@
{"version":3,"file":"pattern-validation.js","sourceRoot":"","sources":["../../../../src/pattern/validation/pattern-validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
type PromiseState = 'pending' | 'fulfilled' | 'rejected';
export declare class TrackedPromise<T> {
promise: Promise<T>;
error: any;
state: PromiseState;
value?: T;
constructor(executor: (resolve: (value: T) => void, reject: (reason?: any) => void) => void);
getPromise(): Promise<T>;
getState(): PromiseState;
isPending(): boolean;
isFulfilled(): boolean;
isRejected(): boolean;
getValue(): T | undefined;
getError(): any;
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
finally(onfinally?: (() => void) | undefined | null): Promise<T>;
}
export {};
@@ -0,0 +1,55 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TrackedPromise = void 0;
class TrackedPromise {
promise;
error;
state;
value;
constructor(executor) {
this.state = 'pending';
this.promise = new Promise((resolve, reject) => {
executor((value) => {
this.state = 'fulfilled';
this.value = value;
resolve(value);
}, (error) => {
this.state = 'rejected';
this.error = error;
reject(error);
});
});
}
getPromise() {
return this.promise;
}
getState() {
return this.state;
}
isPending() {
return this.state === 'pending';
}
isFulfilled() {
return this.state === 'fulfilled';
}
isRejected() {
return this.state === 'rejected';
}
getValue() {
return this.value;
}
getError() {
return this.error;
}
then(onfulfilled, onrejected) {
return this.promise.then(onfulfilled, onrejected);
}
catch(onrejected) {
return this.promise.catch(onrejected);
}
finally(onfinally) {
return this.promise.finally(onfinally);
}
}
exports.TrackedPromise = TrackedPromise;
//# sourceMappingURL=tracked-promise.js.map
@@ -0,0 +1 @@
{"version":3,"file":"tracked-promise.js","sourceRoot":"","sources":["../../../src/promise/tracked-promise.ts"],"names":[],"mappings":";;;AAEA,MAAa,cAAc;IACzB,OAAO,CAAa;IACpB,KAAK,CAAM;IACX,KAAK,CAAe;IACpB,KAAK,CAAK;IAEV,YAAY,QAA+E;QACzF,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QAEvB,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAChD,QAAQ,CACN,CAAC,KAAK,EAAE,EAAE;gBACR,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC;gBACzB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;gBACnB,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC,EACD,CAAC,KAAK,EAAE,EAAE;gBACR,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC;gBACxB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;gBACnB,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC;IAClC,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,KAAK,KAAK,WAAW,CAAC;IACpC,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,KAAK,KAAK,UAAU,CAAC;IACnC,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,IAAI,CACF,WAAiF,EACjF,UAAmF;QAEnF,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CACH,UAAiF;QAEjF,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,CAAC,SAA2C;QACjD,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACzC,CAAC;CACF;AArED,wCAqEC"}
@@ -0,0 +1,42 @@
import { Execution } from "../tasks/scheduled-task";
import { TimeMatcher } from "../time/time-matcher";
type OnFn = (date: Date) => void | Promise<void>;
type OnErrorHookFn = (date: Date, error: Error, execution: Execution) => void | Promise<void>;
type OnHookFn = (date: Date, execution: Execution) => boolean | Promise<boolean>;
type OnMatch = (date: Date, execution: Execution) => any | Promise<any>;
export type RunnerOptions = {
noOverlap?: boolean;
timezone?: string;
maxExecutions?: number;
maxRandomDelay?: number;
onMissedExecution?: OnFn;
onOverlap?: OnFn;
onError?: OnErrorHookFn;
onFinished?: OnHookFn;
beforeRun?: OnHookFn;
onMaxExecutions?: OnFn;
};
export declare class Runner {
timeMatcher: TimeMatcher;
onMatch: OnMatch;
noOverlap: boolean;
maxExecutions?: number;
maxRandomDelay: number;
runCount: number;
running: boolean;
heartBeatTimeout?: NodeJS.Timeout;
onMissedExecution: OnFn;
onOverlap: OnFn;
onError: OnErrorHookFn;
beforeRun: OnHookFn;
onFinished: OnHookFn;
onMaxExecutions: OnFn;
constructor(timeMatcher: TimeMatcher, onMatch: OnMatch, options?: RunnerOptions);
start(): void;
nextRun(): Date;
stop(): void;
isStarted(): boolean;
isStopped(): boolean;
execute(): Promise<void>;
}
export {};
+192
View File
@@ -0,0 +1,192 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Runner = void 0;
const create_id_1 = require("../create-id");
const logger_1 = __importDefault(require("../logger"));
const tracked_promise_1 = require("../promise/tracked-promise");
function emptyOnFn() { }
;
function emptyHookFn() { return true; }
;
function defaultOnError(date, error) {
logger_1.default.error('Task failed with error!', error);
}
class Runner {
timeMatcher;
onMatch;
noOverlap;
maxExecutions;
maxRandomDelay;
runCount;
running;
heartBeatTimeout;
onMissedExecution;
onOverlap;
onError;
beforeRun;
onFinished;
onMaxExecutions;
constructor(timeMatcher, onMatch, options) {
this.timeMatcher = timeMatcher;
this.onMatch = onMatch;
this.noOverlap = options == undefined || options.noOverlap === undefined ? false : options.noOverlap;
this.maxExecutions = options?.maxExecutions;
this.maxRandomDelay = options?.maxRandomDelay || 0;
this.onMissedExecution = options?.onMissedExecution || emptyOnFn;
this.onOverlap = options?.onOverlap || emptyOnFn;
this.onError = options?.onError || defaultOnError;
this.onFinished = options?.onFinished || emptyHookFn;
this.beforeRun = options?.beforeRun || emptyHookFn;
this.onMaxExecutions = options?.onMaxExecutions || emptyOnFn;
this.runCount = 0;
this.running = false;
}
start() {
this.running = true;
let lastExecution;
let expectedNextExecution;
const scheduleNextHeartBeat = (currentDate) => {
if (this.running) {
clearTimeout(this.heartBeatTimeout);
this.heartBeatTimeout = setTimeout(heartBeat, getDelay(this.timeMatcher, currentDate));
}
};
const runTask = (date) => {
return new Promise(async (resolve) => {
const execution = {
id: (0, create_id_1.createID)('exec'),
reason: 'scheduled'
};
const shouldExecute = await this.beforeRun(date, execution);
const randomDelay = Math.floor(Math.random() * this.maxRandomDelay);
if (shouldExecute) {
setTimeout(async () => {
try {
this.runCount++;
execution.startedAt = new Date();
const result = await this.onMatch(date, execution);
execution.finishedAt = new Date();
execution.result = result;
this.onFinished(date, execution);
if (this.maxExecutions && this.runCount >= this.maxExecutions) {
this.onMaxExecutions(date);
this.stop();
}
}
catch (error) {
execution.finishedAt = new Date();
execution.error = error;
this.onError(date, error, execution);
}
resolve(true);
}, randomDelay);
}
});
};
const checkAndRun = (date) => {
return new tracked_promise_1.TrackedPromise(async (resolve, reject) => {
try {
if (this.timeMatcher.match(date)) {
await runTask(date);
}
resolve(true);
}
catch (err) {
reject(err);
}
});
};
const heartBeat = async () => {
const currentDate = nowWithoutMs();
if (expectedNextExecution && expectedNextExecution.getTime() < currentDate.getTime()) {
while (expectedNextExecution.getTime() < currentDate.getTime()) {
logger_1.default.warn(`missed execution at ${expectedNextExecution}! Possible blocking IO or high CPU user at the same process used by node-cron.`);
expectedNextExecution = this.timeMatcher.getNextMatch(expectedNextExecution);
runAsync(this.onMissedExecution, expectedNextExecution, defaultOnError);
}
}
if (lastExecution && lastExecution.getState() === 'pending') {
runAsync(this.onOverlap, currentDate, defaultOnError);
if (this.noOverlap) {
logger_1.default.warn('task still running, new execution blocked by overlap prevention!');
expectedNextExecution = this.timeMatcher.getNextMatch(currentDate);
scheduleNextHeartBeat(currentDate);
return;
}
}
lastExecution = checkAndRun(currentDate);
expectedNextExecution = this.timeMatcher.getNextMatch(currentDate);
scheduleNextHeartBeat(currentDate);
};
this.heartBeatTimeout = setTimeout(() => {
heartBeat();
}, getDelay(this.timeMatcher, nowWithoutMs()));
}
nextRun() {
return this.timeMatcher.getNextMatch(new Date());
}
stop() {
this.running = false;
if (this.heartBeatTimeout) {
clearTimeout(this.heartBeatTimeout);
this.heartBeatTimeout = undefined;
}
}
isStarted() {
return !!this.heartBeatTimeout && this.running;
}
isStopped() {
return !this.isStarted();
}
async execute() {
const date = new Date();
const execution = {
id: (0, create_id_1.createID)('exec'),
reason: 'invoked'
};
try {
const shouldExecute = await this.beforeRun(date, execution);
if (shouldExecute) {
this.runCount++;
execution.startedAt = new Date();
const result = await this.onMatch(date, execution);
execution.finishedAt = new Date();
execution.result = result;
this.onFinished(date, execution);
}
}
catch (error) {
execution.finishedAt = new Date();
execution.error = error;
this.onError(date, error, execution);
}
}
}
exports.Runner = Runner;
async function runAsync(fn, date, onError) {
try {
await fn(date);
}
catch (error) {
onError(date, error);
}
}
function getDelay(timeMatcher, currentDate) {
const maxDelay = 86400000;
const nextRun = timeMatcher.getNextMatch(currentDate);
const now = new Date();
const delay = nextRun.getTime() - now.getTime();
if (delay > maxDelay) {
return maxDelay;
}
return Math.max(0, delay);
}
function nowWithoutMs() {
const date = new Date();
date.setMilliseconds(0);
return date;
}
//# sourceMappingURL=runner.js.map
File diff suppressed because one or more lines are too long
+11
View File
@@ -0,0 +1,11 @@
import { ScheduledTask } from "./tasks/scheduled-task";
declare const tasks: Map<string, ScheduledTask>;
export declare class TaskRegistry {
add(task: ScheduledTask): void;
get(taskId: string): ScheduledTask | undefined;
remove(task: ScheduledTask): void;
all(): typeof tasks;
has(taskId: string): boolean;
killAll(): void;
}
export {};
+35
View File
@@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TaskRegistry = void 0;
const tasks = new Map();
class TaskRegistry {
add(task) {
if (this.has(task.id)) {
throw Error(`task ${task.id} already registred!`);
}
tasks.set(task.id, task);
task.on('task:destroyed', () => {
this.remove(task);
});
}
get(taskId) {
return tasks.get(taskId);
}
remove(task) {
if (this.has(task.id)) {
task?.destroy();
tasks.delete(task.id);
}
}
all() {
return tasks;
}
has(taskId) {
return tasks.has(taskId);
}
killAll() {
tasks.forEach(id => this.remove(id));
}
}
exports.TaskRegistry = TaskRegistry;
//# sourceMappingURL=task-registry.js.map

Some files were not shown because too many files have changed in this diff Show More