Init
This commit is contained in:
40
node_modules/node-schedule/CHANGELOG.md
generated
vendored
Normal file
40
node_modules/node-schedule/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
# Master (Unreleased)
|
||||
|
||||
# 2.1.1 - 11 January, 2023
|
||||
|
||||
### Bug fixes:
|
||||
|
||||
- Bump cron-parser from 3.5.0 to 4.2.0 - security fix #642
|
||||
|
||||
# 2.1.0 - 28 November, 2021
|
||||
|
||||
### New features:
|
||||
|
||||
- Implement support for graceful shutdown #583
|
||||
- Emit a success event after a successful job invocation. #643
|
||||
|
||||
# 2.0.0 - 01 February, 2021
|
||||
|
||||
### Breaking changes:
|
||||
|
||||
- Drop support for Node < 6
|
||||
- Remove support for job objects. See `UPGRADING.md` for more details. #557
|
||||
|
||||
### New features:
|
||||
|
||||
- Introduce compatibility with browsers and Electron #553
|
||||
|
||||
### Bug fixes:
|
||||
|
||||
- Avoid leaking memory on one-off jobs #581
|
||||
- Address anonymous job id collision problem to ensure that node-schedule could run with the unlimited uptime #582
|
||||
|
||||
### Internal changes:
|
||||
|
||||
- Bump cron-parser from 2.18.0 to 3.1.0 #562
|
||||
- Bump sinon from 1.17.7 to 9.2.4 #566
|
||||
- Switch to nyc from istanbul #574
|
||||
- Convert tests from nodeunit to Tape #575
|
||||
- Replace var with let/const #577
|
||||
- Execute airtap tests on a headless Chromium #578
|
||||
- Make structure more modular #579
|
||||
19
node_modules/node-schedule/LICENSE
generated
vendored
Normal file
19
node_modules/node-schedule/LICENSE
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (C) 2015 Matt Patenaude.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
304
node_modules/node-schedule/README.md
generated
vendored
Normal file
304
node_modules/node-schedule/README.md
generated
vendored
Normal file
@ -0,0 +1,304 @@
|
||||
# Node Schedule
|
||||
|
||||
[](https://www.npmjs.com/package/node-schedule)
|
||||
[](https://www.npmjs.com/package/node-schedule)
|
||||
[](https://github.com/node-schedule/node-schedule/actions)
|
||||
[](https://coveralls.io/r/node-schedule/node-schedule?branch=master)
|
||||
[](https://gitter.im/node-schedule/node-schedule?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
[](https://nodei.co/npm/node-schedule/)
|
||||
|
||||
Node Schedule is a flexible cron-like and not-cron-like job scheduler for Node.js.
|
||||
It allows you to schedule jobs (arbitrary functions) for execution at
|
||||
specific dates, with optional recurrence rules. It only uses a single timer
|
||||
at any given time (rather than reevaluating upcoming jobs every second/minute).
|
||||
|
||||
Node 6+ is supported.
|
||||
|
||||
## Overview
|
||||
|
||||
Node Schedule is for time-based scheduling, not interval-based scheduling.
|
||||
|
||||
While you can easily bend it to your will, if you only want to do something like
|
||||
"run this function every 5 minutes", [toad-scheduler](https://github.com/kibertoad/toad-scheduler) would be a better choice. But if you want to, say, "run this function at the :20
|
||||
and :50 of every hour on the third Tuesday of every month," you'll find that
|
||||
Node Schedule suits your needs better. Additionally, Node Schedule has Windows
|
||||
support, unlike true `cron`, since the node runtime is now fully supported.
|
||||
|
||||
Note that Node Schedule is designed for in-process scheduling, i.e. scheduled jobs
|
||||
will only fire as long as your script is running, and the schedule will disappear
|
||||
when execution completes. If you need to schedule jobs that will persist even when
|
||||
your script *isn't* running, consider using actual [cron].
|
||||
|
||||
In case you need durable jobs that persist across restarts and lock system compatible with multi-node deployments,
|
||||
try [agenda](https://github.com/agenda/agenda) or [bree](https://github.com/breejs/bree).
|
||||
|
||||
## Usage
|
||||
|
||||
### Installation
|
||||
|
||||
You can install using [npm](https://www.npmjs.com/package/node-schedule).
|
||||
|
||||
```
|
||||
npm install node-schedule
|
||||
```
|
||||
|
||||
|
||||
### Jobs and Scheduling
|
||||
|
||||
Every scheduled job in Node Schedule is represented by a `Job` object. You can
|
||||
create jobs manually, then execute the `schedule()` method to apply a schedule,
|
||||
or use the convenience function `scheduleJob()` as demonstrated below.
|
||||
|
||||
`Job` objects are `EventEmitter`s, and emit the following events:
|
||||
* A `run` event after each execution.
|
||||
* A `scheduled` event each time they're scheduled to run.
|
||||
* A `canceled` event when an invocation is canceled before it's executed.
|
||||
Note that `canceled` is the single-L American spelling.
|
||||
* An `error` event when a job invocation triggered by a schedule throws or returns
|
||||
a rejected `Promise`.
|
||||
* A `success` event when a job invocation triggered by a schedule returns successfully or
|
||||
returns a resolved `Promise`. In any case, the `success` event receives the value returned
|
||||
by the callback or in case of a promise, the resolved value.
|
||||
|
||||
(Both the `scheduled` and `canceled` events receive a JavaScript date object as
|
||||
a parameter).
|
||||
Note that jobs are scheduled the first time immediately, so if you create a job
|
||||
using the `scheduleJob()` convenience method, you'll miss the first `scheduled`
|
||||
event, but you can query the invocation manually (see below).
|
||||
|
||||
### Cron-style Scheduling
|
||||
|
||||
The cron format consists of:
|
||||
```
|
||||
* * * * * *
|
||||
┬ ┬ ┬ ┬ ┬ ┬
|
||||
│ │ │ │ │ │
|
||||
│ │ │ │ │ └ day of week (0 - 7) (0 or 7 is Sun)
|
||||
│ │ │ │ └───── month (1 - 12)
|
||||
│ │ │ └────────── day of month (1 - 31)
|
||||
│ │ └─────────────── hour (0 - 23)
|
||||
│ └──────────────────── minute (0 - 59)
|
||||
└───────────────────────── second (0 - 59, OPTIONAL)
|
||||
```
|
||||
|
||||
Examples with the cron format:
|
||||
|
||||
```js
|
||||
const schedule = require('node-schedule');
|
||||
|
||||
const job = schedule.scheduleJob('42 * * * *', function(){
|
||||
console.log('The answer to life, the universe, and everything!');
|
||||
});
|
||||
```
|
||||
|
||||
Execute a cron job when the minute is 42 (e.g. 19:42, 20:42, etc.).
|
||||
|
||||
And:
|
||||
|
||||
```js
|
||||
const job = schedule.scheduleJob('0 17 ? * 0,4-6', function(){
|
||||
console.log('Today is recognized by Rebecca Black!');
|
||||
});
|
||||
```
|
||||
|
||||
Execute a cron job every 5 Minutes = */5 * * * *
|
||||
|
||||
You can also get when it is scheduled to run for every invocation of the job:
|
||||
```js
|
||||
const job = schedule.scheduleJob('0 1 * * *', function(fireDate){
|
||||
console.log('This job was supposed to run at ' + fireDate + ', but actually ran at ' + new Date());
|
||||
});
|
||||
```
|
||||
This is useful when you need to check if there is a delay of the job invocation when the system is busy, or save a record of all invocations of a job for audit purpose.
|
||||
#### Unsupported Cron Features
|
||||
|
||||
Currently, `W` (nearest weekday) and `L` (last day of month/week) are not supported.
|
||||
Most other features supported by popular cron implementations should work just fine,
|
||||
including `#` (nth weekday of the month).
|
||||
|
||||
[cron-parser] is used to parse crontab instructions.
|
||||
|
||||
### Date-based Scheduling
|
||||
|
||||
Say you very specifically want a function to execute at 5:30am on December 21, 2012.
|
||||
Remember - in JavaScript - 0 - January, 11 - December.
|
||||
|
||||
```js
|
||||
const schedule = require('node-schedule');
|
||||
const date = new Date(2012, 11, 21, 5, 30, 0);
|
||||
|
||||
const job = schedule.scheduleJob(date, function(){
|
||||
console.log('The world is going to end today.');
|
||||
});
|
||||
```
|
||||
|
||||
To use current data in the future you can use binding:
|
||||
|
||||
```js
|
||||
const schedule = require('node-schedule');
|
||||
const date = new Date(2012, 11, 21, 5, 30, 0);
|
||||
const x = 'Tada!';
|
||||
const job = schedule.scheduleJob(date, function(y){
|
||||
console.log(y);
|
||||
}.bind(null,x));
|
||||
x = 'Changing Data';
|
||||
```
|
||||
This will log 'Tada!' when the scheduled Job runs, rather than 'Changing Data',
|
||||
which x changes to immediately after scheduling.
|
||||
|
||||
### Recurrence Rule Scheduling
|
||||
|
||||
You can build recurrence rules to specify when a job should recur. For instance,
|
||||
consider this rule, which executes the function every hour at 42 minutes after the hour:
|
||||
|
||||
```js
|
||||
const schedule = require('node-schedule');
|
||||
|
||||
const rule = new schedule.RecurrenceRule();
|
||||
rule.minute = 42;
|
||||
|
||||
const job = schedule.scheduleJob(rule, function(){
|
||||
console.log('The answer to life, the universe, and everything!');
|
||||
});
|
||||
```
|
||||
|
||||
You can also use arrays to specify a list of acceptable values, and the `Range`
|
||||
object to specify a range of start and end values, with an optional step parameter.
|
||||
For instance, this will print a message on Thursday, Friday, Saturday, and Sunday at 5pm:
|
||||
|
||||
```js
|
||||
const rule = new schedule.RecurrenceRule();
|
||||
rule.dayOfWeek = [0, new schedule.Range(4, 6)];
|
||||
rule.hour = 17;
|
||||
rule.minute = 0;
|
||||
|
||||
const job = schedule.scheduleJob(rule, function(){
|
||||
console.log('Today is recognized by Rebecca Black!');
|
||||
});
|
||||
```
|
||||
|
||||
Timezones are also supported. Here is an example of executing at the start of every day in the UTC timezone.
|
||||
|
||||
```js
|
||||
const rule = new schedule.RecurrenceRule();
|
||||
rule.hour = 0;
|
||||
rule.minute = 0;
|
||||
rule.tz = 'Etc/UTC';
|
||||
|
||||
const job = schedule.scheduleJob(rule, function(){
|
||||
console.log('A new day has begun in the UTC timezone!');
|
||||
});
|
||||
```
|
||||
|
||||
A list of acceptable tz (timezone) values can be found at <https://en.wikipedia.org/wiki/List_of_tz_database_time_zones>
|
||||
|
||||
#### RecurrenceRule properties
|
||||
|
||||
- `second (0-59)`
|
||||
- `minute (0-59)`
|
||||
- `hour (0-23)`
|
||||
- `date (1-31)`
|
||||
- `month (0-11)`
|
||||
- `year`
|
||||
- `dayOfWeek (0-6) Starting with Sunday`
|
||||
- `tz`
|
||||
|
||||
|
||||
> **Note**: It's worth noting that the default value of a component of a recurrence rule is
|
||||
> `null` (except for second, which is 0 for familiarity with cron). *If we did not
|
||||
> explicitly set `minute` to 0 above, the message would have instead been logged at
|
||||
> 5:00pm, 5:01pm, 5:02pm, ..., 5:59pm.* Probably not what you want.
|
||||
|
||||
#### Object Literal Syntax
|
||||
|
||||
To make things a little easier, an object literal syntax is also supported, like
|
||||
in this example which will log a message every Sunday at 2:30pm:
|
||||
|
||||
```js
|
||||
const job = schedule.scheduleJob({hour: 14, minute: 30, dayOfWeek: 0}, function(){
|
||||
console.log('Time for tea!');
|
||||
});
|
||||
```
|
||||
|
||||
#### Set StartTime and EndTime
|
||||
|
||||
It will run after 5 seconds and stop after 10 seconds in this example.
|
||||
The ruledat supports the above.
|
||||
|
||||
```js
|
||||
const startTime = new Date(Date.now() + 5000);
|
||||
const endTime = new Date(startTime.getTime() + 5000);
|
||||
const job = schedule.scheduleJob({ start: startTime, end: endTime, rule: '*/1 * * * * *' }, function(){
|
||||
console.log('Time for tea!');
|
||||
});
|
||||
```
|
||||
|
||||
### Graceful Shutdown.
|
||||
You can shutdown jobs gracefully.
|
||||
`gracefulShutdown()` will cancel all jobs and return Promise.
|
||||
It will wait until all jobs are terminated.
|
||||
```js
|
||||
schedule.gracefulShutdown();
|
||||
```
|
||||
|
||||
You can also gracefully shutdown jobs when a system interrupt occurs.
|
||||
```
|
||||
process.on('SIGINT', function () {
|
||||
schedule.gracefulShutdown()
|
||||
.then(() => process.exit(0))
|
||||
}
|
||||
```
|
||||
|
||||
### Handle Jobs and Job Invocations
|
||||
|
||||
There are some function to get information for a Job and to handle the Job and
|
||||
Invocations.
|
||||
|
||||
|
||||
#### job.cancel(reschedule)
|
||||
You can invalidate any job with the `cancel()` method:
|
||||
|
||||
```js
|
||||
j.cancel();
|
||||
```
|
||||
All planned invocations will be canceled. When you set the parameter ***reschedule***
|
||||
to true then the Job is newly scheduled afterwards.
|
||||
|
||||
#### job.cancelNext(reschedule)
|
||||
This method invalidates the next planned invocation or the job.
|
||||
When you set the parameter ***reschedule*** to true then the Job is newly scheduled
|
||||
afterwards.
|
||||
|
||||
#### job.reschedule(spec)
|
||||
This method cancels all pending invocation and registers the Job completely new again using the given specification.
|
||||
Return true/false on success/failure.
|
||||
|
||||
#### job.nextInvocation()
|
||||
This method returns a Date object for the planned next Invocation for this Job. If no invocation is planned the method returns null.
|
||||
|
||||
## Contributing
|
||||
|
||||
This module was originally developed by [Matt Patenaude] who eventually passed over maintainer's mantle over to [Tejas Manohar].
|
||||
|
||||
Currently it is being maintained by [Igor Savin] and [our amazing community].
|
||||
|
||||
We'd love to get your contributions. Individuals making significant and valuable
|
||||
contributions are given commit-access to the project to contribute as they see fit.
|
||||
|
||||
Before jumping in, check out our [Contributing] page guide!
|
||||
|
||||
## Copyright and license
|
||||
|
||||
Copyright 2015 Matt Patenaude.
|
||||
|
||||
Licensed under the **[MIT License](https://github.com/node-schedule/node-schedule/blob/master/LICENSE)**.
|
||||
|
||||
|
||||
[cron]: http://unixhelp.ed.ac.uk/CGI/man-cgi?crontab+5
|
||||
[Contributing]: https://github.com/node-schedule/node-schedule/blob/master/CONTRIBUTING.md
|
||||
[Matt Patenaude]: https://github.com/mattpat
|
||||
[Tejas Manohar]: http://tejas.io
|
||||
[Igor Savin]: https://twitter.com/kibertoad
|
||||
[our amazing community]: https://github.com/node-schedule/node-schedule/graphs/contributors
|
||||
[cron-parser]: https://github.com/harrisiirak/cron-parser
|
||||
20
node_modules/node-schedule/UPGRADING.md
generated
vendored
Normal file
20
node_modules/node-schedule/UPGRADING.md
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
## Upgrading to new node-schedule versions
|
||||
|
||||
### Upgrading to version 2.0.0+
|
||||
|
||||
* Node.js versions older than 6 are no longer supported, please update your environment before upgrading.
|
||||
* In order to prevent memory leaks, one-off jobs (targeted to be executed at an exact date) cannot be rescheduled by name, as reference to them is no longer stored indefinitely. If you want to keep rescheduling them, make sure to store reference to the initial job.
|
||||
* The `scheduleJob()` method no longer supports passing an object with the job method. If you were using an object, pass the job method directly.
|
||||
|
||||
E.g. code that previously looked like this:
|
||||
```javascript
|
||||
const obj = {
|
||||
execute() {}
|
||||
};
|
||||
Scheduler.scheduleJob(obj);
|
||||
```
|
||||
should be changed to something like this:
|
||||
```javascript
|
||||
function execute() {}
|
||||
Scheduler.scheduleJob(execute);
|
||||
```
|
||||
17
node_modules/node-schedule/index.js
generated
vendored
Normal file
17
node_modules/node-schedule/index.js
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
const { cancelJob, rescheduleJob, scheduledJobs, scheduleJob, gracefulShutdown} = require('./lib/schedule')
|
||||
const { Invocation, RecurrenceRule, Range} = require('./lib/Invocation')
|
||||
const { Job } = require('./lib/Job')
|
||||
|
||||
module.exports = {
|
||||
Job,
|
||||
Invocation,
|
||||
Range,
|
||||
RecurrenceRule,
|
||||
cancelJob,
|
||||
rescheduleJob,
|
||||
scheduledJobs,
|
||||
scheduleJob,
|
||||
gracefulShutdown,
|
||||
}
|
||||
348
node_modules/node-schedule/lib/Invocation.js
generated
vendored
Normal file
348
node_modules/node-schedule/lib/Invocation.js
generated
vendored
Normal file
@ -0,0 +1,348 @@
|
||||
'use strict';
|
||||
|
||||
const lt = require('long-timeout')
|
||||
const CronDate = require('cron-parser/lib/date')
|
||||
const sorted = require('sorted-array-functions')
|
||||
|
||||
const invocations = [];
|
||||
let currentInvocation = null;
|
||||
|
||||
/* DoesntRecur rule */
|
||||
const DoesntRecur = new RecurrenceRule();
|
||||
DoesntRecur.recurs = false;
|
||||
|
||||
/* Invocation object */
|
||||
function Invocation(job, fireDate, recurrenceRule, endDate) {
|
||||
this.job = job;
|
||||
this.fireDate = fireDate;
|
||||
this.endDate = endDate;
|
||||
this.recurrenceRule = recurrenceRule || DoesntRecur;
|
||||
|
||||
this.timerID = null;
|
||||
}
|
||||
|
||||
function sorter(a, b) {
|
||||
return (a.fireDate.getTime() - b.fireDate.getTime());
|
||||
}
|
||||
|
||||
/* Range object */
|
||||
function Range(start, end, step) {
|
||||
this.start = start || 0;
|
||||
this.end = end || 60;
|
||||
this.step = step || 1;
|
||||
}
|
||||
|
||||
Range.prototype.contains = function(val) {
|
||||
if (this.step === null || this.step === 1) {
|
||||
return (val >= this.start && val <= this.end);
|
||||
} else {
|
||||
for (let i = this.start; i < this.end; i += this.step) {
|
||||
if (i === val) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/* RecurrenceRule object */
|
||||
/*
|
||||
Interpreting each property:
|
||||
null - any value is valid
|
||||
number - fixed value
|
||||
Range - value must fall in range
|
||||
array - value must validate against any item in list
|
||||
|
||||
NOTE: Cron months are 1-based, but RecurrenceRule months are 0-based.
|
||||
*/
|
||||
function RecurrenceRule(year, month, date, dayOfWeek, hour, minute, second) {
|
||||
this.recurs = true;
|
||||
|
||||
this.year = (year == null) ? null : year;
|
||||
this.month = (month == null) ? null : month;
|
||||
this.date = (date == null) ? null : date;
|
||||
this.dayOfWeek = (dayOfWeek == null) ? null : dayOfWeek;
|
||||
this.hour = (hour == null) ? null : hour;
|
||||
this.minute = (minute == null) ? null : minute;
|
||||
this.second = (second == null) ? 0 : second;
|
||||
}
|
||||
|
||||
RecurrenceRule.prototype.isValid = function() {
|
||||
function isValidType(num) {
|
||||
if (Array.isArray(num) || (num instanceof Array)) {
|
||||
return num.every(function(e) {
|
||||
return isValidType(e);
|
||||
});
|
||||
}
|
||||
return !(Number.isNaN(Number(num)) && !(num instanceof Range));
|
||||
}
|
||||
if (this.month !== null && (this.month < 0 || this.month > 11 || !isValidType(this.month))) {
|
||||
return false;
|
||||
}
|
||||
if (this.dayOfWeek !== null && (this.dayOfWeek < 0 || this.dayOfWeek > 6 || !isValidType(this.dayOfWeek))) {
|
||||
return false;
|
||||
}
|
||||
if (this.hour !== null && (this.hour < 0 || this.hour > 23 || !isValidType(this.hour))) {
|
||||
return false;
|
||||
}
|
||||
if (this.minute !== null && (this.minute < 0 || this.minute > 59 || !isValidType(this.minute))) {
|
||||
return false;
|
||||
}
|
||||
if (this.second !== null && (this.second < 0 || this.second > 59 || !isValidType(this.second))) {
|
||||
return false;
|
||||
}
|
||||
if (this.date !== null) {
|
||||
if(!isValidType(this.date)) {
|
||||
return false;
|
||||
}
|
||||
switch (this.month) {
|
||||
case 3:
|
||||
case 5:
|
||||
case 8:
|
||||
case 10:
|
||||
if (this.date < 1 || this. date > 30) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (this.date < 1 || this. date > 29) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (this.date < 1 || this. date > 31) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
RecurrenceRule.prototype.nextInvocationDate = function(base) {
|
||||
const next = this._nextInvocationDate(base);
|
||||
return next ? next.toDate() : null;
|
||||
};
|
||||
|
||||
RecurrenceRule.prototype._nextInvocationDate = function(base) {
|
||||
base = ((base instanceof CronDate) || (base instanceof Date)) ? base : (new Date());
|
||||
if (!this.recurs) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if(!this.isValid()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const now = new CronDate(Date.now(), this.tz);
|
||||
let fullYear = now.getFullYear();
|
||||
if ((this.year !== null) &&
|
||||
(typeof this.year == 'number') &&
|
||||
(this.year < fullYear)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let next = new CronDate(base.getTime(), this.tz);
|
||||
next.addSecond();
|
||||
|
||||
while (true) {
|
||||
if (this.year !== null) {
|
||||
fullYear = next.getFullYear();
|
||||
if ((typeof this.year == 'number') && (this.year < fullYear)) {
|
||||
next = null;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!recurMatch(fullYear, this.year)) {
|
||||
next.addYear();
|
||||
next.setMonth(0);
|
||||
next.setDate(1);
|
||||
next.setHours(0);
|
||||
next.setMinutes(0);
|
||||
next.setSeconds(0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (this.month != null && !recurMatch(next.getMonth(), this.month)) {
|
||||
next.addMonth();
|
||||
continue;
|
||||
}
|
||||
if (this.date != null && !recurMatch(next.getDate(), this.date)) {
|
||||
next.addDay();
|
||||
continue;
|
||||
}
|
||||
if (this.dayOfWeek != null && !recurMatch(next.getDay(), this.dayOfWeek)) {
|
||||
next.addDay();
|
||||
continue;
|
||||
}
|
||||
if (this.hour != null && !recurMatch(next.getHours(), this.hour)) {
|
||||
next.addHour();
|
||||
continue;
|
||||
}
|
||||
if (this.minute != null && !recurMatch(next.getMinutes(), this.minute)) {
|
||||
next.addMinute();
|
||||
continue;
|
||||
}
|
||||
if (this.second != null && !recurMatch(next.getSeconds(), this.second)) {
|
||||
next.addSecond();
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return next;
|
||||
};
|
||||
|
||||
function recurMatch(val, matcher) {
|
||||
if (matcher == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeof matcher === 'number') {
|
||||
return (val === matcher);
|
||||
} else if(typeof matcher === 'string') {
|
||||
return (val === Number(matcher));
|
||||
} else if (matcher instanceof Range) {
|
||||
return matcher.contains(val);
|
||||
} else if (Array.isArray(matcher) || (matcher instanceof Array)) {
|
||||
for (let i = 0; i < matcher.length; i++) {
|
||||
if (recurMatch(val, matcher[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Date-based scheduler */
|
||||
function runOnDate(date, job) {
|
||||
const now = Date.now();
|
||||
const then = date.getTime();
|
||||
|
||||
return lt.setTimeout(function() {
|
||||
if (then > Date.now())
|
||||
runOnDate(date, job);
|
||||
else
|
||||
job();
|
||||
}, (then < now ? 0 : then - now));
|
||||
}
|
||||
|
||||
function scheduleInvocation(invocation) {
|
||||
sorted.add(invocations, invocation, sorter);
|
||||
prepareNextInvocation();
|
||||
const date = invocation.fireDate instanceof CronDate ? invocation.fireDate.toDate() : invocation.fireDate;
|
||||
invocation.job.emit('scheduled', date);
|
||||
}
|
||||
|
||||
function prepareNextInvocation() {
|
||||
if (invocations.length > 0 && currentInvocation !== invocations[0]) {
|
||||
if (currentInvocation !== null) {
|
||||
lt.clearTimeout(currentInvocation.timerID);
|
||||
currentInvocation.timerID = null;
|
||||
currentInvocation = null;
|
||||
}
|
||||
|
||||
currentInvocation = invocations[0];
|
||||
|
||||
const job = currentInvocation.job;
|
||||
const cinv = currentInvocation;
|
||||
currentInvocation.timerID = runOnDate(currentInvocation.fireDate, function() {
|
||||
currentInvocationFinished();
|
||||
|
||||
if (job.callback) {
|
||||
job.callback();
|
||||
}
|
||||
|
||||
if (cinv.recurrenceRule.recurs || cinv.recurrenceRule._endDate === null) {
|
||||
const inv = scheduleNextRecurrence(cinv.recurrenceRule, cinv.job, cinv.fireDate, cinv.endDate);
|
||||
if (inv !== null) {
|
||||
inv.job.trackInvocation(inv);
|
||||
}
|
||||
}
|
||||
|
||||
job.stopTrackingInvocation(cinv);
|
||||
|
||||
try {
|
||||
const result = job.invoke(cinv.fireDate instanceof CronDate ? cinv.fireDate.toDate() : cinv.fireDate);
|
||||
job.emit('run');
|
||||
job.running += 1;
|
||||
|
||||
if (result instanceof Promise) {
|
||||
result.then(function (value) {
|
||||
job.emit('success', value);
|
||||
job.running -= 1;
|
||||
}).catch(function (err) {
|
||||
job.emit('error', err);
|
||||
job.running -= 1;
|
||||
});
|
||||
} else {
|
||||
job.emit('success', result);
|
||||
job.running -= 1;
|
||||
}
|
||||
} catch (err) {
|
||||
job.emit('error', err);
|
||||
job.running -= 1;
|
||||
}
|
||||
|
||||
if (job.isOneTimeJob) {
|
||||
job.deleteFromSchedule();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function currentInvocationFinished() {
|
||||
invocations.shift();
|
||||
currentInvocation = null;
|
||||
prepareNextInvocation();
|
||||
}
|
||||
|
||||
function cancelInvocation(invocation) {
|
||||
const idx = invocations.indexOf(invocation);
|
||||
if (idx > -1) {
|
||||
invocations.splice(idx, 1);
|
||||
if (invocation.timerID !== null) {
|
||||
lt.clearTimeout(invocation.timerID);
|
||||
}
|
||||
|
||||
if (currentInvocation === invocation) {
|
||||
currentInvocation = null;
|
||||
}
|
||||
|
||||
invocation.job.emit('canceled', invocation.fireDate);
|
||||
prepareNextInvocation();
|
||||
}
|
||||
}
|
||||
|
||||
/* Recurrence scheduler */
|
||||
function scheduleNextRecurrence(rule, job, prevDate, endDate) {
|
||||
|
||||
prevDate = (prevDate instanceof CronDate) ? prevDate : new CronDate();
|
||||
|
||||
const date = (rule instanceof RecurrenceRule) ? rule._nextInvocationDate(prevDate) : rule.next();
|
||||
if (date === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ((endDate instanceof CronDate) && date.getTime() > endDate.getTime()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const inv = new Invocation(job, date, rule, endDate);
|
||||
scheduleInvocation(inv);
|
||||
|
||||
return inv;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Range,
|
||||
RecurrenceRule,
|
||||
Invocation,
|
||||
cancelInvocation,
|
||||
scheduleInvocation,
|
||||
scheduleNextRecurrence,
|
||||
sorter,
|
||||
_invocations: invocations
|
||||
}
|
||||
287
node_modules/node-schedule/lib/Job.js
generated
vendored
Normal file
287
node_modules/node-schedule/lib/Job.js
generated
vendored
Normal file
@ -0,0 +1,287 @@
|
||||
'use strict';
|
||||
|
||||
const events = require('events')
|
||||
const cronParser = require('cron-parser')
|
||||
const CronDate = require('cron-parser/lib/date')
|
||||
const sorted = require('sorted-array-functions')
|
||||
|
||||
const { scheduleNextRecurrence, scheduleInvocation, cancelInvocation, RecurrenceRule, sorter, Invocation } = require('./Invocation')
|
||||
const { isValidDate } = require('./utils/dateUtils')
|
||||
|
||||
const scheduledJobs = {};
|
||||
|
||||
let anonJobCounter = 0;
|
||||
function resolveAnonJobName() {
|
||||
const now = new Date()
|
||||
if (anonJobCounter === Number.MAX_SAFE_INTEGER) {
|
||||
anonJobCounter = 0
|
||||
}
|
||||
anonJobCounter++
|
||||
|
||||
return `<Anonymous Job ${anonJobCounter} ${now.toISOString()}>`
|
||||
}
|
||||
|
||||
function Job(name, job, callback) {
|
||||
// setup a private pendingInvocations variable
|
||||
this.pendingInvocations = [];
|
||||
|
||||
//setup a private number of invocations variable
|
||||
let triggeredJobs = 0;
|
||||
|
||||
// Set scope vars
|
||||
const jobName = name && typeof name === 'string' ? name : resolveAnonJobName();
|
||||
this.job = name && typeof name === 'function' ? name : job;
|
||||
|
||||
// Make sure callback is actually a callback
|
||||
if (this.job === name) {
|
||||
// Name wasn't provided and maybe a callback is there
|
||||
this.callback = typeof job === 'function' ? job : false;
|
||||
} else {
|
||||
// Name was provided, and maybe a callback is there
|
||||
this.callback = typeof callback === 'function' ? callback : false;
|
||||
}
|
||||
|
||||
// task count
|
||||
this.running = 0;
|
||||
|
||||
// Check for generator
|
||||
if (typeof this.job === 'function' &&
|
||||
this.job.prototype &&
|
||||
this.job.prototype.next) {
|
||||
this.job = function() {
|
||||
return this.next().value;
|
||||
}.bind(this.job.call(this));
|
||||
}
|
||||
|
||||
// define properties
|
||||
Object.defineProperty(this, 'name', {
|
||||
value: jobName,
|
||||
writable: false,
|
||||
enumerable: true
|
||||
});
|
||||
|
||||
// method that require private access
|
||||
this.trackInvocation = function(invocation) {
|
||||
// add to our invocation list
|
||||
sorted.add(this.pendingInvocations, invocation, sorter);
|
||||
return true;
|
||||
};
|
||||
this.stopTrackingInvocation = function(invocation) {
|
||||
const invIdx = this.pendingInvocations.indexOf(invocation);
|
||||
if (invIdx > -1) {
|
||||
this.pendingInvocations.splice(invIdx, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
this.triggeredJobs = function() {
|
||||
return triggeredJobs;
|
||||
};
|
||||
this.setTriggeredJobs = function(triggeredJob) {
|
||||
triggeredJobs = triggeredJob;
|
||||
};
|
||||
this.deleteFromSchedule = function() {
|
||||
deleteScheduledJob(this.name)
|
||||
};
|
||||
this.cancel = function(reschedule) {
|
||||
reschedule = (typeof reschedule == 'boolean') ? reschedule : false;
|
||||
|
||||
let inv, newInv;
|
||||
const newInvs = [];
|
||||
for (let j = 0; j < this.pendingInvocations.length; j++) {
|
||||
inv = this.pendingInvocations[j];
|
||||
|
||||
cancelInvocation(inv);
|
||||
|
||||
if (reschedule && (inv.recurrenceRule.recurs || inv.recurrenceRule.next)) {
|
||||
newInv = scheduleNextRecurrence(inv.recurrenceRule, this, inv.fireDate, inv.endDate);
|
||||
if (newInv !== null) {
|
||||
newInvs.push(newInv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.pendingInvocations = [];
|
||||
|
||||
for (let k = 0; k < newInvs.length; k++) {
|
||||
this.trackInvocation(newInvs[k]);
|
||||
}
|
||||
|
||||
// remove from scheduledJobs if reschedule === false
|
||||
if (!reschedule) {
|
||||
this.deleteFromSchedule()
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
this.cancelNext = function(reschedule) {
|
||||
reschedule = (typeof reschedule == 'boolean') ? reschedule : true;
|
||||
|
||||
if (!this.pendingInvocations.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let newInv;
|
||||
const nextInv = this.pendingInvocations.shift();
|
||||
|
||||
cancelInvocation(nextInv);
|
||||
|
||||
if (reschedule && (nextInv.recurrenceRule.recurs || nextInv.recurrenceRule.next)) {
|
||||
newInv = scheduleNextRecurrence(nextInv.recurrenceRule, this, nextInv.fireDate, nextInv.endDate);
|
||||
if (newInv !== null) {
|
||||
this.trackInvocation(newInv);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
this.reschedule = function(spec) {
|
||||
let inv;
|
||||
const invocationsToCancel = this.pendingInvocations.slice();
|
||||
|
||||
for (let j = 0; j < invocationsToCancel.length; j++) {
|
||||
inv = invocationsToCancel[j];
|
||||
|
||||
cancelInvocation(inv);
|
||||
}
|
||||
|
||||
this.pendingInvocations = [];
|
||||
|
||||
if (this.schedule(spec)) {
|
||||
this.setTriggeredJobs(0);
|
||||
return true;
|
||||
} else {
|
||||
this.pendingInvocations = invocationsToCancel;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
this.nextInvocation = function() {
|
||||
if (!this.pendingInvocations.length) {
|
||||
return null;
|
||||
}
|
||||
return this.pendingInvocations[0].fireDate;
|
||||
};
|
||||
}
|
||||
|
||||
Object.setPrototypeOf(Job.prototype, events.EventEmitter.prototype);
|
||||
|
||||
Job.prototype.invoke = function(fireDate) {
|
||||
this.setTriggeredJobs(this.triggeredJobs() + 1);
|
||||
return this.job(fireDate);
|
||||
};
|
||||
|
||||
Job.prototype.runOnDate = function(date) {
|
||||
return this.schedule(date);
|
||||
};
|
||||
|
||||
Job.prototype.schedule = function(spec) {
|
||||
const self = this;
|
||||
let success = false;
|
||||
let inv;
|
||||
let start;
|
||||
let end;
|
||||
let tz;
|
||||
|
||||
// save passed-in value before 'spec' is replaced
|
||||
if (typeof spec === 'object' && 'tz' in spec) {
|
||||
tz = spec.tz;
|
||||
}
|
||||
|
||||
if (typeof spec === 'object' && spec.rule) {
|
||||
start = spec.start || undefined;
|
||||
end = spec.end || undefined;
|
||||
spec = spec.rule;
|
||||
|
||||
if (start) {
|
||||
if (!(start instanceof Date)) {
|
||||
start = new Date(start);
|
||||
}
|
||||
|
||||
start = new CronDate(start, tz);
|
||||
if (!isValidDate(start) || start.getTime() < Date.now()) {
|
||||
start = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
if (end && !(end instanceof Date) && !isValidDate(end = new Date(end))) {
|
||||
end = undefined;
|
||||
}
|
||||
|
||||
if (end) {
|
||||
end = new CronDate(end, tz);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const res = cronParser.parseExpression(spec, {currentDate: start, tz: tz});
|
||||
inv = scheduleNextRecurrence(res, self, start, end);
|
||||
if (inv !== null) {
|
||||
success = self.trackInvocation(inv);
|
||||
}
|
||||
} catch (err) {
|
||||
const type = typeof spec;
|
||||
if ((type === 'string') || (type === 'number')) {
|
||||
spec = new Date(spec);
|
||||
}
|
||||
|
||||
if ((spec instanceof Date) && (isValidDate(spec))) {
|
||||
spec = new CronDate(spec);
|
||||
self.isOneTimeJob = true;
|
||||
if (spec.getTime() >= Date.now()) {
|
||||
inv = new Invocation(self, spec);
|
||||
scheduleInvocation(inv);
|
||||
success = self.trackInvocation(inv);
|
||||
}
|
||||
} else if (type === 'object') {
|
||||
self.isOneTimeJob = false;
|
||||
if (!(spec instanceof RecurrenceRule)) {
|
||||
const r = new RecurrenceRule();
|
||||
if ('year' in spec) {
|
||||
r.year = spec.year;
|
||||
}
|
||||
if ('month' in spec) {
|
||||
r.month = spec.month;
|
||||
}
|
||||
if ('date' in spec) {
|
||||
r.date = spec.date;
|
||||
}
|
||||
if ('dayOfWeek' in spec) {
|
||||
r.dayOfWeek = spec.dayOfWeek;
|
||||
}
|
||||
if ('hour' in spec) {
|
||||
r.hour = spec.hour;
|
||||
}
|
||||
if ('minute' in spec) {
|
||||
r.minute = spec.minute;
|
||||
}
|
||||
if ('second' in spec) {
|
||||
r.second = spec.second;
|
||||
}
|
||||
|
||||
spec = r;
|
||||
}
|
||||
|
||||
spec.tz = tz;
|
||||
inv = scheduleNextRecurrence(spec, self, start, end);
|
||||
if (inv !== null) {
|
||||
success = self.trackInvocation(inv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scheduledJobs[this.name] = this;
|
||||
return success;
|
||||
};
|
||||
|
||||
function deleteScheduledJob(name) {
|
||||
if (name) {
|
||||
delete scheduledJobs[name];
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Job,
|
||||
deleteScheduledJob,
|
||||
scheduledJobs
|
||||
}
|
||||
114
node_modules/node-schedule/lib/schedule.js
generated
vendored
Normal file
114
node_modules/node-schedule/lib/schedule.js
generated
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
'use strict';
|
||||
|
||||
/*
|
||||
node-schedule
|
||||
A cron-like and not-cron-like job scheduler for Node.
|
||||
*/
|
||||
|
||||
const { Job, scheduledJobs } = require('./Job')
|
||||
|
||||
/* API
|
||||
invoke()
|
||||
runOnDate(date)
|
||||
schedule(date || recurrenceRule || cronstring)
|
||||
cancel(reschedule = false)
|
||||
cancelNext(reschedule = true)
|
||||
|
||||
Property constraints
|
||||
name: readonly
|
||||
job: readwrite
|
||||
*/
|
||||
|
||||
/* Convenience methods */
|
||||
function scheduleJob() {
|
||||
if (arguments.length < 2) {
|
||||
throw new RangeError('Invalid number of arguments');
|
||||
}
|
||||
|
||||
const name = (arguments.length >= 3 && typeof arguments[0] === 'string') ? arguments[0] : null;
|
||||
const spec = name ? arguments[1] : arguments[0];
|
||||
const method = name ? arguments[2] : arguments[1];
|
||||
const callback = name ? arguments[3] : arguments[2];
|
||||
|
||||
if (typeof method !== 'function') {
|
||||
throw new RangeError('The job method must be a function.');
|
||||
}
|
||||
|
||||
const job = new Job(name, method, callback);
|
||||
|
||||
if (job.schedule(spec)) {
|
||||
return job;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function rescheduleJob(job, spec) {
|
||||
if (job instanceof Job) {
|
||||
if (job.reschedule(spec)) {
|
||||
return job;
|
||||
}
|
||||
} else if (typeof job === 'string') {
|
||||
if (Object.prototype.hasOwnProperty.call(scheduledJobs, job)) {
|
||||
if (scheduledJobs[job].reschedule(spec)) {
|
||||
return scheduledJobs[job];
|
||||
}
|
||||
} else {
|
||||
throw new Error('Cannot reschedule one-off job by name, pass job reference instead')
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function cancelJob(job) {
|
||||
let success = false;
|
||||
if (job instanceof Job) {
|
||||
success = job.cancel();
|
||||
} else if (typeof job == 'string' || job instanceof String) {
|
||||
if (job in scheduledJobs && Object.prototype.hasOwnProperty.call(scheduledJobs, job)) {
|
||||
success = scheduledJobs[job].cancel();
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
function gracefulShutdown() {
|
||||
const jobs = Object.keys(scheduledJobs).map(key => scheduledJobs[key]);
|
||||
jobs.forEach(function (job) {
|
||||
job.cancel();
|
||||
});
|
||||
|
||||
let running = false;
|
||||
for (let i = 0; i < jobs.length; i++) {
|
||||
if (jobs[i].running > 0) {
|
||||
running = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new Promise(function (resolve) {
|
||||
if (running) {
|
||||
setInterval(function () {
|
||||
for (let i = 0; i < jobs.length; i++) {
|
||||
if (jobs[i].running > 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
resolve();
|
||||
}, 500);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* Public API */
|
||||
module.exports = {
|
||||
scheduleJob,
|
||||
rescheduleJob,
|
||||
scheduledJobs,
|
||||
cancelJob,
|
||||
gracefulShutdown,
|
||||
}
|
||||
11
node_modules/node-schedule/lib/utils/dateUtils.js
generated
vendored
Normal file
11
node_modules/node-schedule/lib/utils/dateUtils.js
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
function isValidDate(date) {
|
||||
// Taken from http://stackoverflow.com/a/12372720/1562178
|
||||
// If getTime() returns NaN it'll return false anyway
|
||||
return date.getTime() === date.getTime();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isValidDate
|
||||
}
|
||||
60
node_modules/node-schedule/package.json
generated
vendored
Normal file
60
node_modules/node-schedule/package.json
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
{
|
||||
"name": "node-schedule",
|
||||
"version": "2.1.1",
|
||||
"description": "A cron-like and not-cron-like job scheduler for Node.",
|
||||
"keywords": [
|
||||
"schedule",
|
||||
"task",
|
||||
"job",
|
||||
"cron",
|
||||
"recurrent",
|
||||
"in-memory"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "tape test/*.js",
|
||||
"test:browser": "airtap test/cancel-long-running-jobs.js test/convenience-method-test.js test/date-convenience-methods-test.js test/range-test.js test/recurrence-rule-test.js test/schedule-cron-jobs.js test/start-end-test.js",
|
||||
"coveralls": "nyc report --reporter=lcov",
|
||||
"test:coverage": "nyc tape test/*.js",
|
||||
"lint": "eslint lib test",
|
||||
"lint:fix": "eslint --fix lib test"
|
||||
},
|
||||
"author": {
|
||||
"name": "Matt Patenaude",
|
||||
"email": "matt@mattpatenaude.com",
|
||||
"url": "http://mattpatenaude.com"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Igor Savin",
|
||||
"email": "kibertoad@gmail.com"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/node-schedule/node-schedule.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"cron-parser": "^4.2.0",
|
||||
"long-timeout": "0.1.1",
|
||||
"sorted-array-functions": "^1.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"airtap": "^4.0.4",
|
||||
"eslint": "^8.3.0",
|
||||
"nyc": "^15.1.0",
|
||||
"sinon": "^9.2.4",
|
||||
"tape": "^5.3.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"files": [
|
||||
"CHANGELOG.md",
|
||||
"README.md",
|
||||
"UPGRADING.md",
|
||||
"LICENSE",
|
||||
"lib/*"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user