initial commit

This commit is contained in:
jkoschke
2022-08-26 12:49:14 +02:00
commit 4990667410
573 changed files with 29169 additions and 0 deletions

4
Dockerfile Normal file
View File

@ -0,0 +1,4 @@
FROM node:16
RUN apt-get update && apt-get upgrade
RUN apt-get install wireless-tools -y

174
src/lib/utils.js Normal file
View File

@ -0,0 +1,174 @@
const child_process = require('child_process');
const execSync = child_process.execSync;
const _consoleColorCodes = {
Reset: "\x1b[0m",
Bright: "\x1b[1m",
Dim: "\x1b[2m",
Underscore: "\x1b[4m",
Blink: "\x1b[5m",
Reverse: "\x1b[7m",
Hidden: "\x1b[8m",
FgBlack: "\x1b[30m",
FgRed: "\x1b[31m",
FgGreen: "\x1b[32m",
FgYellow: "\x1b[33m",
FgBlue: "\x1b[34m",
FgMagenta: "\x1b[35m",
FgCyan: "\x1b[36m",
FgWhite: "\x1b[37m",
BgBlack: "\x1b[40m",
BgRed: "\x1b[41m",
BgGreen: "\x1b[42m",
BgYellow: "\x1b[43m",
BgBlue: "\x1b[44m",
BgMagenta: "\x1b[45m",
BgCyan: "\x1b[46m",
BgWhite: "\x1b[47m",
}
function Utils() {
this.consoleColorCodes = _consoleColorCodes;
}
Utils.prototype.isCurrentUserRoot = function () {
return process.getuid() == 0; // UID 0 is always root
}
Utils.prototype.printWelcomeMessage = function () {
console.log("###################################")
console.log("##### RaspiWiFi Intial Setup #####")
console.log("###################################")
}
Utils.prototype.printSetupCanceledMessage = function () {
console.log("")
console.log("")
console.log("===================================================")
console.log("---------------------------------------------------")
console.log("")
console.log("RaspiWiFi installation cancelled. Nothing changed...")
console.log("")
console.log("---------------------------------------------------")
console.log("===================================================")
console.log("")
console.log("")
}
Utils.prototype.printFinishedMessage = function () {
console.log("")
console.log("")
console.log("#####################################")
console.log("##### RaspiWiFi Setup Complete #####")
console.log("#####################################")
console.log("")
console.log("")
}
Utils.prototype.checkForYN = function (input) {
if (input.toLowerCase() !== 'y' && input.toLowerCase() !== 'n') {
this.printColor(this.consoleColorCodes.FgRed, 'Please enter y or n!');
return false;
}
return true;
}
Utils.prototype.printColor = function (color, ...args) {
console.log(color, ...args, this.consoleColorCodes.Reset);
}
Utils.prototype.clearConsole = () => {
//process.stdout.write('\033c');
process.stdout.write('\x1bc');
}
Utils.prototype.installSystemDependencies = function () {
this.clearConsole();
execSync('apt update');
this.clearConsole();
execSync('apt install python3 python3-rpi.gpio python3-pip dnsmasq hostapd -y')
}
Utils.prototype.copyConfigs = function (isWpaEabled) {
/* Creating application directories */
this.printColor(null, 'Creating application directories');
execSync('mkdir /usr/lib/raspiwifi');
execSync('mkdir /etc/raspiwifi');
execSync('mkdir /etc/cron.raspiwifi');
/* Copy application files */
this.printColor(null, 'Copy application files');
execSync('cp -a libs/* /usr/lib/raspiwifi/');
/* Backing up current files */
this.printColor(null, 'Backing up current files');
execSync('mv /etc/wpa_supplicant/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant.conf.original');
execSync('mv /etc/dnsmasq.conf /etc/dnsmasq.conf.original');
execSync('mv /etc/dhcpcd.conf /etc/dhcpcd.conf.original');
/* Copy default files for basic device setup*/
this.printColor(null, 'Copy default files for basic device setup');
execSync('cp /usr/lib/raspiwifi/reset_device/static_files/dnsmasq.conf /etc/');
execSync('cp /usr/lib/raspiwifi/reset_device/static_files/dhcpcd.conf /etc/');
if (isWpaEabled)
execSync('cp /usr/lib/raspiwifi/reset_device/static_files/hostapd.conf.wpa /etc/hostapd/hostapd.conf');
else
execSync('cp /usr/lib/raspiwifi/reset_device/static_files/hostapd.conf.nowpa /etc/hostapd/hostapd.conf');
execSync('cp /usr/lib/raspiwifi/reset_device/static_files/aphost_bootstrapper /etc/cron.raspiwifi')
execSync('chmod +x /etc/cron.raspiwifi/aphost_bootstrapper');
execSync('mv /usr/lib/raspiwifi/reset_device/static_files/raspiwifi.conf /etc/raspiwifi');
/* TODO: Setting up CRON for running monitoring jobs */
this.printColor(null, 'Setting up CRON for running monitoring jobs');
execSync('echo "# RaspiWiFi Startup" >> /etc/crontab');
execSync('echo "@reboot root run-parts /etc/cron.raspiwifi/" >> /etc/crontab');
/* Finishing things up */
this.printColor(null, 'Finishing things up');
execSync('touch /etc/raspiwifi/host_mode');
}
Utils.prototype.updateMainConfigFile = function ({ ssid, autoConfig, autoConfigDelay, sslEnabled, serverPort, wpaEnabled, wpaSecret }) {
console.log(this);
const outputString = this.serializeMainConfigFile({ ssid, autoConfig, autoConfigDelay, sslEnabled, serverPort, wpaEnabled, wpaSecret });
const fileName = '/etc/raspiwifi/raspiwifi.conf'
execSync('cat <<EOF >' + fileName + '\n' + outputString)
}
Utils.prototype.reboot = function () {
execSync('reboot');
}
Utils.prototype.serializeMainConfigFile = function ({ ssid, autoConfig, autoConfigDelay, sslEnabled, serverPort, wpaEnabled, wpaSecret }) {
const output = {
'SSID': ssid,
'AutoReconfig': autoConfig,
'AutoReconfigDelay': autoConfigDelay,
'SSLEnabled': sslEnabled,
'ServerPort': serverPort,
'WPAEnabled': wpaEnabled,
'PSK': wpaSecret ?? '',
}
return JSON.stringify(output, null, 2);
}
Utils.prototype.deserializeMainConfigFile = (input) => {
const obj = JSON.parse(input);
return {
ssid: obj['SSID'],
autoConfig: obj['AutoReconfig'],
autoConfigDelay: obj['AutoReconfigDelay'],
sslEnabled: obj['SSLEnabled'],
serverPort: obj['ServerPort'],
wpaEnabled: obj['WPAEnabled'],
wpaSecret: obj['PSK'] ?? '',
}
}
module.exports = Utils;

19
src/node_modules/.yarn-integrity generated vendored Normal file
View File

@ -0,0 +1,19 @@
{
"systemParams": "darwin-x64-93",
"modulesFolders": [
"node_modules"
],
"flags": [],
"linkedModules": [],
"topLevelPatterns": [
"crontab@^1.4.2",
"readline-sync@^1.4.10"
],
"lockfileEntries": {
"crontab@^1.4.2": "https://registry.yarnpkg.com/crontab/-/crontab-1.4.2.tgz#847452d91574c6029486e70d0186cb27be742892",
"readline-sync@^1.4.10": "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.10.tgz#41df7fbb4b6312d673011594145705bf56d8873b",
"underscore@^1.6.0": "https://registry.yarnpkg.com/underscore/-/underscore-1.13.4.tgz#7886b46bbdf07f768e0052f1828e1dcab40c0dee"
},
"files": [],
"artifacts": {}
}

3
src/node_modules/crontab/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,3 @@
language: node_js
node_js:
- '0.10'

181
src/node_modules/crontab/README.md generated vendored Normal file
View File

@ -0,0 +1,181 @@
# node-crontab
[![Build Status](https://secure.travis-ci.org/dachev/node-crontab.png)](http://travis-ci.org/dachev/node-crontab)
[![Dependencies](https://david-dm.org/dachev/node-crontab.png)](https://david-dm.org/dachev/node-crontab)
[![NPM version](https://badge.fury.io/js/crontab.svg)](http://badge.fury.io/js/crontab)
A module for creating, reading, updating, and deleting system cron jobs
## Installation
```bash
$ npm install crontab
```
## Examples
### Working with jobs
```js
require('crontab').load(function(err, crontab) {
// create with string expression
var job = crontab.create('ls -la', '0 7 * * 1,2,3,4,5');
// create with Date
var job = crontab.create('ls -lh', new Date(1400373907766));
// create with comment
var job = crontab.create('ls -lt', null, 'comment 2');
// create special: @reboot, @hourly, @daily, @weekly, @monthly, @yearly, @annually, @midnight
var job = crontab.create('ls -la', '@reboot');
// check valid
var job = crontab.create();
if (job == null) {
console.log('failed to create job');
}
// remove object
var job = crontab.create('ls -lr', '0 7 * * 1,2,3,4,5', 'comment 3');
crontab.remove(job);
// remove conditions
crontab.remove({command:'ls -lh', comment:/comment 2/});
// manipulate: every business hour
var job = crontab.create('ls -l');
job.minute().at(0);
job.hour().between(8, 17);
job.dow().between('mon', 'fri');
// manipulate: every other hour on weekday nights
var job = crontab.create('ls -l');
job.hour().between(19, 0).every(2);
job.hour().between(0, 6).every(2);
job.dow().between('mon', 'fri');
// manipulate: summer
var job = crontab.create('ls -l');
job.month().between('jun', 'sep');
// manipulate: Christmas
var job = crontab.create('ls -l');
job.minute().at(30);
job.hour().at(9);
job.dom().on(24);
job.month().in('dec');
// show all jobs
var jobs = crontab.jobs();
// show jobs with conditions
var jobs = crontab.jobs({command:'ls -l', comment:/comment 1/});
// reset jobs to their original state
crontab.reset();
// save
crontab.save(function(err, crontab) {
});
console.log(crontab);
});
```
### Working with environment variables
```js
require('crontab').load(function(err, crontab) {
// get all env variables
var vars = crontab.vars();
// find env variables by name
var vars = crontab.vars({name: 'FOO'});
// find env variables by value
var vars = crontab.vars({val: 'bar'});
// find env variables by name and value
var vars = crontab.vars({name: 'FOO', val: 'bar'});
// find env variables by name
var vars = crontab.vars('FOO');
// create with a pair of arguments
crontab.vars().add('FOO', 'foo');
// create multiple with an object argument
crontab.vars().add({'FOO':'foo', 'BAR':'1'});
// remove all env variables
crontab.vars().rm();
// remove selected env variables
crontab.vars({name: 'FOO'}).rm();
// save
crontab.save(function(err, crontab) {
});
});
```
### Naive reboot
```js
require('crontab').load(function(err, crontab) {
if (err) {
return console.error(err);
}
var command = 'ls -l';
crontab.remove({command:command});
crontab.create(command, '@reboot');
crontab.save(function(err, crontab) {
});
});
```
### More robust reboot and forever
```js
require('crontab').load(function(err, crontab) {
if (err) {
return console.error(err);
}
var uuid = '64d967a0-120b-11e0-ac64-0800200c9a66';
var nodePath = process.execPath.split('/').slice(0, -1).join('/');
var exportCommand = 'export PATH=' + nodePath + ':$PATH';
var foreverCommand = require('path').join(__dirname, 'node_modules', 'forever', 'bin', 'forever');
var sysCommand = exportCommand + ' && ' + foreverCommand + ' start ' + __filename;
crontab.remove({comment:uuid});
crontab.create(sysCommand, '@reboot', uuid);
crontab.save(function(err, crontab) {
console.log(err)
});
});
```
### Specific user
```js
// when executing for another user the library uses sudo, unless the
// current process runs as root
require('crontab').load('alice', function(err, crontab) {
if (err) {
return console.error(err);
}
crontab.save(function(err, crontab) {
console.log(err)
});
});
```
## Author
Blagovest Dachev
## Copyright
* Blagovest Dachev (2010-2014)
* Martin Owens (2009-2012)
## Credits
This is a JavaScript port of a Python package by Martin Owens
## License
GPL3

61
src/node_modules/crontab/lib/CronCommand.js generated vendored Normal file
View File

@ -0,0 +1,61 @@
/**
* @class CronCommand
* A JavaScript representation of the command part of a cron job.
*
* Examples:
* var command = new CronCommand('ls -l /');
*
* @param {String} __line__
*/
function CronCommand(line) {
var command = line;
/**
* Returns true if the pattern that was passed matches this command.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* // true
* console.log(jobs[i].command().match('ls -l /'));
* }
* });
*
* @param {String|RegEx} __pattern__
* @return {Boolean}
*/
this.match = function(pattern) {
if (_.isString(pattern) && !!~command.indexOf(pattern)) {
return true;
}
if (_.isRegExp(pattern)) {
return pattern.test(command);
}
return false;
}
/**
* Renders the object to a string as it would be written to the system.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].command().toString());
* }
* });
*
* @return {String}
*/
this.toString = function() {
return command;
}
}
module.exports = CronCommand;

61
src/node_modules/crontab/lib/CronComment.js generated vendored Normal file
View File

@ -0,0 +1,61 @@
/**
* @class CronComment
* A JavaScript representation of the inline comment part of a cron job.
*
* Examples:
* var comment = new CronComment('run this on the weekend');
*
* @param {String} __line__
*/
function CronComment(line) {
var comment = line;
/**
* Returns true if the pattern that was passed matches this comment.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({comment:'run this on the weekend'});
* for (var i = 0; i < jobs.length; i++) {
* // true
* console.log(jobs[i].comment().match('run this on the weekend'));
* }
* });
*
* @param {String|RegEx} __pattern__
* @return {Boolean}
*/
this.match = function(pattern) {
if (_.isString(pattern) && !!~command.indexOf(pattern)) {
return true;
}
if (_.isRegExp(pattern)) {
return pattern.test(comment);
}
return false;
}
/**
* Renders the object to a string as it would be written to the system.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({comment:'run this on the weekend'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].comment().toString());
* }
* });
*
* @return {String}
*/
this.toString = function() {
return comment;
}
}
module.exports = CronComment;

385
src/node_modules/crontab/lib/CronJob.js generated vendored Normal file
View File

@ -0,0 +1,385 @@
/**
* Constants
*/
const ITEMREX = /^\s*([^@#\s]+)\s+([^@#\s]+)\s+([^@#\s]+)\s+([^@#\s]+)\s+([^@#\s]+)\s+([^#\n]*)(\s+#\s*([^\n]*)|$)/;
const SPECREX = /@(\w+)\s([^#\n]*)(\s+#\s*([^\n]*)|$)/;
const SPECIALS = {
'reboot' : '@reboot',
'hourly' : '0 * * * *',
'daily' : '0 0 * * *',
'weekly' : '0 0 * * 0',
'monthly' : '0 0 1 * *',
'yearly' : '0 0 1 1 *',
'annually' : '0 0 1 1 *',
'midnight' : '0 0 * * *'
};
const MONTH_ENUM = ['jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec'];
const WEEK_ENUM = ['sun','mon','tue','wed','thu','fri','sat','sun'];
const SINFO = [
{ 'name' : 'Minute', 'max' : 59, 'min' : 0 },
{ 'name' : 'Hours', 'max' : 23, 'min' : 0 },
{ 'name' : 'Day of Month', 'max' : 31, 'min' : 1 },
{ 'name' : 'Month', 'max' : 12, 'min' : 1, 'enumm' : MONTH_ENUM },
{ 'name' : 'Day of Week', 'max' : 7, 'min' : 0, 'enumm' : WEEK_ENUM },
];
/**
* Imports
*/
var TimeSlot = require('./TimeSlot');
var CronCommand = require('./CronCommand');
var CronComment = require('./CronComment');
/**
* @class CronJob
* A JavaScript representation of a cron job. Each job has exactly 5 time slots as per cron sytax:
* _minute_, _hour_, _day-of-the-month_, _month_, _day-of-the-week_.
*
* Examples:
* var job1 = new CronJob('* * * * * ls -l / #comment');
* var job2 = new CronJob(null, 'ls -l /', 'comment');
*
* @param {String|null} __line__
* @param {String} __[command]__
* @param {String} __[comment]__
*/
function CronJob(line, c, m) {
var self = this;
var command = null;
var comment = null;
var valid = false;
var slots = [];
var special = false;
/**
* Returns true if this cron job is valid.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].isValid());
* }
* });
*
* @return {Boolean}
*/
this.isValid = function() {
return valid;
}
/**
* Renders the object to a string as it would be written to the system.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].render());
* }
* });
*
* @return {String}
*/
this.render = function() {
var time = '';
if (special) {
time = special;
}
else {
var tokens = [];
for (var i = 0; i < 5; i++) {
tokens.push(slots[i].toString());
}
time = tokens.join(' ');
}
var keys = getKeys.call(SPECIALS);
var vals = getVals.call(SPECIALS);
var timeIdx = vals.indexOf(time);
if (timeIdx >=0 ) {
time = '@' + keys[timeIdx];
}
var result = time + ' ' + command.toString();
if (comment.toString() != '') {
result += ' #' + comment.toString();
}
return result;
}
/**
* Clears all time slots. Calling this method amounts to setting the time to '* * * * *'.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].clear());
* }
* });
*/
this.clear = function() {
special = false;
for (var i = 0; i < slots.length; i++) {
slots[i].clear();
}
}
/**
* Returns the minute time slot.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].minute().render());
* }
* });
*
* @return {TimeSlot}
*/
this.minute = function() {
return slots[0];
}
/**
* Returns the hour time slot.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].hour().render());
* }
* });
*
* @return {TimeSlot}
*/
this.hour = function() {
return slots[1];
}
/**
* Returns the day-of-the-month time slot.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].dom().render());
* }
* });
*
* @return {TimeSlot}
*/
this.dom = function() {
return slots[2];
}
/**
* Returns the month time slot.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].month().render());
* }
* });
*
* @return {TimeSlot}
*/
this.month = function() {
return slots[3];
}
/**
* Returns the day-of-the-week time slot.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].dow().render());
* }
* });
*
* @return {TimeSlot}
*/
this.dow = function() {
return slots[4];
}
/**
* Command getter/setter.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].command('new command'));
* }
* });
*
* @param {String} __[command]__
* @return {String}
*/
this.command = function(c) {
if (c) {
command = new CronCommand(c.toString());
}
return command.toString();
}
/**
* Comment getter/setter.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].comment('new comment'));
* }
* });
*
* @param {String} __[comment]__
* @return {String}
*/
this.comment = function(c) {
if (c) {
comment = new CronComment(c.toString());
}
return comment.toString();
}
/**
* Renders the object to a string as it would be written to the system. See __render__.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].toString());
* }
* });
*
* @return {String}
*/
this.toString = function() {
return this.render();
}
/**
* Populates the time slots with TimeSlot objects. Call this method ONLY from __init__!
*
* @param {Array[String]} __[tokens]__ string tokens to parse
*
* @api private
*/
function setSlots(tokens) {
slots = [];
for (var i = 0; i < 5; i++) {
var info = SINFO[i];
var value = (tokens && tokens[i] || null);
var name = info.name;
var min = info.min;
var max = info.max;
var enumm = info.enumm;
var slot = new TimeSlot(name, min, max, enumm, value);
slots.push(slot);
}
}
/**
* Initializes a new CronJob object.
*
* @api private
*/
function init() {
setSlots();
if (line) {
var result = line.match(ITEMREX);
if (result && result.length > 0) {
command = new CronCommand(result[6]);
comment = new CronComment(result[8] || '');
valid = true;
setSlots(result.slice(1,6));
}
else if (line.indexOf('@') < line.indexOf('#') || line.indexOf('#') == -1) {
var result = line.match(SPECREX);
if (result && result.length > 0 && SPECIALS[result[1]]) {
command = new CronCommand(result[2]);
comment = new CronComment(result[4] || '');
var value = SPECIALS[result[1]];
if (value.indexOf('@') >= 0) {
special = value;
}
else {
setSlots(value.split(' '));
}
valid = true;
}
}
}
else if (c) {
valid = true;
command = new CronCommand(c && c.toString() || '');
comment = new CronComment(m && m.toString() || '');
}
else {
throw new Error('Expected either a canonical crontab line or a command string');
}
}
init();
}
/* @api private */
function getKeys() {
return Object.keys(this);
}
function getVals() {
var keys = getKeys.call(this);
var vals = [];
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
vals.push(this[key]);
}
return vals;
}
module.exports = CronJob;

144
src/node_modules/crontab/lib/CronVar.js generated vendored Normal file
View File

@ -0,0 +1,144 @@
/**
* Constants
*/
const ITEMREX = /^(\S+)=(.+)$/;
/**
* @class CronVar
* A JavaScript representation of a cron environment variable.
*
* Examples:
* var env = new CronVar('MAIL=user@domain.org');
*
* @param {String} __line__
*/
function CronVar(line) {
var self = this;
var name = null;
var val = null;
var valid = false;
/**
* Returns true if this env variable is valid.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var vars = tab.vars({name:'MAIL'});
* for (var i = 0; i < vars.length; i++) {
* console.log(vars[i].isValid());
* }
* });
*
* @return {Boolean}
*/
this.isValid = function() {
return valid;
}
/**
* Renders the object to a string as it would be written to the system.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var vars = tab.vars({name:'MAIL'});
* for (var i = 0; i < vars.length; i++) {
* console.log(vars[i].render());
* }
* });
*
* @return {String}
*/
this.render = function() {
return name + '=' + val;
}
/**
* Comment getter/setter.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var vars = tab.vars({name:'MAIL'});
* for (var i = 0; i < vars.length; i++) {
* console.log(vars[i].name('PATH'));
* }
* });
*
* @param {String} __[name]__
* @return {String}
*/
this.name = function(c) {
if (c) {
name = ''+c;
}
return name;
}
/**
* Comment getter/setter.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var vars = tab.vars({name:'MAIL'});
* for (var i = 0; i < vars.length; i++) {
* console.log(vars[i].val('user@domain.org'));
* }
* });
*
* @param {String} __[val]__
* @return {String}
*/
this.val = function(c) {
if (c) {
val = ''+c;
}
return val;
}
/**
* Renders the object to a string as it would be written to the system. See __render__.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var vars = tab.vars({name:'MAIL'});
* for (var i = 0; i < vars.length; i++) {
* console.log(vars[i].toString());
* }
* });
*
* @return {String}
*/
this.toString = function() {
return this.render();
}
/**
* Initializes a new CronVar object.
*
* @api private
*/
function init() {
var tokens = (line||'').match(ITEMREX);
if (tokens && tokens.length > 0) {
name = tokens[1];
val = tokens[2];
valid = true;
}
else {
throw new Error('Expected an env variable declaration line');
}
}
init();
}
module.exports = CronVar;

156
src/node_modules/crontab/lib/TimeRange.js generated vendored Normal file
View File

@ -0,0 +1,156 @@
/**
* @class TimeRange
* A JavaScript representation of a time range. Each range has a _from_, _to_, and _step_ values.
*
* Examples:
* var enumm = ['jan','feb','mar','apr',
* 'may','jun','jul','aug',
* 'sep','oct','nov','dec'];
*
* var slot = new TimeSlot('Month', 1, 12, enumm);
* var range1 = new TimeRange(slot, '* / 2'); // every other month
* var range2 = new TimeRange(slot, 'jun - sep'); // every summer
*
* @param {TimeSlot} __slot__ The owner time slot object
* @param {String} __range__ The range string e.g. _* / 2_, _jun - sep_
*/
function TimeRange(s, range) {
var self = this;
var slot = s;
var from = null;
var to = null;
var step = 1;
/**
* Renders the object to a string as it would be written to the system.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].hour().between(9, 17).render());
* }
* });
*
* @return {String}
*/
this.render = function() {
var value = '*';
if (from > slot.getMin() || to < slot.getMax()) {
value = from + '-' + to;
}
if (step != 1) {
value += '/' + step;
}
return value;
}
/**
* Set the step value for this range.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* // every other business hour
* jobs[i].hour().between(9, 17).every(2);
* }
* });
*/
this.every = function(value) {
step = parseInt(value);
}
/**
* Renders the object to a string as it would be written to the system. See __render__.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].hour().between(9, 17).toString());
* }
* });
*
* @return {String}
*/
this.toString = function() {
return this.render();
}
/**
* Converts a string value representing a range limit to an integer.
*
* @param {String} __value__ e.g. _5_,_mon_,_jan_
* @return {Number}
*
* @api private
*/
function cleanValue(value) {
var sValue = String(value);
var lValue = sValue.toLowerCase();
var enummIdx = (slot.getEnum() || []).indexOf(lValue);
if (enummIdx >= 0) {
value = enummIdx;
}
var iValue = parseInt(value);
if (iValue >= slot.getMin() && iValue <= slot.getMax()) {
return iValue
}
return null;
}
/**
* Initializes a new TimeRange object.
*
* @api private
*/
function init() {
if (!range) {
range = '*';
}
if (range.indexOf('/') > 0) {
var tokens = range.split('/');
range = tokens[0];
step = tokens[1];
}
if (range.indexOf('-') > 0) {
var tokens = range.split('-');
from = cleanValue(tokens[0]);
to = cleanValue(tokens[1]);
if (from == null) {
throw new Error('Invalid range value ' + tokens[0]);
}
else if (to == null) {
throw new Error('Invalid range value ' + tokens[1]);
}
}
else if (range == '*') {
from = slot.getMin();
to = slot.getMax();
}
else {
throw new Error('Unknown time range value ' + range);
}
}
init();
}
module.exports = TimeRange;

282
src/node_modules/crontab/lib/TimeSlot.js generated vendored Normal file
View File

@ -0,0 +1,282 @@
/**
* Imports
*/
var TimeRange = require('./TimeRange');
/**
* @class TimeSlot
* A JavaScript representation of a time slot (e.g. minute, hour, month). Each slot has zero or
* more time ranges coresponding to the comma separated list in the cron sytax
* (e.g. _* / 4_, _10_, 5-15/2).
*
* Examples:
* var enumm = ['jan','feb','mar','apr',
* 'may','jun','jul','aug',
* 'sep','oct','nov','dec'];
*
* var slot1 = new TimeSlot('Month', 1, 12, enumm);
* var slot2 = new TimeSlot('Minute', 0, 59, null, '');
*
* @param {String} __name__ (e.g 'Minute', 'Month')
* @param {Number} __min__ minimum value
* @param {Number} __max__ maximum value
* @param {Object|null} __enumm__ an object enumerating all possible values
* @param {String|null} __value__ a value to parse (e.g '19-0/2,0-3')
*/
function TimeSlot(name, min, max, enumm, value) {
var self = this;
var name = name;
var min = min;
var max = max;
var enumm = enumm;
var parts = [];
/**
* Returns the minimum value for this time slot.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].month().getMin());
* }
* });
*
* @return {Number}
*/
this.getMin = function() {
return min;
}
/**
* Returns the maximum value for this time slot.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].month().getMax());
* }
* });
*
* @return {Number}
*/
this.getMax = function() {
return max;
}
/**
* Returns the allowed value enumeration for this time slot.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].month().getEnum());
* }
* });
*
* @return {Object}
*/
this.getEnum = function() {
return enumm;
}
/**
* Renders the object to a string as it would be written to the system.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].month().render());
* }
* });
*
* @return {Object}
*/
this.render = function() {
return parts.map(function(part) {
return part.toString();
}).join(',') || '*';
}
/**
* Set this time slot to repeat every n units e.g. _* / n_
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* // every other month
* jobs[i].month().every(2);
* }
* });
*
* @param {Number} __number__
* @return {TimeRange}
*/
this.every = function(n) {
try {
var range = new TimeRange(self, '*/' + parseInt(n));
parts.push(range);
return range;
}
catch (e) {}
return null;
}
/**
* Set this time slot to repeat exactly at the specified values e.g. _0,12_
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* // at midnight and noon
* jobs[i].hour().on(0, 12);
* jobs[i].minute().on(0);
* }
* });
*
* @param {Number} __value+__ one or more values
* @return {TimeRange}
*/
this.on = function() {
for (var i = 0; i < arguments.length; i++) {
parts.push(arguments[i]);
}
}
/**
* Set this time slot to repeat exactly at the specified values e.g. _0,12_
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* // at midnight and noon
* jobs[i].hour().on(0, 12);
* jobs[i].minute().on(0);
* }
* });
*
* @param {Number} __value+__ one or more values
* @return {TimeRange}
*/
this.at = this.on;
this.in = this.on;
/**
* Set this time slot to repeat between from and to e.g. _from - to_
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* // business hours
* jobs[i].hour().between(9, 17);
* }
* });
*
* @param {Number} __from__
* @param {Number} __to__
* @return {TimeRange}
*/
this.between = function(from, to) {
try {
var range = new TimeRange(self, from + '-' + to);
parts.push(range);
return range;
}
catch (e) {}
return null;
}
/**
* Clears this time slot. Calling this method amounts to setting the slot to '*'.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].month().clear());
* }
* });
*/
this.clear = function() {
parts = [];
}
/**
* Renders the object to a string as it would be written to the system. See __render__.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].month().toString());
* }
* });
*
* @return {String}
*/
this.toString = function() {
return this.render();
}
/**
* Initializes a new TimeSlot object.
*
* @api private
*/
function init() {
if (value) {
var tokens = value.split(',');
for (var i = 0; i < tokens.length; i++) {
var token = tokens[i];
if (token.indexOf('/') > 0 || token.indexOf('-') > 0 || token == '*') {
var range = new TimeRange(self, token);
parts.push(range);
}
else {
var lPart = token.toLowerCase();
var enummIdx = (enumm || []).indexOf(lPart);
if (enummIdx >= 0) {
token = enummIdx;
}
var iPart = parseInt(token);
if (iPart !== iPart) {
throw new Error('Unknown cron time part for ' + name + ': ' + token);
}
parts.push(iPart);
}
}
}
}
init();
}
module.exports = TimeSlot;

96
src/node_modules/crontab/lib/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,96 @@
// Type definitions for crontab
// Project: crontab
// Definitions by: Werner Robitza
declare namespace crontab {
type CrontabCallback = (error: Error | null, crontab: CronTab) => void;
function load(user: string, callback: CrontabCallback): void;
function load(callback: CrontabCallback): void;
class CronTab {
jobs(options?: {
command?: string | RegExp;
comment?: string | RegExp;
}): CronJob[];
find(options?: {
command?: string | RegExp;
comment?: string | RegExp;
}): CronJob[];
vars(
options: string | { name?: string | RegExp; val?: string | RegExp }
): CronVar[];
save(callback?: CrontabCallback): void;
render(): string;
create(
command: string,
when?: string | Date | null,
comment?: string | RegExp
): CronJob | null;
parse(line: string): CronJob;
remove(jobs: string[]): void;
remove(job: CronJob): void;
remove(options: {
command?: string | RegExp;
comment?: string | RegExp;
}): void;
reset(): void;
load(callback?: CrontabCallback): void;
}
class CronVar {
constructor(line: string);
isValid(): boolean;
render(): string;
name(): string;
val(): string;
toString(): string;
}
class CronJob {
constructor(
line: string | null,
command?: string | RegExp,
comment?: string | RegExp
);
isValid(): boolean;
render(): string;
clear(): void;
minute(): TimeSlot;
hour(): TimeSlot;
dom(): TimeSlot;
month(): TimeSlot;
dow(): TimeSlot;
command(c?: string): string;
comment(c?: string): string;
toString(): string;
}
class TimeSlot {
constructor(
name: string,
min: number,
max: number,
enumm?: object | null,
value?: string | null
);
getMin(): number;
getMax(): number;
getEnum(): object;
render(): string;
every(n: number): TimeRange;
on(...value: number[]): TimeRange;
between(from: number, to: number): TimeRange | null;
clear(): void;
toString(): string;
}
class TimeRange {
constructor(s: TimeSlot, range: string);
render(): string;
every(value: number): void;
toString(): string;
}
}
export = crontab;

574
src/node_modules/crontab/lib/index.js generated vendored Normal file
View File

@ -0,0 +1,574 @@
/**
* Constants
*/
const COMMAND = 'crontab';
/**
* @ignore
*/
var Spawn = require('child_process').spawn;
var _ = require('underscore');
var CronJob = require('./CronJob');
var CronVar = require('./CronVar');
/**
* @class CronTab
* A JavaScript representation of a user crontab. Each tab has zero or more cron jobs corresponding
* to the individual lines in the cron syntax.
*
* Examples:
* new CronTab('bob', function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* console.log("bob's tab: " + tab.render());
* });
*
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* console.log("current user's tab: " + tab.render());
* });
*
* @param {String} __username__
* @param {Function} __callback__
*/
function CronTab(u, cb) {
var self = this;
var user = u || '';
var root = (process.getuid() == 0);
var backup = {lines:[], jobs:[], vars:[]};
var lines = [];
var jobs = [];
var vars = [];
load(cb);
/**
* Provides access to the jobs collection.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /', comment:'this should run every night'});
* for (var i = 0; i < jobs.length; i++) {
* console.log(jobs[i].render());
* }
* });
*
* @param {Object} __[options]__
* @return {Array[CronJob]}
*/
this.jobs = function(options) {
if (!options) {
return jobs.slice();
}
if (!options.command && !options.comment) {
return jobs.slice();
}
var queries = _.keys(options);
if (_.without(queries, 'comment', 'command').length > 0) {
return [];
}
var results = [];
for (var i = 0; i < jobs.length; i++) {
var job = jobs[i];
var match = true;
for (var j = 0; j < queries.length; j++) {
var query = queries[j];
if (!job[query]().match(options[query])) {
match = false;
break;
}
}
if (match) {
results.push(job);
}
}
return results;
}
this.find = this.jobs;
/**
* Provides access to the vars collection.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var vars = tab.vars({key:'MAIL', val:'user@domain.org'});
* for (var i = 0; i < vars.length; i++) {
* console.log(vars[i].render());
* }
* });
*
* @param {Object|String} __[options]__
* @return {Array[CronVar]}
*/
this.vars = function(options) {
if (_.isString(options)) {
options = {name: options}
}
var results = [];
var queries = _.keys(options);
if (queries.length < 1) {
results = vars.slice();
}
else if (_.without(queries, 'name', 'val').length == 0) {
for (var i = 0; i < vars.length; i++) {
var env = vars[i];
var match = true;
for (var j = 0; j < queries.length; j++) {
var query = queries[j];
if (!env[query]().match(options[query])) {
match = false;
break;
}
}
if (match) {
results.push(env);
}
}
}
results.add = function(name, val) {
var pairs = {};
if (_.isString(name) && _.isString(val)) {
pairs[name] = val;
}
else if (_.isObject(name)) {
pairs = _.extend({}, name);
}
var insertIndex = _.findIndex(lines, function(val) {
return val instanceof CronJob;
});
if (insertIndex < 0) {
insertIndex = 0;
}
for (name in pairs) {
var val = pairs[name];
var env = new CronVar(name + '=' + val);
lines.splice(insertIndex++, 0, env);
vars.push(env);
}
}
results.rm = function() {
lines = _.difference(lines, results);
vars = _.difference(vars, results);
results.splice(0, results.length);
}
results.val = function(a) {
return results.length && results[0].val();
}
return results;
}
/**
* Writes the crontab to the system. Saves all information.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* tab.remove(jobs);
*
* tab.save(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* console.log('saved');
* });
* });
*
* @param {Function} __callback__
*/
this.save = function(cb) {
var stdout = '';
var stderr = '';
var args = makeChildArgs('save');
var command = makeChildCommand();
var child = Spawn(command, args);
child.stdout.setEncoding('utf8');
child.stderr.setEncoding('utf8');
child.stdout.on('data', function(chunk) {
stdout += chunk;
});
child.stderr.on('data', function(chunk) {
stderr += chunk;
});
child.on('error', function (err) {
});
child.on('close', function (code) {
if (code == 0) {
cb && cb(null, self);
}
else {
cb && cb(new Error(stderr), self);
}
});
child.stdin.write(this.render());
child.stdin.end();
}
/**
* Renders the object to a string as it would be written to the system.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* console.log(tab.render());
* });
*
* @return {String}
*/
this.render = function() {
var tokens = [];
for (var i = 0; i < lines.length; i++) {
var job = lines[i];
if (job.isValid && !job.isValid()) {
tokens.push('# ' + job.toString());
continue;
}
tokens.push(job.toString());
}
return tokens.join('\n').trim() + '\n';
}
/**
* Creates a new job with the specified command, comment and date.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var future = Date.parse('2010/7/11');
*
* tab.create('ls -l /');
* tab.create('ls -l /', 'just a silly example');
* tab.create('ls -l /', 'just a silly example', future);
* });
*
* @param {String} __command__
* @param {String|Date} __[when]__
* @param {String} __[comment]__
* @return {CronJob|null}
*/
this.create = function(command, when, comment) {
if (when && !_.isString(when) && !_.isDate(when)) {
return null;
}
command = (command || '').trim();
comment = (comment || '').trim();
var job = null;
if (_.isString(when)) {
job = makeJob(when + ' ' + command + ' #' + comment);
}
else {
job = makeJob(null, command, comment);
}
if (job && _.isDate(when)) {
job.minute().on(when.getMinutes());
job.hour().on(when.getHours());
job.dom().on(when.getDate());
job.month().on(when.getMonth()+1);
}
if (job) {
jobs.push(job);
lines.push(job);
}
return job;
}
/**
* Parses a raw crontab line and returns a CronJob object
*
* @param {String} __line__
* @return {CronJob|null}
*/
this.parse = function(line) {
return makeJob(line);
}
/**
* Removes the specified jobs from the crontab.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* tab.remove(jobs);
* });
*
* @param {String} __Array[CronJob]__
*/
this.remove = function(jobs) {
if (jobs instanceof CronJob) {
jobs = [jobs];
}
else if (_.isArray(jobs)) {
// do nothing, we do this because _.isObject([]) == true
}
else if (_.isObject(jobs)) {
// jobs is actually search options
jobs = this.jobs(jobs);
}
else {
jobs = [];
}
for (var i = 0; i < jobs.length; i++) {
remove(jobs[i]);
}
truncateLines();
}
/**
* Restores this crontab to its original state.
*
* Examples:
* new CronTab(function(err, tab) {
* if (err) { console.log(err); process.exit(1); }
*
* var jobs = tab.jobs({command:'ls -l /'});
* tab.remove(jobs);
* tab.reset();
* });
*/
this.reset = function() {
lines = backup.lines.slice();
jobs = backup.jobs.slice();
vars = backup.vars.slice();
}
/**
* Loads the system crontab into this object.
*
* @param {function} __callback__
*
* @api private
*/
function load(cb) {
var stdout = '';
var stderr = '';
var args = makeChildArgs('load');
var command = makeChildCommand();
var child = Spawn(command, args);
lines = [];
jobs = [];
vars = [];
child.stdout.setEncoding('utf8');
child.stderr.setEncoding('utf8');
child.stdout.on('data', function(chunk) {
stdout += chunk;
});
child.stderr.on('data', function(chunk) {
stderr += chunk;
});
child.on('error', function (err) {
});
child.on('close', function (code) {
if (code != 0 && stderr.indexOf('no crontab for ') < 0) {
cb && cb(new Error(stderr), null);
return;
}
var tokens = stdout.split('\n');
for (var i = 0; i < tokens.length; i++) {
var token = tokens[i];
var job = makeJob(token);
var env = makeVar(token);
if (job != null && job.isValid()) {
jobs.push(job);
lines.push(job);
}
else if (env != null && env.isValid()) {
vars.push(env);
lines.push(env);
}
else {
lines.push(token);
}
}
truncateLines();
backup.lines = lines.slice();
backup.jobs = jobs.slice();
backup.vars = vars.slice();
cb && cb(null, self);
});
}
/**
* Removes the specified job from the crontab.
*
* @param {CronJob} __job__
*
* @api private
*/
function remove(job) {
var oldJobs = jobs;
var oldLines = lines;
jobs = [];
lines = [];
for (var i = 0; i < oldJobs.length; i++) {
var oldJob = oldJobs[i];
if (oldJob != job) {
jobs.push(oldJob);
}
}
for (var i = 0; i < oldLines.length; i++) {
var oldLine = oldLines[i];
if (oldLine != job) {
lines.push(oldLine);
}
}
}
/**
* Creates an array of CL arguments for the system "crontab" command. Intended to be passed to
* child_process.spawn.
*
* @param {String} __action__ 'load' | 'save'
*
* @api private
*/
function makeChildArgs(action) {
var args = [];
if (user) {
args = args.concat('-u', user);
}
if (action == 'load') {
args.push('-l');
}
if (action == 'save' && process.platform !== 'sunos') {
args.push('-');
}
return args;
}
/**
* Creates a system command string to run crontab. Intended to be passed to
* child_process.spawn. If this is going to run for another user and the
* current user is not root, we prefix the command with sudo.
*
* @api private
*/
function makeChildCommand() {
var command = COMMAND;
if (user.length > 0 && root == false) {
command = 'sudo ' + command;
}
return command;
}
/**
* Creates a new job. This method exists to catch instantiation exceptions.
* @see CronJob
*
* @param {String|null} __line__
* @param {String} __[command]__
* @param {String} __[comment]__
*
* @api private
*/
function makeJob(line, command, comment) {
try {
var job = new CronJob(line, command, comment);
if (!job || !job.isValid()) {
throw new Error('invalid job');
}
return job;
} catch(e) {}
return null;
}
/**
* Creates a new job. This method exists to catch instantiation exceptions.
* @see CronJob
*
* @param {String} __line__
*
* @api private
*/
function makeVar(line) {
try {
var env = new CronVar(line);
if (!env || !env.isValid()) {
throw new Error('invalid env variable');
}
return env;
} catch(e) {}
return null;
}
/**
* Compacts the line collection by removes empty lines from the end.
*
* @api private
*/
function truncateLines() {
var undefined;
var line = lines.pop();
while (line != undefined && line.toString().trim() == '') {
line = lines.pop();
}
if (line != undefined) {
lines.push(line);
}
}
}
// public API
module.exports = {
load:function() {
if (_.isString(arguments[0]) && _.isFunction(arguments[1])) {
new CronTab(arguments[0], arguments[1]);
}
else if (_.isFunction(arguments[0])) {
new CronTab('', arguments[0]);
}
}
};

43
src/node_modules/crontab/package.json generated vendored Normal file
View File

@ -0,0 +1,43 @@
{
"name": "crontab",
"description": "A module for reading, creating, deleting, manipulating, and saving system cronjobs with node.js",
"keywords": [
"cron",
"crontab",
"schedule",
"system",
"run",
"process"
],
"version": "1.4.2",
"main": "./lib/index",
"dependencies": {
"underscore": "^1.6.0"
},
"devDependencies": {
"vows": "0.7.0"
},
"scripts": {
"test": "test/runner.js"
},
"engines": {
"node": ">= 0.10.0"
},
"author": {
"name": "Blagovest Dachev",
"email": "blago@dachev.com",
"url": "http://www.dachev.com"
},
"homepage": "https://github.com/dachev/node-crontab",
"repository": {
"type": "git",
"url": "git://github.com/dachev/node-crontab.git"
},
"licenses": [
{
"type": "GPL3",
"url": "http://opensource.org/licenses/MIT"
}
],
"types": "lib/index.d.ts"
}

822
src/node_modules/crontab/test/runner.js generated vendored Executable file
View File

@ -0,0 +1,822 @@
#!/usr/bin/env node
var events = require('events');
require('child_process').spawn = mockChild;
// Mock child_process
function mockChild(command, args) {
var undefined;
var action = (args.indexOf('-l') >= 0) ? 'load' : 'save';
var uRegEx = /-u\s([^\s]+)/;
var tokens = args.join(' ').match(uRegEx);
var user = tokens && tokens[1] || '';
function load(child) {
process.nextTick(function() {
// run for another user = user option will be first
if (user.length > 0 && args[0] != '-u') {
child.stderr.emit('data', 'crontab: if running for another user the -u option must come first');
child.emit('close', 1);
return;
}
// run for another user + not root = sudo
if (user.length > 0 && mockChild.user != 'root' && !!~command.indexOf('sudo') == false) {
child.stderr.emit('data', 'crontab: must be privileged to use -u');
child.emit('close', 1);
return;
}
// run for another user + root = no sudo
if (user.length > 0 && mockChild.user == 'root' && !!~command.indexOf('sudo') == true) {
child.stderr.emit('data', 'crontab: must not use sudo if already root and using -u');
child.emit('close', 1);
return;
}
var tabs = mockChild.tabs[user || mockChild.user];
if (tabs == undefined && user != '') {
child.stderr.emit('data', 'crontab: user ' + user + ' unknown');
child.emit('close', 1);
return;
}
if (tabs == null) {
child.stderr.emit('data', 'crontab: no crontab for ...');
child.emit('close', 1);
return;
}
child.stdout.emit('data', tabs.join('\n'));
child.emit('close', 0);
});
}
function save(child, newTabs) {
process.nextTick(function() {
// run for another user = user option will be first
if (user.length > 0 && args[0] != '-u') {
child.stderr.emit('data', 'crontab: if running for another user the -u option must come first');
child.emit('close', 1);
return;
}
// run for another user + not root = sudo
if (user.length > 0 && mockChild.user != 'root' && !!~command.indexOf('sudo') == false) {
child.stderr.emit('data', 'crontab: must be privileged to use -u');
child.emit('close', 1);
return;
}
// run for another user + root = no sudo
if (user.length > 0 && mockChild.user == 'root' && !!~command.indexOf('sudo') == true) {
child.stderr.emit('data', 'crontab: must not use sudo if already root and using -u');
child.emit('close', 1);
return;
}
// save + sunos = no "-"" argument
if (!!~args.indexOf('-') && process.platform == 'sunos') {
child.stderr.emit('data', 'crontab: sunos\' flavor of crontab does not recognize -');
child.emit('close', 1);
return;
}
mockChild.tabs[user || mockChild.user] = newTabs.split('\n');
child.emit('close', 0);
});
}
var child = new events.EventEmitter;
child.stdout = new events.EventEmitter;
child.stderr = new events.EventEmitter;
child.stdin = {
buffer : '',
write : function(tabs) { this.buffer = tabs; },
end : function(tabs) { save(child, this.buffer); }
}
child.stdout.setEncoding =function(){};
child.stderr.setEncoding =function(){};
if (action == 'load') {
load(child);
}
return child;
}
mockChild.user = 'blago';
mockChild.tabs = {
empty : [],
reset : [],
alice : ['0 8-17 * * 1-5 /usr/bin/env echo "check email"',
'* 19-0,0-3 * * 1-5 /usr/bin/env echo "hack node.js"',
'30 11 * * 6-0 /usr/bin/env echo "wake up"',
'* * * 5-8 * /usr/bin/env echo "go to Bulgaria"',
'30 9 24 12 * /usr/bin/env echo "get presents"'],
bob : ['0 8-17 * * 1-5 /usr/bin/env echo "check email"',
'* 19-0,0-3 * * 1-5 /usr/bin/env echo "hack node.js"',
'30 11 * * 6-0 /usr/bin/env echo "wake up"'],
blago : null,
root : [],
remove : ['0 7 * * 1,2,3,4,5 ls -la # every weekday @7',
'0 8 * * 1,2,3,4,5 ls -lh # every weekday @8',
'0 9 * * 1,2,3,4,5 ls -lt # every weekday @9'],
special : ['@reboot /usr/bin/env echo "starting service (reboot)" #reboot',
'@hourly /usr/bin/env echo "starting service (hourly)"',
'@daily /usr/bin/env echo "starting service (daily)"',
'@weekly /usr/bin/env echo "starting service (weekly)"',
'@monthly /usr/bin/env echo "starting service (monthly)"',
'@yearly /usr/bin/env echo "starting service (yearly)"',
'@annually /usr/bin/env echo "starting service (annually)"',
'@midnight /usr/bin/env echo "starting service (midnight)"'],
comments: ['0 8-17 * * 1-5 /usr/bin/env echo "check email" #every business hour'],
commands: ['0 8-17 * * 1-5 /usr/bin/env echo "check email" #every business hour'],
env: ['FOO=bar',
'BAZ=1',
'* * * * * /usr/bin/true']
};
// Test helpers
function loadTabs(user) {
var promise = new(events.EventEmitter);
CronTab.load(user, function(err, tab) {
if (err) { promise.emit('error', err); }
else { promise.emit('success', tab); }
});
return promise;
}
function saveTabs(tab) {
var promise = new(events.EventEmitter);
tab.save(function(err, tab) {
if (err) { promise.emit('error', err); }
else { promise.emit('success', tab); }
});
return promise;
}
function makeTabArrayFromTopicStack() {
var tab1 = arguments[0];
var tab2 = arguments[2];
return [tab1, tab2];
}
// Test batches
var nonRootLoadsAnotherUserCrons = {
'non-root user loads another user\'s crons': {
topic: function() {
mockChild.user = 'blago';
return loadTabs('bob');
},
'should succeed loading because we use sudo':function(err, tab) {
nonRootLoadsAnotherUserCrons.tab = tab;
Assert.isNull(err);
Assert.isObject(tab);
Assert.isArray(tab.jobs());
Assert.equal(tab.jobs().length, 3);
}
}
};
var rootLoadsAnotherUserCrons = {
'root user loads another (existing) user\'s crons': {
topic: function() {
mockChild.user = 'root';
var originalGetuid = process.getuid;
process.getuid = function() {
return 0;
}
var tabs = loadTabs('bob');
process.getuid = originalGetuid;
return tabs;
},
'should succeed loading':function(err, tab) {
rootLoadsAnotherUserCrons.tab = tab;
Assert.isNull(err);
Assert.isObject(tab);
Assert.isArray(tab.jobs());
Assert.equal(tab.jobs().length, 3);
}
}
};
var rootLoadsAnotherNonExistingUserCrons = {
'root user loads another (non-existing) user\'s crons': {
topic: function() {
mockChild.user = 'root';
var originalGetuid = process.getuid;
process.getuid = function() {
return 0;
}
var tabs = loadTabs('tom');
process.getuid = originalGetuid;
return tabs;
},
'should fail loading':function(err, tab) {
Assert.isObject(err);
Assert.isString(err.message);
Assert.matches(err.message, /unknown/);
}
}
};
var userLoadsHisOwnEmptyCrons = {
'user loads his own (empty) crons': {
topic: function() {
mockChild.user = 'blago';
return loadTabs('');
},
'should succeed loading':function(err, tab) {
userLoadsHisOwnEmptyCrons.tab = tab;
Assert.isNull(err);
Assert.isObject(tab);
Assert.isArray(tab.jobs());
Assert.equal(tab.jobs().length, 0);
}
}
};
var userLoadsHerOwnNonEmptyCrons = {
'user loads her own (non-empty) crons': {
topic: function() {
mockChild.user = 'alice';
return loadTabs('');
},
'should succeed loading':function(err, tab) {
userLoadsHerOwnNonEmptyCrons.tab = tab;
Assert.isNull(err);
Assert.isObject(tab);
Assert.isArray(tab.jobs());
Assert.equal(tab.jobs().length, 5);
}
}
};
var userSavesHerOwnNonEmptyCrons = {
'user saves her own (non-empty) crons': {
topic: function() {
return saveTabs(userLoadsHerOwnNonEmptyCrons.tab);
},
'should succeed saving':function(err, tab) {
Assert.isNull(err);
Assert.isObject(tab);
}
}
};
var userLoadsHerOwnNonEmptyCronsAgain = {
'user loads her own (non-empty) crons again': {
topic: function() {
mockChild.user = 'alice';
return loadTabs('');
},
'should succeed loading':function(err, tab) {
userLoadsHerOwnNonEmptyCronsAgain.tab = tab;
Assert.isNull(err);
Assert.isObject(tab);
Assert.isArray(tab.jobs());
Assert.equal(tab.jobs().length, 5);
},
'are the same':function(err, tab) {
Assert.equal(tab.render().trim(), mockChild.tabs.alice.join('\n').trim());
}
}
};
var canLoadEnvironment = {
'can load environment variables' : {
topic: function() {
mockChild.user = 'env';
return loadTabs('');
},
'should load environment variables':function(err, tab) {
Assert.isArray(tab.vars());
Assert.equal(tab.vars().length, 2);
Assert.equal(tab.vars('FOO').length, 1);
Assert.equal(tab.vars('BAZ').length, 1);
Assert.equal(tab.vars('FOO').val(), 'bar');
Assert.equal(tab.vars('BAZ').val(), '1');
}
}
};
var canQueryEnvironment = {
'can query environment variables' : {
topic: function() {
mockChild.user = 'env';
return loadTabs('');
},
'should succeed with a key argument':function(err, tab) {
Assert.isArray(tab.vars('FOO'));
Assert.equal(tab.vars('FOO').length, 1);
Assert.equal(tab.vars('FOO').val(), 'bar');
},
'should succeed with an object argument':function(err, tab) {
Assert.isArray(tab.vars({name:'FOO'}));
Assert.equal(tab.vars({name:'FOO'}).length, 1);
Assert.equal(tab.vars({name:'FOO'}).val(), 'bar');
Assert.equal(tab.vars({name:'FOO', val: 'bar'}).length, 1);
},
'should succeed with no arguments':function(err, tab) {
Assert.isArray(tab.vars());
Assert.equal(tab.vars().length, 2);
}
}
}
var canCreateEnvironment = {
'can create environment variables' : {
topic: function() {
mockChild.user = 'empty';
return loadTabs('');
},
'should succeed with a pair of arguments':function(err, tab) {
Assert.equal(tab.vars().length, 0);
tab.vars().add('FOO', 'foo');
tab.vars().add('BAR', '1');
Assert.equal(tab.vars().length, 2);
Assert.equal(tab.vars({name:'FOO'}).length, 1);
Assert.equal(tab.vars({name:'BAR'}).length, 1);
Assert.equal(tab.vars({name:'FOO'}).val(), 'foo');
Assert.equal(tab.vars({name:'BAR'}).val(), '1');
tab.vars().rm();
},
'should succeed with an object argument':function(err, tab) {
Assert.equal(tab.vars().length, 0);
tab.vars().add({'FOO':'foo', 'BAR':'1'});
Assert.equal(tab.vars().length, 2);
Assert.equal(tab.vars({name:'FOO'}).length, 1);
Assert.equal(tab.vars({name:'BAR'}).length, 1);
Assert.equal(tab.vars({name:'FOO'}).val(), 'foo');
Assert.equal(tab.vars({name:'BAR'}).val(), '1');
tab.vars().rm();
}
}
}
var canRemoveEnvironment = {
'can remove environment variables' : {
topic: function() {
mockChild.user = 'empty';
return loadTabs('');
},
'should succeed':function(err, tab) {
Assert.equal(tab.vars().length, 0);
tab.vars().add({'FOO':'foo', 'BAR':'1'});
Assert.equal(tab.vars().length, 2);
tab.vars({name: 'FOO'}).rm();
Assert.equal(tab.vars().length, 1);
tab.vars().rm();
Assert.equal(tab.vars().length, 0);
}
}
}
var canCreateJob = {
'can create job': {
topic: function() {
mockChild.user = 'empty';
return loadTabs('');
},
'should return null with invalid cron syntax':function(err, tab) {
Assert.equal(tab.create('<command to execute', '<when to execute', '<comment>'), null);
Assert.equal(tab.create('ls -l', ''), null);
Assert.equal(tab.create(), null);
Assert.equal(tab.create(null), null);
Assert.equal(tab.create(null, null, null), null);
},
'should succeed with string expression and comment':function(err, tab) {
var job = tab.create('ls -l', '0 7 * * 1,2,3,4,5', 'test');
Assert.isTrue(job.isValid());
Assert.equal(job.minute().toString(), '0');
Assert.equal(job.hour().toString(), '7');
Assert.equal(job.dom().toString(), '*');
Assert.equal(job.month().toString(), '*');
Assert.equal(job.dow().toString(), '1,2,3,4,5');
Assert.equal(job.command(), 'ls -l');
Assert.equal(job.comment(), 'test');
},
'should succeed with date and comment':function(err, tab) {
var date = new Date(1400373907766);
var job = tab.create('ls -l', date, 'test');
Assert.isTrue(job.isValid());
Assert.equal(job.minute(), date.getMinutes());
Assert.equal(job.hour(), date.getHours());
Assert.equal(job.dom(), date.getDate());
Assert.equal(job.month(), date.getMonth()+1);
Assert.equal(job.dow().toString(), '*');
Assert.equal(job.command(), 'ls -l');
Assert.equal(job.comment(), 'test');
},
'should succeed with date and no comment':function(err, tab) {
var date = new Date(1400373907766);
var job = tab.create('ls -l', date);
Assert.isTrue(job.isValid());
Assert.equal(job.minute(), date.getMinutes());
Assert.equal(job.hour(), date.getHours());
Assert.equal(job.dom(), date.getDate());
Assert.equal(job.month(), date.getMonth()+1);
Assert.equal(job.dow().toString(), '*');
Assert.equal(job.command(), 'ls -l');
Assert.equal(job.comment(), '');
},
'should succeed with no date and comment':function(err, tab) {
var job = tab.create('ls -l', null, 'test');
Assert.isTrue(job.isValid());
Assert.equal(job.minute().toString(), '*');
Assert.equal(job.hour().toString(), '*');
Assert.equal(job.dom().toString(), '*');
Assert.equal(job.month().toString(), '*');
Assert.equal(job.dow().toString(), '*');
Assert.equal(job.command(), 'ls -l');
Assert.equal(job.comment(), 'test');
},
'should succeed with no date and no comment':function(err, tab) {
var job = tab.create('ls -l', null, null);
Assert.isTrue(job.isValid());
Assert.equal(job.minute().toString(), '*');
Assert.equal(job.hour().toString(), '*');
Assert.equal(job.dom().toString(), '*');
Assert.equal(job.month().toString(), '*');
Assert.equal(job.dow().toString(), '*');
Assert.equal(job.command(), 'ls -l');
Assert.equal(job.comment(), '');
}
}
};
var canRemoveJob = {
'can remove job': {
topic: function() {
mockChild.user = 'remove';
return loadTabs('');
},
'should succeed with job object':function(err, tab) {
var count = tab.jobs().length;
var job = tab.jobs({command:'ls -la'})[0];
tab.remove(job);
Assert.equal(tab.jobs().length, count-1);
},
'should succeed with command query':function(err, tab) {
var count = tab.jobs().length;
tab.remove({command:'ls -lh'});
Assert.equal(tab.jobs().length, count-1);
},
'should succeed with comment query':function(err, tab) {
var count = tab.jobs().length;
tab.remove({comment:'every weekday @9'});
Assert.equal(tab.jobs().length, count-1);
}
}
};
var canParseRawLine = {
'can parse raw line': {
topic: function() {
mockChild.user = 'special';
return loadTabs('');
},
'should succeed parsing raw line':function(err, tab) {
var job = tab.parse('0 7 * * 1,2,3,4,5 ls -l #test');
Assert.isTrue(job.isValid());
Assert.equal(job.minute().toString(), '0');
Assert.equal(job.hour().toString(), '7');
Assert.equal(job.dom().toString(), '*');
Assert.equal(job.month().toString(), '*');
Assert.equal(job.dow().toString(), '1,2,3,4,5');
Assert.equal(job.command(), 'ls -l');
Assert.equal(job.comment(), 'test');
}
}
}
var canParseSpecialSyntax = {
'can parse special cron syntax': {
topic: function() {
mockChild.user = 'special';
return loadTabs('');
},
'should succeed loading':function(err, tab) {
Assert.isNull(err);
Assert.isObject(tab);
Assert.isArray(tab.jobs());
Assert.equal(tab.jobs().length, 8);
},
'@reboot':function(err, tab) {
var jobs = tab.jobs({command:'reboot'});
var job = jobs[0];
Assert.isArray(jobs);
Assert.equal(jobs.length, 1);
Assert.isTrue(job.isValid());
Assert.equal(job.comment(), 'reboot');
},
'@hourly':function(tab) {
var jobs = tab.jobs({command:'hourly'});
var job = jobs[0];
Assert.isArray(jobs);
Assert.equal(jobs.length, 1);
Assert.isTrue(job.isValid());
Assert.equal(job.minute().toString(), '0');
Assert.equal(job.hour().toString(), '*');
Assert.equal(job.dom().toString(), '*');
Assert.equal(job.month().toString(), '*');
Assert.equal(job.dow().toString(), '*');
},
'@daily':function(tab) {
var jobs = tab.jobs({command:'daily'});
var job = jobs[0];
Assert.isArray(jobs);
Assert.equal(jobs.length, 1);
Assert.isTrue(job.isValid());
Assert.equal(job.minute().toString(), '0');
Assert.equal(job.hour().toString(), '0');
Assert.equal(job.dom().toString(), '*');
Assert.equal(job.month().toString(), '*');
Assert.equal(job.dow().toString(), '*');
},
'@weekly':function(tab) {
var jobs = tab.jobs({command:'weekly'});
var job = jobs[0];
Assert.isArray(jobs);
Assert.equal(jobs.length, 1);
Assert.isTrue(job.isValid());
Assert.equal(job.minute().toString(), '0');
Assert.equal(job.hour().toString(), '0');
Assert.equal(job.dom().toString(), '*');
Assert.equal(job.month().toString(), '*');
Assert.equal(job.dow().toString(), '0');
},
'@monthly':function(tab) {
var jobs = tab.jobs({command:'monthly'});
var job = jobs[0];
Assert.isArray(jobs);
Assert.equal(jobs.length, 1);
Assert.isTrue(job.isValid());
Assert.equal(job.minute().toString(), '0');
Assert.equal(job.hour().toString(), '0');
Assert.equal(job.dom().toString(), '1');
Assert.equal(job.month().toString(), '*');
Assert.equal(job.dow().toString(), '*');
},
'@yearly':function(tab) {
var jobs = tab.jobs({command:'yearly'});
var job = jobs[0];
Assert.isArray(jobs);
Assert.equal(jobs.length, 1);
Assert.isTrue(job.isValid());
Assert.equal(job.minute().toString(), '0');
Assert.equal(job.hour().toString(), '0');
Assert.equal(job.dom().toString(), '1');
Assert.equal(job.month().toString(), '1');
Assert.equal(job.dow().toString(), '*');
},
'@annually':function(tab) {
var jobs = tab.jobs({command:'yearly'});
var job = jobs[0];
Assert.isArray(jobs);
Assert.equal(jobs.length, 1);
Assert.isTrue(job.isValid());
Assert.equal(job.minute().toString(), '0');
Assert.equal(job.hour().toString(), '0');
Assert.equal(job.dom().toString(), '1');
Assert.equal(job.month().toString(), '1');
Assert.equal(job.dow().toString(), '*');
},
'@midnight':function(tab) {
var jobs = tab.jobs({command:'midnight'});
var job = jobs[0];
Assert.isArray(jobs);
Assert.equal(jobs.length, 1);
Assert.isTrue(job.isValid());
Assert.equal(job.minute().toString(), '0');
Assert.equal(job.hour().toString(), '0');
Assert.equal(job.dom().toString(), '*');
Assert.equal(job.month().toString(), '*');
Assert.equal(job.dow().toString(), '*');
}
}
};
var canParseCommands = {
'can parse commands' : {
topic: function() {
mockChild.user = 'commands';
return loadTabs('');
},
'should succeed loading':function(err, tab) {
Assert.isNull(err);
Assert.isObject(tab);
Assert.isArray(tab.jobs());
Assert.equal(tab.jobs().length, 1);
},
'command should match':function(err, tab) {
var job = tab.jobs()[0];
Assert.equal(job.command(), '/usr/bin/env echo "check email"');
}
}
}
var canParseInlineComments = {
'can parse inline comments' : {
topic: function() {
mockChild.user = 'comments';
return loadTabs('');
},
'should succeed loading':function(err, tab) {
Assert.isNull(err);
Assert.isObject(tab);
Assert.isArray(tab.jobs());
Assert.equal(tab.jobs().length, 1);
},
'comment should match':function(err, tab) {
var job = tab.jobs()[0];
Assert.equal(job.comment(), 'every business hour');
}
}
};
var canFindJobsByCommand = {
'can find jobs by command' : {
topic: function() {
mockChild.user = 'commands';
return loadTabs('');
},
'should succeed loading':function(err, tab) {
Assert.isNull(err);
Assert.isObject(tab);
Assert.isArray(tab.jobs());
Assert.equal(tab.jobs().length, 1);
},
'should find jobs by substring':function(err, tab) {
var jobs = tab.jobs({command:'/usr/bin/env echo'});
Assert.isArray(jobs);
Assert.equal(jobs.length, 1);
},
'should find jobs by regular expression':function(err, tab) {
var jobs = tab.jobs({command:/echo/});
Assert.isArray(jobs);
Assert.equal(jobs.length, 1);
}
}
};
var canFindJobsByComment = {
'can find jobs by comment' : {
topic: function() {
mockChild.user = 'comments';
return loadTabs('');
},
'should succeed loading':function(err, tab) {
Assert.isNull(err);
Assert.isObject(tab);
Assert.isArray(tab.jobs());
Assert.equal(tab.jobs().length, 1);
},
'should find jobs by substring':function(err, tab) {
var jobs = tab.jobs({comment:'every business hour'});
Assert.isArray(jobs);
Assert.equal(jobs.length, 1);
},
'should find jobs by regular expression':function(err, tab) {
var jobs = tab.jobs({comment:/business/});
Assert.isArray(jobs);
Assert.equal(jobs.length, 1);
}
}
};
var canSaveCreatedJobs = {
'can save jobs' : {
topic: function() {
mockChild.user = 'comments';
return loadTabs('');
},
'should succeed loading':function(err, tab) {
var jobs = tab.jobs();
Assert.equal(jobs.length, 1);
},
'after a successful load': {
topic: function(tab) {
tab.create('ls -l', '0 7 * * 1,2,3,4,5', 'test');
return saveTabs(tab);
},
'should succeed saving':function(err, tab) {
var jobs = tab.jobs();
Assert.equal(jobs.length, 2);
}
}
}
};
var canResetJobs = {
'can reset jobs' : {
topic: function() {
mockChild.user = 'reset';
return loadTabs('');
},
'should succeed reseting':function(err, tab) {
Assert.equal(tab.jobs().length, 0);
tab.create('ls -l', '0 7 * * 1,2,3,4,5', 'test 1');
tab.create('ls -l', '0 7 * * 1,2,3,4,5', 'test 2');
tab.create('ls -l', '0 7 * * 1,2,3,4,5', 'test 3');
Assert.equal(tab.jobs().length, 3);
Assert.equal(tab.vars().length, 0);
tab.vars().add('FOO', 'foo');
tab.vars().add('BAR', '1');
Assert.equal(tab.vars().length, 2);
tab.reset();
Assert.equal(tab.jobs().length, 0);
Assert.equal(tab.vars().length, 0);
}
}
};
var willWorkOnManyPlatforms = {
'can save in sunos' : {
topic: function() {
process.originalPlatform = process.platform;
process.platform = 'sunos';
return saveTabs(userLoadsHerOwnNonEmptyCrons.tab);
},
'should succeed saving in sunos':function(err, tab) {
process.platform = process.originalPlatform;
Assert.isNull(err);
Assert.isObject(tab);
Assert.isArray(tab.jobs());
}
}
};
var willFailWithError = {
'Failures should throw Error objects' : {
topic: function() {
mockChild.user = 'blago';
// since user Tom does not exist this should trigger a failure
return loadTabs('tom');
},
'load will fail with Error': function(err, tab) {
Assert.isNotNull(err);
Assert.isTrue(err instanceof Error);
}
}
};
var Vows = require('vows');
var Assert = require('assert');
var CronTab = require('../lib/index');
Vows.describe('crontab').
addBatch(nonRootLoadsAnotherUserCrons).
addBatch(rootLoadsAnotherUserCrons).
addBatch(rootLoadsAnotherNonExistingUserCrons).
addBatch(userLoadsHisOwnEmptyCrons).
addBatch(userLoadsHerOwnNonEmptyCrons).
addBatch(userSavesHerOwnNonEmptyCrons).
addBatch(userLoadsHerOwnNonEmptyCronsAgain).
addBatch(canLoadEnvironment).
addBatch(canQueryEnvironment).
addBatch(canCreateEnvironment).
addBatch(canRemoveEnvironment).
addBatch(canCreateJob).
addBatch(canRemoveJob).
addBatch(canParseRawLine).
addBatch(canParseSpecialSyntax).
addBatch(canParseCommands).
addBatch(canParseInlineComments).
addBatch(canFindJobsByCommand).
addBatch(canFindJobsByComment).
addBatch(canSaveCreatedJobs).
addBatch(canResetJobs).
addBatch(willWorkOnManyPlatforms).
addBatch(willFailWithError).
export(module);

21
src/node_modules/readline-sync/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 anseki
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.

89
src/node_modules/readline-sync/README-Deprecated.md generated vendored Normal file
View File

@ -0,0 +1,89 @@
# readlineSync
## <a name="deprecated_methods_and_options"></a>Deprecated Methods and Options
The readlineSync current version is fully compatible with older version.
The following methods and options are deprecated.
### <a name="deprecated_methods_and_options-setprint_method"></a>`setPrint` method
Use the [`print`](README.md#basic_options-print) option.
For the [Default Options](README.md#basic_options), use:
```js
readlineSync.setDefaultOptions({print: value});
```
instead of:
```js
readlineSync.setPrint(value);
```
### <a name="deprecated_methods_and_options-setprompt_method"></a>`setPrompt` method
Use the [`prompt`](README.md#basic_options-prompt) option.
For the [Default Options](README.md#basic_options), use:
```js
readlineSync.setDefaultOptions({prompt: value});
```
instead of:
```js
readlineSync.setPrompt(value);
```
### <a name="deprecated_methods_and_options-setencoding_method"></a>`setEncoding` method
Use the [`encoding`](README.md#basic_options-encoding) option.
For the [Default Options](README.md#basic_options), use:
```js
readlineSync.setDefaultOptions({encoding: value});
```
instead of:
```js
readlineSync.setEncoding(value);
```
### <a name="deprecated_methods_and_options-setmask_method"></a>`setMask` method
Use the [`mask`](README.md#basic_options-mask) option.
For the [Default Options](README.md#basic_options), use:
```js
readlineSync.setDefaultOptions({mask: value});
```
instead of:
```js
readlineSync.setMask(value);
```
### <a name="deprecated_methods_and_options-setbuffersize_method"></a>`setBufferSize` method
Use the [`bufferSize`](README.md#basic_options-buffersize) option.
For the [Default Options](README.md#basic_options), use:
```js
readlineSync.setDefaultOptions({bufferSize: value});
```
instead of:
```js
readlineSync.setBufferSize(value);
```
### <a name="deprecated_methods_and_options-noechoback_option"></a>`noEchoBack` option
Use [`hideEchoBack`](README.md#basic_options-hideechoback) option instead of it.
### <a name="deprecated_methods_and_options-notrim_option"></a>`noTrim` option
Use [`keepWhitespace`](README.md#basic_options-keepwhitespace) option instead of it.

1836
src/node_modules/readline-sync/README.md generated vendored Normal file

File diff suppressed because it is too large Load Diff

24
src/node_modules/readline-sync/lib/encrypt.js generated vendored Normal file
View File

@ -0,0 +1,24 @@
/*
* readlineSync
* https://github.com/anseki/readline-sync
*
* Copyright (c) 2019 anseki
* Licensed under the MIT license.
*/
var cipher = require('crypto').createCipher(
process.argv[2] /*algorithm*/, process.argv[3] /*password*/),
stdin = process.stdin,
stdout = process.stdout,
crypted = '';
stdin.resume();
stdin.setEncoding('utf8');
stdin.on('data', function(d) {
crypted += cipher.update(d, 'utf8', 'hex');
});
stdin.on('end', function() {
stdout.write(crypted + cipher.final('hex'), 'binary', function() {
process.exit(0);
});
});

123
src/node_modules/readline-sync/lib/read.cs.js generated vendored Normal file
View File

@ -0,0 +1,123 @@
/* jshint wsh:true */
/*
* readlineSync
* https://github.com/anseki/readline-sync
*
* Copyright (c) 2019 anseki
* Licensed under the MIT license.
*/
var
FSO_ForReading = 1, FSO_ForWriting = 2,
PS_MSG = 'Microsoft Windows PowerShell is required.' +
' https://technet.microsoft.com/en-us/library/hh847837.aspx',
input = '', fso, tty,
options = (function(conf) {
var options = {}, arg, args =// Array.prototype.slice.call(WScript.Arguments),
(function() {
var args = [], i, iLen;
for (i = 0, iLen = WScript.Arguments.length; i < iLen; i++)
{ args.push(WScript.Arguments(i)); }
return args;
})(),
confLc = {}, key;
function decodeArg(arg) {
return arg.replace(/#(\d+);/g, function(str, charCode) {
return String.fromCharCode(+charCode);
});
}
for (key in conf) {
if (conf.hasOwnProperty(key))
{ confLc[key.toLowerCase()] = {key: key, type: conf[key]}; }
}
while (typeof(arg = args.shift()) === 'string') {
if (!(arg = (arg.match(/^\-+(.+)$/) || [])[1])) { continue; }
arg = arg.toLowerCase();
if (confLc[arg]) {
options[confLc[arg].key] =
confLc[arg].type === 'boolean' ? true :
confLc[arg].type === 'string' ? args.shift() : null;
}
}
for (key in conf) {
if (conf.hasOwnProperty(key) && conf[key] === 'string') {
if (typeof options[key] !== 'string') { options[key] = ''; }
else { options[key] = decodeArg(options[key]); }
}
}
return options;
})({
display: 'string',
displayOnly: 'boolean',
keyIn: 'boolean',
hideEchoBack: 'boolean',
mask: 'string'
});
if (!options.hideEchoBack && !options.keyIn) {
if (options.display) { writeTTY(options.display); }
if (!options.displayOnly) { input = readByFSO(); }
} else if (options.hideEchoBack && !options.keyIn && !options.mask) {
if (options.display) { writeTTY(options.display); }
if (!options.displayOnly) { input = readByPW(); }
} else {
WScript.StdErr.WriteLine(PS_MSG);
WScript.Quit(1);
}
WScript.StdOut.Write('\'' + input + '\'');
WScript.Quit();
function writeTTY(text) {
try {
tty = tty || getFso().OpenTextFile('CONOUT$', FSO_ForWriting, true);
tty.Write(text);
} catch (e) {
WScript.StdErr.WriteLine('TTY Write Error: ' + e.number +
'\n' + e.description + '\n' + PS_MSG);
WScript.Quit(e.number || 1);
}
}
function readByFSO() {
var text;
try {
text = getFso().OpenTextFile('CONIN$', FSO_ForReading).ReadLine();
} catch (e) {
WScript.StdErr.WriteLine('TTY Read Error: ' + e.number +
'\n' + e.description + '\n' + PS_MSG);
WScript.Quit(e.number || 1);
}
return text;
}
// TTY must be STDIN that is not redirected and not piped.
function readByPW() {
var text;
try {
text = WScript.CreateObject('ScriptPW.Password').GetPassword()
// Bug? Illegal data may be returned when user types before initializing.
.replace(/[\u4000-\u40FF]/g, function(chr) {
var charCode = chr.charCodeAt(0);
return charCode >= 0x4020 && charCode <= 0x407F ?
String.fromCharCode(charCode - 0x4000) : '';
});
} catch (e) {
WScript.StdErr.WriteLine('ScriptPW.Password Error: ' + e.number +
'\n' + e.description + '\n' + PS_MSG);
WScript.Quit(e.number || 1);
}
writeTTY('\n');
return text;
}
function getFso() {
if (!fso) { fso = new ActiveXObject('Scripting.FileSystemObject'); }
return fso;
}

128
src/node_modules/readline-sync/lib/read.ps1 generated vendored Normal file
View File

@ -0,0 +1,128 @@
# readlineSync
# https://github.com/anseki/readline-sync
#
# Copyright (c) 2019 anseki
# Licensed under the MIT license.
Param(
[string] $display,
[switch] $displayOnly,
[switch] $keyIn,
[switch] $hideEchoBack,
[string] $mask,
[string] $limit,
[switch] $caseSensitive
)
$ErrorActionPreference = 'Stop' # for cmdlet
trap {
# `throw $_` and `Write-Error $_` return exit-code 0
$Host.UI.WriteErrorLine($_)
exit 1
}
function decodeArg ($arg) {
[Regex]::Replace($arg, '#(\d+);', { [char][int] $args[0].Groups[1].Value })
}
$options = @{}
foreach ($arg in @('display', 'displayOnly', 'keyIn', 'hideEchoBack', 'mask', 'limit', 'caseSensitive')) {
$options.Add($arg, (Get-Variable $arg -ValueOnly))
}
$argList = New-Object string[] $options.Keys.Count
$options.Keys.CopyTo($argList, 0)
foreach ($arg in $argList) {
if ($options[$arg] -is [string] -and $options[$arg])
{ $options[$arg] = decodeArg $options[$arg] }
}
[string] $inputTTY = ''
[bool] $silent = -not $options.display -and
$options.keyIn -and $options.hideEchoBack -and -not $options.mask
[bool] $isCooked = -not $options.hideEchoBack -and -not $options.keyIn
# Instant method that opens TTY without CreateFile via P/Invoke in .NET Framework
# **NOTE** Don't include special characters of DOS in $command when $getRes is True.
# [string] $cmdPath = $Env:ComSpec
# [string] $psPath = 'powershell.exe'
function execWithTTY ($command, $getRes = $False, $throwError = $False) {
if ($getRes) {
$res = (cmd.exe /C "<CON powershell.exe -Command $command")
if ($LastExitCode -ne 0) {
if ($throwError) { throw $LastExitCode }
else { exit $LastExitCode }
}
return $res
} else {
$command | cmd.exe /C ">CON powershell.exe -Command -"
if ($LastExitCode -ne 0) {
if ($throwError) { throw $LastExitCode }
else { exit $LastExitCode }
}
}
}
function writeTTY ($text) {
execWithTTY ('Write-Host (''' +
(($text -replace '''', '''''') -replace '[\r\n]', '''+"`n"+''') + ''') -NoNewline')
}
if ($options.display) {
writeTTY $options.display
}
if ($options.displayOnly) { return "''" }
if (-not $options.keyIn -and $options.hideEchoBack -and $options.mask -eq '*') {
# It fails when it's not ready.
try {
$inputTTY = execWithTTY ('$text = Read-Host -AsSecureString;' +
'$bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($text);' +
'[Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)') $True $True
return '''' + $inputTTY + ''''
} catch {} # ignore
}
if ($options.keyIn) { $reqSize = 1 }
if ($options.keyIn -and $options.limit) {
$limitPtn = '[^' + $options.limit + ']'
}
while ($True) {
if (-not $isCooked) {
$chunk = [char][int] (execWithTTY '[int] [Console]::ReadKey($True).KeyChar' $True)
} else {
$chunk = execWithTTY 'Read-Host' $True
$chunk += "`n"
}
if ($chunk -and $chunk -match '^(.*?)[\r\n]') {
$chunk = $Matches[1]
$atEol = $True
} else { $atEol = $False }
# other ctrl-chars
if ($chunk) { $chunk = $chunk -replace '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]', '' }
if ($chunk -and $limitPtn) {
if ($options.caseSensitive) { $chunk = $chunk -creplace $limitPtn, '' }
else { $chunk = $chunk -ireplace $limitPtn, '' }
}
if ($chunk) {
if (-not $isCooked) {
if (-not $options.hideEchoBack) {
writeTTY $chunk
} elseif ($options.mask) {
writeTTY ($options.mask * $chunk.Length)
}
}
$inputTTY += $chunk
}
if ((-not $options.keyIn -and $atEol) -or
($options.keyIn -and $inputTTY.Length -ge $reqSize)) { break }
}
if (-not $isCooked -and -not $silent) { execWithTTY 'Write-Host ''''' } # new line
return "'$inputTTY'"

137
src/node_modules/readline-sync/lib/read.sh generated vendored Normal file
View File

@ -0,0 +1,137 @@
# readlineSync
# https://github.com/anseki/readline-sync
#
# Copyright (c) 2019 anseki
# Licensed under the MIT license.
# Use perl for compatibility of sed/awk of GNU / POSIX, BSD. (and tr)
# Hide "\n" from shell by "\fNL"
decode_arg() {
printf '%s' "$(printf '%s' "$1" | perl -pe 's/#(\d+);/sprintf("%c", $1)/ge; s/[\r\n]/\fNL/g')"
}
# getopt(s)
while [ $# -ge 1 ]; do
arg="$(printf '%s' "$1" | grep -E '^-+[^-]+$' | tr '[A-Z]' '[a-z]' | tr -d '-')"
case "$arg" in
'display') shift; options_display="$(decode_arg "$1")";;
'displayonly') options_displayOnly=true;;
'keyin') options_keyIn=true;;
'hideechoback') options_hideEchoBack=true;;
'mask') shift; options_mask="$(decode_arg "$1")";;
'limit') shift; options_limit="$(decode_arg "$1")";;
'casesensitive') options_caseSensitive=true;;
esac
shift
done
reset_tty() {
if [ -n "$save_tty" ]; then
stty --file=/dev/tty "$save_tty" 2>/dev/null || \
stty -F /dev/tty "$save_tty" 2>/dev/null || \
stty -f /dev/tty "$save_tty" || exit $?
fi
}
trap 'reset_tty' EXIT
save_tty="$(stty --file=/dev/tty -g 2>/dev/null || stty -F /dev/tty -g 2>/dev/null || stty -f /dev/tty -g || exit $?)"
[ -z "$options_display" ] && [ "$options_keyIn" = true ] && \
[ "$options_hideEchoBack" = true ] && [ -z "$options_mask" ] && silent=true
[ "$options_hideEchoBack" != true ] && [ "$options_keyIn" != true ] && is_cooked=true
write_tty() {
# if [ "$2" = true ]; then
# printf '%b' "$1" >/dev/tty
# else
# printf '%s' "$1" >/dev/tty
# fi
printf '%s' "$1" | perl -pe 's/\fNL/\r\n/g' >/dev/tty
}
replace_allchars() { (
text=''
for i in $(seq 1 ${#1})
do
text="$text$2"
done
printf '%s' "$text"
) }
if [ -n "$options_display" ]; then
write_tty "$options_display"
fi
if [ "$options_displayOnly" = true ]; then
printf "'%s'" ''
exit 0
fi
if [ "$is_cooked" = true ]; then
stty --file=/dev/tty cooked 2>/dev/null || \
stty -F /dev/tty cooked 2>/dev/null || \
stty -f /dev/tty cooked || exit $?
else
stty --file=/dev/tty raw -echo 2>/dev/null || \
stty -F /dev/tty raw -echo 2>/dev/null || \
stty -f /dev/tty raw -echo || exit $?
fi
[ "$options_keyIn" = true ] && req_size=1
if [ "$options_keyIn" = true ] && [ -n "$options_limit" ]; then
if [ "$options_caseSensitive" = true ]; then
limit_ptn="$options_limit"
else
# Safe list
# limit_ptn="$(printf '%s' "$options_limit" | sed 's/\([a-z]\)/\L\1\U\1/ig')"
limit_ptn="$(printf '%s' "$options_limit" | perl -pe 's/([a-z])/lc($1) . uc($1)/ige')"
fi
fi
while :
do
if [ "$is_cooked" != true ]; then
# chunk="$(dd if=/dev/tty bs=1 count=1 2>/dev/null)"
chunk="$(dd if=/dev/tty bs=1 count=1 2>/dev/null | perl -pe 's/[\r\n]/\fNL/g')"
else
IFS= read -r chunk </dev/tty || exit $?
chunk="$(printf '%s\fNL' "$chunk")"
fi
# if [ -n "$chunk" ] && [ "$(printf '%s' "$chunk" | tr '\r' '\n' | wc -l)" != "0" ]; then
# chunk="$(printf '%s' "$chunk" | tr '\r' '\n' | head -n 1)"
if [ -n "$chunk" ] && printf '%s' "$chunk" | perl -ne '/\fNL/ or exit 1'; then
chunk="$(printf '%s' "$chunk" | perl -pe 's/^(.*?)\fNL.*$/$1/')"
at_eol=true
fi
# other ctrl-chars
if [ -n "$chunk" ]; then
# chunk="$(printf '%s' "$chunk" | tr -d '\00-\10\13\14\16-\37\177')"
# for System V
chunk="$(printf '%s' "$chunk" | tr -d '\00\01\02\03\04\05\06\07\10\13\14\16\17\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37\177')"
fi
if [ -n "$chunk" ] && [ -n "$limit_ptn" ]; then
chunk="$(printf '%s' "$chunk" | tr -cd "$limit_ptn")"
fi
if [ -n "$chunk" ]; then
if [ "$is_cooked" != true ]; then
if [ "$options_hideEchoBack" != true ]; then
write_tty "$chunk"
elif [ -n "$options_mask" ]; then
write_tty "$(replace_allchars "$chunk" "$options_mask")"
fi
fi
input="$input$chunk"
fi
if ( [ "$options_keyIn" != true ] && [ "$at_eol" = true ] ) || \
( [ "$options_keyIn" = true ] && [ ${#input} -ge $req_size ] ); then break; fi
done
if [ "$is_cooked" != true ] && [ "$silent" != true ]; then write_tty "$(printf '%b' '\fNL')"; fi
printf "'%s'" "$input"
exit 0

1329
src/node_modules/readline-sync/lib/readline-sync.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

40
src/node_modules/readline-sync/package.json generated vendored Normal file
View File

@ -0,0 +1,40 @@
{
"name": "readline-sync",
"version": "1.4.10",
"title": "readlineSync",
"description": "Synchronous Readline for interactively running to have a conversation with the user via a console(TTY).",
"keywords": [
"readline",
"synchronous",
"interactive",
"prompt",
"question",
"password",
"cli",
"tty",
"command",
"repl",
"keyboard",
"wait",
"block"
],
"main": "./lib/readline-sync.js",
"files": [
"lib/*.@(js|ps1|sh)",
"README-Deprecated.md"
],
"engines": {
"node": ">= 0.8.0"
},
"homepage": "https://github.com/anseki/readline-sync",
"repository": {
"type": "git",
"url": "git://github.com/anseki/readline-sync.git"
},
"bugs": "https://github.com/anseki/readline-sync/issues",
"license": "MIT",
"author": {
"name": "anseki",
"url": "https://github.com/anseki"
}
}

22
src/node_modules/underscore/LICENSE generated vendored Normal file
View File

@ -0,0 +1,22 @@
Copyright (c) 2009-2022 Jeremy Ashkenas, Julian Gonggrijp, and DocumentCloud and Investigative Reporters & Editors
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.

34
src/node_modules/underscore/README.md generated vendored Normal file
View File

@ -0,0 +1,34 @@
__
/\ \ __
__ __ ___ \_\ \ __ _ __ ____ ___ ___ _ __ __ /\_\ ____
/\ \/\ \ /' _ `\ /'_ \ /'__`\/\ __\/ ,__\ / ___\ / __`\/\ __\/'__`\ \/\ \ /',__\
\ \ \_\ \/\ \/\ \/\ \ \ \/\ __/\ \ \//\__, `\/\ \__//\ \ \ \ \ \//\ __/ __ \ \ \/\__, `\
\ \____/\ \_\ \_\ \___,_\ \____\\ \_\\/\____/\ \____\ \____/\ \_\\ \____\/\_\ _\ \ \/\____/
\/___/ \/_/\/_/\/__,_ /\/____/ \/_/ \/___/ \/____/\/___/ \/_/ \/____/\/_//\ \_\ \/___/
\ \____/
\/___/
Underscore.js is a utility-belt library for JavaScript that provides
support for the usual functional suspects (each, map, reduce, filter...)
without extending any core JavaScript objects.
For Docs, License, Tests, and pre-packed downloads, see:
https://underscorejs.org
For support and questions, please consult
our [security policy](SECURITY.md),
[the gitter channel](https://gitter.im/jashkenas/underscore)
or [stackoverflow](https://stackoverflow.com/search?q=underscore.js)
Underscore is an open-sourced component of DocumentCloud:
https://github.com/documentcloud
Many thanks to our contributors:
https://github.com/jashkenas/underscore/contributors
You can support the project by donating on
[Patreon](https://patreon.com/juliangonggrijp).
Enterprise coverage is available as part of the
[Tidelift Subscription](https://tidelift.com/subscription/pkg/npm-underscore?utm_source=npm-underscore&utm_medium=referral&utm_campaign=enterprise).
This project adheres to a [code of conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code.

21
src/node_modules/underscore/amd/_baseCreate.js generated vendored Normal file
View File

@ -0,0 +1,21 @@
define(['./isObject', './_setup'], function (isObject, _setup) {
// Create a naked function reference for surrogate-prototype-swapping.
function ctor() {
return function(){};
}
// An internal function for creating a new object that inherits from another.
function baseCreate(prototype) {
if (!isObject(prototype)) return {};
if (_setup.nativeCreate) return _setup.nativeCreate(prototype);
var Ctor = ctor();
Ctor.prototype = prototype;
var result = new Ctor;
Ctor.prototype = null;
return result;
}
return baseCreate;
});

15
src/node_modules/underscore/amd/_baseIteratee.js generated vendored Normal file
View File

@ -0,0 +1,15 @@
define(['./identity', './isFunction', './isObject', './isArray', './matcher', './property', './_optimizeCb'], function (identity, isFunction, isObject, isArray, matcher, property, _optimizeCb) {
// An internal function to generate callbacks that can be applied to each
// element in a collection, returning the desired result — either `_.identity`,
// an arbitrary callback, a property matcher, or a property accessor.
function baseIteratee(value, context, argCount) {
if (value == null) return identity;
if (isFunction(value)) return _optimizeCb(value, context, argCount);
if (isObject(value) && !isArray(value)) return matcher(value);
return property(value);
}
return baseIteratee;
});

12
src/node_modules/underscore/amd/_cb.js generated vendored Normal file
View File

@ -0,0 +1,12 @@
define(['./underscore', './_baseIteratee', './iteratee'], function (underscore, _baseIteratee, iteratee) {
// The function we call internally to generate a callback. It invokes
// `_.iteratee` if overridden, otherwise `baseIteratee`.
function cb(value, context, argCount) {
if (underscore.iteratee !== iteratee) return underscore.iteratee(value, context);
return _baseIteratee(value, context, argCount);
}
return cb;
});

10
src/node_modules/underscore/amd/_chainResult.js generated vendored Normal file
View File

@ -0,0 +1,10 @@
define(['./underscore'], function (underscore) {
// Helper function to continue chaining intermediate results.
function chainResult(instance, obj) {
return instance._chain ? underscore(obj).chain() : obj;
}
return chainResult;
});

View File

@ -0,0 +1,42 @@
define(['./_setup', './isFunction', './_has'], function (_setup, isFunction, _has) {
// Internal helper to create a simple lookup structure.
// `collectNonEnumProps` used to depend on `_.contains`, but this led to
// circular imports. `emulatedSet` is a one-off solution that only works for
// arrays of strings.
function emulatedSet(keys) {
var hash = {};
for (var l = keys.length, i = 0; i < l; ++i) hash[keys[i]] = true;
return {
contains: function(key) { return hash[key] === true; },
push: function(key) {
hash[key] = true;
return keys.push(key);
}
};
}
// Internal helper. Checks `keys` for the presence of keys in IE < 9 that won't
// be iterated by `for key in ...` and thus missed. Extends `keys` in place if
// needed.
function collectNonEnumProps(obj, keys) {
keys = emulatedSet(keys);
var nonEnumIdx = _setup.nonEnumerableProps.length;
var constructor = obj.constructor;
var proto = (isFunction(constructor) && constructor.prototype) || _setup.ObjProto;
// Constructor is a special case.
var prop = 'constructor';
if (_has(obj, prop) && !keys.contains(prop)) keys.push(prop);
while (nonEnumIdx--) {
prop = _setup.nonEnumerableProps[nonEnumIdx];
if (prop in obj && obj[prop] !== proto[prop] && !keys.contains(prop)) {
keys.push(prop);
}
}
}
return collectNonEnumProps;
});

24
src/node_modules/underscore/amd/_createAssigner.js generated vendored Normal file
View File

@ -0,0 +1,24 @@
define(function () {
// An internal function for creating assigner functions.
function createAssigner(keysFunc, defaults) {
return function(obj) {
var length = arguments.length;
if (defaults) obj = Object(obj);
if (length < 2 || obj == null) return obj;
for (var index = 1; index < length; index++) {
var source = arguments[index],
keys = keysFunc(source),
l = keys.length;
for (var i = 0; i < l; i++) {
var key = keys[i];
if (!defaults || obj[key] === void 0) obj[key] = source[key];
}
}
return obj;
};
}
return createAssigner;
});

21
src/node_modules/underscore/amd/_createEscaper.js generated vendored Normal file
View File

@ -0,0 +1,21 @@
define(['./keys'], function (keys) {
// Internal helper to generate functions for escaping and unescaping strings
// to/from HTML interpolation.
function createEscaper(map) {
var escaper = function(match) {
return map[match];
};
// Regexes for identifying a key that needs to be escaped.
var source = '(?:' + keys(map).join('|') + ')';
var testRegexp = RegExp(source);
var replaceRegexp = RegExp(source, 'g');
return function(string) {
string = string == null ? '' : '' + string;
return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
};
}
return createEscaper;
});

30
src/node_modules/underscore/amd/_createIndexFinder.js generated vendored Normal file
View File

@ -0,0 +1,30 @@
define(['./_getLength', './_setup', './isNaN'], function (_getLength, _setup, _isNaN) {
// Internal function to generate the `_.indexOf` and `_.lastIndexOf` functions.
function createIndexFinder(dir, predicateFind, sortedIndex) {
return function(array, item, idx) {
var i = 0, length = _getLength(array);
if (typeof idx == 'number') {
if (dir > 0) {
i = idx >= 0 ? idx : Math.max(idx + length, i);
} else {
length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
}
} else if (sortedIndex && idx && length) {
idx = sortedIndex(array, item);
return array[idx] === item ? idx : -1;
}
if (item !== item) {
idx = predicateFind(_setup.slice.call(array, i, length), _isNaN);
return idx >= 0 ? idx + i : -1;
}
for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
if (array[idx] === item) return idx;
}
return -1;
};
}
return createIndexFinder;
});

View File

@ -0,0 +1,18 @@
define(['./_cb', './_getLength'], function (_cb, _getLength) {
// Internal function to generate `_.findIndex` and `_.findLastIndex`.
function createPredicateIndexFinder(dir) {
return function(array, predicate, context) {
predicate = _cb(predicate, context);
var length = _getLength(array);
var index = dir > 0 ? 0 : length - 1;
for (; index >= 0 && index < length; index += dir) {
if (predicate(array[index], index, array)) return index;
}
return -1;
};
}
return createPredicateIndexFinder;
});

30
src/node_modules/underscore/amd/_createReduce.js generated vendored Normal file
View File

@ -0,0 +1,30 @@
define(['./_isArrayLike', './keys', './_optimizeCb'], function (_isArrayLike, keys, _optimizeCb) {
// Internal helper to create a reducing function, iterating left or right.
function createReduce(dir) {
// Wrap code that reassigns argument variables in a separate function than
// the one that accesses `arguments.length` to avoid a perf hit. (#1991)
var reducer = function(obj, iteratee, memo, initial) {
var _keys = !_isArrayLike(obj) && keys(obj),
length = (_keys || obj).length,
index = dir > 0 ? 0 : length - 1;
if (!initial) {
memo = obj[_keys ? _keys[index] : index];
index += dir;
}
for (; index >= 0 && index < length; index += dir) {
var currentKey = _keys ? _keys[index] : index;
memo = iteratee(memo, obj[currentKey], currentKey, obj);
}
return memo;
};
return function(obj, iteratee, memo, context) {
var initial = arguments.length >= 3;
return reducer(obj, _optimizeCb(iteratee, context, 4), memo, initial);
};
}
return createReduce;
});

View File

@ -0,0 +1,13 @@
define(['./_setup'], function (_setup) {
// Common internal logic for `isArrayLike` and `isBufferLike`.
function createSizePropertyCheck(getSizeProperty) {
return function(collection) {
var sizeProperty = getSizeProperty(collection);
return typeof sizeProperty == 'number' && sizeProperty >= 0 && sizeProperty <= _setup.MAX_ARRAY_INDEX;
}
}
return createSizePropertyCheck;
});

15
src/node_modules/underscore/amd/_deepGet.js generated vendored Normal file
View File

@ -0,0 +1,15 @@
define(function () {
// Internal function to obtain a nested property in `obj` along `path`.
function deepGet(obj, path) {
var length = path.length;
for (var i = 0; i < length; i++) {
if (obj == null) return void 0;
obj = obj[path[i]];
}
return length ? obj : void 0;
}
return deepGet;
});

15
src/node_modules/underscore/amd/_escapeMap.js generated vendored Normal file
View File

@ -0,0 +1,15 @@
define(function () {
// Internal list of HTML entities for escaping.
var escapeMap = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#x27;',
'`': '&#x60;'
};
return escapeMap;
});

16
src/node_modules/underscore/amd/_executeBound.js generated vendored Normal file
View File

@ -0,0 +1,16 @@
define(['./_baseCreate', './isObject'], function (_baseCreate, isObject) {
// Internal function to execute `sourceFunc` bound to `context` with optional
// `args`. Determines whether to execute a function as a constructor or as a
// normal function.
function executeBound(sourceFunc, boundFunc, context, callingContext, args) {
if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
var self = _baseCreate(sourceFunc.prototype);
var result = sourceFunc.apply(self, args);
if (isObject(result)) return result;
return self;
}
return executeBound;
});

32
src/node_modules/underscore/amd/_flatten.js generated vendored Normal file
View File

@ -0,0 +1,32 @@
define(['./_getLength', './_isArrayLike', './isArray', './isArguments'], function (_getLength, _isArrayLike, isArray, isArguments) {
// Internal implementation of a recursive `flatten` function.
function flatten(input, depth, strict, output) {
output = output || [];
if (!depth && depth !== 0) {
depth = Infinity;
} else if (depth <= 0) {
return output.concat(input);
}
var idx = output.length;
for (var i = 0, length = _getLength(input); i < length; i++) {
var value = input[i];
if (_isArrayLike(value) && (isArray(value) || isArguments(value))) {
// Flatten current level of array or arguments object.
if (depth > 1) {
flatten(value, depth - 1, strict, output);
idx = output.length;
} else {
var j = 0, len = value.length;
while (j < len) output[idx++] = value[j++];
}
} else if (!strict) {
output[idx++] = value;
}
}
return output;
}
return flatten;
});

8
src/node_modules/underscore/amd/_getByteLength.js generated vendored Normal file
View File

@ -0,0 +1,8 @@
define(['./_shallowProperty'], function (_shallowProperty) {
// Internal helper to obtain the `byteLength` property of an object.
var getByteLength = _shallowProperty('byteLength');
return getByteLength;
});

8
src/node_modules/underscore/amd/_getLength.js generated vendored Normal file
View File

@ -0,0 +1,8 @@
define(['./_shallowProperty'], function (_shallowProperty) {
// Internal helper to obtain the `length` property of an object.
var getLength = _shallowProperty('length');
return getLength;
});

18
src/node_modules/underscore/amd/_group.js generated vendored Normal file
View File

@ -0,0 +1,18 @@
define(['./_cb', './each'], function (_cb, each) {
// An internal function used for aggregate "group by" operations.
function group(behavior, partition) {
return function(obj, iteratee, context) {
var result = partition ? [[], []] : {};
iteratee = _cb(iteratee, context);
each(obj, function(value, index) {
var key = iteratee(value, index, obj);
behavior(result, value, key);
});
return result;
};
}
return group;
});

10
src/node_modules/underscore/amd/_has.js generated vendored Normal file
View File

@ -0,0 +1,10 @@
define(['./_setup'], function (_setup) {
// Internal function to check whether `key` is an own property name of `obj`.
function has(obj, key) {
return obj != null && _setup.hasOwnProperty.call(obj, key);
}
return has;
});

7
src/node_modules/underscore/amd/_hasObjectTag.js generated vendored Normal file
View File

@ -0,0 +1,7 @@
define(['./_tagTester'], function (_tagTester) {
var hasObjectTag = _tagTester('Object');
return hasObjectTag;
});

11
src/node_modules/underscore/amd/_isArrayLike.js generated vendored Normal file
View File

@ -0,0 +1,11 @@
define(['./_createSizePropertyCheck', './_getLength'], function (_createSizePropertyCheck, _getLength) {
// Internal helper for collection methods to determine whether a collection
// should be iterated as an array or as an object.
// Related: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
// Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
var isArrayLike = _createSizePropertyCheck(_getLength);
return isArrayLike;
});

9
src/node_modules/underscore/amd/_isBufferLike.js generated vendored Normal file
View File

@ -0,0 +1,9 @@
define(['./_createSizePropertyCheck', './_getByteLength'], function (_createSizePropertyCheck, _getByteLength) {
// Internal helper to determine whether we should spend extensive checks against
// `ArrayBuffer` et al.
var isBufferLike = _createSizePropertyCheck(_getByteLength);
return isBufferLike;
});

11
src/node_modules/underscore/amd/_keyInObj.js generated vendored Normal file
View File

@ -0,0 +1,11 @@
define(function () {
// Internal `_.pick` helper function to determine whether `key` is an enumerable
// property name of `obj`.
function keyInObj(value, key, obj) {
return key in obj;
}
return keyInObj;
});

44
src/node_modules/underscore/amd/_methodFingerprint.js generated vendored Normal file
View File

@ -0,0 +1,44 @@
define(['exports', './_getLength', './isFunction', './allKeys'], function (exports, _getLength, isFunction, allKeys) {
// Since the regular `Object.prototype.toString` type tests don't work for
// some types in IE 11, we use a fingerprinting heuristic instead, based
// on the methods. It's not great, but it's the best we got.
// The fingerprint method lists are defined below.
function ie11fingerprint(methods) {
var length = _getLength(methods);
return function(obj) {
if (obj == null) return false;
// `Map`, `WeakMap` and `Set` have no enumerable keys.
var keys = allKeys(obj);
if (_getLength(keys)) return false;
for (var i = 0; i < length; i++) {
if (!isFunction(obj[methods[i]])) return false;
}
// If we are testing against `WeakMap`, we need to ensure that
// `obj` doesn't have a `forEach` method in order to distinguish
// it from a regular `Map`.
return methods !== weakMapMethods || !isFunction(obj[forEachName]);
};
}
// In the interest of compact minification, we write
// each string in the fingerprints only once.
var forEachName = 'forEach',
hasName = 'has',
commonInit = ['clear', 'delete'],
mapTail = ['get', hasName, 'set'];
// `Map`, `WeakMap` and `Set` each have slightly different
// combinations of the above sublists.
var mapMethods = commonInit.concat(forEachName, mapTail),
weakMapMethods = commonInit.concat(mapTail),
setMethods = ['add'].concat(commonInit, forEachName, hasName);
exports.ie11fingerprint = ie11fingerprint;
exports.mapMethods = mapMethods;
exports.setMethods = setMethods;
exports.weakMapMethods = weakMapMethods;
Object.defineProperty(exports, '__esModule', { value: true });
});

27
src/node_modules/underscore/amd/_optimizeCb.js generated vendored Normal file
View File

@ -0,0 +1,27 @@
define(function () {
// Internal function that returns an efficient (for current engines) version
// of the passed-in callback, to be repeatedly applied in other Underscore
// functions.
function optimizeCb(func, context, argCount) {
if (context === void 0) return func;
switch (argCount == null ? 3 : argCount) {
case 1: return function(value) {
return func.call(context, value);
};
// The 2-argument case is omitted because were not using it.
case 3: return function(value, index, collection) {
return func.call(context, value, index, collection);
};
case 4: return function(accumulator, value, index, collection) {
return func.call(context, accumulator, value, index, collection);
};
}
return function() {
return func.apply(context, arguments);
};
}
return optimizeCb;
});

70
src/node_modules/underscore/amd/_setup.js generated vendored Normal file
View File

@ -0,0 +1,70 @@
define(['exports'], function (exports) {
// Current version.
var VERSION = '1.13.4';
// Establish the root object, `window` (`self`) in the browser, `global`
// on the server, or `this` in some virtual machines. We use `self`
// instead of `window` for `WebWorker` support.
var root = (typeof self == 'object' && self.self === self && self) ||
(typeof global == 'object' && global.global === global && global) ||
Function('return this')() ||
{};
// Save bytes in the minified (but not gzipped) version:
var ArrayProto = Array.prototype, ObjProto = Object.prototype;
var SymbolProto = typeof Symbol !== 'undefined' ? Symbol.prototype : null;
// Create quick reference variables for speed access to core prototypes.
var push = ArrayProto.push,
slice = ArrayProto.slice,
toString = ObjProto.toString,
hasOwnProperty = ObjProto.hasOwnProperty;
// Modern feature detection.
var supportsArrayBuffer = typeof ArrayBuffer !== 'undefined',
supportsDataView = typeof DataView !== 'undefined';
// All **ECMAScript 5+** native function implementations that we hope to use
// are declared here.
var nativeIsArray = Array.isArray,
nativeKeys = Object.keys,
nativeCreate = Object.create,
nativeIsView = supportsArrayBuffer && ArrayBuffer.isView;
// Create references to these builtin functions because we override them.
var _isNaN = isNaN,
_isFinite = isFinite;
// Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
// The largest integer that can be represented exactly.
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
exports.ArrayProto = ArrayProto;
exports.MAX_ARRAY_INDEX = MAX_ARRAY_INDEX;
exports.ObjProto = ObjProto;
exports.SymbolProto = SymbolProto;
exports.VERSION = VERSION;
exports._isFinite = _isFinite;
exports._isNaN = _isNaN;
exports.hasEnumBug = hasEnumBug;
exports.hasOwnProperty = hasOwnProperty;
exports.nativeCreate = nativeCreate;
exports.nativeIsArray = nativeIsArray;
exports.nativeIsView = nativeIsView;
exports.nativeKeys = nativeKeys;
exports.nonEnumerableProps = nonEnumerableProps;
exports.push = push;
exports.root = root;
exports.slice = slice;
exports.supportsArrayBuffer = supportsArrayBuffer;
exports.supportsDataView = supportsDataView;
exports.toString = toString;
Object.defineProperty(exports, '__esModule', { value: true });
});

12
src/node_modules/underscore/amd/_shallowProperty.js generated vendored Normal file
View File

@ -0,0 +1,12 @@
define(function () {
// Internal helper to generate a function to obtain property `key` from `obj`.
function shallowProperty(key) {
return function(obj) {
return obj == null ? void 0 : obj[key];
};
}
return shallowProperty;
});

16
src/node_modules/underscore/amd/_stringTagBug.js generated vendored Normal file
View File

@ -0,0 +1,16 @@
define(['exports', './_setup', './_hasObjectTag'], function (exports, _setup, _hasObjectTag) {
// In IE 10 - Edge 13, `DataView` has string tag `'[object Object]'`.
// In IE 11, the most common among them, this problem also applies to
// `Map`, `WeakMap` and `Set`.
var hasStringTagBug = (
_setup.supportsDataView && _hasObjectTag(new DataView(new ArrayBuffer(8)))
),
isIE11 = (typeof Map !== 'undefined' && _hasObjectTag(new Map));
exports.hasStringTagBug = hasStringTagBug;
exports.isIE11 = isIE11;
Object.defineProperty(exports, '__esModule', { value: true });
});

13
src/node_modules/underscore/amd/_tagTester.js generated vendored Normal file
View File

@ -0,0 +1,13 @@
define(['./_setup'], function (_setup) {
// Internal function for creating a `toString`-based type tester.
function tagTester(name) {
var tag = '[object ' + name + ']';
return function(obj) {
return _setup.toString.call(obj) === tag;
};
}
return tagTester;
});

15
src/node_modules/underscore/amd/_toBufferView.js generated vendored Normal file
View File

@ -0,0 +1,15 @@
define(['./_getByteLength'], function (_getByteLength) {
// Internal function to wrap or shallow-copy an ArrayBuffer,
// typed array or DataView to a new view, reusing the buffer.
function toBufferView(bufferSource) {
return new Uint8Array(
bufferSource.buffer || bufferSource,
bufferSource.byteOffset || 0,
_getByteLength(bufferSource)
);
}
return toBufferView;
});

11
src/node_modules/underscore/amd/_toPath.js generated vendored Normal file
View File

@ -0,0 +1,11 @@
define(['./underscore', './toPath'], function (underscore, toPath$1) {
// Internal wrapper for `_.toPath` to enable minification.
// Similar to `cb` for `_.iteratee`.
function toPath(path) {
return underscore.toPath(path);
}
return toPath;
});

8
src/node_modules/underscore/amd/_unescapeMap.js generated vendored Normal file
View File

@ -0,0 +1,8 @@
define(['./invert', './_escapeMap'], function (invert, _escapeMap) {
// Internal list of HTML entities for unescaping.
var unescapeMap = invert(_escapeMap);
return unescapeMap;
});

14
src/node_modules/underscore/amd/after.js generated vendored Normal file
View File

@ -0,0 +1,14 @@
define(function () {
// Returns a function that will only be executed on and after the Nth call.
function after(times, func) {
return function() {
if (--times < 1) {
return func.apply(this, arguments);
}
};
}
return after;
});

15
src/node_modules/underscore/amd/allKeys.js generated vendored Normal file
View File

@ -0,0 +1,15 @@
define(['./isObject', './_setup', './_collectNonEnumProps'], function (isObject, _setup, _collectNonEnumProps) {
// Retrieve all the enumerable property names of an object.
function allKeys(obj) {
if (!isObject(obj)) return [];
var keys = [];
for (var key in obj) keys.push(key);
// Ahem, IE < 9.
if (_setup.hasEnumBug) _collectNonEnumProps(obj, keys);
return keys;
}
return allKeys;
});

18
src/node_modules/underscore/amd/before.js generated vendored Normal file
View File

@ -0,0 +1,18 @@
define(function () {
// Returns a function that will only be executed up to (but not including) the
// Nth call.
function before(times, func) {
var memo;
return function() {
if (--times > 0) {
memo = func.apply(this, arguments);
}
if (times <= 1) func = null;
return memo;
};
}
return before;
});

15
src/node_modules/underscore/amd/bind.js generated vendored Normal file
View File

@ -0,0 +1,15 @@
define(['./restArguments', './isFunction', './_executeBound'], function (restArguments, isFunction, _executeBound) {
// Create a function bound to a given object (assigning `this`, and arguments,
// optionally).
var bind = restArguments(function(func, context, args) {
if (!isFunction(func)) throw new TypeError('Bind must be called on a function');
var bound = restArguments(function(callArgs) {
return _executeBound(func, bound, context, this, args.concat(callArgs));
});
return bound;
});
return bind;
});

19
src/node_modules/underscore/amd/bindAll.js generated vendored Normal file
View File

@ -0,0 +1,19 @@
define(['./restArguments', './_flatten', './bind'], function (restArguments, _flatten, bind) {
// Bind a number of an object's methods to that object. Remaining arguments
// are the method names to be bound. Useful for ensuring that all callbacks
// defined on an object belong to it.
var bindAll = restArguments(function(obj, keys) {
keys = _flatten(keys, false, false);
var index = keys.length;
if (index < 1) throw new Error('bindAll must be passed function names');
while (index--) {
var key = keys[index];
obj[key] = bind(obj[key], obj);
}
return obj;
});
return bindAll;
});

12
src/node_modules/underscore/amd/chain.js generated vendored Normal file
View File

@ -0,0 +1,12 @@
define(['./underscore'], function (underscore) {
// Start chaining a wrapped Underscore object.
function chain(obj) {
var instance = underscore(obj);
instance._chain = true;
return instance;
}
return chain;
});

17
src/node_modules/underscore/amd/chunk.js generated vendored Normal file
View File

@ -0,0 +1,17 @@
define(['./_setup'], function (_setup) {
// Chunk a single array into multiple arrays, each containing `count` or fewer
// items.
function chunk(array, count) {
if (count == null || count < 1) return [];
var result = [];
var i = 0, length = array.length;
while (i < length) {
result.push(_setup.slice.call(array, i, i += count));
}
return result;
}
return chunk;
});

11
src/node_modules/underscore/amd/clone.js generated vendored Normal file
View File

@ -0,0 +1,11 @@
define(['./isObject', './isArray', './extend'], function (isObject, isArray, extend) {
// Create a (shallow-cloned) duplicate of an object.
function clone(obj) {
if (!isObject(obj)) return obj;
return isArray(obj) ? obj.slice() : extend({}, obj);
}
return clone;
});

10
src/node_modules/underscore/amd/compact.js generated vendored Normal file
View File

@ -0,0 +1,10 @@
define(['./filter'], function (filter) {
// Trim out all falsy values from an array.
function compact(array) {
return filter(array, Boolean);
}
return compact;
});

18
src/node_modules/underscore/amd/compose.js generated vendored Normal file
View File

@ -0,0 +1,18 @@
define(function () {
// Returns a function that is the composition of a list of functions, each
// consuming the return value of the function that follows.
function compose() {
var args = arguments;
var start = args.length - 1;
return function() {
var i = start;
var result = args[start].apply(this, arguments);
while (i--) result = args[i].call(this, result);
return result;
};
}
return compose;
});

12
src/node_modules/underscore/amd/constant.js generated vendored Normal file
View File

@ -0,0 +1,12 @@
define(function () {
// Predicate-generating function. Often useful outside of Underscore.
function constant(value) {
return function() {
return value;
};
}
return constant;
});

12
src/node_modules/underscore/amd/contains.js generated vendored Normal file
View File

@ -0,0 +1,12 @@
define(['./_isArrayLike', './values', './indexOf'], function (_isArrayLike, values, indexOf) {
// Determine if the array or object contains a given item (using `===`).
function contains(obj, item, fromIndex, guard) {
if (!_isArrayLike(obj)) obj = values(obj);
if (typeof fromIndex != 'number' || guard) fromIndex = 0;
return indexOf(obj, item, fromIndex) >= 0;
}
return contains;
});

12
src/node_modules/underscore/amd/countBy.js generated vendored Normal file
View File

@ -0,0 +1,12 @@
define(['./_group', './_has'], function (_group, _has) {
// Counts instances of an object that group by a certain criterion. Pass
// either a string attribute to count by, or a function that returns the
// criterion.
var countBy = _group(function(result, value, key) {
if (_has(result, key)) result[key]++; else result[key] = 1;
});
return countBy;
});

14
src/node_modules/underscore/amd/create.js generated vendored Normal file
View File

@ -0,0 +1,14 @@
define(['./_baseCreate', './extendOwn'], function (_baseCreate, extendOwn) {
// Creates an object that inherits from the given prototype object.
// If additional properties are provided then they will be added to the
// created object.
function create(prototype, props) {
var result = _baseCreate(prototype);
if (props) extendOwn(result, props);
return result;
}
return create;
});

43
src/node_modules/underscore/amd/debounce.js generated vendored Normal file
View File

@ -0,0 +1,43 @@
define(['./restArguments', './now'], function (restArguments, now) {
// When a sequence of calls of the returned function ends, the argument
// function is triggered. The end of a sequence is defined by the `wait`
// parameter. If `immediate` is passed, the argument function will be
// triggered at the beginning of the sequence instead of at the end.
function debounce(func, wait, immediate) {
var timeout, previous, args, result, context;
var later = function() {
var passed = now() - previous;
if (wait > passed) {
timeout = setTimeout(later, wait - passed);
} else {
timeout = null;
if (!immediate) result = func.apply(context, args);
// This check is needed because `func` can recursively invoke `debounced`.
if (!timeout) args = context = null;
}
};
var debounced = restArguments(function(_args) {
context = this;
args = _args;
previous = now();
if (!timeout) {
timeout = setTimeout(later, wait);
if (immediate) result = func.apply(context, args);
}
return result;
});
debounced.cancel = function() {
clearTimeout(timeout);
timeout = args = context = null;
};
return debounced;
}
return debounce;
});

8
src/node_modules/underscore/amd/defaults.js generated vendored Normal file
View File

@ -0,0 +1,8 @@
define(['./_createAssigner', './allKeys'], function (_createAssigner, allKeys) {
// Fill in a given object with default properties.
var defaults = _createAssigner(allKeys, true);
return defaults;
});

9
src/node_modules/underscore/amd/defer.js generated vendored Normal file
View File

@ -0,0 +1,9 @@
define(['./partial', './delay', './underscore'], function (partial, delay, underscore) {
// Defers a function, scheduling it to run after the current call stack has
// cleared.
var defer = partial(delay, underscore, 1);
return defer;
});

13
src/node_modules/underscore/amd/delay.js generated vendored Normal file
View File

@ -0,0 +1,13 @@
define(['./restArguments'], function (restArguments) {
// Delays a function for the given number of milliseconds, and then calls
// it with the arguments supplied.
var delay = restArguments(function(func, wait, args) {
return setTimeout(function() {
return func.apply(null, args);
}, wait);
});
return delay;
});

14
src/node_modules/underscore/amd/difference.js generated vendored Normal file
View File

@ -0,0 +1,14 @@
define(['./restArguments', './_flatten', './filter', './contains'], function (restArguments, _flatten, filter, contains) {
// Take the difference between one array and a number of other arrays.
// Only the elements present in just the first array will remain.
var difference = restArguments(function(array, rest) {
rest = _flatten(rest, true, true);
return filter(array, function(value){
return !contains(rest, value);
});
});
return difference;
});

25
src/node_modules/underscore/amd/each.js generated vendored Normal file
View File

@ -0,0 +1,25 @@
define(['./_optimizeCb', './_isArrayLike', './keys'], function (_optimizeCb, _isArrayLike, keys) {
// The cornerstone for collection functions, an `each`
// implementation, aka `forEach`.
// Handles raw objects in addition to array-likes. Treats all
// sparse array-likes as if they were dense.
function each(obj, iteratee, context) {
iteratee = _optimizeCb(iteratee, context);
var i, length;
if (_isArrayLike(obj)) {
for (i = 0, length = obj.length; i < length; i++) {
iteratee(obj[i], i, obj);
}
} else {
var _keys = keys(obj);
for (i = 0, length = _keys.length; i < length; i++) {
iteratee(obj[_keys[i]], _keys[i], obj);
}
}
return obj;
}
return each;
});

8
src/node_modules/underscore/amd/escape.js generated vendored Normal file
View File

@ -0,0 +1,8 @@
define(['./_createEscaper', './_escapeMap'], function (_createEscaper, _escapeMap) {
// Function for escaping strings to HTML interpolation.
var _escape = _createEscaper(_escapeMap);
return _escape;
});

17
src/node_modules/underscore/amd/every.js generated vendored Normal file
View File

@ -0,0 +1,17 @@
define(['./_cb', './_isArrayLike', './keys'], function (_cb, _isArrayLike, keys) {
// Determine whether all of the elements pass a truth test.
function every(obj, predicate, context) {
predicate = _cb(predicate, context);
var _keys = !_isArrayLike(obj) && keys(obj),
length = (_keys || obj).length;
for (var index = 0; index < length; index++) {
var currentKey = _keys ? _keys[index] : index;
if (!predicate(obj[currentKey], currentKey, obj)) return false;
}
return true;
}
return every;
});

8
src/node_modules/underscore/amd/extend.js generated vendored Normal file
View File

@ -0,0 +1,8 @@
define(['./_createAssigner', './allKeys'], function (_createAssigner, allKeys) {
// Extend a given object with all the properties in passed-in object(s).
var extend = _createAssigner(allKeys);
return extend;
});

10
src/node_modules/underscore/amd/extendOwn.js generated vendored Normal file
View File

@ -0,0 +1,10 @@
define(['./_createAssigner', './keys'], function (_createAssigner, keys) {
// Assigns a given object with all the own properties in the passed-in
// object(s).
// (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
var extendOwn = _createAssigner(keys);
return extendOwn;
});

15
src/node_modules/underscore/amd/filter.js generated vendored Normal file
View File

@ -0,0 +1,15 @@
define(['./_cb', './each'], function (_cb, each) {
// Return all the elements that pass a truth test.
function filter(obj, predicate, context) {
var results = [];
predicate = _cb(predicate, context);
each(obj, function(value, index, list) {
if (predicate(value, index, list)) results.push(value);
});
return results;
}
return filter;
});

12
src/node_modules/underscore/amd/find.js generated vendored Normal file
View File

@ -0,0 +1,12 @@
define(['./_isArrayLike', './findIndex', './findKey'], function (_isArrayLike, findIndex, findKey) {
// Return the first value which passes a truth test.
function find(obj, predicate, context) {
var keyFinder = _isArrayLike(obj) ? findIndex : findKey;
var key = keyFinder(obj, predicate, context);
if (key !== void 0 && key !== -1) return obj[key];
}
return find;
});

8
src/node_modules/underscore/amd/findIndex.js generated vendored Normal file
View File

@ -0,0 +1,8 @@
define(['./_createPredicateIndexFinder'], function (_createPredicateIndexFinder) {
// Returns the first index on an array-like that passes a truth test.
var findIndex = _createPredicateIndexFinder(1);
return findIndex;
});

15
src/node_modules/underscore/amd/findKey.js generated vendored Normal file
View File

@ -0,0 +1,15 @@
define(['./_cb', './keys'], function (_cb, keys) {
// Returns the first key on an object that passes a truth test.
function findKey(obj, predicate, context) {
predicate = _cb(predicate, context);
var _keys = keys(obj), key;
for (var i = 0, length = _keys.length; i < length; i++) {
key = _keys[i];
if (predicate(obj[key], key, obj)) return key;
}
}
return findKey;
});

8
src/node_modules/underscore/amd/findLastIndex.js generated vendored Normal file
View File

@ -0,0 +1,8 @@
define(['./_createPredicateIndexFinder'], function (_createPredicateIndexFinder) {
// Returns the last index on an array-like that passes a truth test.
var findLastIndex = _createPredicateIndexFinder(-1);
return findLastIndex;
});

11
src/node_modules/underscore/amd/findWhere.js generated vendored Normal file
View File

@ -0,0 +1,11 @@
define(['./find', './matcher'], function (find, matcher) {
// Convenience version of a common use case of `_.find`: getting the first
// object containing specific `key:value` pairs.
function findWhere(obj, attrs) {
return find(obj, matcher(attrs));
}
return findWhere;
});

13
src/node_modules/underscore/amd/first.js generated vendored Normal file
View File

@ -0,0 +1,13 @@
define(['./initial'], function (initial) {
// Get the first element of an array. Passing **n** will return the first N
// values in the array. The **guard** check allows it to work with `_.map`.
function first(array, n, guard) {
if (array == null || array.length < 1) return n == null || guard ? void 0 : [];
if (n == null || guard) return array[0];
return initial(array, array.length - n);
}
return first;
});

11
src/node_modules/underscore/amd/flatten.js generated vendored Normal file
View File

@ -0,0 +1,11 @@
define(['./_flatten'], function (_flatten) {
// Flatten out an array, either recursively (by default), or up to `depth`.
// Passing `true` or `false` as `depth` means `1` or `Infinity`, respectively.
function flatten(array, depth) {
return _flatten(array, depth, false);
}
return flatten;
});

14
src/node_modules/underscore/amd/functions.js generated vendored Normal file
View File

@ -0,0 +1,14 @@
define(['./isFunction'], function (isFunction) {
// Return a sorted list of the function names available on the object.
function functions(obj) {
var names = [];
for (var key in obj) {
if (isFunction(obj[key])) names.push(key);
}
return names.sort();
}
return functions;
});

14
src/node_modules/underscore/amd/get.js generated vendored Normal file
View File

@ -0,0 +1,14 @@
define(['./_toPath', './_deepGet', './isUndefined'], function (_toPath, _deepGet, isUndefined) {
// Get the value of the (deep) property on `path` from `object`.
// If any property in `path` does not exist or if the value is
// `undefined`, return `defaultValue` instead.
// The `path` is normalized through `_.toPath`.
function get(object, path, defaultValue) {
var value = _deepGet(object, _toPath(path));
return isUndefined(value) ? defaultValue : value;
}
return get;
});

11
src/node_modules/underscore/amd/groupBy.js generated vendored Normal file
View File

@ -0,0 +1,11 @@
define(['./_group', './_has'], function (_group, _has) {
// Groups the object's values by a criterion. Pass either a string attribute
// to group by, or a function that returns the criterion.
var groupBy = _group(function(result, value, key) {
if (_has(result, key)) result[key].push(value); else result[key] = [value];
});
return groupBy;
});

19
src/node_modules/underscore/amd/has.js generated vendored Normal file
View File

@ -0,0 +1,19 @@
define(['./_has', './_toPath'], function (_has, _toPath) {
// Shortcut function for checking if an object has a given property directly on
// itself (in other words, not on a prototype). Unlike the internal `has`
// function, this public version can also traverse nested properties.
function has(obj, path) {
path = _toPath(path);
var length = path.length;
for (var i = 0; i < length; i++) {
var key = path[i];
if (!_has(obj, key)) return false;
obj = obj[key];
}
return !!length;
}
return has;
});

10
src/node_modules/underscore/amd/identity.js generated vendored Normal file
View File

@ -0,0 +1,10 @@
define(function () {
// Keep the identity function around for default iteratees.
function identity(value) {
return value;
}
return identity;
});

12
src/node_modules/underscore/amd/index-default.js generated vendored Normal file
View File

@ -0,0 +1,12 @@
define(['./index', './mixin'], function (index, mixin) {
// Default Export
// Add all of the Underscore functions to the wrapper object.
var _ = mixin(index);
// Legacy Node.js API.
_._ = _;
return _;
});

154
src/node_modules/underscore/amd/index.js generated vendored Normal file
View File

@ -0,0 +1,154 @@
define(['exports', './_setup', './restArguments', './isObject', './isNull', './isUndefined', './isBoolean', './isElement', './isString', './isNumber', './isDate', './isRegExp', './isError', './isSymbol', './isArrayBuffer', './isDataView', './isArray', './isFunction', './isArguments', './isFinite', './isNaN', './isTypedArray', './isEmpty', './isMatch', './isEqual', './isMap', './isWeakMap', './isSet', './isWeakSet', './keys', './allKeys', './values', './pairs', './invert', './functions', './extend', './extendOwn', './defaults', './create', './clone', './tap', './get', './has', './mapObject', './identity', './constant', './noop', './toPath', './property', './propertyOf', './matcher', './times', './random', './now', './escape', './unescape', './templateSettings', './template', './result', './uniqueId', './chain', './iteratee', './partial', './bind', './bindAll', './memoize', './delay', './defer', './throttle', './debounce', './wrap', './negate', './compose', './after', './before', './once', './findKey', './findIndex', './findLastIndex', './sortedIndex', './indexOf', './lastIndexOf', './find', './findWhere', './each', './map', './reduce', './reduceRight', './filter', './reject', './every', './some', './contains', './invoke', './pluck', './where', './max', './min', './shuffle', './sample', './sortBy', './groupBy', './indexBy', './countBy', './partition', './toArray', './size', './pick', './omit', './first', './initial', './last', './rest', './compact', './flatten', './without', './uniq', './union', './intersection', './difference', './unzip', './zip', './object', './range', './chunk', './mixin', './underscore-array-methods', './underscore'], function (exports, _setup, restArguments, isObject, isNull, isUndefined, isBoolean, isElement, isString, isNumber, isDate, isRegExp, isError, isSymbol, isArrayBuffer, isDataView, isArray, isFunction, isArguments, _isFinite, _isNaN, isTypedArray, isEmpty, isMatch, isEqual, isMap, isWeakMap, isSet, isWeakSet, keys, allKeys, values, pairs, invert, functions, extend, extendOwn, defaults, create, clone, tap, get, has, mapObject, identity, constant, noop, toPath, property, propertyOf, matcher, times, random, now, _escape, _unescape, templateSettings, template, result, uniqueId, chain, iteratee, partial, bind, bindAll, memoize, delay, defer, throttle, debounce, wrap, negate, compose, after, before, once, findKey, findIndex, findLastIndex, sortedIndex, indexOf, lastIndexOf, find, findWhere, each, map, reduce, reduceRight, filter, reject, every, some, contains, invoke, pluck, where, max, min, shuffle, sample, sortBy, groupBy, indexBy, countBy, partition, toArray, size, pick, omit, first, initial, last, rest, compact, flatten, without, uniq, union, intersection, difference, unzip, zip, object, range, chunk, mixin, underscoreArrayMethods, underscore) {
// Named Exports
exports.VERSION = _setup.VERSION;
exports.restArguments = restArguments;
exports.isObject = isObject;
exports.isNull = isNull;
exports.isUndefined = isUndefined;
exports.isBoolean = isBoolean;
exports.isElement = isElement;
exports.isString = isString;
exports.isNumber = isNumber;
exports.isDate = isDate;
exports.isRegExp = isRegExp;
exports.isError = isError;
exports.isSymbol = isSymbol;
exports.isArrayBuffer = isArrayBuffer;
exports.isDataView = isDataView;
exports.isArray = isArray;
exports.isFunction = isFunction;
exports.isArguments = isArguments;
exports.isFinite = _isFinite;
exports.isNaN = _isNaN;
exports.isTypedArray = isTypedArray;
exports.isEmpty = isEmpty;
exports.isMatch = isMatch;
exports.isEqual = isEqual;
exports.isMap = isMap;
exports.isWeakMap = isWeakMap;
exports.isSet = isSet;
exports.isWeakSet = isWeakSet;
exports.keys = keys;
exports.allKeys = allKeys;
exports.values = values;
exports.pairs = pairs;
exports.invert = invert;
exports.functions = functions;
exports.methods = functions;
exports.extend = extend;
exports.assign = extendOwn;
exports.extendOwn = extendOwn;
exports.defaults = defaults;
exports.create = create;
exports.clone = clone;
exports.tap = tap;
exports.get = get;
exports.has = has;
exports.mapObject = mapObject;
exports.identity = identity;
exports.constant = constant;
exports.noop = noop;
exports.toPath = toPath;
exports.property = property;
exports.propertyOf = propertyOf;
exports.matcher = matcher;
exports.matches = matcher;
exports.times = times;
exports.random = random;
exports.now = now;
exports.escape = _escape;
exports.unescape = _unescape;
exports.templateSettings = templateSettings;
exports.template = template;
exports.result = result;
exports.uniqueId = uniqueId;
exports.chain = chain;
exports.iteratee = iteratee;
exports.partial = partial;
exports.bind = bind;
exports.bindAll = bindAll;
exports.memoize = memoize;
exports.delay = delay;
exports.defer = defer;
exports.throttle = throttle;
exports.debounce = debounce;
exports.wrap = wrap;
exports.negate = negate;
exports.compose = compose;
exports.after = after;
exports.before = before;
exports.once = once;
exports.findKey = findKey;
exports.findIndex = findIndex;
exports.findLastIndex = findLastIndex;
exports.sortedIndex = sortedIndex;
exports.indexOf = indexOf;
exports.lastIndexOf = lastIndexOf;
exports.detect = find;
exports.find = find;
exports.findWhere = findWhere;
exports.each = each;
exports.forEach = each;
exports.collect = map;
exports.map = map;
exports.foldl = reduce;
exports.inject = reduce;
exports.reduce = reduce;
exports.foldr = reduceRight;
exports.reduceRight = reduceRight;
exports.filter = filter;
exports.select = filter;
exports.reject = reject;
exports.all = every;
exports.every = every;
exports.any = some;
exports.some = some;
exports.contains = contains;
exports.include = contains;
exports.includes = contains;
exports.invoke = invoke;
exports.pluck = pluck;
exports.where = where;
exports.max = max;
exports.min = min;
exports.shuffle = shuffle;
exports.sample = sample;
exports.sortBy = sortBy;
exports.groupBy = groupBy;
exports.indexBy = indexBy;
exports.countBy = countBy;
exports.partition = partition;
exports.toArray = toArray;
exports.size = size;
exports.pick = pick;
exports.omit = omit;
exports.first = first;
exports.head = first;
exports.take = first;
exports.initial = initial;
exports.last = last;
exports.drop = rest;
exports.rest = rest;
exports.tail = rest;
exports.compact = compact;
exports.flatten = flatten;
exports.without = without;
exports.uniq = uniq;
exports.unique = uniq;
exports.union = union;
exports.intersection = intersection;
exports.difference = difference;
exports.transpose = unzip;
exports.unzip = unzip;
exports.zip = zip;
exports.object = object;
exports.range = range;
exports.chunk = chunk;
exports.mixin = mixin;
exports.default = underscore;
Object.defineProperty(exports, '__esModule', { value: true });
});

11
src/node_modules/underscore/amd/indexBy.js generated vendored Normal file
View File

@ -0,0 +1,11 @@
define(['./_group'], function (_group) {
// Indexes the object's values by a criterion, similar to `_.groupBy`, but for
// when you know that your index values will be unique.
var indexBy = _group(function(result, value, key) {
result[key] = value;
});
return indexBy;
});

11
src/node_modules/underscore/amd/indexOf.js generated vendored Normal file
View File

@ -0,0 +1,11 @@
define(['./sortedIndex', './findIndex', './_createIndexFinder'], function (sortedIndex, findIndex, _createIndexFinder) {
// Return the position of the first occurrence of an item in an array,
// or -1 if the item is not included in the array.
// If the array is large and already in sort order, pass `true`
// for **isSorted** to use binary search.
var indexOf = _createIndexFinder(1, findIndex, sortedIndex);
return indexOf;
});

12
src/node_modules/underscore/amd/initial.js generated vendored Normal file
View File

@ -0,0 +1,12 @@
define(['./_setup'], function (_setup) {
// Returns everything but the last entry of the array. Especially useful on
// the arguments object. Passing **n** will return all the values in
// the array, excluding the last N.
function initial(array, n, guard) {
return _setup.slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
}
return initial;
});

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