1. 调整计划列表展示项

2. 调整设备列表展示项
This commit is contained in:
2025-09-21 23:39:21 +08:00
parent 9a6561d4ae
commit a47c191cbb
40 changed files with 11533 additions and 12 deletions

19
node_modules/.package-lock.json generated vendored
View File

@@ -3836,6 +3836,17 @@
"node": ">=10"
}
},
"node_modules/cron-parser": {
"version": "5.4.0",
"resolved": "https://registry.npmmirror.com/cron-parser/-/cron-parser-5.4.0.tgz",
"integrity": "sha512-HxYB8vTvnQFx4dLsZpGRa0uHp6X3qIzS3ZJgJ9v6l/5TJMgeWQbLkR5yiJ5hOxGbc9+jCADDnydIe15ReLZnJA==",
"dependencies": {
"luxon": "^3.7.1"
},
"engines": {
"node": ">=18"
}
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -6633,6 +6644,14 @@
"yallist": "^3.0.2"
}
},
"node_modules/luxon": {
"version": "3.7.2",
"resolved": "https://registry.npmmirror.com/luxon/-/luxon-3.7.2.tgz",
"integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==",
"engines": {
"node": ">=12"
}
},
"node_modules/magic-string": {
"version": "0.30.19",
"resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.19.tgz",

21
node_modules/cron-parser/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014-2023 Harri Siirak
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.

398
node_modules/cron-parser/README.md generated vendored Normal file
View File

@@ -0,0 +1,398 @@
# cron-parser
[![Build Status](https://github.com/harrisiirak/cron-parser/actions/workflows/push.yml/badge.svg?branch=master)](https://github.com/harrisiirak/cron-parser/actions/workflows/push.yml)
[![NPM version](https://badge.fury.io/js/cron-parser.png)](http://badge.fury.io/js/cron-parser)
![Statements](./coverage/badge-statements.svg)
A JavaScript library for parsing and manipulating cron expressions. Features timezone support, DST handling, and iterator capabilities.
[API documentation](https://harrisiirak.github.io/cron-parser/)
## Requirements
- Node.js >= 18
- TypeScript >= 5
## Installation
```bash
npm install cron-parser
```
## Cron Format
```
* * * * * *
┬ ┬ ┬ ┬ ┬ ┬
│ │ │ │ │ │
│ │ │ │ │ └─ day of week (0-7, 1L-7L) (0 or 7 is Sun)
│ │ │ │ └────── month (1-12, JAN-DEC)
│ │ │ └─────────── day of month (1-31, L)
│ │ └──────────────── hour (0-23)
│ └───────────────────── minute (0-59)
└────────────────────────── second (0-59, optional)
```
### Special Characters
| Character | Description | Example |
| --------- | ------------------------- | ---------------------------------------------------------------------- |
| `*` | Any value | `* * * * *` (every minute) |
| `?` | Any value (alias for `*`) | `? * * * *` (every minute) |
| `,` | Value list separator | `1,2,3 * * * *` (1st, 2nd, and 3rd minute) |
| `-` | Range of values | `1-5 * * * *` (every minute from 1 through 5) |
| `/` | Step values | `*/5 * * * *` (every 5th minute) |
| `L` | Last day of month/week | `0 0 L * *` (midnight on last day of month) |
| `#` | Nth day of month | `0 0 * * 1#1` (first Monday of month) |
| `H` | Randomized value | `H * * * *` (every n minute where n is randomly picked within [0, 59]) |
### Predefined Expressions
| Expression | Description | Equivalent |
| ----------- | ----------------------------------------- | --------------- |
| `@yearly` | Once a year at midnight of January 1 | `0 0 0 1 1 *` |
| `@monthly` | Once a month at midnight of first day | `0 0 0 1 * *` |
| `@weekly` | Once a week at midnight on Sunday | `0 0 0 * * 0` |
| `@daily` | Once a day at midnight | `0 0 0 * * *` |
| `@hourly` | Once an hour at the beginning of the hour | `0 0 * * * *` |
| `@minutely` | Once a minute | `0 * * * * *` |
| `@secondly` | Once a second | `* * * * * *` |
| `@weekdays` | Every weekday at midnight | `0 0 0 * * 1-5` |
| `@weekends` | Every weekend at midnight | `0 0 0 * * 0,6` |
### Field Values
| Field | Values | Special Characters | Aliases |
| ------------ | ------ | ------------------------------- | ------------------------------ |
| second | 0-59 | `*` `?` `,` `-` `/` `H` | |
| minute | 0-59 | `*` `?` `,` `-` `/` `H` | |
| hour | 0-23 | `*` `?` `,` `-` `/` `H` | |
| day of month | 1-31 | `*` `?` `,` `-` `/` `H` `L` | |
| month | 1-12 | `*` `?` `,` `-` `/` `H` | `JAN`-`DEC` |
| day of week | 0-7 | `*` `?` `,` `-` `/` `H` `L` `#` | `SUN`-`SAT` (0 or 7 is Sunday) |
## Options
| Option | Type | Description |
| ----------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------------- |
| currentDate | Date \| string \| number | Current date. Defaults to current local time in UTC. If not provided but startDate is set, startDate is used as currentDate |
| endDate | Date \| string \| number | End date of iteration range. Sets iteration range end point |
| startDate | Date \| string \| number | Start date of iteration range. Set iteration range start point |
| tz | string | Timezone (e.g., 'Europe/London') |
| hashSeed | string | A seed to be used in conjunction with the `H` special character |
| strict | boolean | Enable strict mode validation |
When using string dates, the following formats are supported:
- ISO8601
- HTTP and RFC2822
- SQL
## Basic Usage
### Expression Parsing
```typescript
import { CronExpressionParser } from 'cron-parser';
try {
const interval = CronExpressionParser.parse('*/2 * * * *');
// Get next date
console.log('Next:', interval.next().toString());
// Get next 3 dates
console.log(
'Next 3:',
interval.take(3).map((date) => date.toString()),
);
// Get previous date
console.log('Previous:', interval.prev().toString());
} catch (err) {
console.log('Error:', err.message);
}
```
### With Options
```typescript
import { CronExpressionParser } from 'cron-parser';
const options = {
currentDate: '2023-01-01T00:00:00Z',
endDate: '2024-01-01T00:00:00Z',
tz: 'Europe/London',
};
try {
const interval = CronExpressionParser.parse('0 0 * * *', options);
console.log('Next:', interval.next().toString());
} catch (err) {
console.log('Error:', err.message);
}
```
### Date Range Handling
The library provides handling of date ranges with automatic adjustment of the `currentDate`:
**startDate as fallback**: If `currentDate` is not provided but `startDate` is, the `startDate` will be used as the `currentDate`.
```typescript
const options = {
startDate: '2023-01-01T00:00:00Z', // No currentDate provided
};
// currentDate will be set to 2023-01-01T00:00:00Z automatically
const interval = CronExpressionParser.parse('0 0 * * *', options);
```
**Automatic clamping**: If `currentDate` is outside the bounds defined by `startDate` and `endDate`, it will be automatically adjusted:
```typescript
const options = {
currentDate: '2022-01-01T00:00:00Z', // Before startDate
startDate: '2023-01-01T00:00:00Z',
endDate: '2024-01-01T00:00:00Z',
};
// currentDate will be clamped to startDate (2023-01-01T00:00:00Z)
const interval = CronExpressionParser.parse('0 0 * * *', options);
```
**Validation during iteration**: While the initial `currentDate` is automatically adjusted, the library still validates date bounds during iteration:
```typescript
const options = {
currentDate: '2023-12-31T00:00:00Z',
endDate: '2024-01-01T00:00:00Z', // Very close end date
};
const interval = CronExpressionParser.parse('0 0 * * *', options);
console.log('Next:', interval.next().toString()); // Works fine
// This will throw an error because it would exceed endDate
try {
console.log('Next:', interval.next().toString());
} catch (err) {
console.log('Error:', err.message); // "Out of the time span range"
}
```
This behavior simplifies working with date ranges by removing the need to manually ensure that `currentDate` is within bounds, reducing confusion and making the API more intuitive.
### Crontab File Operations
For working with crontab files, use the CronFileParser:
```typescript
import { CronFileParser } from 'cron-parser';
// Async file parsing
try {
const result = await CronFileParser.parseFile('/path/to/crontab');
console.log('Variables:', result.variables);
console.log('Expressions:', result.expressions);
console.log('Errors:', result.errors);
} catch (err) {
console.log('Error:', err.message);
}
// Sync file parsing
try {
const result = CronFileParser.parseFileSync('/path/to/crontab');
console.log('Variables:', result.variables);
console.log('Expressions:', result.expressions);
console.log('Errors:', result.errors);
} catch (err) {
console.log('Error:', err.message);
}
```
## Advanced Features
### Strict Mode
In several implementations of CRON, it's ambiguous to specify both the Day Of Month and Day Of Week parameters simultaneously, as it's unclear which one should take precedence. Despite this ambiguity, this library allows both parameters to be set by default, although the resultant behavior might not align with your expectations.
To resolve this ambiguity, you can activate the strict mode of the library. When strict mode is enabled, the library enforces several validation rules:
1. **Day Of Month and Day Of Week**: Prevents the simultaneous setting of both Day Of Month and Day Of Week fields
2. **Complete Expression**: Requires all 6 fields to be present in the expression (second, minute, hour, day of month, month, day of week)
3. **Non-empty Expression**: Rejects empty expressions that would otherwise default to '0 \* \* \* \* \*'
These validations help ensure that your cron expressions are unambiguous and correctly formatted.
```typescript
import { CronExpressionParser } from 'cron-parser';
// This will throw an error in strict mode because it uses both dayOfMonth and dayOfWeek
const options = {
currentDate: new Date('Mon, 12 Sep 2022 14:00:00'),
strict: true,
};
try {
// This will throw an error in strict mode
CronExpressionParser.parse('0 0 12 1-31 * 1', options);
} catch (err) {
console.log('Error:', err.message);
// Error: Cannot use both dayOfMonth and dayOfWeek together in strict mode!
}
// This will also throw an error in strict mode because it has fewer than 6 fields
try {
CronExpressionParser.parse('0 20 15 * *', { strict: true });
} catch (err) {
console.log('Error:', err.message);
// Error: Invalid cron expression, expected 6 fields
}
```
### Last Day of Month/Week Support
The library supports parsing the range `0L - 7L` in the `weekday` position of the cron expression, where the `L` means "last occurrence of this weekday for the month in progress".
For example, the following expression will run on the last Monday of the month at midnight:
```typescript
import { CronExpressionParser } from 'cron-parser';
// Last Monday of every month at midnight
const lastMonday = CronExpressionParser.parse('0 0 0 * * 1L');
// You can also combine L expressions with other weekday expressions
// This will run every Monday and the last Wednesday of the month
const mixedWeekdays = CronExpressionParser.parse('0 0 0 * * 1,3L');
// Last day of every month
const lastDay = CronExpressionParser.parse('0 0 L * *');
```
### Using Iterator
```typescript
import { CronExpressionParser } from 'cron-parser';
const interval = CronExpressionParser.parse('0 */2 * * *');
// Using for...of
for (const date of interval) {
console.log('Iterator value:', date.toString());
if (someCondition) break;
}
// Using take() for a specific number of iterations
const nextFiveDates = interval.take(5);
console.log(
'Next 5 dates:',
nextFiveDates.map((date) => date.toString()),
);
```
### Timezone Support
The library provides robust timezone support using Luxon, handling DST transitions correctly:
```typescript
import { CronExpressionParser } from 'cron-parser';
const options = {
currentDate: '2023-03-26T01:00:00',
tz: 'Europe/London',
};
const interval = CronExpressionParser.parse('0 * * * *', options);
// Will correctly handle DST transition
console.log('Next dates during DST transition:');
console.log(interval.next().toString());
console.log(interval.next().toString());
console.log(interval.next().toString());
```
### Field Manipulation
You can modify cron fields programmatically using `CronFieldCollection.from` and construct a new expression:
```typescript
import { CronExpressionParser, CronFieldCollection, CronHour, CronMinute } from 'cron-parser';
// Parse original expression
const interval = CronExpressionParser.parse('0 7 * * 1-5');
// Create new collection with modified fields using raw values
const modified = CronFieldCollection.from(interval.fields, {
hour: [8],
minute: [30],
dayOfWeek: [1, 3, 5],
});
console.log(modified.stringify()); // "30 8 * * 1,3,5"
// You can also use CronField instances
const modified2 = CronFieldCollection.from(interval.fields, {
hour: new CronHour([15]),
minute: new CronMinute([30]),
});
console.log(modified2.stringify()); // "30 15 * * 1-5"
```
The `CronFieldCollection.from` method accepts either CronField instances or raw values that would be valid for creating new CronField instances. This is particularly useful when you need to modify only specific fields while keeping others unchanged.
### Hash support
The library supports adding [jitter](https://en.wikipedia.org/wiki/Jitter) to the returned intervals using the `H` special character in a field. When `H` is specified instead of `*`, a random value is used (`H` is replaced by `23`, where 23 is picked randomly, within the valid range of the field).
This jitter allows to spread the load when it comes to job scheduling. This feature is inspired by Jenkins's cron syntax.
```typescript
import { CronExpressionParser } from 'cron-parser';
// At 23:<randomized> on every day-of-week from Monday through Friday.
const interval = CronExpressionParser.parse('H 23 * * 1-5');
// At <randomized>:30 everyday.
const interval = CronExpressionParser.parse('30 H * * *');
// At every minutes of <randomized> hour at <randomized> second everyday.
const interval = CronExpressionParser.parse('H * H * * *');
// At every 5th minute starting from a random offset.
// For example, if the random offset is 3, it will run at minutes 3, 8, 13, 18, etc.
const interval = CronExpressionParser.parse('H/5 * * * *');
// At a random minute within the range 0-10 everyday.
const interval = CronExpressionParser.parse('H(0-10) * * * *');
// At every 5th minute starting from a random offset within the range 0-4.
// For example, if the random offset is 2, it will run at minutes 2, 7, 12, 17, etc.
// The random offset is constrained to be less than the step value.
const interval = CronExpressionParser.parse('H(0-29)/5 * * * *');
// At every minute of the third <randomized> day of the month
const interval = CronExpressionParser.parse('* * * * H#3');
```
The randomness is seed-able using the `hashSeed` option of `CronExpressionOptions`:
```typescript
import { CronExpressionParser } from 'cron-parser';
const options = {
currentDate: '2023-03-26T01:00:00',
hashSeed: 'main-backup', // Generally, hashSeed would be a job name for example
};
const interval = CronExpressionParser.parse('H * * * H', options);
console.log(interval.stringify()); // "12 * * * 4"
const otherInterval = CronExpressionParser.parse('H * * * H', options);
// Using the same seed will always return the same jitter
console.log(otherInterval.stringify()); // "12 * * * 4"
```
## License
MIT

497
node_modules/cron-parser/dist/CronDate.js generated vendored Normal file
View File

@@ -0,0 +1,497 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CronDate = exports.DAYS_IN_MONTH = exports.DateMathOp = exports.TimeUnit = void 0;
const luxon_1 = require("luxon");
var TimeUnit;
(function (TimeUnit) {
TimeUnit["Second"] = "Second";
TimeUnit["Minute"] = "Minute";
TimeUnit["Hour"] = "Hour";
TimeUnit["Day"] = "Day";
TimeUnit["Month"] = "Month";
TimeUnit["Year"] = "Year";
})(TimeUnit || (exports.TimeUnit = TimeUnit = {}));
var DateMathOp;
(function (DateMathOp) {
DateMathOp["Add"] = "Add";
DateMathOp["Subtract"] = "Subtract";
})(DateMathOp || (exports.DateMathOp = DateMathOp = {}));
exports.DAYS_IN_MONTH = Object.freeze([31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]);
/**
* CronDate class that wraps the Luxon DateTime object to provide
* a consistent API for working with dates and times in the context of cron.
*/
class CronDate {
#date;
#dstStart = null;
#dstEnd = null;
/**
* Maps the verb to the appropriate method
*/
#verbMap = {
add: {
[TimeUnit.Year]: this.addYear.bind(this),
[TimeUnit.Month]: this.addMonth.bind(this),
[TimeUnit.Day]: this.addDay.bind(this),
[TimeUnit.Hour]: this.addHour.bind(this),
[TimeUnit.Minute]: this.addMinute.bind(this),
[TimeUnit.Second]: this.addSecond.bind(this),
},
subtract: {
[TimeUnit.Year]: this.subtractYear.bind(this),
[TimeUnit.Month]: this.subtractMonth.bind(this),
[TimeUnit.Day]: this.subtractDay.bind(this),
[TimeUnit.Hour]: this.subtractHour.bind(this),
[TimeUnit.Minute]: this.subtractMinute.bind(this),
[TimeUnit.Second]: this.subtractSecond.bind(this),
},
};
/**
* Constructs a new CronDate instance.
* @param {CronDate | Date | number | string} [timestamp] - The timestamp to initialize the CronDate with.
* @param {string} [tz] - The timezone to use for the CronDate.
*/
constructor(timestamp, tz) {
const dateOpts = { zone: tz };
// Initialize the internal DateTime object based on the type of timestamp provided.
if (!timestamp) {
this.#date = luxon_1.DateTime.local();
}
else if (timestamp instanceof CronDate) {
this.#date = timestamp.#date;
this.#dstStart = timestamp.#dstStart;
this.#dstEnd = timestamp.#dstEnd;
}
else if (timestamp instanceof Date) {
this.#date = luxon_1.DateTime.fromJSDate(timestamp, dateOpts);
}
else if (typeof timestamp === 'number') {
this.#date = luxon_1.DateTime.fromMillis(timestamp, dateOpts);
}
else {
this.#date = luxon_1.DateTime.fromISO(timestamp, dateOpts);
this.#date.isValid || (this.#date = luxon_1.DateTime.fromRFC2822(timestamp, dateOpts));
this.#date.isValid || (this.#date = luxon_1.DateTime.fromSQL(timestamp, dateOpts));
this.#date.isValid || (this.#date = luxon_1.DateTime.fromFormat(timestamp, 'EEE, d MMM yyyy HH:mm:ss', dateOpts));
}
// Check for valid DateTime and throw an error if not valid.
if (!this.#date.isValid) {
throw new Error(`CronDate: unhandled timestamp: ${timestamp}`);
}
// Set the timezone if it is provided and different from the current zone.
if (tz && tz !== this.#date.zoneName) {
this.#date = this.#date.setZone(tz);
}
}
/**
* Determines if the given year is a leap year.
* @param {number} year - The year to check
* @returns {boolean} - True if the year is a leap year, false otherwise
* @private
*/
static #isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
}
/**
* Returns daylight savings start time.
* @returns {number | null}
*/
get dstStart() {
return this.#dstStart;
}
/**
* Sets daylight savings start time.
* @param {number | null} value
*/
set dstStart(value) {
this.#dstStart = value;
}
/**
* Returns daylight savings end time.
* @returns {number | null}
*/
get dstEnd() {
return this.#dstEnd;
}
/**
* Sets daylight savings end time.
* @param {number | null} value
*/
set dstEnd(value) {
this.#dstEnd = value;
}
/**
* Adds one year to the current CronDate.
*/
addYear() {
this.#date = this.#date.plus({ years: 1 });
}
/**
* Adds one month to the current CronDate.
*/
addMonth() {
this.#date = this.#date.plus({ months: 1 }).startOf('month');
}
/**
* Adds one day to the current CronDate.
*/
addDay() {
this.#date = this.#date.plus({ days: 1 }).startOf('day');
}
/**
* Adds one hour to the current CronDate.
*/
addHour() {
this.#date = this.#date.plus({ hours: 1 }).startOf('hour');
}
/**
* Adds one minute to the current CronDate.
*/
addMinute() {
this.#date = this.#date.plus({ minutes: 1 }).startOf('minute');
}
/**
* Adds one second to the current CronDate.
*/
addSecond() {
this.#date = this.#date.plus({ seconds: 1 });
}
/**
* Subtracts one year from the current CronDate.
*/
subtractYear() {
this.#date = this.#date.minus({ years: 1 });
}
/**
* Subtracts one month from the current CronDate.
* If the month is 1, it will subtract one year instead.
*/
subtractMonth() {
this.#date = this.#date.minus({ months: 1 }).endOf('month').startOf('second');
}
/**
* Subtracts one day from the current CronDate.
* If the day is 1, it will subtract one month instead.
*/
subtractDay() {
this.#date = this.#date.minus({ days: 1 }).endOf('day').startOf('second');
}
/**
* Subtracts one hour from the current CronDate.
* If the hour is 0, it will subtract one day instead.
*/
subtractHour() {
this.#date = this.#date.minus({ hours: 1 }).endOf('hour').startOf('second');
}
/**
* Subtracts one minute from the current CronDate.
* If the minute is 0, it will subtract one hour instead.
*/
subtractMinute() {
this.#date = this.#date.minus({ minutes: 1 }).endOf('minute').startOf('second');
}
/**
* Subtracts one second from the current CronDate.
* If the second is 0, it will subtract one minute instead.
*/
subtractSecond() {
this.#date = this.#date.minus({ seconds: 1 });
}
/**
* Adds a unit of time to the current CronDate.
* @param {TimeUnit} unit
*/
addUnit(unit) {
this.#verbMap.add[unit]();
}
/**
* Subtracts a unit of time from the current CronDate.
* @param {TimeUnit} unit
*/
subtractUnit(unit) {
this.#verbMap.subtract[unit]();
}
/**
* Handles a math operation.
* @param {DateMathOp} verb - {'add' | 'subtract'}
* @param {TimeUnit} unit - {'year' | 'month' | 'day' | 'hour' | 'minute' | 'second'}
*/
invokeDateOperation(verb, unit) {
if (verb === DateMathOp.Add) {
this.addUnit(unit);
return;
}
if (verb === DateMathOp.Subtract) {
this.subtractUnit(unit);
return;
}
/* istanbul ignore next - this would only happen if an end user call the handleMathOp with an invalid verb */
throw new Error(`Invalid verb: ${verb}`);
}
/**
* Returns the day.
* @returns {number}
*/
getDate() {
return this.#date.day;
}
/**
* Returns the year.
* @returns {number}
*/
getFullYear() {
return this.#date.year;
}
/**
* Returns the day of the week.
* @returns {number}
*/
getDay() {
const weekday = this.#date.weekday;
return weekday === 7 ? 0 : weekday;
}
/**
* Returns the month.
* @returns {number}
*/
getMonth() {
return this.#date.month - 1;
}
/**
* Returns the hour.
* @returns {number}
*/
getHours() {
return this.#date.hour;
}
/**
* Returns the minutes.
* @returns {number}
*/
getMinutes() {
return this.#date.minute;
}
/**
* Returns the seconds.
* @returns {number}
*/
getSeconds() {
return this.#date.second;
}
/**
* Returns the milliseconds.
* @returns {number}
*/
getMilliseconds() {
return this.#date.millisecond;
}
/**
* Returns the time.
* @returns {number}
*/
getTime() {
return this.#date.valueOf();
}
/**
* Returns the UTC day.
* @returns {number}
*/
getUTCDate() {
return this.#getUTC().day;
}
/**
* Returns the UTC year.
* @returns {number}
*/
getUTCFullYear() {
return this.#getUTC().year;
}
/**
* Returns the UTC day of the week.
* @returns {number}
*/
getUTCDay() {
const weekday = this.#getUTC().weekday;
return weekday === 7 ? 0 : weekday;
}
/**
* Returns the UTC month.
* @returns {number}
*/
getUTCMonth() {
return this.#getUTC().month - 1;
}
/**
* Returns the UTC hour.
* @returns {number}
*/
getUTCHours() {
return this.#getUTC().hour;
}
/**
* Returns the UTC minutes.
* @returns {number}
*/
getUTCMinutes() {
return this.#getUTC().minute;
}
/**
* Returns the UTC seconds.
* @returns {number}
*/
getUTCSeconds() {
return this.#getUTC().second;
}
/**
* Returns the UTC milliseconds.
* @returns {string | null}
*/
toISOString() {
return this.#date.toUTC().toISO();
}
/**
* Returns the date as a JSON string.
* @returns {string | null}
*/
toJSON() {
return this.#date.toJSON();
}
/**
* Sets the day.
* @param d
*/
setDate(d) {
this.#date = this.#date.set({ day: d });
}
/**
* Sets the year.
* @param y
*/
setFullYear(y) {
this.#date = this.#date.set({ year: y });
}
/**
* Sets the day of the week.
* @param d
*/
setDay(d) {
this.#date = this.#date.set({ weekday: d });
}
/**
* Sets the month.
* @param m
*/
setMonth(m) {
this.#date = this.#date.set({ month: m + 1 });
}
/**
* Sets the hour.
* @param h
*/
setHours(h) {
this.#date = this.#date.set({ hour: h });
}
/**
* Sets the minutes.
* @param m
*/
setMinutes(m) {
this.#date = this.#date.set({ minute: m });
}
/**
* Sets the seconds.
* @param s
*/
setSeconds(s) {
this.#date = this.#date.set({ second: s });
}
/**
* Sets the milliseconds.
* @param s
*/
setMilliseconds(s) {
this.#date = this.#date.set({ millisecond: s });
}
/**
* Returns the date as a string.
* @returns {string}
*/
toString() {
return this.toDate().toString();
}
/**
* Returns the date as a Date object.
* @returns {Date}
*/
toDate() {
return this.#date.toJSDate();
}
/**
* Returns true if the day is the last day of the month.
* @returns {boolean}
*/
isLastDayOfMonth() {
const { day, month } = this.#date;
// Special handling for February in leap years
if (month === 2) {
const isLeap = CronDate.#isLeapYear(this.#date.year);
return day === exports.DAYS_IN_MONTH[month - 1] - (isLeap ? 0 : 1);
}
// For other months, check against the static map
return day === exports.DAYS_IN_MONTH[month - 1];
}
/**
* Returns true if the day is the last weekday of the month.
* @returns {boolean}
*/
isLastWeekdayOfMonth() {
const { day, month } = this.#date;
// Get the last day of the current month
let lastDay;
if (month === 2) {
// Special handling for February
lastDay = exports.DAYS_IN_MONTH[month - 1] - (CronDate.#isLeapYear(this.#date.year) ? 0 : 1);
}
else {
lastDay = exports.DAYS_IN_MONTH[month - 1];
}
// Check if the current day is within 7 days of the end of the month
return day > lastDay - 7;
}
/**
* Primarily for internal use.
* @param {DateMathOp} op - The operation to perform.
* @param {TimeUnit} unit - The unit of time to use.
* @param {number} [hoursLength] - The length of the hours. Required when unit is not month or day.
*/
applyDateOperation(op, unit, hoursLength) {
if (unit === TimeUnit.Month || unit === TimeUnit.Day) {
this.invokeDateOperation(op, unit);
return;
}
const previousHour = this.getHours();
this.invokeDateOperation(op, unit);
const currentHour = this.getHours();
const diff = currentHour - previousHour;
if (diff === 2) {
if (hoursLength !== 24) {
this.dstStart = currentHour;
}
}
else if (diff === 0 && this.getMinutes() === 0 && this.getSeconds() === 0) {
if (hoursLength !== 24) {
this.dstEnd = currentHour;
}
}
}
/**
* Returns the UTC date.
* @private
* @returns {DateTime}
*/
#getUTC() {
return this.#date.toUTC();
}
}
exports.CronDate = CronDate;
exports.default = CronDate;

407
node_modules/cron-parser/dist/CronExpression.js generated vendored Normal file
View File

@@ -0,0 +1,407 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CronExpression = exports.LOOPS_LIMIT_EXCEEDED_ERROR_MESSAGE = exports.TIME_SPAN_OUT_OF_BOUNDS_ERROR_MESSAGE = void 0;
const CronDate_1 = require("./CronDate");
/**
* Error message for when the current date is outside the specified time span.
*/
exports.TIME_SPAN_OUT_OF_BOUNDS_ERROR_MESSAGE = 'Out of the time span range';
/**
* Error message for when the loop limit is exceeded during iteration.
*/
exports.LOOPS_LIMIT_EXCEEDED_ERROR_MESSAGE = 'Invalid expression, loop limit exceeded';
/**
* Cron iteration loop safety limit
*/
const LOOP_LIMIT = 10000;
/**
* Class representing a Cron expression.
*/
class CronExpression {
#options;
#tz;
#currentDate;
#startDate;
#endDate;
#fields;
/**
* Creates a new CronExpression instance.
*
* @param {CronFieldCollection} fields - Cron fields.
* @param {CronExpressionOptions} options - Parser options.
*/
constructor(fields, options) {
this.#options = options;
this.#tz = options.tz;
this.#startDate = options.startDate ? new CronDate_1.CronDate(options.startDate, this.#tz) : null;
this.#endDate = options.endDate ? new CronDate_1.CronDate(options.endDate, this.#tz) : null;
let currentDateValue = options.currentDate ?? options.startDate;
if (currentDateValue) {
const tempCurrentDate = new CronDate_1.CronDate(currentDateValue, this.#tz);
if (this.#startDate && tempCurrentDate.getTime() < this.#startDate.getTime()) {
currentDateValue = this.#startDate;
}
else if (this.#endDate && tempCurrentDate.getTime() > this.#endDate.getTime()) {
currentDateValue = this.#endDate;
}
}
this.#currentDate = new CronDate_1.CronDate(currentDateValue, this.#tz);
this.#fields = fields;
}
/**
* Getter for the cron fields.
*
* @returns {CronFieldCollection} Cron fields.
*/
get fields() {
return this.#fields;
}
/**
* Converts cron fields back to a CronExpression instance.
*
* @public
* @param {Record<string, number[]>} fields - The input cron fields object.
* @param {CronExpressionOptions} [options] - Optional parsing options.
* @returns {CronExpression} - A new CronExpression instance.
*/
static fieldsToExpression(fields, options) {
return new CronExpression(fields, options || {});
}
/**
* Checks if the given value matches any element in the sequence.
*
* @param {number} value - The value to be matched.
* @param {number[]} sequence - The sequence to be checked against.
* @returns {boolean} - True if the value matches an element in the sequence; otherwise, false.
* @memberof CronExpression
* @private
*/
static #matchSchedule(value, sequence) {
return sequence.some((element) => element === value);
}
/**
* Determines if the current date matches the last specified weekday of the month.
*
* @param {Array<(number|string)>} expressions - An array of expressions containing weekdays and "L" for the last weekday.
* @param {CronDate} currentDate - The current date object.
* @returns {boolean} - True if the current date matches the last specified weekday of the month; otherwise, false.
* @memberof CronExpression
* @private
*/
static #isLastWeekdayOfMonthMatch(expressions, currentDate) {
const isLastWeekdayOfMonth = currentDate.isLastWeekdayOfMonth();
return expressions.some((expression) => {
// The first character represents the weekday
const weekday = parseInt(expression.toString().charAt(0), 10) % 7;
if (Number.isNaN(weekday)) {
throw new Error(`Invalid last weekday of the month expression: ${expression}`);
}
// Check if the current date matches the last specified weekday of the month
return currentDate.getDay() === weekday && isLastWeekdayOfMonth;
});
}
/**
* Find the next scheduled date based on the cron expression.
* @returns {CronDate} - The next scheduled date or an ES6 compatible iterator object.
* @memberof CronExpression
* @public
*/
next() {
return this.#findSchedule();
}
/**
* Find the previous scheduled date based on the cron expression.
* @returns {CronDate} - The previous scheduled date or an ES6 compatible iterator object.
* @memberof CronExpression
* @public
*/
prev() {
return this.#findSchedule(true);
}
/**
* Check if there is a next scheduled date based on the current date and cron expression.
* @returns {boolean} - Returns true if there is a next scheduled date, false otherwise.
* @memberof CronExpression
* @public
*/
hasNext() {
const current = this.#currentDate;
try {
this.#findSchedule();
return true;
}
catch {
return false;
}
finally {
this.#currentDate = current;
}
}
/**
* Check if there is a previous scheduled date based on the current date and cron expression.
* @returns {boolean} - Returns true if there is a previous scheduled date, false otherwise.
* @memberof CronExpression
* @public
*/
hasPrev() {
const current = this.#currentDate;
try {
this.#findSchedule(true);
return true;
}
catch {
return false;
}
finally {
this.#currentDate = current;
}
}
/**
* Iterate over a specified number of steps and optionally execute a callback function for each step.
* @param {number} steps - The number of steps to iterate. Positive value iterates forward, negative value iterates backward.
* @returns {CronDate[]} - An array of iterator fields or CronDate objects.
* @memberof CronExpression
* @public
*/
take(limit) {
const items = [];
if (limit >= 0) {
for (let i = 0; i < limit; i++) {
try {
items.push(this.next());
}
catch {
return items;
}
}
}
else {
for (let i = 0; i > limit; i--) {
try {
items.push(this.prev());
}
catch {
return items;
}
}
}
return items;
}
/**
* Reset the iterators current date to a new date or the initial date.
* @param {Date | CronDate} [newDate] - Optional new date to reset to. If not provided, it will reset to the initial date.
* @memberof CronExpression
* @public
*/
reset(newDate) {
this.#currentDate = new CronDate_1.CronDate(newDate || this.#options.currentDate);
}
/**
* Generate a string representation of the cron expression.
* @param {boolean} [includeSeconds=false] - Whether to include the seconds field in the string representation.
* @returns {string} - The string representation of the cron expression.
* @memberof CronExpression
* @public
*/
stringify(includeSeconds = false) {
return this.#fields.stringify(includeSeconds);
}
/**
* Check if the cron expression includes the given date
* @param {Date|CronDate} date
* @returns {boolean}
*/
includesDate(date) {
const { second, minute, hour, month } = this.#fields;
const dt = new CronDate_1.CronDate(date, this.#tz);
// Check basic time fields first
if (!second.values.includes(dt.getSeconds()) ||
!minute.values.includes(dt.getMinutes()) ||
!hour.values.includes(dt.getHours()) ||
!month.values.includes((dt.getMonth() + 1))) {
return false;
}
// Check day of month and day of week using the same logic as #findSchedule
if (!this.#matchDayOfMonth(dt)) {
return false;
}
// Check nth day of week if specified
if (this.#fields.dayOfWeek.nthDay > 0) {
const weekInMonth = Math.ceil(dt.getDate() / 7);
if (weekInMonth !== this.#fields.dayOfWeek.nthDay) {
return false;
}
}
return true;
}
/**
* Returns the string representation of the cron expression.
* @returns {CronDate} - The next schedule date.
*/
toString() {
/* istanbul ignore next - should be impossible under normal use to trigger the or branch */
return this.#options.expression || this.stringify(true);
}
/**
* Determines if the given date matches the cron expression's day of month and day of week fields.
*
* The function checks the following rules:
* Rule 1: If both "day of month" and "day of week" are restricted (not wildcard), then one or both must match the current day.
* Rule 2: If "day of month" is restricted and "day of week" is not restricted, then "day of month" must match the current day.
* Rule 3: If "day of month" is a wildcard, "day of week" is not a wildcard, and "day of week" matches the current day, then the match is accepted.
* If none of the rules match, the match is rejected.
*
* @param {CronDate} currentDate - The current date to be evaluated against the cron expression.
* @returns {boolean} Returns true if the current date matches the cron expression's day of month and day of week fields, otherwise false.
* @memberof CronExpression
* @private
*/
#matchDayOfMonth(currentDate) {
// Check if day of month and day of week fields are wildcards or restricted (not wildcard).
const isDayOfMonthWildcardMatch = this.#fields.dayOfMonth.isWildcard;
const isRestrictedDayOfMonth = !isDayOfMonthWildcardMatch;
const isDayOfWeekWildcardMatch = this.#fields.dayOfWeek.isWildcard;
const isRestrictedDayOfWeek = !isDayOfWeekWildcardMatch;
// Calculate if the current date matches the day of month and day of week fields.
const matchedDOM = CronExpression.#matchSchedule(currentDate.getDate(), this.#fields.dayOfMonth.values) ||
(this.#fields.dayOfMonth.hasLastChar && currentDate.isLastDayOfMonth());
const matchedDOW = CronExpression.#matchSchedule(currentDate.getDay(), this.#fields.dayOfWeek.values) ||
(this.#fields.dayOfWeek.hasLastChar &&
CronExpression.#isLastWeekdayOfMonthMatch(this.#fields.dayOfWeek.values, currentDate));
// Rule 1: Both "day of month" and "day of week" are restricted; one or both must match the current day.
if (isRestrictedDayOfMonth && isRestrictedDayOfWeek && (matchedDOM || matchedDOW)) {
return true;
}
// Rule 2: "day of month" restricted and "day of week" not restricted; "day of month" must match the current day.
if (matchedDOM && !isRestrictedDayOfWeek) {
return true;
}
// Rule 3: "day of month" is a wildcard, "day of week" is not a wildcard, and "day of week" matches the current day.
if (isDayOfMonthWildcardMatch && !isDayOfWeekWildcardMatch && matchedDOW) {
return true;
}
// If none of the rules match, the match is rejected.
return false;
}
/**
* Determines if the current hour matches the cron expression.
*
* @param {CronDate} currentDate - The current date object.
* @param {DateMathOp} dateMathVerb - The date math operation enumeration value.
* @param {boolean} reverse - A flag indicating whether the matching should be done in reverse order.
* @returns {boolean} - True if the current hour matches the cron expression; otherwise, false.
*/
#matchHour(currentDate, dateMathVerb, reverse) {
const currentHour = currentDate.getHours();
const isMatch = CronExpression.#matchSchedule(currentHour, this.#fields.hour.values);
const isDstStart = currentDate.dstStart === currentHour;
const isDstEnd = currentDate.dstEnd === currentHour;
if (!isMatch && !isDstStart) {
currentDate.dstStart = null;
currentDate.applyDateOperation(dateMathVerb, CronDate_1.TimeUnit.Hour, this.#fields.hour.values.length);
return false;
}
if (isDstStart && !CronExpression.#matchSchedule(currentHour - 1, this.#fields.hour.values)) {
currentDate.invokeDateOperation(dateMathVerb, CronDate_1.TimeUnit.Hour);
return false;
}
if (isDstEnd && !reverse) {
currentDate.dstEnd = null;
currentDate.applyDateOperation(CronDate_1.DateMathOp.Add, CronDate_1.TimeUnit.Hour, this.#fields.hour.values.length);
return false;
}
return true;
}
/**
* Validates the current date against the start and end dates of the cron expression.
* If the current date is outside the specified time span, an error is thrown.
*
* @param currentDate {CronDate} - The current date to validate.
* @throws {Error} If the current date is outside the specified time span.
* @private
*/
#validateTimeSpan(currentDate) {
if (!this.#startDate && !this.#endDate) {
return;
}
const currentTime = currentDate.getTime();
if (this.#startDate && currentTime < this.#startDate.getTime()) {
throw new Error(exports.TIME_SPAN_OUT_OF_BOUNDS_ERROR_MESSAGE);
}
if (this.#endDate && currentTime > this.#endDate.getTime()) {
throw new Error(exports.TIME_SPAN_OUT_OF_BOUNDS_ERROR_MESSAGE);
}
}
/**
* Finds the next or previous schedule based on the cron expression.
*
* @param {boolean} [reverse=false] - If true, finds the previous schedule; otherwise, finds the next schedule.
* @returns {CronDate} - The next or previous schedule date.
* @private
*/
#findSchedule(reverse = false) {
const dateMathVerb = reverse ? CronDate_1.DateMathOp.Subtract : CronDate_1.DateMathOp.Add;
const currentDate = new CronDate_1.CronDate(this.#currentDate);
const startTimestamp = currentDate.getTime();
let stepCount = 0;
while (++stepCount < LOOP_LIMIT) {
this.#validateTimeSpan(currentDate);
if (!this.#matchDayOfMonth(currentDate)) {
currentDate.applyDateOperation(dateMathVerb, CronDate_1.TimeUnit.Day, this.#fields.hour.values.length);
continue;
}
if (!(this.#fields.dayOfWeek.nthDay <= 0 || Math.ceil(currentDate.getDate() / 7) === this.#fields.dayOfWeek.nthDay)) {
currentDate.applyDateOperation(dateMathVerb, CronDate_1.TimeUnit.Day, this.#fields.hour.values.length);
continue;
}
if (!CronExpression.#matchSchedule(currentDate.getMonth() + 1, this.#fields.month.values)) {
currentDate.applyDateOperation(dateMathVerb, CronDate_1.TimeUnit.Month, this.#fields.hour.values.length);
continue;
}
if (!this.#matchHour(currentDate, dateMathVerb, reverse)) {
continue;
}
if (!CronExpression.#matchSchedule(currentDate.getMinutes(), this.#fields.minute.values)) {
currentDate.applyDateOperation(dateMathVerb, CronDate_1.TimeUnit.Minute, this.#fields.hour.values.length);
continue;
}
if (!CronExpression.#matchSchedule(currentDate.getSeconds(), this.#fields.second.values)) {
currentDate.applyDateOperation(dateMathVerb, CronDate_1.TimeUnit.Second, this.#fields.hour.values.length);
continue;
}
if (startTimestamp === currentDate.getTime()) {
if (dateMathVerb === 'Add' || currentDate.getMilliseconds() === 0) {
currentDate.applyDateOperation(dateMathVerb, CronDate_1.TimeUnit.Second, this.#fields.hour.values.length);
}
continue;
}
break;
}
/* istanbul ignore next - should be impossible under normal use to trigger the branch */
if (stepCount > LOOP_LIMIT) {
throw new Error(exports.LOOPS_LIMIT_EXCEEDED_ERROR_MESSAGE);
}
if (currentDate.getMilliseconds() !== 0) {
currentDate.setMilliseconds(0);
}
this.#currentDate = currentDate;
return currentDate;
}
/**
* Returns an iterator for iterating through future CronDate instances
*
* @name Symbol.iterator
* @memberof CronExpression
* @returns {Iterator<CronDate>} An iterator object for CronExpression that returns CronDate values.
*/
[Symbol.iterator]() {
return {
next: () => {
const schedule = this.#findSchedule();
return { value: schedule, done: !this.hasNext() };
},
};
}
}
exports.CronExpression = CronExpression;
exports.default = CronExpression;

382
node_modules/cron-parser/dist/CronExpressionParser.js generated vendored Normal file
View File

@@ -0,0 +1,382 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CronExpressionParser = exports.DayOfWeek = exports.Months = exports.CronUnit = exports.PredefinedExpressions = void 0;
const CronFieldCollection_1 = require("./CronFieldCollection");
const CronExpression_1 = require("./CronExpression");
const random_1 = require("./utils/random");
const fields_1 = require("./fields");
var PredefinedExpressions;
(function (PredefinedExpressions) {
PredefinedExpressions["@yearly"] = "0 0 0 1 1 *";
PredefinedExpressions["@annually"] = "0 0 0 1 1 *";
PredefinedExpressions["@monthly"] = "0 0 0 1 * *";
PredefinedExpressions["@weekly"] = "0 0 0 * * 0";
PredefinedExpressions["@daily"] = "0 0 0 * * *";
PredefinedExpressions["@hourly"] = "0 0 * * * *";
PredefinedExpressions["@minutely"] = "0 * * * * *";
PredefinedExpressions["@secondly"] = "* * * * * *";
PredefinedExpressions["@weekdays"] = "0 0 0 * * 1-5";
PredefinedExpressions["@weekends"] = "0 0 0 * * 0,6";
})(PredefinedExpressions || (exports.PredefinedExpressions = PredefinedExpressions = {}));
var CronUnit;
(function (CronUnit) {
CronUnit["Second"] = "Second";
CronUnit["Minute"] = "Minute";
CronUnit["Hour"] = "Hour";
CronUnit["DayOfMonth"] = "DayOfMonth";
CronUnit["Month"] = "Month";
CronUnit["DayOfWeek"] = "DayOfWeek";
})(CronUnit || (exports.CronUnit = CronUnit = {}));
// these need to be lowercase for the parser to work
var Months;
(function (Months) {
Months[Months["jan"] = 1] = "jan";
Months[Months["feb"] = 2] = "feb";
Months[Months["mar"] = 3] = "mar";
Months[Months["apr"] = 4] = "apr";
Months[Months["may"] = 5] = "may";
Months[Months["jun"] = 6] = "jun";
Months[Months["jul"] = 7] = "jul";
Months[Months["aug"] = 8] = "aug";
Months[Months["sep"] = 9] = "sep";
Months[Months["oct"] = 10] = "oct";
Months[Months["nov"] = 11] = "nov";
Months[Months["dec"] = 12] = "dec";
})(Months || (exports.Months = Months = {}));
// these need to be lowercase for the parser to work
var DayOfWeek;
(function (DayOfWeek) {
DayOfWeek[DayOfWeek["sun"] = 0] = "sun";
DayOfWeek[DayOfWeek["mon"] = 1] = "mon";
DayOfWeek[DayOfWeek["tue"] = 2] = "tue";
DayOfWeek[DayOfWeek["wed"] = 3] = "wed";
DayOfWeek[DayOfWeek["thu"] = 4] = "thu";
DayOfWeek[DayOfWeek["fri"] = 5] = "fri";
DayOfWeek[DayOfWeek["sat"] = 6] = "sat";
})(DayOfWeek || (exports.DayOfWeek = DayOfWeek = {}));
/**
* Static class that parses a cron expression and returns a CronExpression object.
* @static
* @class CronExpressionParser
*/
class CronExpressionParser {
/**
* Parses a cron expression and returns a CronExpression object.
* @param {string} expression - The cron expression to parse.
* @param {CronExpressionOptions} [options={}] - The options to use when parsing the expression.
* @param {boolean} [options.strict=false] - If true, will throw an error if the expression contains both dayOfMonth and dayOfWeek.
* @param {CronDate} [options.currentDate=new CronDate(undefined, 'UTC')] - The date to use when calculating the next/previous occurrence.
*
* @returns {CronExpression} A CronExpression object.
*/
static parse(expression, options = {}) {
const { strict = false, hashSeed } = options;
const rand = (0, random_1.seededRandom)(hashSeed);
expression = PredefinedExpressions[expression] || expression;
const rawFields = CronExpressionParser.#getRawFields(expression, strict);
if (!(rawFields.dayOfMonth === '*' || rawFields.dayOfWeek === '*' || !strict)) {
throw new Error('Cannot use both dayOfMonth and dayOfWeek together in strict mode!');
}
const second = CronExpressionParser.#parseField(CronUnit.Second, rawFields.second, fields_1.CronSecond.constraints, rand);
const minute = CronExpressionParser.#parseField(CronUnit.Minute, rawFields.minute, fields_1.CronMinute.constraints, rand);
const hour = CronExpressionParser.#parseField(CronUnit.Hour, rawFields.hour, fields_1.CronHour.constraints, rand);
const month = CronExpressionParser.#parseField(CronUnit.Month, rawFields.month, fields_1.CronMonth.constraints, rand);
const dayOfMonth = CronExpressionParser.#parseField(CronUnit.DayOfMonth, rawFields.dayOfMonth, fields_1.CronDayOfMonth.constraints, rand);
const { dayOfWeek: _dayOfWeek, nthDayOfWeek } = CronExpressionParser.#parseNthDay(rawFields.dayOfWeek);
const dayOfWeek = CronExpressionParser.#parseField(CronUnit.DayOfWeek, _dayOfWeek, fields_1.CronDayOfWeek.constraints, rand);
const fields = new CronFieldCollection_1.CronFieldCollection({
second: new fields_1.CronSecond(second, { rawValue: rawFields.second }),
minute: new fields_1.CronMinute(minute, { rawValue: rawFields.minute }),
hour: new fields_1.CronHour(hour, { rawValue: rawFields.hour }),
dayOfMonth: new fields_1.CronDayOfMonth(dayOfMonth, { rawValue: rawFields.dayOfMonth }),
month: new fields_1.CronMonth(month, { rawValue: rawFields.month }),
dayOfWeek: new fields_1.CronDayOfWeek(dayOfWeek, { rawValue: rawFields.dayOfWeek, nthDayOfWeek }),
});
return new CronExpression_1.CronExpression(fields, { ...options, expression });
}
/**
* Get the raw fields from a cron expression.
* @param {string} expression - The cron expression to parse.
* @param {boolean} strict - If true, will throw an error if the expression contains both dayOfMonth and dayOfWeek.
* @private
* @returns {RawCronFields} The raw fields.
*/
static #getRawFields(expression, strict) {
if (strict && !expression.length) {
throw new Error('Invalid cron expression');
}
expression = expression || '0 * * * * *';
const atoms = expression.trim().split(/\s+/);
if (strict && atoms.length < 6) {
throw new Error('Invalid cron expression, expected 6 fields');
}
if (atoms.length > 6) {
throw new Error('Invalid cron expression, too many fields');
}
const defaults = ['*', '*', '*', '*', '*', '0'];
if (atoms.length < defaults.length) {
atoms.unshift(...defaults.slice(atoms.length));
}
const [second, minute, hour, dayOfMonth, month, dayOfWeek] = atoms;
return { second, minute, hour, dayOfMonth, month, dayOfWeek };
}
/**
* Parse a field from a cron expression.
* @param {CronUnit} field - The field to parse.
* @param {string} value - The value of the field.
* @param {CronConstraints} constraints - The constraints for the field.
* @private
* @returns {(number | string)[]} The parsed field.
*/
static #parseField(field, value, constraints, rand) {
// Replace aliases for month and dayOfWeek
if (field === CronUnit.Month || field === CronUnit.DayOfWeek) {
value = value.replace(/[a-z]{3}/gi, (match) => {
match = match.toLowerCase();
const replacer = Months[match] || DayOfWeek[match];
if (replacer === undefined) {
throw new Error(`Validation error, cannot resolve alias "${match}"`);
}
return replacer.toString();
});
}
// Check for valid characters
if (!constraints.validChars.test(value)) {
throw new Error(`Invalid characters, got value: ${value}`);
}
value = this.#parseWildcard(value, constraints);
value = this.#parseHashed(value, constraints, rand);
return this.#parseSequence(field, value, constraints);
}
/**
* Parse a wildcard from a cron expression.
* @param {string} value - The value to parse.
* @param {CronConstraints} constraints - The constraints for the field.
* @private
*/
static #parseWildcard(value, constraints) {
return value.replace(/[*?]/g, constraints.min + '-' + constraints.max);
}
/**
* Parse a hashed value from a cron expression.
* @param {string} value - The value to parse.
* @param {CronConstraints} constraints - The constraints for the field.
* @param {PRNG} rand - The random number generator to use.
* @private
*/
static #parseHashed(value, constraints, rand) {
const randomValue = rand();
return value.replace(/H(?:\((\d+)-(\d+)\))?(?:\/(\d+))?/g, (_, min, max, step) => {
// H(range)/step
if (min && max && step) {
const minNum = parseInt(min, 10);
const maxNum = parseInt(max, 10);
const stepNum = parseInt(step, 10);
if (minNum > maxNum) {
throw new Error(`Invalid range: ${minNum}-${maxNum}, min > max`);
}
if (stepNum <= 0) {
throw new Error(`Invalid step: ${stepNum}, must be positive`);
}
const minStart = Math.max(minNum, constraints.min);
const offset = Math.floor(randomValue * stepNum);
const values = [];
for (let i = Math.floor(minStart / stepNum) * stepNum + offset; i <= maxNum; i += stepNum) {
if (i >= minStart) {
values.push(i);
}
}
return values.join(',');
}
// H(range)
else if (min && max) {
const minNum = parseInt(min, 10);
const maxNum = parseInt(max, 10);
if (minNum > maxNum) {
throw new Error(`Invalid range: ${minNum}-${maxNum}, min > max`);
}
return String(Math.floor(randomValue * (maxNum - minNum + 1)) + minNum);
}
// H/step
else if (step) {
const stepNum = parseInt(step, 10);
// Validate step
if (stepNum <= 0) {
throw new Error(`Invalid step: ${stepNum}, must be positive`);
}
const offset = Math.floor(randomValue * stepNum);
const values = [];
for (let i = Math.floor(constraints.min / stepNum) * stepNum + offset; i <= constraints.max; i += stepNum) {
if (i >= constraints.min) {
values.push(i);
}
}
return values.join(',');
}
// H
else {
return String(Math.floor(randomValue * (constraints.max - constraints.min + 1) + constraints.min));
}
});
}
/**
* Parse a sequence from a cron expression.
* @param {CronUnit} field - The field to parse.
* @param {string} val - The sequence to parse.
* @param {CronConstraints} constraints - The constraints for the field.
* @private
*/
static #parseSequence(field, val, constraints) {
const stack = [];
function handleResult(result, constraints) {
if (Array.isArray(result)) {
stack.push(...result);
}
else {
if (CronExpressionParser.#isValidConstraintChar(constraints, result)) {
stack.push(result);
}
else {
const v = parseInt(result.toString(), 10);
const isValid = v >= constraints.min && v <= constraints.max;
if (!isValid) {
throw new Error(`Constraint error, got value ${result} expected range ${constraints.min}-${constraints.max}`);
}
stack.push(field === CronUnit.DayOfWeek ? v % 7 : result);
}
}
}
const atoms = val.split(',');
atoms.forEach((atom) => {
if (!(atom.length > 0)) {
throw new Error('Invalid list value format');
}
handleResult(CronExpressionParser.#parseRepeat(field, atom, constraints), constraints);
});
return stack;
}
/**
* Parse repeat from a cron expression.
* @param {CronUnit} field - The field to parse.
* @param {string} val - The repeat to parse.
* @param {CronConstraints} constraints - The constraints for the field.
* @private
* @returns {(number | string)[]} The parsed repeat.
*/
static #parseRepeat(field, val, constraints) {
const atoms = val.split('/');
if (atoms.length > 2) {
throw new Error(`Invalid repeat: ${val}`);
}
if (atoms.length === 2) {
if (!isNaN(parseInt(atoms[0], 10))) {
atoms[0] = `${atoms[0]}-${constraints.max}`;
}
return CronExpressionParser.#parseRange(field, atoms[0], parseInt(atoms[1], 10), constraints);
}
return CronExpressionParser.#parseRange(field, val, 1, constraints);
}
/**
* Validate a cron range.
* @param {number} min - The minimum value of the range.
* @param {number} max - The maximum value of the range.
* @param {CronConstraints} constraints - The constraints for the field.
* @private
* @returns {void}
* @throws {Error} Throws an error if the range is invalid.
*/
static #validateRange(min, max, constraints) {
const isValid = !isNaN(min) && !isNaN(max) && min >= constraints.min && max <= constraints.max;
if (!isValid) {
throw new Error(`Constraint error, got range ${min}-${max} expected range ${constraints.min}-${constraints.max}`);
}
if (min > max) {
throw new Error(`Invalid range: ${min}-${max}, min(${min}) > max(${max})`);
}
}
/**
* Validate a cron repeat interval.
* @param {number} repeatInterval - The repeat interval to validate.
* @private
* @returns {void}
* @throws {Error} Throws an error if the repeat interval is invalid.
*/
static #validateRepeatInterval(repeatInterval) {
if (!(!isNaN(repeatInterval) && repeatInterval > 0)) {
throw new Error(`Constraint error, cannot repeat at every ${repeatInterval} time.`);
}
}
/**
* Create a range from a cron expression.
* @param {CronUnit} field - The field to parse.
* @param {number} min - The minimum value of the range.
* @param {number} max - The maximum value of the range.
* @param {number} repeatInterval - The repeat interval of the range.
* @private
* @returns {number[]} The created range.
*/
static #createRange(field, min, max, repeatInterval) {
const stack = [];
if (field === CronUnit.DayOfWeek && max % 7 === 0) {
stack.push(0);
}
for (let index = min; index <= max; index += repeatInterval) {
if (stack.indexOf(index) === -1) {
stack.push(index);
}
}
return stack;
}
/**
* Parse a range from a cron expression.
* @param {CronUnit} field - The field to parse.
* @param {string} val - The range to parse.
* @param {number} repeatInterval - The repeat interval of the range.
* @param {CronConstraints} constraints - The constraints for the field.
* @private
* @returns {number[] | string[] | number | string} The parsed range.
*/
static #parseRange(field, val, repeatInterval, constraints) {
const atoms = val.split('-');
if (atoms.length <= 1) {
return isNaN(+val) ? val : +val;
}
const [min, max] = atoms.map((num) => parseInt(num, 10));
this.#validateRange(min, max, constraints);
this.#validateRepeatInterval(repeatInterval);
// Create range
return this.#createRange(field, min, max, repeatInterval);
}
/**
* Parse a cron expression.
* @param {string} val - The cron expression to parse.
* @private
* @returns {string} The parsed cron expression.
*/
static #parseNthDay(val) {
const atoms = val.split('#');
if (atoms.length <= 1) {
return { dayOfWeek: atoms[0] };
}
const nthValue = +atoms[atoms.length - 1];
const matches = val.match(/([,-/])/);
if (matches !== null) {
throw new Error(`Constraint error, invalid dayOfWeek \`#\` and \`${matches?.[0]}\` special characters are incompatible`);
}
if (!(atoms.length <= 2 && !isNaN(nthValue) && nthValue >= 1 && nthValue <= 5)) {
throw new Error('Constraint error, invalid dayOfWeek occurrence number (#)');
}
return { dayOfWeek: atoms[0], nthDayOfWeek: nthValue };
}
/**
* Checks if a character is valid for a field.
* @param {CronConstraints} constraints - The constraints for the field.
* @param {string | number} value - The value to check.
* @private
* @returns {boolean} Whether the character is valid for the field.
*/
static #isValidConstraintChar(constraints, value) {
return constraints.chars.some((char) => value.toString().includes(char));
}
}
exports.CronExpressionParser = CronExpressionParser;

371
node_modules/cron-parser/dist/CronFieldCollection.js generated vendored Normal file
View File

@@ -0,0 +1,371 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CronFieldCollection = void 0;
const fields_1 = require("./fields");
/**
* Represents a complete set of cron fields.
* @class CronFieldCollection
*/
class CronFieldCollection {
#second;
#minute;
#hour;
#dayOfMonth;
#month;
#dayOfWeek;
/**
* Creates a new CronFieldCollection instance by partially overriding fields from an existing one.
* @param {CronFieldCollection} base - The base CronFieldCollection to copy fields from
* @param {CronFieldOverride} fields - The fields to override, can be CronField instances or raw values
* @returns {CronFieldCollection} A new CronFieldCollection instance
* @example
* const base = new CronFieldCollection({
* second: new CronSecond([0]),
* minute: new CronMinute([0]),
* hour: new CronHour([12]),
* dayOfMonth: new CronDayOfMonth([1]),
* month: new CronMonth([1]),
* dayOfWeek: new CronDayOfWeek([1])
* });
*
* // Using CronField instances
* const modified1 = CronFieldCollection.from(base, {
* hour: new CronHour([15]),
* minute: new CronMinute([30])
* });
*
* // Using raw values
* const modified2 = CronFieldCollection.from(base, {
* hour: [15], // Will create new CronHour
* minute: [30] // Will create new CronMinute
* });
*/
static from(base, fields) {
return new CronFieldCollection({
second: this.resolveField(fields_1.CronSecond, base.second, fields.second),
minute: this.resolveField(fields_1.CronMinute, base.minute, fields.minute),
hour: this.resolveField(fields_1.CronHour, base.hour, fields.hour),
dayOfMonth: this.resolveField(fields_1.CronDayOfMonth, base.dayOfMonth, fields.dayOfMonth),
month: this.resolveField(fields_1.CronMonth, base.month, fields.month),
dayOfWeek: this.resolveField(fields_1.CronDayOfWeek, base.dayOfWeek, fields.dayOfWeek),
});
}
/**
* Resolves a field value, either using the provided CronField instance or creating a new one from raw values.
* @param constructor - The constructor for creating new field instances
* @param baseField - The base field to use if no override is provided
* @param fieldValue - The override value, either a CronField instance or raw values
* @returns The resolved CronField instance
* @private
*/
static resolveField(constructor, baseField, fieldValue) {
if (!fieldValue) {
return baseField;
}
if (fieldValue instanceof fields_1.CronField) {
return fieldValue;
}
return new constructor(fieldValue);
}
/**
* CronFieldCollection constructor. Initializes the cron fields with the provided values.
* @param {CronFields} param0 - The cron fields values
* @throws {Error} if validation fails
* @example
* const cronFields = new CronFieldCollection({
* second: new CronSecond([0]),
* minute: new CronMinute([0, 30]),
* hour: new CronHour([9]),
* dayOfMonth: new CronDayOfMonth([15]),
* month: new CronMonth([1]),
* dayOfWeek: new CronDayOfTheWeek([1, 2, 3, 4, 5]),
* })
*
* console.log(cronFields.second.values); // [0]
* console.log(cronFields.minute.values); // [0, 30]
* console.log(cronFields.hour.values); // [9]
* console.log(cronFields.dayOfMonth.values); // [15]
* console.log(cronFields.month.values); // [1]
* console.log(cronFields.dayOfWeek.values); // [1, 2, 3, 4, 5]
*/
constructor({ second, minute, hour, dayOfMonth, month, dayOfWeek }) {
if (!second) {
throw new Error('Validation error, Field second is missing');
}
if (!minute) {
throw new Error('Validation error, Field minute is missing');
}
if (!hour) {
throw new Error('Validation error, Field hour is missing');
}
if (!dayOfMonth) {
throw new Error('Validation error, Field dayOfMonth is missing');
}
if (!month) {
throw new Error('Validation error, Field month is missing');
}
if (!dayOfWeek) {
throw new Error('Validation error, Field dayOfWeek is missing');
}
if (month.values.length === 1 && !dayOfMonth.hasLastChar) {
if (!(parseInt(dayOfMonth.values[0], 10) <= fields_1.CronMonth.daysInMonth[month.values[0] - 1])) {
throw new Error('Invalid explicit day of month definition');
}
}
this.#second = second;
this.#minute = minute;
this.#hour = hour;
this.#month = month;
this.#dayOfWeek = dayOfWeek;
this.#dayOfMonth = dayOfMonth;
}
/**
* Returns the second field.
* @returns {CronSecond}
*/
get second() {
return this.#second;
}
/**
* Returns the minute field.
* @returns {CronMinute}
*/
get minute() {
return this.#minute;
}
/**
* Returns the hour field.
* @returns {CronHour}
*/
get hour() {
return this.#hour;
}
/**
* Returns the day of the month field.
* @returns {CronDayOfMonth}
*/
get dayOfMonth() {
return this.#dayOfMonth;
}
/**
* Returns the month field.
* @returns {CronMonth}
*/
get month() {
return this.#month;
}
/**
* Returns the day of the week field.
* @returns {CronDayOfWeek}
*/
get dayOfWeek() {
return this.#dayOfWeek;
}
/**
* Returns a string representation of the cron fields.
* @param {(number | CronChars)[]} input - The cron fields values
* @static
* @returns {FieldRange[]} - The compacted cron fields
*/
static compactField(input) {
if (input.length === 0) {
return [];
}
// Initialize the output array and current IFieldRange
const output = [];
let current = undefined;
input.forEach((item, i, arr) => {
// If the current FieldRange is undefined, create a new one with the current item as the start.
if (current === undefined) {
current = { start: item, count: 1 };
return;
}
// Cache the previous and next items in the array.
const prevItem = arr[i - 1] || current.start;
const nextItem = arr[i + 1];
// If the current item is 'L' or 'W', push the current FieldRange to the output and
// create a new FieldRange with the current item as the start.
// 'L' and 'W' characters are special cases that need to be handled separately.
if (item === 'L' || item === 'W') {
output.push(current);
output.push({ start: item, count: 1 });
current = undefined;
return;
}
// If the current step is undefined and there is a next item, update the current IFieldRange.
// This block checks if the current step needs to be updated and does so if needed.
if (current.step === undefined && nextItem !== undefined) {
const step = item - prevItem;
const nextStep = nextItem - item;
// If the current step is less or equal to the next step, update the current FieldRange to include the current item.
if (step <= nextStep) {
current = { ...current, count: 2, end: item, step };
return;
}
current.step = 1;
}
// If the difference between the current item and the current end is equal to the current step,
// update the current IFieldRange's count and end.
// This block checks if the current item is part of the current range and updates the range accordingly.
if (item - (current.end ?? 0) === current.step) {
current.count++;
current.end = item;
}
else {
// If the count is 1, push a new FieldRange with the current start.
// This handles the case where the current range has only one element.
if (current.count === 1) {
// If the count is 2, push two separate IFieldRanges, one for each element.
output.push({ start: current.start, count: 1 });
}
else if (current.count === 2) {
output.push({ start: current.start, count: 1 });
// current.end can never be undefined here but typescript doesn't know that
// this is why we ?? it and then ignore the prevItem in the coverage
output.push({
start: current.end ?? /* istanbul ignore next - see above */ prevItem,
count: 1,
});
}
else {
// Otherwise, push the current FieldRange to the output.
output.push(current);
}
// Reset the current FieldRange with the current item as the start.
current = { start: item, count: 1 };
}
});
// Push the final IFieldRange, if any, to the output array.
if (current) {
output.push(current);
}
return output;
}
/**
* Handles a single range.
* @param {CronField} field - The cron field to stringify
* @param {FieldRange} range {start: number, end: number, step: number, count: number} The range to handle.
* @param {number} max The maximum value for the field.
* @returns {string | null} The stringified range or null if it cannot be stringified.
* @private
*/
static #handleSingleRange(field, range, max) {
const step = range.step;
if (!step) {
return null;
}
if (step === 1 && range.start === field.min && range.end && range.end >= max) {
return field.hasQuestionMarkChar ? '?' : '*';
}
if (step !== 1 && range.start === field.min && range.end && range.end >= max - step + 1) {
return `*/${step}`;
}
return null;
}
/**
* Handles multiple ranges.
* @param {FieldRange} range {start: number, end: number, step: number, count: number} The range to handle.
* @param {number} max The maximum value for the field.
* @returns {string} The stringified range.
* @private
*/
static #handleMultipleRanges(range, max) {
const step = range.step;
if (step === 1) {
return `${range.start}-${range.end}`;
}
const multiplier = range.start === 0 ? range.count - 1 : range.count;
/* istanbul ignore if */
if (!step) {
throw new Error('Unexpected range step');
}
/* istanbul ignore if */
if (!range.end) {
throw new Error('Unexpected range end');
}
if (step * multiplier > range.end) {
const mapFn = (_, index) => {
/* istanbul ignore if */
if (typeof range.start !== 'number') {
throw new Error('Unexpected range start');
}
return index % step === 0 ? range.start + index : null;
};
/* istanbul ignore if */
if (typeof range.start !== 'number') {
throw new Error('Unexpected range start');
}
const seed = { length: range.end - range.start + 1 };
return Array.from(seed, mapFn)
.filter((value) => value !== null)
.join(',');
}
return range.end === max - step + 1 ? `${range.start}/${step}` : `${range.start}-${range.end}/${step}`;
}
/**
* Returns a string representation of the cron fields.
* @param {CronField} field - The cron field to stringify
* @static
* @returns {string} - The stringified cron field
*/
stringifyField(field) {
let max = field.max;
let values = field.values;
if (field instanceof fields_1.CronDayOfWeek) {
max = 6;
const dayOfWeek = this.#dayOfWeek.values;
values = dayOfWeek[dayOfWeek.length - 1] === 7 ? dayOfWeek.slice(0, -1) : dayOfWeek;
}
if (field instanceof fields_1.CronDayOfMonth) {
max = this.#month.values.length === 1 ? fields_1.CronMonth.daysInMonth[this.#month.values[0] - 1] : field.max;
}
const ranges = CronFieldCollection.compactField(values);
if (ranges.length === 1) {
const singleRangeResult = CronFieldCollection.#handleSingleRange(field, ranges[0], max);
if (singleRangeResult) {
return singleRangeResult;
}
}
return ranges
.map((range) => {
const value = range.count === 1 ? range.start.toString() : CronFieldCollection.#handleMultipleRanges(range, max);
if (field instanceof fields_1.CronDayOfWeek && field.nthDay > 0) {
return `${value}#${field.nthDay}`;
}
return value;
})
.join(',');
}
/**
* Returns a string representation of the cron field values.
* @param {boolean} includeSeconds - Whether to include seconds in the output
* @returns {string} The formatted cron string
*/
stringify(includeSeconds = false) {
const arr = [];
if (includeSeconds) {
arr.push(this.stringifyField(this.#second)); // second
}
arr.push(this.stringifyField(this.#minute), // minute
this.stringifyField(this.#hour), // hour
this.stringifyField(this.#dayOfMonth), // dayOfMonth
this.stringifyField(this.#month), // month
this.stringifyField(this.#dayOfWeek));
return arr.join(' ');
}
/**
* Returns a serialized representation of the cron fields values.
* @returns {SerializedCronFields} An object containing the cron field values
*/
serialize() {
return {
second: this.#second.serialize(),
minute: this.#minute.serialize(),
hour: this.#hour.serialize(),
dayOfMonth: this.#dayOfMonth.serialize(),
month: this.#month.serialize(),
dayOfWeek: this.#dayOfWeek.serialize(),
};
}
}
exports.CronFieldCollection = CronFieldCollection;

109
node_modules/cron-parser/dist/CronFileParser.js generated vendored Normal file
View File

@@ -0,0 +1,109 @@
"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;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.CronFileParser = void 0;
const CronExpressionParser_1 = require("./CronExpressionParser");
/**
* Parser for crontab files that handles both synchronous and asynchronous operations.
*/
class CronFileParser {
/**
* Parse a crontab file asynchronously
* @param filePath Path to crontab file
* @returns Promise resolving to parse results
* @throws If file cannot be read
*/
static async parseFile(filePath) {
const { readFile } = await Promise.resolve().then(() => __importStar(require('fs/promises')));
const data = await readFile(filePath, 'utf8');
return CronFileParser.#parseContent(data);
}
/**
* Parse a crontab file synchronously
* @param filePath Path to crontab file
* @returns Parse results
* @throws If file cannot be read
*/
static parseFileSync(filePath) {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { readFileSync } = require('fs');
const data = readFileSync(filePath, 'utf8');
return CronFileParser.#parseContent(data);
}
/**
* Internal method to parse crontab file content
* @private
*/
static #parseContent(data) {
const blocks = data.split('\n');
const result = {
variables: {},
expressions: [],
errors: {},
};
for (const block of blocks) {
const entry = block.trim();
if (entry.length === 0 || entry.startsWith('#')) {
continue;
}
const variableMatch = entry.match(/^(.*)=(.*)$/);
if (variableMatch) {
const [, key, value] = variableMatch;
result.variables[key] = value.replace(/["']/g, ''); // Remove quotes
continue;
}
try {
const parsedEntry = CronFileParser.#parseEntry(entry);
result.expressions.push(parsedEntry.interval);
}
catch (err) {
result.errors[entry] = err;
}
}
return result;
}
/**
* Parse a single crontab entry
* @private
*/
static #parseEntry(entry) {
const atoms = entry.split(' ');
return {
interval: CronExpressionParser_1.CronExpressionParser.parse(atoms.slice(0, 5).join(' ')),
command: atoms.slice(5, atoms.length),
};
}
}
exports.CronFileParser = CronFileParser;

44
node_modules/cron-parser/dist/fields/CronDayOfMonth.js generated vendored Normal file
View File

@@ -0,0 +1,44 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CronDayOfMonth = void 0;
const CronField_1 = require("./CronField");
const MIN_DAY = 1;
const MAX_DAY = 31;
const DAY_CHARS = Object.freeze(['L']);
/**
* Represents the "day of the month" field within a cron expression.
* @class CronDayOfMonth
* @extends CronField
*/
class CronDayOfMonth extends CronField_1.CronField {
static get min() {
return MIN_DAY;
}
static get max() {
return MAX_DAY;
}
static get chars() {
return DAY_CHARS;
}
static get validChars() {
return /^[?,*\dLH/-]+$|^.*H\(\d+-\d+\)\/\d+.*$|^.*H\(\d+-\d+\).*$|^.*H\/\d+.*$/;
}
/**
* CronDayOfMonth constructor. Initializes the "day of the month" field with the provided values.
* @param {DayOfMonthRange[]} values - Values for the "day of the month" field
* @param {CronFieldOptions} [options] - Options provided by the parser
* @throws {Error} if validation fails
*/
constructor(values, options) {
super(values, options);
this.validate();
}
/**
* Returns an array of allowed values for the "day of the month" field.
* @returns {DayOfMonthRange[]}
*/
get values() {
return super.values;
}
}
exports.CronDayOfMonth = CronDayOfMonth;

51
node_modules/cron-parser/dist/fields/CronDayOfWeek.js generated vendored Normal file
View File

@@ -0,0 +1,51 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CronDayOfWeek = void 0;
const CronField_1 = require("./CronField");
const MIN_DAY = 0;
const MAX_DAY = 7;
const DAY_CHARS = Object.freeze(['L']);
/**
* Represents the "day of the week" field within a cron expression.
* @class CronDayOfTheWeek
* @extends CronField
*/
class CronDayOfWeek extends CronField_1.CronField {
static get min() {
return MIN_DAY;
}
static get max() {
return MAX_DAY;
}
static get chars() {
return DAY_CHARS;
}
static get validChars() {
return /^[?,*\dLH#/-]+$|^.*H\(\d+-\d+\)\/\d+.*$|^.*H\(\d+-\d+\).*$|^.*H\/\d+.*$/;
}
/**
* CronDayOfTheWeek constructor. Initializes the "day of the week" field with the provided values.
* @param {DayOfWeekRange[]} values - Values for the "day of the week" field
* @param {CronFieldOptions} [options] - Options provided by the parser
*/
constructor(values, options) {
super(values, options);
this.validate();
}
/**
* Returns an array of allowed values for the "day of the week" field.
* @returns {DayOfWeekRange[]}
*/
get values() {
return super.values;
}
/**
* Returns the nth day of the week if specified in the cron expression.
* This is used for the '#' character in the cron expression.
* @returns {number} The nth day of the week (1-5) or 0 if not specified.
*/
get nthDay() {
return this.options.nthDayOfWeek ?? 0;
}
}
exports.CronDayOfWeek = CronDayOfWeek;

183
node_modules/cron-parser/dist/fields/CronField.js generated vendored Normal file
View File

@@ -0,0 +1,183 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CronField = void 0;
/**
* Represents a field within a cron expression.
* This is a base class and should not be instantiated directly.
* @class CronField
*/
class CronField {
#hasLastChar = false;
#hasQuestionMarkChar = false;
#wildcard = false;
#values = [];
options = { rawValue: '' };
/**
* Returns the minimum value allowed for this field.
*/
/* istanbul ignore next */ static get min() {
/* istanbul ignore next */
throw new Error('min must be overridden');
}
/**
* Returns the maximum value allowed for this field.
*/
/* istanbul ignore next */ static get max() {
/* istanbul ignore next */
throw new Error('max must be overridden');
}
/**
* Returns the allowed characters for this field.
*/
/* istanbul ignore next */ static get chars() {
/* istanbul ignore next - this is overridden */
return Object.freeze([]);
}
/**
* Returns the regular expression used to validate this field.
*/
static get validChars() {
return /^[?,*\dH/-]+$|^.*H\(\d+-\d+\)\/\d+.*$|^.*H\(\d+-\d+\).*$|^.*H\/\d+.*$/;
}
/**
* Returns the constraints for this field.
*/
static get constraints() {
return { min: this.min, max: this.max, chars: this.chars, validChars: this.validChars };
}
/**
* CronField constructor. Initializes the field with the provided values.
* @param {number[] | string[]} values - Values for this field
* @param {CronFieldOptions} [options] - Options provided by the parser
* @throws {TypeError} if the constructor is called directly
* @throws {Error} if validation fails
*/
constructor(values, options = { rawValue: '' }) {
if (!Array.isArray(values)) {
throw new Error(`${this.constructor.name} Validation error, values is not an array`);
}
if (!(values.length > 0)) {
throw new Error(`${this.constructor.name} Validation error, values contains no values`);
}
/* istanbul ignore next */
this.options = {
...options,
rawValue: options.rawValue ?? '',
};
this.#values = values.sort(CronField.sorter);
this.#wildcard = this.options.wildcard !== undefined ? this.options.wildcard : this.#isWildcardValue();
this.#hasLastChar = this.options.rawValue.includes('L') || values.includes('L');
this.#hasQuestionMarkChar = this.options.rawValue.includes('?') || values.includes('?');
}
/**
* Returns the minimum value allowed for this field.
* @returns {number}
*/
get min() {
// return the static value from the child class
return this.constructor.min;
}
/**
* Returns the maximum value allowed for this field.
* @returns {number}
*/
get max() {
// return the static value from the child class
return this.constructor.max;
}
/**
* Returns an array of allowed special characters for this field.
* @returns {string[]}
*/
get chars() {
// return the frozen static value from the child class
return this.constructor.chars;
}
/**
* Indicates whether this field has a "last" character.
* @returns {boolean}
*/
get hasLastChar() {
return this.#hasLastChar;
}
/**
* Indicates whether this field has a "question mark" character.
* @returns {boolean}
*/
get hasQuestionMarkChar() {
return this.#hasQuestionMarkChar;
}
/**
* Indicates whether this field is a wildcard.
* @returns {boolean}
*/
get isWildcard() {
return this.#wildcard;
}
/**
* Returns an array of allowed values for this field.
* @returns {CronFieldType}
*/
get values() {
return this.#values;
}
/**
* Helper function to sort values in ascending order.
* @param {number | string} a - First value to compare
* @param {number | string} b - Second value to compare
* @returns {number} - A negative, zero, or positive value, depending on the sort order
*/
static sorter(a, b) {
const aIsNumber = typeof a === 'number';
const bIsNumber = typeof b === 'number';
if (aIsNumber && bIsNumber)
return a - b;
if (!aIsNumber && !bIsNumber)
return a.localeCompare(b);
return aIsNumber ? /* istanbul ignore next - A will always be a number until L-2 is supported */ -1 : 1;
}
/**
* Serializes the field to an object.
* @returns {SerializedCronField}
*/
serialize() {
return {
wildcard: this.#wildcard,
values: this.#values,
};
}
/**
* Validates the field values against the allowed range and special characters.
* @throws {Error} if validation fails
*/
validate() {
let badValue;
const charsString = this.chars.length > 0 ? ` or chars ${this.chars.join('')}` : '';
const charTest = (value) => (char) => new RegExp(`^\\d{0,2}${char}$`).test(value);
const rangeTest = (value) => {
badValue = value;
return typeof value === 'number' ? value >= this.min && value <= this.max : this.chars.some(charTest(value));
};
const isValidRange = this.#values.every(rangeTest);
if (!isValidRange) {
throw new Error(`${this.constructor.name} Validation error, got value ${badValue} expected range ${this.min}-${this.max}${charsString}`);
}
// check for duplicate value in this.#values array
const duplicate = this.#values.find((value, index) => this.#values.indexOf(value) !== index);
if (duplicate) {
throw new Error(`${this.constructor.name} Validation error, duplicate values found: ${duplicate}`);
}
}
/**
* Determines if the field is a wildcard based on the values.
* When options.rawValue is not empty, it checks if the raw value is a wildcard, otherwise it checks if all values in the range are included.
* @returns {boolean}
*/
#isWildcardValue() {
if (this.options.rawValue.length > 0) {
return ['*', '?'].includes(this.options.rawValue);
}
return Array.from({ length: this.max - this.min + 1 }, (_, i) => i + this.min).every((value) => this.#values.includes(value));
}
}
exports.CronField = CronField;

40
node_modules/cron-parser/dist/fields/CronHour.js generated vendored Normal file
View File

@@ -0,0 +1,40 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CronHour = void 0;
const CronField_1 = require("./CronField");
const MIN_HOUR = 0;
const MAX_HOUR = 23;
const HOUR_CHARS = Object.freeze([]);
/**
* Represents the "hour" field within a cron expression.
* @class CronHour
* @extends CronField
*/
class CronHour extends CronField_1.CronField {
static get min() {
return MIN_HOUR;
}
static get max() {
return MAX_HOUR;
}
static get chars() {
return HOUR_CHARS;
}
/**
* CronHour constructor. Initializes the "hour" field with the provided values.
* @param {HourRange[]} values - Values for the "hour" field
* @param {CronFieldOptions} [options] - Options provided by the parser
*/
constructor(values, options) {
super(values, options);
this.validate();
}
/**
* Returns an array of allowed values for the "hour" field.
* @returns {HourRange[]}
*/
get values() {
return super.values;
}
}
exports.CronHour = CronHour;

40
node_modules/cron-parser/dist/fields/CronMinute.js generated vendored Normal file
View File

@@ -0,0 +1,40 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CronMinute = void 0;
const CronField_1 = require("./CronField");
const MIN_MINUTE = 0;
const MAX_MINUTE = 59;
const MINUTE_CHARS = Object.freeze([]);
/**
* Represents the "second" field within a cron expression.
* @class CronSecond
* @extends CronField
*/
class CronMinute extends CronField_1.CronField {
static get min() {
return MIN_MINUTE;
}
static get max() {
return MAX_MINUTE;
}
static get chars() {
return MINUTE_CHARS;
}
/**
* CronSecond constructor. Initializes the "second" field with the provided values.
* @param {SixtyRange[]} values - Values for the "second" field
* @param {CronFieldOptions} [options] - Options provided by the parser
*/
constructor(values, options) {
super(values, options);
this.validate();
}
/**
* Returns an array of allowed values for the "second" field.
* @returns {SixtyRange[]}
*/
get values() {
return super.values;
}
}
exports.CronMinute = CronMinute;

44
node_modules/cron-parser/dist/fields/CronMonth.js generated vendored Normal file
View File

@@ -0,0 +1,44 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CronMonth = void 0;
const CronDate_1 = require("../CronDate");
const CronField_1 = require("./CronField");
const MIN_MONTH = 1;
const MAX_MONTH = 12;
const MONTH_CHARS = Object.freeze([]);
/**
* Represents the "day of the month" field within a cron expression.
* @class CronDayOfMonth
* @extends CronField
*/
class CronMonth extends CronField_1.CronField {
static get min() {
return MIN_MONTH;
}
static get max() {
return MAX_MONTH;
}
static get chars() {
return MONTH_CHARS;
}
static get daysInMonth() {
return CronDate_1.DAYS_IN_MONTH;
}
/**
* CronDayOfMonth constructor. Initializes the "day of the month" field with the provided values.
* @param {MonthRange[]} values - Values for the "day of the month" field
* @param {CronFieldOptions} [options] - Options provided by the parser
*/
constructor(values, options) {
super(values, options);
this.validate();
}
/**
* Returns an array of allowed values for the "day of the month" field.
* @returns {MonthRange[]}
*/
get values() {
return super.values;
}
}
exports.CronMonth = CronMonth;

40
node_modules/cron-parser/dist/fields/CronSecond.js generated vendored Normal file
View File

@@ -0,0 +1,40 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CronSecond = void 0;
const CronField_1 = require("./CronField");
const MIN_SECOND = 0;
const MAX_SECOND = 59;
const SECOND_CHARS = Object.freeze([]);
/**
* Represents the "second" field within a cron expression.
* @class CronSecond
* @extends CronField
*/
class CronSecond extends CronField_1.CronField {
static get min() {
return MIN_SECOND;
}
static get max() {
return MAX_SECOND;
}
static get chars() {
return SECOND_CHARS;
}
/**
* CronSecond constructor. Initializes the "second" field with the provided values.
* @param {SixtyRange[]} values - Values for the "second" field
* @param {CronFieldOptions} [options] - Options provided by the parser
*/
constructor(values, options) {
super(values, options);
this.validate();
}
/**
* Returns an array of allowed values for the "second" field.
* @returns {SixtyRange[]}
*/
get values() {
return super.values;
}
}
exports.CronSecond = CronSecond;

24
node_modules/cron-parser/dist/fields/index.js generated vendored Normal file
View File

@@ -0,0 +1,24 @@
"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 __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./types"), exports);
__exportStar(require("./CronDayOfMonth"), exports);
__exportStar(require("./CronDayOfWeek"), exports);
__exportStar(require("./CronField"), exports);
__exportStar(require("./CronHour"), exports);
__exportStar(require("./CronMinute"), exports);
__exportStar(require("./CronMonth"), exports);
__exportStar(require("./CronSecond"), exports);

2
node_modules/cron-parser/dist/fields/types.js generated vendored Normal file
View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

31
node_modules/cron-parser/dist/index.js generated vendored Normal file
View File

@@ -0,0 +1,31 @@
"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 __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CronFileParser = exports.CronExpressionParser = exports.CronExpression = exports.CronFieldCollection = exports.CronDate = void 0;
/* istanbul ignore file */
const CronExpressionParser_1 = require("./CronExpressionParser");
var CronDate_1 = require("./CronDate");
Object.defineProperty(exports, "CronDate", { enumerable: true, get: function () { return CronDate_1.CronDate; } });
var CronFieldCollection_1 = require("./CronFieldCollection");
Object.defineProperty(exports, "CronFieldCollection", { enumerable: true, get: function () { return CronFieldCollection_1.CronFieldCollection; } });
var CronExpression_1 = require("./CronExpression");
Object.defineProperty(exports, "CronExpression", { enumerable: true, get: function () { return CronExpression_1.CronExpression; } });
var CronExpressionParser_2 = require("./CronExpressionParser");
Object.defineProperty(exports, "CronExpressionParser", { enumerable: true, get: function () { return CronExpressionParser_2.CronExpressionParser; } });
var CronFileParser_1 = require("./CronFileParser");
Object.defineProperty(exports, "CronFileParser", { enumerable: true, get: function () { return CronFileParser_1.CronFileParser; } });
__exportStar(require("./fields"), exports);
exports.default = CronExpressionParser_1.CronExpressionParser;

273
node_modules/cron-parser/dist/types/CronDate.d.ts generated vendored Normal file
View File

@@ -0,0 +1,273 @@
export declare enum TimeUnit {
Second = "Second",
Minute = "Minute",
Hour = "Hour",
Day = "Day",
Month = "Month",
Year = "Year"
}
export declare enum DateMathOp {
Add = "Add",
Subtract = "Subtract"
}
export declare const DAYS_IN_MONTH: readonly number[];
/**
* CronDate class that wraps the Luxon DateTime object to provide
* a consistent API for working with dates and times in the context of cron.
*/
export declare class CronDate {
#private;
/**
* Constructs a new CronDate instance.
* @param {CronDate | Date | number | string} [timestamp] - The timestamp to initialize the CronDate with.
* @param {string} [tz] - The timezone to use for the CronDate.
*/
constructor(timestamp?: CronDate | Date | number | string, tz?: string);
/**
* Returns daylight savings start time.
* @returns {number | null}
*/
get dstStart(): number | null;
/**
* Sets daylight savings start time.
* @param {number | null} value
*/
set dstStart(value: number | null);
/**
* Returns daylight savings end time.
* @returns {number | null}
*/
get dstEnd(): number | null;
/**
* Sets daylight savings end time.
* @param {number | null} value
*/
set dstEnd(value: number | null);
/**
* Adds one year to the current CronDate.
*/
addYear(): void;
/**
* Adds one month to the current CronDate.
*/
addMonth(): void;
/**
* Adds one day to the current CronDate.
*/
addDay(): void;
/**
* Adds one hour to the current CronDate.
*/
addHour(): void;
/**
* Adds one minute to the current CronDate.
*/
addMinute(): void;
/**
* Adds one second to the current CronDate.
*/
addSecond(): void;
/**
* Subtracts one year from the current CronDate.
*/
subtractYear(): void;
/**
* Subtracts one month from the current CronDate.
* If the month is 1, it will subtract one year instead.
*/
subtractMonth(): void;
/**
* Subtracts one day from the current CronDate.
* If the day is 1, it will subtract one month instead.
*/
subtractDay(): void;
/**
* Subtracts one hour from the current CronDate.
* If the hour is 0, it will subtract one day instead.
*/
subtractHour(): void;
/**
* Subtracts one minute from the current CronDate.
* If the minute is 0, it will subtract one hour instead.
*/
subtractMinute(): void;
/**
* Subtracts one second from the current CronDate.
* If the second is 0, it will subtract one minute instead.
*/
subtractSecond(): void;
/**
* Adds a unit of time to the current CronDate.
* @param {TimeUnit} unit
*/
addUnit(unit: TimeUnit): void;
/**
* Subtracts a unit of time from the current CronDate.
* @param {TimeUnit} unit
*/
subtractUnit(unit: TimeUnit): void;
/**
* Handles a math operation.
* @param {DateMathOp} verb - {'add' | 'subtract'}
* @param {TimeUnit} unit - {'year' | 'month' | 'day' | 'hour' | 'minute' | 'second'}
*/
invokeDateOperation(verb: DateMathOp, unit: TimeUnit): void;
/**
* Returns the day.
* @returns {number}
*/
getDate(): number;
/**
* Returns the year.
* @returns {number}
*/
getFullYear(): number;
/**
* Returns the day of the week.
* @returns {number}
*/
getDay(): number;
/**
* Returns the month.
* @returns {number}
*/
getMonth(): number;
/**
* Returns the hour.
* @returns {number}
*/
getHours(): number;
/**
* Returns the minutes.
* @returns {number}
*/
getMinutes(): number;
/**
* Returns the seconds.
* @returns {number}
*/
getSeconds(): number;
/**
* Returns the milliseconds.
* @returns {number}
*/
getMilliseconds(): number;
/**
* Returns the time.
* @returns {number}
*/
getTime(): number;
/**
* Returns the UTC day.
* @returns {number}
*/
getUTCDate(): number;
/**
* Returns the UTC year.
* @returns {number}
*/
getUTCFullYear(): number;
/**
* Returns the UTC day of the week.
* @returns {number}
*/
getUTCDay(): number;
/**
* Returns the UTC month.
* @returns {number}
*/
getUTCMonth(): number;
/**
* Returns the UTC hour.
* @returns {number}
*/
getUTCHours(): number;
/**
* Returns the UTC minutes.
* @returns {number}
*/
getUTCMinutes(): number;
/**
* Returns the UTC seconds.
* @returns {number}
*/
getUTCSeconds(): number;
/**
* Returns the UTC milliseconds.
* @returns {string | null}
*/
toISOString(): string | null;
/**
* Returns the date as a JSON string.
* @returns {string | null}
*/
toJSON(): string | null;
/**
* Sets the day.
* @param d
*/
setDate(d: number): void;
/**
* Sets the year.
* @param y
*/
setFullYear(y: number): void;
/**
* Sets the day of the week.
* @param d
*/
setDay(d: number): void;
/**
* Sets the month.
* @param m
*/
setMonth(m: number): void;
/**
* Sets the hour.
* @param h
*/
setHours(h: number): void;
/**
* Sets the minutes.
* @param m
*/
setMinutes(m: number): void;
/**
* Sets the seconds.
* @param s
*/
setSeconds(s: number): void;
/**
* Sets the milliseconds.
* @param s
*/
setMilliseconds(s: number): void;
/**
* Returns the date as a string.
* @returns {string}
*/
toString(): string;
/**
* Returns the date as a Date object.
* @returns {Date}
*/
toDate(): Date;
/**
* Returns true if the day is the last day of the month.
* @returns {boolean}
*/
isLastDayOfMonth(): boolean;
/**
* Returns true if the day is the last weekday of the month.
* @returns {boolean}
*/
isLastWeekdayOfMonth(): boolean;
/**
* Primarily for internal use.
* @param {DateMathOp} op - The operation to perform.
* @param {TimeUnit} unit - The unit of time to use.
* @param {number} [hoursLength] - The length of the hours. Required when unit is not month or day.
*/
applyDateOperation(op: DateMathOp, unit: TimeUnit, hoursLength?: number): void;
}
export default CronDate;

118
node_modules/cron-parser/dist/types/CronExpression.d.ts generated vendored Normal file
View File

@@ -0,0 +1,118 @@
import { CronDate } from './CronDate';
import { CronFieldCollection } from './CronFieldCollection';
export type CronExpressionOptions = {
currentDate?: Date | string | number | CronDate;
endDate?: Date | string | number | CronDate;
startDate?: Date | string | number | CronDate;
tz?: string;
expression?: string;
hashSeed?: string;
strict?: boolean;
};
/**
* Error message for when the current date is outside the specified time span.
*/
export declare const TIME_SPAN_OUT_OF_BOUNDS_ERROR_MESSAGE = "Out of the time span range";
/**
* Error message for when the loop limit is exceeded during iteration.
*/
export declare const LOOPS_LIMIT_EXCEEDED_ERROR_MESSAGE = "Invalid expression, loop limit exceeded";
/**
* Class representing a Cron expression.
*/
export declare class CronExpression {
#private;
/**
* Creates a new CronExpression instance.
*
* @param {CronFieldCollection} fields - Cron fields.
* @param {CronExpressionOptions} options - Parser options.
*/
constructor(fields: CronFieldCollection, options: CronExpressionOptions);
/**
* Getter for the cron fields.
*
* @returns {CronFieldCollection} Cron fields.
*/
get fields(): CronFieldCollection;
/**
* Converts cron fields back to a CronExpression instance.
*
* @public
* @param {Record<string, number[]>} fields - The input cron fields object.
* @param {CronExpressionOptions} [options] - Optional parsing options.
* @returns {CronExpression} - A new CronExpression instance.
*/
static fieldsToExpression(fields: CronFieldCollection, options?: CronExpressionOptions): CronExpression;
/**
* Find the next scheduled date based on the cron expression.
* @returns {CronDate} - The next scheduled date or an ES6 compatible iterator object.
* @memberof CronExpression
* @public
*/
next(): CronDate;
/**
* Find the previous scheduled date based on the cron expression.
* @returns {CronDate} - The previous scheduled date or an ES6 compatible iterator object.
* @memberof CronExpression
* @public
*/
prev(): CronDate;
/**
* Check if there is a next scheduled date based on the current date and cron expression.
* @returns {boolean} - Returns true if there is a next scheduled date, false otherwise.
* @memberof CronExpression
* @public
*/
hasNext(): boolean;
/**
* Check if there is a previous scheduled date based on the current date and cron expression.
* @returns {boolean} - Returns true if there is a previous scheduled date, false otherwise.
* @memberof CronExpression
* @public
*/
hasPrev(): boolean;
/**
* Iterate over a specified number of steps and optionally execute a callback function for each step.
* @param {number} steps - The number of steps to iterate. Positive value iterates forward, negative value iterates backward.
* @returns {CronDate[]} - An array of iterator fields or CronDate objects.
* @memberof CronExpression
* @public
*/
take(limit: number): CronDate[];
/**
* Reset the iterators current date to a new date or the initial date.
* @param {Date | CronDate} [newDate] - Optional new date to reset to. If not provided, it will reset to the initial date.
* @memberof CronExpression
* @public
*/
reset(newDate?: Date | CronDate): void;
/**
* Generate a string representation of the cron expression.
* @param {boolean} [includeSeconds=false] - Whether to include the seconds field in the string representation.
* @returns {string} - The string representation of the cron expression.
* @memberof CronExpression
* @public
*/
stringify(includeSeconds?: boolean): string;
/**
* Check if the cron expression includes the given date
* @param {Date|CronDate} date
* @returns {boolean}
*/
includesDate(date: Date | CronDate): boolean;
/**
* Returns the string representation of the cron expression.
* @returns {CronDate} - The next schedule date.
*/
toString(): string;
/**
* Returns an iterator for iterating through future CronDate instances
*
* @name Symbol.iterator
* @memberof CronExpression
* @returns {Iterator<CronDate>} An iterator object for CronExpression that returns CronDate values.
*/
[Symbol.iterator](): Iterator<CronDate>;
}
export default CronExpression;

View File

@@ -0,0 +1,70 @@
import { CronExpression, CronExpressionOptions } from './CronExpression';
export declare enum PredefinedExpressions {
'@yearly' = "0 0 0 1 1 *",
'@annually' = "0 0 0 1 1 *",
'@monthly' = "0 0 0 1 * *",
'@weekly' = "0 0 0 * * 0",
'@daily' = "0 0 0 * * *",
'@hourly' = "0 0 * * * *",
'@minutely' = "0 * * * * *",
'@secondly' = "* * * * * *",
'@weekdays' = "0 0 0 * * 1-5",
'@weekends' = "0 0 0 * * 0,6"
}
export declare enum CronUnit {
Second = "Second",
Minute = "Minute",
Hour = "Hour",
DayOfMonth = "DayOfMonth",
Month = "Month",
DayOfWeek = "DayOfWeek"
}
export declare enum Months {
jan = 1,
feb = 2,
mar = 3,
apr = 4,
may = 5,
jun = 6,
jul = 7,
aug = 8,
sep = 9,
oct = 10,
nov = 11,
dec = 12
}
export declare enum DayOfWeek {
sun = 0,
mon = 1,
tue = 2,
wed = 3,
thu = 4,
fri = 5,
sat = 6
}
export type RawCronFields = {
second: string;
minute: string;
hour: string;
dayOfMonth: string;
month: string;
dayOfWeek: string;
};
/**
* Static class that parses a cron expression and returns a CronExpression object.
* @static
* @class CronExpressionParser
*/
export declare class CronExpressionParser {
#private;
/**
* Parses a cron expression and returns a CronExpression object.
* @param {string} expression - The cron expression to parse.
* @param {CronExpressionOptions} [options={}] - The options to use when parsing the expression.
* @param {boolean} [options.strict=false] - If true, will throw an error if the expression contains both dayOfMonth and dayOfWeek.
* @param {CronDate} [options.currentDate=new CronDate(undefined, 'UTC')] - The date to use when calculating the next/previous occurrence.
*
* @returns {CronExpression} A CronExpression object.
*/
static parse(expression: string, options?: CronExpressionOptions): CronExpression;
}

View File

@@ -0,0 +1,153 @@
import { CronSecond, CronMinute, CronHour, CronDayOfMonth, CronMonth, CronDayOfWeek, CronField, SerializedCronField, CronChars } from './fields';
import { SixtyRange, HourRange, DayOfMonthRange, MonthRange, DayOfWeekRange } from './fields/types';
export type FieldRange = {
start: number | CronChars;
count: number;
end?: number;
step?: number;
};
export type CronFields = {
second: CronSecond;
minute: CronMinute;
hour: CronHour;
dayOfMonth: CronDayOfMonth;
month: CronMonth;
dayOfWeek: CronDayOfWeek;
};
export type CronFieldOverride = {
second?: CronSecond | SixtyRange[];
minute?: CronMinute | SixtyRange[];
hour?: CronHour | HourRange[];
dayOfMonth?: CronDayOfMonth | DayOfMonthRange[];
month?: CronMonth | MonthRange[];
dayOfWeek?: CronDayOfWeek | DayOfWeekRange[];
};
export type SerializedCronFields = {
second: SerializedCronField;
minute: SerializedCronField;
hour: SerializedCronField;
dayOfMonth: SerializedCronField;
month: SerializedCronField;
dayOfWeek: SerializedCronField;
};
/**
* Represents a complete set of cron fields.
* @class CronFieldCollection
*/
export declare class CronFieldCollection {
#private;
/**
* Creates a new CronFieldCollection instance by partially overriding fields from an existing one.
* @param {CronFieldCollection} base - The base CronFieldCollection to copy fields from
* @param {CronFieldOverride} fields - The fields to override, can be CronField instances or raw values
* @returns {CronFieldCollection} A new CronFieldCollection instance
* @example
* const base = new CronFieldCollection({
* second: new CronSecond([0]),
* minute: new CronMinute([0]),
* hour: new CronHour([12]),
* dayOfMonth: new CronDayOfMonth([1]),
* month: new CronMonth([1]),
* dayOfWeek: new CronDayOfWeek([1])
* });
*
* // Using CronField instances
* const modified1 = CronFieldCollection.from(base, {
* hour: new CronHour([15]),
* minute: new CronMinute([30])
* });
*
* // Using raw values
* const modified2 = CronFieldCollection.from(base, {
* hour: [15], // Will create new CronHour
* minute: [30] // Will create new CronMinute
* });
*/
static from(base: CronFieldCollection, fields: CronFieldOverride): CronFieldCollection;
/**
* Resolves a field value, either using the provided CronField instance or creating a new one from raw values.
* @param constructor - The constructor for creating new field instances
* @param baseField - The base field to use if no override is provided
* @param fieldValue - The override value, either a CronField instance or raw values
* @returns The resolved CronField instance
* @private
*/
private static resolveField;
/**
* CronFieldCollection constructor. Initializes the cron fields with the provided values.
* @param {CronFields} param0 - The cron fields values
* @throws {Error} if validation fails
* @example
* const cronFields = new CronFieldCollection({
* second: new CronSecond([0]),
* minute: new CronMinute([0, 30]),
* hour: new CronHour([9]),
* dayOfMonth: new CronDayOfMonth([15]),
* month: new CronMonth([1]),
* dayOfWeek: new CronDayOfTheWeek([1, 2, 3, 4, 5]),
* })
*
* console.log(cronFields.second.values); // [0]
* console.log(cronFields.minute.values); // [0, 30]
* console.log(cronFields.hour.values); // [9]
* console.log(cronFields.dayOfMonth.values); // [15]
* console.log(cronFields.month.values); // [1]
* console.log(cronFields.dayOfWeek.values); // [1, 2, 3, 4, 5]
*/
constructor({ second, minute, hour, dayOfMonth, month, dayOfWeek }: CronFields);
/**
* Returns the second field.
* @returns {CronSecond}
*/
get second(): CronSecond;
/**
* Returns the minute field.
* @returns {CronMinute}
*/
get minute(): CronMinute;
/**
* Returns the hour field.
* @returns {CronHour}
*/
get hour(): CronHour;
/**
* Returns the day of the month field.
* @returns {CronDayOfMonth}
*/
get dayOfMonth(): CronDayOfMonth;
/**
* Returns the month field.
* @returns {CronMonth}
*/
get month(): CronMonth;
/**
* Returns the day of the week field.
* @returns {CronDayOfWeek}
*/
get dayOfWeek(): CronDayOfWeek;
/**
* Returns a string representation of the cron fields.
* @param {(number | CronChars)[]} input - The cron fields values
* @static
* @returns {FieldRange[]} - The compacted cron fields
*/
static compactField(input: (number | CronChars)[]): FieldRange[];
/**
* Returns a string representation of the cron fields.
* @param {CronField} field - The cron field to stringify
* @static
* @returns {string} - The stringified cron field
*/
stringifyField(field: CronField): string;
/**
* Returns a string representation of the cron field values.
* @param {boolean} includeSeconds - Whether to include seconds in the output
* @returns {string} The formatted cron string
*/
stringify(includeSeconds?: boolean): string;
/**
* Returns a serialized representation of the cron fields values.
* @returns {SerializedCronFields} An object containing the cron field values
*/
serialize(): SerializedCronFields;
}

View File

@@ -0,0 +1,30 @@
import { CronExpression } from './CronExpression';
export type CronFileParserResult = {
variables: {
[key: string]: string;
};
expressions: CronExpression[];
errors: {
[key: string]: unknown;
};
};
/**
* Parser for crontab files that handles both synchronous and asynchronous operations.
*/
export declare class CronFileParser {
#private;
/**
* Parse a crontab file asynchronously
* @param filePath Path to crontab file
* @returns Promise resolving to parse results
* @throws If file cannot be read
*/
static parseFile(filePath: string): Promise<CronFileParserResult>;
/**
* Parse a crontab file synchronously
* @param filePath Path to crontab file
* @returns Parse results
* @throws If file cannot be read
*/
static parseFileSync(filePath: string): CronFileParserResult;
}

View File

@@ -0,0 +1,25 @@
import { CronField, CronFieldOptions } from './CronField';
import { CronChars, CronMax, CronMin, DayOfMonthRange } from './types';
/**
* Represents the "day of the month" field within a cron expression.
* @class CronDayOfMonth
* @extends CronField
*/
export declare class CronDayOfMonth extends CronField {
static get min(): CronMin;
static get max(): CronMax;
static get chars(): CronChars[];
static get validChars(): RegExp;
/**
* CronDayOfMonth constructor. Initializes the "day of the month" field with the provided values.
* @param {DayOfMonthRange[]} values - Values for the "day of the month" field
* @param {CronFieldOptions} [options] - Options provided by the parser
* @throws {Error} if validation fails
*/
constructor(values: DayOfMonthRange[], options?: CronFieldOptions);
/**
* Returns an array of allowed values for the "day of the month" field.
* @returns {DayOfMonthRange[]}
*/
get values(): DayOfMonthRange[];
}

View File

@@ -0,0 +1,30 @@
import { CronField, CronFieldOptions } from './CronField';
import { CronChars, CronMax, CronMin, DayOfWeekRange } from './types';
/**
* Represents the "day of the week" field within a cron expression.
* @class CronDayOfTheWeek
* @extends CronField
*/
export declare class CronDayOfWeek extends CronField {
static get min(): CronMin;
static get max(): CronMax;
static get chars(): readonly CronChars[];
static get validChars(): RegExp;
/**
* CronDayOfTheWeek constructor. Initializes the "day of the week" field with the provided values.
* @param {DayOfWeekRange[]} values - Values for the "day of the week" field
* @param {CronFieldOptions} [options] - Options provided by the parser
*/
constructor(values: DayOfWeekRange[], options?: CronFieldOptions);
/**
* Returns an array of allowed values for the "day of the week" field.
* @returns {DayOfWeekRange[]}
*/
get values(): DayOfWeekRange[];
/**
* Returns the nth day of the week if specified in the cron expression.
* This is used for the '#' character in the cron expression.
* @returns {number} The nth day of the week (1-5) or 0 if not specified.
*/
get nthDay(): number;
}

View File

@@ -0,0 +1,114 @@
import { CronChars, CronConstraints, CronFieldType, CronMax, CronMin } from './types';
/**
* Represents the serialized form of a cron field.
* @typedef {Object} SerializedCronField
* @property {boolean} wildcard - Indicates if the field is a wildcard.
* @property {(number|string)[]} values - The values of the field.
*/
export type SerializedCronField = {
wildcard: boolean;
values: (number | string)[];
};
/**
* Represents the options for a cron field.
* @typedef {Object} CronFieldOptions
* @property {string} rawValue - The raw value of the field.
* @property {boolean} [wildcard] - Indicates if the field is a wildcard.
* @property {number} [nthDayOfWeek] - The nth day of the week.
*/
export type CronFieldOptions = {
rawValue?: string;
wildcard?: boolean;
nthDayOfWeek?: number;
};
/**
* Represents a field within a cron expression.
* This is a base class and should not be instantiated directly.
* @class CronField
*/
export declare abstract class CronField {
#private;
protected readonly options: CronFieldOptions & {
rawValue: string;
};
/**
* Returns the minimum value allowed for this field.
*/
static get min(): CronMin;
/**
* Returns the maximum value allowed for this field.
*/
static get max(): CronMax;
/**
* Returns the allowed characters for this field.
*/
static get chars(): readonly CronChars[];
/**
* Returns the regular expression used to validate this field.
*/
static get validChars(): RegExp;
/**
* Returns the constraints for this field.
*/
static get constraints(): CronConstraints;
/**
* CronField constructor. Initializes the field with the provided values.
* @param {number[] | string[]} values - Values for this field
* @param {CronFieldOptions} [options] - Options provided by the parser
* @throws {TypeError} if the constructor is called directly
* @throws {Error} if validation fails
*/
protected constructor(values: (number | string)[], options?: CronFieldOptions);
/**
* Returns the minimum value allowed for this field.
* @returns {number}
*/
get min(): number;
/**
* Returns the maximum value allowed for this field.
* @returns {number}
*/
get max(): number;
/**
* Returns an array of allowed special characters for this field.
* @returns {string[]}
*/
get chars(): readonly string[];
/**
* Indicates whether this field has a "last" character.
* @returns {boolean}
*/
get hasLastChar(): boolean;
/**
* Indicates whether this field has a "question mark" character.
* @returns {boolean}
*/
get hasQuestionMarkChar(): boolean;
/**
* Indicates whether this field is a wildcard.
* @returns {boolean}
*/
get isWildcard(): boolean;
/**
* Returns an array of allowed values for this field.
* @returns {CronFieldType}
*/
get values(): CronFieldType;
/**
* Helper function to sort values in ascending order.
* @param {number | string} a - First value to compare
* @param {number | string} b - Second value to compare
* @returns {number} - A negative, zero, or positive value, depending on the sort order
*/
static sorter(a: number | string, b: number | string): number;
/**
* Serializes the field to an object.
* @returns {SerializedCronField}
*/
serialize(): SerializedCronField;
/**
* Validates the field values against the allowed range and special characters.
* @throws {Error} if validation fails
*/
validate(): void;
}

View File

@@ -0,0 +1,23 @@
import { CronField, CronFieldOptions } from './CronField';
import { CronChars, CronMax, CronMin, HourRange } from './types';
/**
* Represents the "hour" field within a cron expression.
* @class CronHour
* @extends CronField
*/
export declare class CronHour extends CronField {
static get min(): CronMin;
static get max(): CronMax;
static get chars(): readonly CronChars[];
/**
* CronHour constructor. Initializes the "hour" field with the provided values.
* @param {HourRange[]} values - Values for the "hour" field
* @param {CronFieldOptions} [options] - Options provided by the parser
*/
constructor(values: HourRange[], options?: CronFieldOptions);
/**
* Returns an array of allowed values for the "hour" field.
* @returns {HourRange[]}
*/
get values(): HourRange[];
}

View File

@@ -0,0 +1,23 @@
import { CronField, CronFieldOptions } from './CronField';
import { CronChars, CronMax, CronMin, SixtyRange } from './types';
/**
* Represents the "second" field within a cron expression.
* @class CronSecond
* @extends CronField
*/
export declare class CronMinute extends CronField {
static get min(): CronMin;
static get max(): CronMax;
static get chars(): readonly CronChars[];
/**
* CronSecond constructor. Initializes the "second" field with the provided values.
* @param {SixtyRange[]} values - Values for the "second" field
* @param {CronFieldOptions} [options] - Options provided by the parser
*/
constructor(values: SixtyRange[], options?: CronFieldOptions);
/**
* Returns an array of allowed values for the "second" field.
* @returns {SixtyRange[]}
*/
get values(): SixtyRange[];
}

View File

@@ -0,0 +1,24 @@
import { CronField, CronFieldOptions } from './CronField';
import { CronChars, CronMax, CronMin, MonthRange } from './types';
/**
* Represents the "day of the month" field within a cron expression.
* @class CronDayOfMonth
* @extends CronField
*/
export declare class CronMonth extends CronField {
static get min(): CronMin;
static get max(): CronMax;
static get chars(): readonly CronChars[];
static get daysInMonth(): readonly number[];
/**
* CronDayOfMonth constructor. Initializes the "day of the month" field with the provided values.
* @param {MonthRange[]} values - Values for the "day of the month" field
* @param {CronFieldOptions} [options] - Options provided by the parser
*/
constructor(values: MonthRange[], options?: CronFieldOptions);
/**
* Returns an array of allowed values for the "day of the month" field.
* @returns {MonthRange[]}
*/
get values(): MonthRange[];
}

View File

@@ -0,0 +1,23 @@
import { CronChars, CronMax, CronMin, SixtyRange } from './types';
import { CronField, CronFieldOptions } from './CronField';
/**
* Represents the "second" field within a cron expression.
* @class CronSecond
* @extends CronField
*/
export declare class CronSecond extends CronField {
static get min(): CronMin;
static get max(): CronMax;
static get chars(): readonly CronChars[];
/**
* CronSecond constructor. Initializes the "second" field with the provided values.
* @param {SixtyRange[]} values - Values for the "second" field
* @param {CronFieldOptions} [options] - Options provided by the parser
*/
constructor(values: SixtyRange[], options?: CronFieldOptions);
/**
* Returns an array of allowed values for the "second" field.
* @returns {SixtyRange[]}
*/
get values(): SixtyRange[];
}

View File

@@ -0,0 +1,8 @@
export * from './types';
export * from './CronDayOfMonth';
export * from './CronDayOfWeek';
export * from './CronField';
export * from './CronHour';
export * from './CronMinute';
export * from './CronMonth';
export * from './CronSecond';

18
node_modules/cron-parser/dist/types/fields/types.d.ts generated vendored Normal file
View File

@@ -0,0 +1,18 @@
export type RangeFrom<LENGTH extends number, ACC extends unknown[] = []> = ACC['length'] extends LENGTH ? ACC : RangeFrom<LENGTH, [...ACC, 1]>;
export type IntRange<FROM extends number[], TO extends number, ACC extends number = never> = FROM['length'] extends TO ? ACC | TO : IntRange<[...FROM, 1], TO, ACC | FROM['length']>;
export type SixtyRange = IntRange<RangeFrom<0>, 59>;
export type HourRange = IntRange<RangeFrom<0>, 23>;
export type DayOfMonthRange = IntRange<RangeFrom<1>, 31> | 'L';
export type MonthRange = IntRange<RangeFrom<1>, 12>;
export type DayOfWeekRange = IntRange<RangeFrom<0>, 7> | 'L';
export type CronFieldType = SixtyRange[] | HourRange[] | DayOfMonthRange[] | MonthRange[] | DayOfWeekRange[];
export type CronChars = 'L' | 'W';
export type CronMin = 0 | 1;
export type CronMax = 7 | 12 | 23 | 31 | 59;
export type ParseRangeResponse = number[] | string[] | number | string;
export type CronConstraints = {
min: CronMin;
max: CronMax;
chars: readonly CronChars[];
validChars: RegExp;
};

10
node_modules/cron-parser/dist/types/utils/random.d.ts generated vendored Normal file
View File

@@ -0,0 +1,10 @@
/**
* A type representing a Pseudorandom Number Generator, similar to Math.random()
*/
export type PRNG = () => number;
/**
* Generates a PRNG using a given seed. When not provided, the seed is randomly generated
* @param {string} str A string to derive the seed from
* @returns {PRNG} A random number generator correctly seeded
*/
export declare function seededRandom(str?: string): PRNG;

38
node_modules/cron-parser/dist/utils/random.js generated vendored Normal file
View File

@@ -0,0 +1,38 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.seededRandom = seededRandom;
/**
* Computes a numeric hash from a given string
* @param {string} str A value to hash
* @returns {number} A numeric hash computed from the given value
*/
function xfnv1a(str) {
let h = 2166136261 >>> 0;
for (let i = 0; i < str.length; i++) {
h ^= str.charCodeAt(i);
h = Math.imul(h, 16777619);
}
return () => h >>> 0;
}
/**
* Initialize a new PRNG using a given seed
* @param {number} seed The seed used to initialize the PRNG
* @returns {PRNG} A random number generator
*/
function mulberry32(seed) {
return () => {
let t = (seed += 0x6d2b79f5);
t = Math.imul(t ^ (t >>> 15), t | 1);
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};
}
/**
* Generates a PRNG using a given seed. When not provided, the seed is randomly generated
* @param {string} str A string to derive the seed from
* @returns {PRNG} A random number generator correctly seeded
*/
function seededRandom(str) {
const seed = str ? xfnv1a(str)() : Math.floor(Math.random() * 10_000_000_000);
return mulberry32(seed);
}

7792
node_modules/luxon/build/node/luxon.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

1
node_modules/luxon/build/node/luxon.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

20
package-lock.json generated
View File

@@ -10,6 +10,7 @@
"license": "MIT",
"dependencies": {
"axios": "^1.6.0",
"cron-parser": "^5.4.0",
"element-plus": "^2.4.0",
"vue": "^3.4.0",
"vue-router": "^4.2.0",
@@ -3863,6 +3864,17 @@
"node": ">=10"
}
},
"node_modules/cron-parser": {
"version": "5.4.0",
"resolved": "https://registry.npmmirror.com/cron-parser/-/cron-parser-5.4.0.tgz",
"integrity": "sha512-HxYB8vTvnQFx4dLsZpGRa0uHp6X3qIzS3ZJgJ9v6l/5TJMgeWQbLkR5yiJ5hOxGbc9+jCADDnydIe15ReLZnJA==",
"dependencies": {
"luxon": "^3.7.1"
},
"engines": {
"node": ">=18"
}
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -6674,6 +6686,14 @@
"yallist": "^3.0.2"
}
},
"node_modules/luxon": {
"version": "3.7.2",
"resolved": "https://registry.npmmirror.com/luxon/-/luxon-3.7.2.tgz",
"integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==",
"engines": {
"node": ">=12"
}
},
"node_modules/magic-string": {
"version": "0.30.19",
"resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.19.tgz",

View File

@@ -18,6 +18,7 @@
"license": "MIT",
"dependencies": {
"axios": "^1.6.0",
"cron-parser": "^5.4.0",
"element-plus": "^2.4.0",
"vue": "^3.4.0",
"vue-router": "^4.2.0",

View File

@@ -39,7 +39,6 @@
:row-class-name="tableRowClassName"
:highlight-current-row="false">
<el-table-column width="40"></el-table-column>
<el-table-column prop="id" label="设备ID" min-width="80" />
<el-table-column prop="name" label="设备名称" min-width="120" />
<el-table-column prop="type" label="设备类型" min-width="100">
<template #default="scope">

View File

@@ -8,21 +8,27 @@
</div>
</template>
<el-table :data="plans" style="width: 100%">
<el-table-column prop="id" label="计划ID" width="80" />
<el-table-column prop="name" label="计划名称" width="180" />
<el-table-column prop="description" label="描述" />
<el-table-column prop="execution_type" label="执行类型" width="120">
<el-table :data="plans" style="width: 100%" table-layout="auto" fit>
<el-table-column prop="name" label="计划名称" />
<el-table-column prop="description" label="计划描述" />
<el-table-column prop="execution_type" label="执行类型">
<template #default="scope">
<el-tag v-if="scope.row.execution_type === 'automatic'"></el-tag>
<el-tag v-else>手动</el-tag>
<el-tag v-if="scope.row.execution_type === 'manual'"></el-tag>
<el-tag v-else-if="scope.row.execute_num === 0" type="success">自动(无限执行)</el-tag>
<el-tag v-else type="warning">自动({{ scope.row.execute_num }})</el-tag>
</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="100">
<el-table-column prop="execute_count" label="已执行次数" />
<el-table-column prop="status" label="状态">
<template #default="scope">
<el-tag v-if="scope.row.status === 0" type="success"></el-tag>
<el-tag v-else-if="scope.row.status === 1" type="warning"></el-tag>
<el-tag v-else type="info">已完成</el-tag>
<el-tag v-if="scope.row.status === 0" type="danger"></el-tag>
<el-tag v-else-if="scope.row.status === 1" type="success"></el-tag>
<el-tag v-else type="info">执行完毕</el-tag>
</template>
</el-table-column>
<el-table-column prop="cron_expression" label="下次执行时间">
<template #default="scope">
{{ formatNextExecutionTime(scope.row.cron_expression) }}
</template>
</el-table-column>
<el-table-column label="操作" width="200">
@@ -51,6 +57,7 @@
<script>
import apiClient from '../api/index.js';
import PlanForm from './PlanForm.vue';
import cronParser from 'cron-parser';
export default {
name: 'PlanList',
@@ -88,6 +95,24 @@ export default {
}
},
// 格式化下次执行时间
formatNextExecutionTime(cronExpression) {
if (!cronExpression) {
return '-';
}
try {
// 正确使用cron-parser库
const parser = cronParser.default || cronParser;
const interval = parser.parse(cronExpression);
const next = interval.next().toDate();
return next.toLocaleString('zh-CN');
} catch (err) {
console.error('解析cron表达式失败:', err);
return '无效的表达式';
}
},
addPlan() {
this.currentPlan = {
id: null,