diff --git a/package-lock.json b/package-lock.json index 76499d3..c43fb99 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "axios": "^0.21.1", "chalk": "^3.0.0", "codecov": "^3.8.1", + "cron-validate": "^1.4.2", "cron-validator": "^1.2.1", "cronstrue": "^1.110.0", "crypto-js": "^4.0.0", @@ -29,6 +30,7 @@ "minify": "^6.0.1", "moment": "2.29.1", "moment-timezone": "^0.5.32", + "node-cron": "^3.0.0", "nyc": "^15.1.0", "ora": "^5.2.0", "shelljs": "^0.8.4", @@ -48,6 +50,7 @@ "@types/crypto-js": "^3.1.43", "@types/mocha": "^7.0.0", "@types/node": "13.9.3", + "@types/node-cron": "^2.0.3", "@types/shelljs": "^0.8.8", "@types/signale": "^1.2.1", "chai": "^4.2.0", @@ -272,6 +275,14 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/runtime": { + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz", + "integrity": "sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==", + "dependencies": { + "regenerator-runtime": "^0.13.4" + } + }, "node_modules/@babel/template": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", @@ -2084,10 +2095,9 @@ } }, "node_modules/@types/lodash": { - "version": "4.14.149", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", - "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==", - "dev": true + "version": "4.14.168", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz", + "integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==" }, "node_modules/@types/minimatch": { "version": "3.0.3", @@ -2106,6 +2116,15 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-13.9.3.tgz", "integrity": "sha512-01s+ac4qerwd6RHD+mVbOEsraDHSgUaefQlEdBbUolnQFjKwCr7luvAlEwW1RFojh67u0z4OUTjPn9LEl4zIkA==" }, + "node_modules/@types/node-cron": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/node-cron/-/node-cron-2.0.3.tgz", + "integrity": "sha512-gwBBGeY2XeYBLE0R01K9Sm2hvNcPGmoloL6aqthA3QmBB1GYXTHIJ42AGZL7bdXBRiwbRV8b6NB5iKpl20R3gw==", + "dev": true, + "dependencies": { + "@types/tz-offset": "*" + } + }, "node_modules/@types/responselike": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", @@ -2139,6 +2158,12 @@ "integrity": "sha512-T+m89VdXj/eidZyejvmoP9jivXgBDdkOSBVQjU9kF349NEx10QdPNGxHeZUaj1IlJ32/ewdyXJjnJxyxJroYwg==", "dev": true }, + "node_modules/@types/tz-offset": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/@types/tz-offset/-/tz-offset-0.0.0.tgz", + "integrity": "sha512-XLD/llTSB6EBe3thkN+/I0L+yCTB6sjrcVovQdx2Cnl6N6bTzHmwe/J8mWnsXFgxLrj/emzdv8IR4evKYG2qxQ==", + "dev": true + }, "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", @@ -3188,6 +3213,14 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "node_modules/cron-validate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/cron-validate/-/cron-validate-1.4.2.tgz", + "integrity": "sha512-GdjNeiZjNA9u6BItfhnd1MFPbT86wmJ2/2BwDQyXZY0mb9nhLSeh3PVKk7G185qfUSwbtGNtCLrKI/9pclvGrg==", + "dependencies": { + "yup": "0.32.8" + } + }, "node_modules/cron-validator": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/cron-validator/-/cron-validator-1.2.1.tgz", @@ -5517,6 +5550,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "node_modules/lodash._reinterpolate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", @@ -6014,6 +6052,11 @@ "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" }, + "node_modules/nanoclone": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz", + "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==" + }, "node_modules/natural-orderby": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-2.0.3.tgz", @@ -6068,6 +6111,17 @@ "tslib": "^2.0.3" } }, + "node_modules/node-cron": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.0.tgz", + "integrity": "sha512-DDwIvvuCwrNiaU7HEivFDULcaQualDv7KoNlB/UU1wPW0n1tDEmBJKhEIE6DlF2FuoOHcNbLJ8ITL2Iv/3AWmA==", + "dependencies": { + "moment-timezone": "^0.5.31" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/node-environment-flags": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", @@ -7160,6 +7214,11 @@ "node": ">= 0.8.0" } }, + "node_modules/property-expr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.4.tgz", + "integrity": "sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg==" + }, "node_modules/proxy-agent": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.1.1.tgz", @@ -7426,6 +7485,11 @@ "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", "dev": true }, + "node_modules/regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + }, "node_modules/registry-auth-token": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.0.tgz", @@ -9321,6 +9385,11 @@ "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==" }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=" + }, "node_modules/tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", @@ -10050,6 +10119,23 @@ "engines": { "node": ">=6" } + }, + "node_modules/yup": { + "version": "0.32.8", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.8.tgz", + "integrity": "sha512-SZulv5FIZ9d5H99EN5tRCRPXL0eyoYxWIP1AacCrjC9d4DfP13J1dROdKGfpfRHT3eQB6/ikBl5jG21smAfCkA==", + "dependencies": { + "@babel/runtime": "^7.10.5", + "@types/lodash": "^4.14.165", + "lodash": "^4.17.20", + "lodash-es": "^4.17.11", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } } }, "dependencies": { @@ -10253,6 +10339,14 @@ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.0.tgz", "integrity": "sha512-qvRvi4oI8xii8NllyEc4MDJjuZiNaRzyb7Y7lup1NqJV8TZHF4O27CcP+72WPn/k1zkgJ6WJfnIbk4jTsVAZHw==" }, + "@babel/runtime": { + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz", + "integrity": "sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, "@babel/template": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", @@ -11730,10 +11824,9 @@ } }, "@types/lodash": { - "version": "4.14.149", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", - "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==", - "dev": true + "version": "4.14.168", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz", + "integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==" }, "@types/minimatch": { "version": "3.0.3", @@ -11752,6 +11845,15 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-13.9.3.tgz", "integrity": "sha512-01s+ac4qerwd6RHD+mVbOEsraDHSgUaefQlEdBbUolnQFjKwCr7luvAlEwW1RFojh67u0z4OUTjPn9LEl4zIkA==" }, + "@types/node-cron": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/node-cron/-/node-cron-2.0.3.tgz", + "integrity": "sha512-gwBBGeY2XeYBLE0R01K9Sm2hvNcPGmoloL6aqthA3QmBB1GYXTHIJ42AGZL7bdXBRiwbRV8b6NB5iKpl20R3gw==", + "dev": true, + "requires": { + "@types/tz-offset": "*" + } + }, "@types/responselike": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", @@ -11785,6 +11887,12 @@ "integrity": "sha512-T+m89VdXj/eidZyejvmoP9jivXgBDdkOSBVQjU9kF349NEx10QdPNGxHeZUaj1IlJ32/ewdyXJjnJxyxJroYwg==", "dev": true }, + "@types/tz-offset": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/@types/tz-offset/-/tz-offset-0.0.0.tgz", + "integrity": "sha512-XLD/llTSB6EBe3thkN+/I0L+yCTB6sjrcVovQdx2Cnl6N6bTzHmwe/J8mWnsXFgxLrj/emzdv8IR4evKYG2qxQ==", + "dev": true + }, "@yarnpkg/lockfile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", @@ -12608,6 +12716,14 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "cron-validate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/cron-validate/-/cron-validate-1.4.2.tgz", + "integrity": "sha512-GdjNeiZjNA9u6BItfhnd1MFPbT86wmJ2/2BwDQyXZY0mb9nhLSeh3PVKk7G185qfUSwbtGNtCLrKI/9pclvGrg==", + "requires": { + "yup": "0.32.8" + } + }, "cron-validator": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/cron-validator/-/cron-validator-1.2.1.tgz", @@ -14424,6 +14540,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" }, + "lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "lodash._reinterpolate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", @@ -14848,6 +14969,11 @@ "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" }, + "nanoclone": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz", + "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==" + }, "natural-orderby": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-2.0.3.tgz", @@ -14892,6 +15018,14 @@ "tslib": "^2.0.3" } }, + "node-cron": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.0.tgz", + "integrity": "sha512-DDwIvvuCwrNiaU7HEivFDULcaQualDv7KoNlB/UU1wPW0n1tDEmBJKhEIE6DlF2FuoOHcNbLJ8ITL2Iv/3AWmA==", + "requires": { + "moment-timezone": "^0.5.31" + } + }, "node-environment-flags": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", @@ -15750,6 +15884,11 @@ "resolved": "https://registry.npmjs.org/promise-queue/-/promise-queue-2.2.5.tgz", "integrity": "sha1-L29ffA9tCBCelnZZx5uIqe1ek7Q=" }, + "property-expr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.4.tgz", + "integrity": "sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg==" + }, "proxy-agent": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.1.1.tgz", @@ -15984,6 +16123,11 @@ "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", "dev": true }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + }, "registry-auth-token": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.0.tgz", @@ -17577,6 +17721,11 @@ "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==" }, + "toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=" + }, "tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", @@ -18181,6 +18330,20 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true + }, + "yup": { + "version": "0.32.8", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.8.tgz", + "integrity": "sha512-SZulv5FIZ9d5H99EN5tRCRPXL0eyoYxWIP1AacCrjC9d4DfP13J1dROdKGfpfRHT3eQB6/ikBl5jG21smAfCkA==", + "requires": { + "@babel/runtime": "^7.10.5", + "@types/lodash": "^4.14.165", + "lodash": "^4.17.20", + "lodash-es": "^4.17.11", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + } } } } diff --git a/package.json b/package.json index 5116ac9..2f49bed 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "axios": "^0.21.1", "chalk": "^3.0.0", "codecov": "^3.8.1", + "cron-validate": "^1.4.2", "cron-validator": "^1.2.1", "cronstrue": "^1.110.0", "crypto-js": "^4.0.0", @@ -30,6 +31,7 @@ "minify": "^6.0.1", "moment": "2.29.1", "moment-timezone": "^0.5.32", + "node-cron": "^3.0.0", "nyc": "^15.1.0", "ora": "^5.2.0", "shelljs": "^0.8.4", @@ -46,6 +48,7 @@ "@types/crypto-js": "^3.1.43", "@types/mocha": "^7.0.0", "@types/node": "13.9.3", + "@types/node-cron": "^2.0.3", "@types/shelljs": "^0.8.8", "@types/signale": "^1.2.1", "chai": "^4.2.0", diff --git a/src/commands/cron.ts b/src/commands/cron.ts index e41072a..2c1050f 100644 --- a/src/commands/cron.ts +++ b/src/commands/cron.ts @@ -1,10 +1,14 @@ import {Command, flags} from '@oclif/command' import chalk from 'chalk' -import {isValidCron} from 'cron-validator' +import CronValidate from 'cron-validate' import cronstrue from 'cronstrue' +import NodeCron from 'node-cron' +import shelljs from 'shelljs' import Logger from '../utilities/logger' import Utilities from '../utilities/utilities' + +// https://github.com/Airfooox/cron-validate /* * this Commands add support for cron jobs * */ @@ -14,11 +18,46 @@ export default class Cron extends Command { static RUN = 'run' static DESCRIBE = 'desc' + static PRESET_DEFAULT = { + preset: 'default', + override: { + useAliases: true, // optional, default to false + useBlankDay: true, + } + } + + static PRESET_DEFAULT_WITH_SECONDS = { + preset: 'default', + override: { + useSeconds: true, // override preset option + useAliases: true, // optional, default to false + useBlankDay: true, + } + } + static PRESET_DEFAULT_WITH_SECONDS_AND_YEARS = { + preset: 'default', + override: { + useSeconds: true, // override preset option + useYears: true, + useAliases: true, // optional, default to false + useBlankDay: true, + } + } + + // adding more options to have bit loosen validation rules + static VALIDATOR_OPTIONS = { + seconds: true, + allowBlankDay: true, + alias: true , + allowSevenAsSunday: true + } + static flags = { help: flags.help({char: 'h'}), string: flags.string({char: 's' , description: 'Cron expression'}), describe: flags.boolean({char: 'd' , description: 'Describe cron expressions into human readable descriptions'}), run: flags.boolean({char: 'r' , description: 'run command using cron expression'}), + command: flags.string({char: 'c' , description: 'unix command to be executed'}), } static args = [{name: 'string'}] @@ -30,6 +69,8 @@ export default class Cron extends Command { args.string = Utilities.getInputStringFromCmd(this, flags, args) // from either -s or args args.action = this.getAction(flags, args) //by default let it be sha1 + args.command = this.getCommand(flags, args) //by default let it be sha1 + //check params after evaluating all this.checkParameters(flags, args) this.evalCron(flags, args) @@ -41,8 +82,22 @@ export default class Cron extends Command { if (args.string === undefined || args.string === '') Logger.error(this, 'Input string is empty or undefined') - if (!isValidCron(args.string)) { - Logger.error(this, `Invalid Cron expression : ${chalk.red(args.string)}`) + // for more present settings check - https://github.com/Airfooox/cron-validate + let preset = Cron.PRESET_DEFAULT + + // if we have 6 inputs enable seconds as an option + let charCount = (args.string.match(/\s+/g) || []).length + 1 + if (charCount === 6) { + preset = Cron.PRESET_DEFAULT_WITH_SECONDS + } else if (charCount === 7) { + preset = Cron.PRESET_DEFAULT_WITH_SECONDS_AND_YEARS + } + const cronResult = CronValidate(args.string, preset) + + if (!cronResult.isValid()) { + const errorValue = cronResult.getError() + // The error value contains an array of strings, which represent the cron validation errors. + Logger.error(this, `Invalid Cron expression : ${chalk.yellow(errorValue)}`) } if (args.action === undefined || args.string === '') @@ -52,11 +107,15 @@ export default class Cron extends Command { // tslint:disable-next-line:no-unused private evalCron(flags: any, args: any) { // Logger.success(this, `Action: ${chalk.green(args.action)}`) + let cronSchedule = cronstrue.toString(args.string) + if (args.action === Cron.DESCRIBE) { - let output = cronstrue.toString(args.string) - Logger.success(this, output) + Logger.success(this, cronSchedule) } else if (args.action === Cron.RUN) { - Logger.success(this, 'run command, coming soon...') + Logger.success(this, `running command ${chalk.green(cronSchedule)}, use ${chalk.yellow('Ctrl+C')} to exit.`) + NodeCron.schedule(args.string, function () { + shelljs.exec(args.command) + }) } } @@ -68,4 +127,13 @@ export default class Cron extends Command { return Cron.RUN Logger.error(this, 'Invalid Or Unsupported action') } + + // tslint:disable-next-line:no-unused + private getCommand(flags: any, args: any) { + // we only need this if actions is run + if (flags.command) // find human readable descriptions for cron + return flags.command + if (args.action === Cron.RUN) + Logger.error(this, 'Invalid Or Unsupported Command') + } } diff --git a/test/commands/cron.test.ts b/test/commands/cron.test.ts index 764bbb2..92c93e8 100644 --- a/test/commands/cron.test.ts +++ b/test/commands/cron.test.ts @@ -30,4 +30,32 @@ describe('cron', () => { expect(ctx.stdout).to.contain('At 10:00 PM, Monday through Friday') }) + test + .stdout() + .command(['cron', '-d', '-s', '10 * * * * *']) + .it('Seconds functionality Enabled', ctx => { + expect(ctx.stdout).to.contain('At 10 seconds past the minute') + }) + + test + .stdout() + .command(['cron', '-d', '-s', '0 22 * * 1-5']) + .it('Range functionality enabled', ctx => { + expect(ctx.stdout).to.contain('At 10:00 PM, Monday through Friday') + }) + + test + .stdout() + .command(['cron', '-d', '-s', '0 0 12 1/2 * ? 2020']) + .it('Year functionality enabled', ctx => { + expect(ctx.stdout).to.contain('At 12:00 PM, every 2 days, only in 2020') + }) + + test + .stdout() + .command(['cron', '-d', '-s', '0 0 12 1/2 mon,tue']) + .it('Days functionality enabled', ctx => { + expect(ctx.stdout).to.contain('At 12:00 AM, on day 12 of the month, and on Monday and Tuesday, every 2 months') + }) + })